LibreOffice Module vcl (master) 1
builder.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
9
10#include <config_feature_desktop.h>
11#include <config_options.h>
12#include <config_vclplug.h>
13
14#include <memory>
15#include <string_view>
16#include <unordered_map>
17#include <com/sun/star/accessibility/AccessibleRole.hpp>
18
19#include <comphelper/lok.hxx>
20#include <i18nutil/unicode.hxx>
21#include <jsdialog/enabled.hxx>
22#include <o3tl/string_view.hxx>
23#include <officecfg/Office/Common.hxx>
24#include <osl/module.hxx>
25#include <sal/log.hxx>
27#include <unotools/resmgr.hxx>
28#include <utility>
29#include <vcl/builder.hxx>
30#include <vcl/dialoghelper.hxx>
31#include <vcl/menu.hxx>
34#include <vcl/toolkit/edit.hxx>
35#include <vcl/toolkit/field.hxx>
36#include <vcl/fieldvalues.hxx>
38#include <vcl/toolkit/fixed.hxx>
40#include <vcl/headbar.hxx>
43#include <vcl/layout.hxx>
46#include <vcl/mnemonic.hxx>
49#include <vcl/split.hxx>
50#include <vcl/svapp.hxx>
52#include <vcl/tabctrl.hxx>
53#include <vcl/tabpage.hxx>
55#include <vcl/toolbox.hxx>
58#include <vcl/settings.hxx>
59#include <slider.hxx>
60#include <vcl/weld.hxx>
61#include <vcl/weldutils.hxx>
63#include <iconview.hxx>
64#include <svdata.hxx>
65#include <bitmaps.hlst>
66#include <managedmenubutton.hxx>
67#include <messagedialog.hxx>
68#include <ContextVBox.hxx>
69#include <DropdownBox.hxx>
70#include <IPrioritable.hxx>
71#include <OptionalBox.hxx>
73#include <PriorityHBox.hxx>
74#include <window.h>
77#include <calendar.hxx>
78#include <menutogglebutton.hxx>
79#include <salinst.hxx>
80#include <strings.hrc>
81#include <treeglue.hxx>
83#include <verticaltabctrl.hxx>
84#include <wizdlg.hxx>
85#include <tools/svlibrary.h>
87
88#if defined(DISABLE_DYNLOADING) || defined(LINUX)
89#include <dlfcn.h>
90#endif
91
92static bool toBool(std::string_view rValue)
93{
94 return (!rValue.empty() && (rValue[0] == 't' || rValue[0] == 'T' || rValue[0] == '1'));
95}
96
97namespace
98{
99 OUString mapStockToImageResource(std::u16string_view sType)
100 {
101 if (sType == u"view-refresh")
102 return SV_RESID_BITMAP_REFRESH;
103 else if (sType == u"dialog-error")
104 return IMG_ERROR;
105 else if (sType == u"list-add")
106 return IMG_ADD;
107 else if (sType == u"list-remove")
108 return IMG_REMOVE;
109 else if (sType == u"edit-copy")
110 return IMG_COPY;
111 else if (sType == u"edit-paste")
112 return IMG_PASTE;
113 else if (sType == u"document-open")
114 return IMG_OPEN;
115 else if (sType == u"open-menu-symbolic")
116 return IMG_MENU;
117 else if (sType == u"window-close-symbolic")
118 return SV_RESID_BITMAP_CLOSEDOC;
119 else if (sType == u"x-office-calendar")
120 return IMG_CALENDAR;
121 return OUString();
122 }
123
124}
125
126SymbolType VclBuilder::mapStockToSymbol(std::u16string_view sType)
127{
129 if (sType == u"media-skip-forward")
130 eRet = SymbolType::NEXT;
131 else if (sType == u"media-skip-backward")
132 eRet = SymbolType::PREV;
133 else if (sType == u"media-playback-start")
134 eRet = SymbolType::PLAY;
135 else if (sType == u"media-playback-stop")
136 eRet = SymbolType::STOP;
137 else if (sType == u"go-first")
138 eRet = SymbolType::FIRST;
139 else if (sType == u"go-last")
140 eRet = SymbolType::LAST;
141 else if (sType == u"go-previous")
143 else if (sType == u"go-next")
145 else if (sType == u"go-up")
147 else if (sType == u"go-down")
149 else if (sType == u"missing-image")
150 eRet = SymbolType::IMAGE;
151 else if (sType == u"help-browser" || sType == u"help-browser-symbolic")
152 eRet = SymbolType::HELP;
153 else if (sType == u"window-close")
154 eRet = SymbolType::CLOSE;
155 else if (sType == u"document-new")
156 eRet = SymbolType::PLUS;
157 else if (sType == u"pan-down-symbolic")
159 else if (sType == u"pan-up-symbolic")
160 eRet = SymbolType::SPIN_UP;
161 else if (!mapStockToImageResource(sType).isEmpty())
162 eRet = SymbolType::IMAGE;
163 return eRet;
164}
165
166namespace
167{
168 void setupFromActionName(Button *pButton, VclBuilder::stringmap &rMap, const css::uno::Reference<css::frame::XFrame>& rFrame);
169
170#if defined SAL_LOG_WARN
171 bool isButtonType(WindowType nType)
172 {
173 return nType == WindowType::PUSHBUTTON ||
181 }
182#endif
183
184}
185
186std::unique_ptr<weld::Builder> Application::CreateBuilder(weld::Widget* pParent, const OUString &rUIFile, bool bMobile, sal_uInt64 nLOKWindowId)
187{
189 {
191 return JSInstanceBuilder::CreateSidebarBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile, nLOKWindowId);
192 else if (jsdialog::isBuilderEnabledForPopup(rUIFile))
194 else if (jsdialog::isBuilderEnabled(rUIFile, bMobile))
196 }
197
198 return ImplGetSVData()->mpDefInst->CreateBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile);
199}
200
201std::unique_ptr<weld::Builder> Application::CreateInterimBuilder(vcl::Window* pParent, const OUString &rUIFile, bool bAllowCycleFocusOut, sal_uInt64 nLOKWindowId)
202{
204 {
205 // Notebookbar sub controls
207 return JSInstanceBuilder::CreateNotebookbarBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile, css::uno::Reference<css::frame::XFrame>(), nLOKWindowId);
208 else if (rUIFile == u"modules/scalc/ui/inputbar.ui")
209 return JSInstanceBuilder::CreateFormulabarBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile, nLOKWindowId);
210 }
211
212 return ImplGetSVData()->mpDefInst->CreateInterimBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile, bAllowCycleFocusOut, nLOKWindowId);
213}
214
216 VclButtonsType eButtonType, const OUString& rPrimaryMessage)
217{
219 return JSInstanceBuilder::CreateMessageDialog(pParent, eMessageType, eButtonType, rPrimaryMessage);
220 else
221 return ImplGetSVData()->mpDefInst->CreateMessageDialog(pParent, eMessageType, eButtonType, rPrimaryMessage);
222}
223
224weld::Window* Application::GetFrameWeld(const css::uno::Reference<css::awt::XWindow>& rWindow)
225{
226 return ImplGetSVData()->mpDefInst->GetFrameWeld(rWindow);
227}
228
229namespace weld
230{
232 {
233 const FieldUnitStringList& rList = ImplGetFieldUnits();
234 // return unit's default string (ie, the first one )
235 auto it = std::find_if(
236 rList.begin(), rList.end(),
237 [&rUnit](const std::pair<OUString, FieldUnit>& rItem) { return rItem.second == rUnit; });
238 if (it != rList.end())
239 return it->first;
240
241 return OUString();
242 }
243
244 IMPL_LINK_NOARG(MetricSpinButton, spin_button_value_changed, SpinButton&, void)
245 {
246 signal_value_changed();
247 }
248
249 IMPL_LINK(MetricSpinButton, spin_button_output, SpinButton&, rSpinButton, void)
250 {
251 OUString sNewText(format_number(rSpinButton.get_value()));
252 if (sNewText != rSpinButton.get_text())
253 rSpinButton.set_text(sNewText);
254 }
255
257 {
258 sal_Int64 min, max;
259 m_xSpinButton->get_range(min, max);
260 auto width = std::max(m_xSpinButton->get_pixel_size(format_number(min)).Width(),
261 m_xSpinButton->get_pixel_size(format_number(max)).Width());
262 int chars = ceil(width / m_xSpinButton->get_approximate_digit_width());
263 m_xSpinButton->set_width_chars(chars);
264 }
265
266 unsigned int SpinButton::Power10(unsigned int n)
267 {
268 unsigned int nValue = 1;
269 for (unsigned int i = 0; i < n; ++i)
270 nValue *= 10;
271 return nValue;
272 }
273
274 sal_Int64 SpinButton::denormalize(sal_Int64 nValue) const
275 {
276 const int nFactor = Power10(get_digits());
277
278 if ((nValue < (std::numeric_limits<sal_Int64>::min() + nFactor)) ||
279 (nValue > (std::numeric_limits<sal_Int64>::max() - nFactor)))
280 {
281 return nValue / nFactor;
282 }
283
284 const int nHalf = nFactor / 2;
285
286 if (nValue < 0)
287 return (nValue - nHalf) / nFactor;
288 return (nValue + nHalf) / nFactor;
289 }
290
291 OUString MetricSpinButton::format_number(sal_Int64 nValue) const
292 {
293 OUString aStr;
294
296
297 unsigned int nDecimalDigits = m_xSpinButton->get_digits();
298 //pawn percent off to icu to decide whether percent is separated from its number for this locale
299 if (m_eSrcUnit == FieldUnit::PERCENT)
300 {
301 double fValue = nValue;
302 fValue /= SpinButton::Power10(nDecimalDigits);
303 aStr = unicode::formatPercent(fValue, rLocaleData.getLanguageTag());
304 }
305 else
306 {
307 aStr = rLocaleData.getNum(nValue, nDecimalDigits, true, true);
308 OUString aSuffix = MetricToString(m_eSrcUnit);
309 if (m_eSrcUnit != FieldUnit::NONE && m_eSrcUnit != FieldUnit::DEGREE && m_eSrcUnit != FieldUnit::INCH && m_eSrcUnit != FieldUnit::FOOT)
310 aStr += " ";
311 if (m_eSrcUnit == FieldUnit::INCH)
312 {
313 OUString sDoublePrime = u"\u2033";
314 if (aSuffix != "\"" && aSuffix != sDoublePrime)
315 aStr += " ";
316 else
317 aSuffix = sDoublePrime;
318 }
319 else if (m_eSrcUnit == FieldUnit::FOOT)
320 {
321 OUString sPrime = u"\u2032";
322 if (aSuffix != "'" && aSuffix != sPrime)
323 aStr += " ";
324 else
325 aSuffix = sPrime;
326 }
327
328 assert(m_eSrcUnit != FieldUnit::PERCENT);
329 aStr += aSuffix;
330 }
331
332 return aStr;
333 }
334
335 void MetricSpinButton::set_digits(unsigned int digits)
336 {
337 int step, page;
338 get_increments(step, page, m_eSrcUnit);
339 sal_Int64 value = get_value(m_eSrcUnit);
340 m_xSpinButton->set_digits(digits);
341 set_increments(step, page, m_eSrcUnit);
344 }
345
347 {
348 if (eUnit != m_eSrcUnit)
349 {
350 int step, page;
351 get_increments(step, page, m_eSrcUnit);
352 sal_Int64 value = get_value(m_eSrcUnit);
353 m_eSrcUnit = eUnit;
354 set_increments(step, page, m_eSrcUnit);
356 spin_button_output(*m_xSpinButton);
358 }
359 }
360
361 sal_Int64 MetricSpinButton::ConvertValue(sal_Int64 nValue, FieldUnit eInUnit, FieldUnit eOutUnit) const
362 {
363 return vcl::ConvertValue(nValue, 0, m_xSpinButton->get_digits(), eInUnit, eOutUnit);
364 }
365
366 IMPL_LINK(MetricSpinButton, spin_button_input, int*, result, bool)
367 {
369 double fResult(0.0);
370 bool bRet = vcl::TextToValue(get_text(), fResult, 0, m_xSpinButton->get_digits(), rLocaleData, m_eSrcUnit);
371 if (bRet)
372 {
373 if (fResult > SAL_MAX_INT32)
374 fResult = SAL_MAX_INT32;
375 else if (fResult < SAL_MIN_INT32)
376 fResult = SAL_MIN_INT32;
377 *result = fResult;
378 }
379 return bRet;
380 }
381
382 EntryTreeView::EntryTreeView(std::unique_ptr<Entry> xEntry, std::unique_ptr<TreeView> xTreeView)
383 : m_xEntry(std::move(xEntry))
384 , m_xTreeView(std::move(xTreeView))
385 {
386 m_xTreeView->connect_changed(LINK(this, EntryTreeView, ClickHdl));
387 m_xEntry->connect_changed(LINK(this, EntryTreeView, ModifyHdl));
388 }
389
390 IMPL_LINK(EntryTreeView, ClickHdl, weld::TreeView&, rView, void)
391 {
392 m_xEntry->set_text(rView.get_selected_text());
393 m_aChangeHdl.Call(*this);
394 }
395
397 {
398 m_aChangeHdl.Call(*this);
399 }
400
402 {
403 int nHeight = nRows == -1 ? -1 : m_xTreeView->get_height_rows(nRows);
404 m_xTreeView->set_size_request(m_xTreeView->get_size_request().Width(), nHeight);
405 }
406
407 size_t GetAbsPos(const weld::TreeView& rTreeView, const weld::TreeIter& rIter)
408 {
409 size_t nAbsPos = 0;
410
411 std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator(&rIter));
412 if (!rTreeView.get_iter_first(*xEntry))
413 xEntry.reset();
414
415 while (xEntry && rTreeView.iter_compare(*xEntry, rIter) != 0)
416 {
417 if (!rTreeView.iter_next(*xEntry))
418 xEntry.reset();
419 nAbsPos++;
420 }
421
422 return nAbsPos;
423 }
424
425 bool IsEntryVisible(const weld::TreeView& rTreeView, const weld::TreeIter& rIter)
426 {
427 // short circuit for the common case
428 if (rTreeView.get_iter_depth(rIter) == 0)
429 return true;
430
431 std::unique_ptr<weld::TreeIter> xEntry(rTreeView.make_iterator(&rIter));
432 bool bRetVal = false;
433 do
434 {
435 if (rTreeView.get_iter_depth(*xEntry) == 0)
436 {
437 bRetVal = true;
438 break;
439 }
440 } while (rTreeView.iter_parent(*xEntry) && rTreeView.get_row_expanded(*xEntry));
441 return bRetVal;
442 }
443}
444
445VclBuilder::VclBuilder(vcl::Window* pParent, const OUString& sUIDir, const OUString& sUIFile,
446 OString sID, css::uno::Reference<css::frame::XFrame> xFrame,
447 bool bLegacy, const NotebookBarAddonsItem* pNotebookBarAddonsItem)
448 : m_pNotebookBarAddonsItem(pNotebookBarAddonsItem
449 ? new NotebookBarAddonsItem(*pNotebookBarAddonsItem)
450 : new NotebookBarAddonsItem{})
451 , m_sID(std::move(sID))
452 , m_sHelpRoot(OUStringToOString(sUIFile, RTL_TEXTENCODING_UTF8))
453 , m_pStringReplace(Translate::GetReadStringHook())
454 , m_pParent(pParent)
455 , m_bToplevelParentFound(false)
456 , m_bLegacy(bLegacy)
457 , m_pParserState(new ParserState)
458 , m_xFrame(std::move(xFrame))
459{
460 m_bToplevelHasDeferredInit = pParent &&
461 ((pParent->IsSystemWindow() && static_cast<SystemWindow*>(pParent)->isDeferredInit()) ||
462 (pParent->IsDockingWindow() && static_cast<DockingWindow*>(pParent)->isDeferredInit()));
464
465 sal_Int32 nIdx = m_sHelpRoot.lastIndexOf('.');
466 if (nIdx != -1)
467 m_sHelpRoot = m_sHelpRoot.copy(0, nIdx);
468 m_sHelpRoot += "/";
469
470 OUString sUri = sUIDir + sUIFile;
471
472 try
473 {
474 xmlreader::XmlReader reader(sUri);
475
476 handleChild(pParent, nullptr, reader);
477 }
478 catch (const css::uno::Exception &rExcept)
479 {
480 DBG_UNHANDLED_EXCEPTION("vcl.builder", "Unable to read .ui file");
481 CrashReporter::addKeyValue("VclBuilderException", "Unable to read .ui file: " + rExcept.Message, CrashReporter::Write);
482 throw;
483 }
484
485 //Set Mnemonic widgets when everything has been imported
486 for (auto const& mnemonicWidget : m_pParserState->m_aMnemonicWidgetMaps)
487 {
488 FixedText *pOne = get<FixedText>(mnemonicWidget.m_sID);
489 vcl::Window *pOther = get(mnemonicWidget.m_sValue.toUtf8());
490 SAL_WARN_IF(!pOne || !pOther, "vcl", "missing either source " << mnemonicWidget.m_sID
491 << " or target " << mnemonicWidget.m_sValue << " member of Mnemonic Widget Mapping");
492 if (pOne && pOther)
493 pOne->set_mnemonic_widget(pOther);
494 }
495
496 //Set a11y relations and role when everything has been imported
497 for (auto const& elemAtk : m_pParserState->m_aAtkInfo)
498 {
499 vcl::Window *pSource = elemAtk.first;
500 const stringmap &rMap = elemAtk.second;
501
502 for (auto const& elemMap : rMap)
503 {
504 const OString &rType = elemMap.first;
505 const OUString &rParam = elemMap.second;
506 if (rType == "role")
507 {
508 sal_Int16 role = BuilderUtils::getRoleFromName(rParam.toUtf8());
509 if (role != com::sun::star::accessibility::AccessibleRole::UNKNOWN)
510 pSource->SetAccessibleRole(role);
511 }
512 else
513 {
514 vcl::Window *pTarget = get(rParam.toUtf8());
515 SAL_WARN_IF(!pTarget, "vcl", "missing parameter of a11y relation: " << rParam);
516 if (!pTarget)
517 continue;
518 if (rType == "labelled-by")
519 pSource->SetAccessibleRelationLabeledBy(pTarget);
520 else if (rType == "label-for")
521 pSource->SetAccessibleRelationLabelFor(pTarget);
522 else
523 {
524 SAL_WARN("vcl.builder", "unhandled a11y relation :" << rType);
525 }
526 }
527 }
528 }
529
530 //Set radiobutton groups when everything has been imported
531 for (auto const& elem : m_pParserState->m_aGroupMaps)
532 {
533 RadioButton *pOne = get<RadioButton>(elem.m_sID);
534 RadioButton *pOther = get<RadioButton>(elem.m_sValue);
535 SAL_WARN_IF(!pOne || !pOther, "vcl", "missing member of radiobutton group");
536 if (pOne && pOther)
537 {
538 if (m_bLegacy)
539 pOne->group(*pOther);
540 else
541 {
542 pOther->group(*pOne);
543 std::stable_sort(pOther->m_xGroup->begin(), pOther->m_xGroup->end(), sortIntoBestTabTraversalOrder(this));
544 }
545 }
546 }
547
548#ifndef NDEBUG
550#endif
551 //Set ComboBox models when everything has been imported
552 for (auto const& elem : m_pParserState->m_aModelMaps)
553 {
554 assert(models.insert(elem.m_sValue).second && "a liststore or treestore is used in duplicate widgets");
555 vcl::Window* pTarget = get(elem.m_sID);
556 ListBox *pListBoxTarget = dynamic_cast<ListBox*>(pTarget);
557 ComboBox *pComboBoxTarget = dynamic_cast<ComboBox*>(pTarget);
558 SvTabListBox *pTreeBoxTarget = dynamic_cast<SvTabListBox*>(pTarget);
559 // pStore may be empty
560 const ListStore *pStore = get_model_by_name(elem.m_sValue.toUtf8());
561 SAL_WARN_IF(!pListBoxTarget && !pComboBoxTarget && !pTreeBoxTarget && !dynamic_cast<IconView*>(pTarget), "vcl", "missing elements of combobox");
562 if (pListBoxTarget && pStore)
563 mungeModel(*pListBoxTarget, *pStore, elem.m_nActiveId);
564 else if (pComboBoxTarget && pStore)
565 mungeModel(*pComboBoxTarget, *pStore, elem.m_nActiveId);
566 else if (pTreeBoxTarget && pStore)
567 mungeModel(*pTreeBoxTarget, *pStore, elem.m_nActiveId);
568 }
569
570 //Set TextView buffers when everything has been imported
571 for (auto const& elem : m_pParserState->m_aTextBufferMaps)
572 {
573 VclMultiLineEdit *pTarget = get<VclMultiLineEdit>(elem.m_sID);
574 const TextBuffer *pBuffer = get_buffer_by_name(elem.m_sValue.toUtf8());
575 SAL_WARN_IF(!pTarget || !pBuffer, "vcl", "missing elements of textview/textbuffer");
576 if (pTarget && pBuffer)
577 mungeTextBuffer(*pTarget, *pBuffer);
578 }
579
580 //Set SpinButton adjustments when everything has been imported
581 for (auto const& elem : m_pParserState->m_aNumericFormatterAdjustmentMaps)
582 {
583 NumericFormatter *pTarget = dynamic_cast<NumericFormatter*>(get(elem.m_sID));
584 const Adjustment *pAdjustment = get_adjustment_by_name(elem.m_sValue.toUtf8());
585 SAL_WARN_IF(!pTarget, "vcl", "missing NumericFormatter element of spinbutton/adjustment");
586 SAL_WARN_IF(!pAdjustment, "vcl", "missing Adjustment element of spinbutton/adjustment");
587 if (pTarget && pAdjustment)
588 mungeAdjustment(*pTarget, *pAdjustment);
589 }
590
591 for (auto const& elem : m_pParserState->m_aFormattedFormatterAdjustmentMaps)
592 {
593 FormattedField *pTarget = dynamic_cast<FormattedField*>(get(elem.m_sID));
594 const Adjustment *pAdjustment = get_adjustment_by_name(elem.m_sValue.toUtf8());
595 SAL_WARN_IF(!pTarget, "vcl", "missing FormattedField element of spinbutton/adjustment");
596 SAL_WARN_IF(!pAdjustment, "vcl", "missing Adjustment element of spinbutton/adjustment");
597 if (pTarget && pAdjustment)
598 mungeAdjustment(*pTarget, *pAdjustment);
599 }
600
601 //Set ScrollBar adjustments when everything has been imported
602 for (auto const& elem : m_pParserState->m_aScrollAdjustmentMaps)
603 {
604 ScrollBar *pTarget = get<ScrollBar>(elem.m_sID);
605 const Adjustment *pAdjustment = get_adjustment_by_name(elem.m_sValue.toUtf8());
606 SAL_WARN_IF(!pTarget || !pAdjustment, "vcl", "missing elements of scrollbar/adjustment");
607 if (pTarget && pAdjustment)
608 mungeAdjustment(*pTarget, *pAdjustment);
609 }
610
611 //Set Scale(Slider) adjustments
612 for (auto const& elem : m_pParserState->m_aSliderAdjustmentMaps)
613 {
614 Slider* pTarget = dynamic_cast<Slider*>(get(elem.m_sID));
615 const Adjustment* pAdjustment = get_adjustment_by_name(elem.m_sValue.toUtf8());
616 SAL_WARN_IF(!pTarget || !pAdjustment, "vcl", "missing elements of scale(slider)/adjustment");
617 if (pTarget && pAdjustment)
618 {
619 mungeAdjustment(*pTarget, *pAdjustment);
620 }
621 }
622
623 //Set size-groups when all widgets have been imported
624 for (auto const& sizeGroup : m_pParserState->m_aSizeGroups)
625 {
626 std::shared_ptr<VclSizeGroup> xGroup(std::make_shared<VclSizeGroup>());
627
628 for (auto const& elem : sizeGroup.m_aProperties)
629 {
630 const OString &rKey = elem.first;
631 const OUString &rValue = elem.second;
632 xGroup->set_property(rKey, rValue);
633 }
634
635 for (auto const& elem : sizeGroup.m_aWidgets)
636 {
637 vcl::Window* pWindow = get(elem.getStr());
638 pWindow->add_to_size_group(xGroup);
639 }
640 }
641
642 //Set button images when everything has been imported
643 std::set<OUString> aImagesToBeRemoved;
644 for (auto const& elem : m_pParserState->m_aButtonImageWidgetMaps)
645 {
646 PushButton *pTargetButton = nullptr;
647 RadioButton *pTargetRadio = nullptr;
648 Button *pTarget = nullptr;
649
650 if (!elem.m_bRadio)
651 {
652 pTargetButton = get<PushButton>(elem.m_sID);
653 pTarget = pTargetButton;
654 }
655 else
656 {
657 pTargetRadio = get<RadioButton>(elem.m_sID);
658 pTarget = pTargetRadio;
659 }
660
661 FixedImage *pImage = get<FixedImage>(elem.m_sValue.toUtf8());
662 SAL_WARN_IF(!pTarget || !pImage,
663 "vcl", "missing elements of button/image/stock");
664 if (!pTarget || !pImage)
665 continue;
666 aImagesToBeRemoved.insert(elem.m_sValue);
667
668 if (!elem.m_bRadio)
669 {
670 const Image& rImage = pImage->GetImage();
673 {
674 pTargetButton->SetSymbol(eSymbol);
675 //fdo#76457 keep symbol images small e.g. tools->customize->menu
676 //but images the right size. Really the PushButton::CalcMinimumSize
677 //and PushButton::ImplDrawPushButton are the better place to handle
678 //this, but its such a train-wreck
679 pTargetButton->SetStyle(pTargetButton->GetStyle() | WB_SMALLSTYLE);
680 }
681 else
682 {
683 pTargetButton->SetModeImage(rImage);
684 if (pImage->GetStyle() & WB_SMALLSTYLE)
685 {
686 Size aSz(rImage.GetSizePixel());
687 aSz.AdjustWidth(6);
688 aSz.AdjustHeight(6);
689 if (pTargetButton->get_width_request() == -1)
690 pTargetButton->set_width_request(aSz.Width());
691 if (pTargetButton->get_height_request() == -1)
692 pTargetButton->set_height_request(aSz.Height());
693 }
694 }
695 }
696 else
697 pTargetRadio->SetModeRadioImage(pImage->GetImage());
698
699 auto aFind = m_pParserState->m_aImageSizeMap.find(elem.m_sValue.toUtf8());
700 if (aFind != m_pParserState->m_aImageSizeMap.end())
701 {
702 switch (aFind->second)
703 {
704 case 1:
705 pTarget->SetSmallSymbol();
706 break;
707 case 2:
708 assert(pImage->GetStyle() & WB_SMALLSTYLE);
709 pTarget->SetStyle(pTarget->GetStyle() | WB_SMALLSTYLE);
710 break;
711 case 3:
712 pTarget->SetStyle(pTarget->GetStyle() | WB_SMALLSTYLE);
713 // large toolbar, make bigger than normal (4)
714 pTarget->set_width_request(pTarget->GetOptimalSize().Width() * 1.5);
715 pTarget->set_height_request(pTarget->GetOptimalSize().Height() * 1.5);
716 break;
717 case 4:
718 break;
719 default:
720 SAL_WARN("vcl.builder", "unsupported image size " << aFind->second);
721 break;
722 }
723 m_pParserState->m_aImageSizeMap.erase(aFind);
724 }
725 }
726
727 //There may be duplicate use of an Image, so we used a set to collect and
728 //now we can remove them from the tree after their final munge
729 for (auto const& elem : aImagesToBeRemoved)
730 {
731 delete_by_name(elem.toUtf8());
732 }
733
734 //Set button menus when everything has been imported
735 for (auto const& elem : m_pParserState->m_aButtonMenuMaps)
736 {
737 MenuButton *pTarget = get<MenuButton>(elem.m_sID);
738 PopupMenu *pMenu = get_menu(elem.m_sValue.toUtf8());
739 SAL_WARN_IF(!pTarget || !pMenu,
740 "vcl", "missing elements of button/menu");
741 if (!pTarget || !pMenu)
742 continue;
743 pTarget->SetPopupMenu(pMenu);
744 }
745
746 //Remove ScrollWindow parent widgets whose children in vcl implement scrolling
747 //internally.
748 for (auto const& elem : m_pParserState->m_aRedundantParentWidgets)
749 {
750 delete_by_window(elem.first);
751 }
752
753 //fdo#67378 merge the label into the disclosure button
754 for (auto const& elem : m_pParserState->m_aExpanderWidgets)
755 {
756 vcl::Window *pChild = elem->get_child();
758 if (pLabel && pLabel != pChild && pLabel->GetType() == WindowType::FIXEDTEXT)
759 {
760 FixedText *pLabelWidget = static_cast<FixedText*>(pLabel);
761 elem->set_label(pLabelWidget->GetText());
762 if (pLabelWidget->IsControlFont())
763 elem->get_label_widget()->SetControlFont(pLabelWidget->GetControlFont());
764 delete_by_window(pLabel);
765 }
766 }
767
768 // create message dialog message area now
769 for (auto const& elem : m_pParserState->m_aMessageDialogs)
770 elem->create_message_area();
771
772 //drop maps, etc. that we don't need again
773 m_pParserState.reset();
774
775 SAL_WARN_IF(!m_sID.isEmpty() && (!m_bToplevelParentFound && !get_by_name(m_sID)), "vcl.builder",
776 "Requested top level widget \"" << m_sID << "\" not found in " << sUIFile);
777
778#if defined SAL_LOG_WARN
780 {
781 int nButtons = 0;
782 bool bHasDefButton = false;
783 for (auto const& child : m_aChildren)
784 {
785 if (isButtonType(child.m_pWindow->GetType()))
786 {
787 ++nButtons;
788 if (child.m_pWindow->GetStyle() & WB_DEFBUTTON)
789 {
790 bHasDefButton = true;
791 break;
792 }
793 }
794 }
795 SAL_WARN_IF(nButtons && !bHasDefButton, "vcl.builder", "No default button defined in " << sUIFile);
796 }
797#endif
798
799 const bool bHideHelp = comphelper::LibreOfficeKit::isActive() &&
800 officecfg::Office::Common::Help::HelpRootURL::get().isEmpty();
801 if (bHideHelp)
802 {
803 if (vcl::Window *pHelpButton = get("help"))
804 pHelpButton->Hide();
805 }
806}
807
809{
811}
812
814{
815 for (std::vector<WinAndId>::reverse_iterator aI = m_aChildren.rbegin(),
816 aEnd = m_aChildren.rend(); aI != aEnd; ++aI)
817 {
818 aI->m_pWindow.disposeAndClear();
819 }
820 m_aChildren.clear();
821
822 for (std::vector<MenuAndId>::reverse_iterator aI = m_aMenus.rbegin(),
823 aEnd = m_aMenus.rend(); aI != aEnd; ++aI)
824 {
825 aI->m_pMenu.disposeAndClear();
826 }
827 m_aMenus.clear();
829}
830
831namespace
832{
833 bool extractHasFrame(VclBuilder::stringmap& rMap)
834 {
835 bool bHasFrame = true;
836 VclBuilder::stringmap::iterator aFind = rMap.find("has-frame");
837 if (aFind != rMap.end())
838 {
839 bHasFrame = toBool(aFind->second);
840 rMap.erase(aFind);
841 }
842 return bHasFrame;
843 }
844
845 bool extractDrawValue(VclBuilder::stringmap& rMap)
846 {
847 bool bDrawValue = true;
848 VclBuilder::stringmap::iterator aFind = rMap.find("draw-value");
849 if (aFind != rMap.end())
850 {
851 bDrawValue = toBool(aFind->second);
852 rMap.erase(aFind);
853 }
854 return bDrawValue;
855 }
856
857 OUString extractPopupMenu(VclBuilder::stringmap& rMap)
858 {
859 OUString sRet;
860 VclBuilder::stringmap::iterator aFind = rMap.find("popup");
861 if (aFind != rMap.end())
862 {
863 sRet = aFind->second;
864 rMap.erase(aFind);
865 }
866 return sRet;
867 }
868
869 OUString extractWidgetName(VclBuilder::stringmap& rMap)
870 {
871 OUString sRet;
872 VclBuilder::stringmap::iterator aFind = rMap.find("name");
873 if (aFind != rMap.end())
874 {
875 sRet = aFind->second;
876 rMap.erase(aFind);
877 }
878 return sRet;
879 }
880
881 OUString extractValuePos(VclBuilder::stringmap& rMap)
882 {
883 OUString sRet("top");
884 VclBuilder::stringmap::iterator aFind = rMap.find("value-pos");
885 if (aFind != rMap.end())
886 {
887 sRet = aFind->second;
888 rMap.erase(aFind);
889 }
890 return sRet;
891 }
892
893 OUString extractTypeHint(VclBuilder::stringmap &rMap)
894 {
895 OUString sRet("normal");
896 VclBuilder::stringmap::iterator aFind = rMap.find("type-hint");
897 if (aFind != rMap.end())
898 {
899 sRet = aFind->second;
900 rMap.erase(aFind);
901 }
902 return sRet;
903 }
904
905 bool extractResizable(VclBuilder::stringmap &rMap)
906 {
907 bool bResizable = true;
908 VclBuilder::stringmap::iterator aFind = rMap.find("resizable");
909 if (aFind != rMap.end())
910 {
911 bResizable = toBool(aFind->second);
912 rMap.erase(aFind);
913 }
914 return bResizable;
915 }
916
917#if HAVE_FEATURE_DESKTOP
918 bool extractModal(VclBuilder::stringmap &rMap)
919 {
920 bool bModal = false;
921 VclBuilder::stringmap::iterator aFind = rMap.find("modal");
922 if (aFind != rMap.end())
923 {
924 bModal = toBool(aFind->second);
925 rMap.erase(aFind);
926 }
927 return bModal;
928 }
929#endif
930
931 bool extractDecorated(VclBuilder::stringmap &rMap)
932 {
933 bool bDecorated = true;
934 VclBuilder::stringmap::iterator aFind = rMap.find("decorated");
935 if (aFind != rMap.end())
936 {
937 bDecorated = toBool(aFind->second);
938 rMap.erase(aFind);
939 }
940 return bDecorated;
941 }
942
943 bool extractCloseable(VclBuilder::stringmap &rMap)
944 {
945 bool bCloseable = true;
946 VclBuilder::stringmap::iterator aFind = rMap.find("deletable");
947 if (aFind != rMap.end())
948 {
949 bCloseable = toBool(aFind->second);
950 rMap.erase(aFind);
951 }
952 return bCloseable;
953 }
954
955 bool extractEntry(VclBuilder::stringmap &rMap)
956 {
957 bool bHasEntry = false;
958 VclBuilder::stringmap::iterator aFind = rMap.find("has-entry");
959 if (aFind != rMap.end())
960 {
961 bHasEntry = toBool(aFind->second);
962 rMap.erase(aFind);
963 }
964 return bHasEntry;
965 }
966
967 bool extractOrientation(VclBuilder::stringmap &rMap)
968 {
969 bool bVertical = false;
970 VclBuilder::stringmap::iterator aFind = rMap.find("orientation");
971 if (aFind != rMap.end())
972 {
973 bVertical = aFind->second.equalsIgnoreAsciiCase("vertical");
974 rMap.erase(aFind);
975 }
976 return bVertical;
977 }
978
979 bool extractVerticalTabPos(VclBuilder::stringmap &rMap)
980 {
981 bool bVertical = false;
982 VclBuilder::stringmap::iterator aFind = rMap.find("tab-pos");
983 if (aFind != rMap.end())
984 {
985 bVertical = aFind->second.equalsIgnoreAsciiCase("left") ||
986 aFind->second.equalsIgnoreAsciiCase("right");
987 rMap.erase(aFind);
988 }
989 return bVertical;
990 }
991
992 bool extractInconsistent(VclBuilder::stringmap &rMap)
993 {
994 bool bInconsistent = false;
995 VclBuilder::stringmap::iterator aFind = rMap.find("inconsistent");
996 if (aFind != rMap.end())
997 {
998 bInconsistent = toBool(aFind->second);
999 rMap.erase(aFind);
1000 }
1001 return bInconsistent;
1002 }
1003
1004 OUString extractIconName(VclBuilder::stringmap &rMap)
1005 {
1006 OUString sIconName;
1007 // allow pixbuf, but prefer icon-name
1008 {
1009 VclBuilder::stringmap::iterator aFind = rMap.find(OString("pixbuf"));
1010 if (aFind != rMap.end())
1011 {
1012 sIconName = aFind->second;
1013 rMap.erase(aFind);
1014 }
1015 }
1016 {
1017 VclBuilder::stringmap::iterator aFind = rMap.find(OString("icon-name"));
1018 if (aFind != rMap.end())
1019 {
1020 sIconName = aFind->second;
1021 rMap.erase(aFind);
1022 }
1023 }
1024 if (sIconName == "missing-image")
1025 return OUString();
1026 OUString sReplace = mapStockToImageResource(sIconName);
1027 return !sReplace.isEmpty() ? sReplace : sIconName;
1028 }
1029
1030 WinBits extractRelief(VclBuilder::stringmap &rMap)
1031 {
1032 WinBits nBits = WB_3DLOOK;
1033 VclBuilder::stringmap::iterator aFind = rMap.find(OString("relief"));
1034 if (aFind != rMap.end())
1035 {
1036 assert(aFind->second != "half" && "relief of 'half' unsupported");
1037 if (aFind->second == "none")
1038 nBits = WB_FLATBUTTON;
1039 rMap.erase(aFind);
1040 }
1041 return nBits;
1042 }
1043
1044 OUString extractLabel(VclBuilder::stringmap &rMap)
1045 {
1046 OUString sType;
1047 VclBuilder::stringmap::iterator aFind = rMap.find(OString("label"));
1048 if (aFind != rMap.end())
1049 {
1050 sType = aFind->second;
1051 rMap.erase(aFind);
1052 }
1053 return sType;
1054 }
1055
1056 OUString extractActionName(VclBuilder::stringmap &rMap)
1057 {
1058 OUString sActionName;
1059 VclBuilder::stringmap::iterator aFind = rMap.find(OString("action-name"));
1060 if (aFind != rMap.end())
1061 {
1062 sActionName = aFind->second;
1063 rMap.erase(aFind);
1064 }
1065 return sActionName;
1066 }
1067
1068 bool extractVisible(VclBuilder::stringmap &rMap)
1069 {
1070 bool bRet = false;
1071 VclBuilder::stringmap::iterator aFind = rMap.find(OString("visible"));
1072 if (aFind != rMap.end())
1073 {
1074 bRet = toBool(aFind->second);
1075 rMap.erase(aFind);
1076 }
1077 return bRet;
1078 }
1079
1080 Size extractSizeRequest(VclBuilder::stringmap &rMap)
1081 {
1082 OUString sWidthRequest("0");
1083 OUString sHeightRequest("0");
1084 VclBuilder::stringmap::iterator aFind = rMap.find(OString("width-request"));
1085 if (aFind != rMap.end())
1086 {
1087 sWidthRequest = aFind->second;
1088 rMap.erase(aFind);
1089 }
1090 aFind = rMap.find("height-request");
1091 if (aFind != rMap.end())
1092 {
1093 sHeightRequest = aFind->second;
1094 rMap.erase(aFind);
1095 }
1096 return Size(sWidthRequest.toInt32(), sHeightRequest.toInt32());
1097 }
1098
1099 OUString extractTooltipText(VclBuilder::stringmap &rMap)
1100 {
1101 OUString sTooltipText;
1102 VclBuilder::stringmap::iterator aFind = rMap.find(OString("tooltip-text"));
1103 if (aFind == rMap.end())
1104 aFind = rMap.find(OString("tooltip-markup"));
1105 if (aFind != rMap.end())
1106 {
1107 sTooltipText = aFind->second;
1108 rMap.erase(aFind);
1109 }
1110 return sTooltipText;
1111 }
1112
1113 float extractAlignment(VclBuilder::stringmap &rMap)
1114 {
1115 float f = 0.0;
1116 VclBuilder::stringmap::iterator aFind = rMap.find(OString("alignment"));
1117 if (aFind != rMap.end())
1118 {
1119 f = aFind->second.toFloat();
1120 rMap.erase(aFind);
1121 }
1122 return f;
1123 }
1124
1125 OUString extractTitle(VclBuilder::stringmap &rMap)
1126 {
1127 OUString sTitle;
1128 VclBuilder::stringmap::iterator aFind = rMap.find(OString("title"));
1129 if (aFind != rMap.end())
1130 {
1131 sTitle = aFind->second;
1132 rMap.erase(aFind);
1133 }
1134 return sTitle;
1135 }
1136
1137 bool extractHeadersVisible(VclBuilder::stringmap &rMap)
1138 {
1139 bool bHeadersVisible = true;
1140 VclBuilder::stringmap::iterator aFind = rMap.find(OString("headers-visible"));
1141 if (aFind != rMap.end())
1142 {
1143 bHeadersVisible = toBool(aFind->second);
1144 rMap.erase(aFind);
1145 }
1146 return bHeadersVisible;
1147 }
1148
1149 bool extractSortIndicator(VclBuilder::stringmap &rMap)
1150 {
1151 bool bSortIndicator = false;
1152 VclBuilder::stringmap::iterator aFind = rMap.find(OString("sort-indicator"));
1153 if (aFind != rMap.end())
1154 {
1155 bSortIndicator = toBool(aFind->second);
1156 rMap.erase(aFind);
1157 }
1158 return bSortIndicator;
1159 }
1160
1161 bool extractClickable(VclBuilder::stringmap &rMap)
1162 {
1163 bool bClickable = false;
1164 VclBuilder::stringmap::iterator aFind = rMap.find(OString("clickable"));
1165 if (aFind != rMap.end())
1166 {
1167 bClickable = toBool(aFind->second);
1168 rMap.erase(aFind);
1169 }
1170 return bClickable;
1171 }
1172
1173 void setupFromActionName(Button *pButton, VclBuilder::stringmap &rMap, const css::uno::Reference<css::frame::XFrame>& rFrame)
1174 {
1175 if (!rFrame.is())
1176 return;
1177
1178 OUString aCommand(extractActionName(rMap));
1179 if (aCommand.isEmpty())
1180 return;
1181
1182 OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(rFrame));
1183 auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(aCommand, aModuleName);
1185 if (!aLabel.isEmpty())
1186 pButton->SetText(aLabel);
1187
1188 OUString aTooltip(vcl::CommandInfoProvider::GetTooltipForCommand(aCommand, aProperties, rFrame));
1189 if (!aTooltip.isEmpty())
1190 pButton->SetQuickHelpText(aTooltip);
1191
1192 Image aImage(vcl::CommandInfoProvider::GetImageForCommand(aCommand, rFrame));
1193 pButton->SetModeImage(aImage);
1194
1195 pButton->SetCommandHandler(aCommand, rFrame);
1196 }
1197
1198 VclPtr<Button> extractStockAndBuildPushButton(vcl::Window *pParent, VclBuilder::stringmap &rMap, bool bToggle)
1199 {
1201 if (bToggle)
1202 nBits |= WB_TOGGLE;
1203
1204 nBits |= extractRelief(rMap);
1205
1206 VclPtr<Button> xWindow = VclPtr<PushButton>::Create(pParent, nBits);
1207 return xWindow;
1208 }
1209
1210 VclPtr<MenuButton> extractStockAndBuildMenuButton(vcl::Window *pParent, VclBuilder::stringmap &rMap)
1211 {
1213
1214 nBits |= extractRelief(rMap);
1215
1216 VclPtr<MenuButton> xWindow = VclPtr<MenuButton>::Create(pParent, nBits);
1217 return xWindow;
1218 }
1219
1220 VclPtr<MenuButton> extractStockAndBuildMenuToggleButton(vcl::Window *pParent, VclBuilder::stringmap &rMap)
1221 {
1223
1224 nBits |= extractRelief(rMap);
1225
1226 VclPtr<MenuButton> xWindow = VclPtr<MenuToggleButton>::Create(pParent, nBits);
1227 return xWindow;
1228 }
1229
1230 WinBits extractDeferredBits(VclBuilder::stringmap &rMap)
1231 {
1232 WinBits nBits = WB_3DLOOK|WB_HIDE;
1233 if (extractResizable(rMap))
1234 nBits |= WB_SIZEABLE;
1235 if (extractCloseable(rMap))
1236 nBits |= WB_CLOSEABLE;
1237 if (!extractDecorated(rMap))
1238 nBits |= WB_OWNERDRAWDECORATION;
1239 OUString sType(extractTypeHint(rMap));
1240 if (sType == "utility")
1242 else if (sType == "popup-menu")
1244 else if (sType == "dock")
1245 nBits |= WB_DOCKABLE | WB_MOVEABLE;
1246 else
1247 nBits |= WB_MOVEABLE;
1248 return nBits;
1249 }
1250}
1251
1252void VclBuilder::extractGroup(const OString &id, stringmap &rMap)
1253{
1254 VclBuilder::stringmap::iterator aFind = rMap.find(OString("group"));
1255 if (aFind != rMap.end())
1256 {
1257 OUString sID = aFind->second;
1258 sal_Int32 nDelim = sID.indexOf(':');
1259 if (nDelim != -1)
1260 sID = sID.copy(0, nDelim);
1261 m_pParserState->m_aGroupMaps.emplace_back(id, sID.toUtf8());
1262 rMap.erase(aFind);
1263 }
1264}
1265
1266void VclBuilder::connectNumericFormatterAdjustment(const OString &id, const OUString &rAdjustment)
1267{
1268 if (!rAdjustment.isEmpty())
1269 m_pParserState->m_aNumericFormatterAdjustmentMaps.emplace_back(id, rAdjustment);
1270}
1271
1272void VclBuilder::connectFormattedFormatterAdjustment(const OString &id, const OUString &rAdjustment)
1273{
1274 if (!rAdjustment.isEmpty())
1275 m_pParserState->m_aFormattedFormatterAdjustmentMaps.emplace_back(id, rAdjustment);
1276}
1277
1278bool VclBuilder::extractAdjustmentToMap(const OString& id, VclBuilder::stringmap& rMap, std::vector<WidgetAdjustmentMap>& rAdjustmentMap)
1279{
1280 VclBuilder::stringmap::iterator aFind = rMap.find(OString("adjustment"));
1281 if (aFind != rMap.end())
1282 {
1283 rAdjustmentMap.emplace_back(id, aFind->second);
1284 rMap.erase(aFind);
1285 return true;
1286 }
1287 return false;
1288}
1289
1290namespace
1291{
1292 sal_Int32 extractActive(VclBuilder::stringmap &rMap)
1293 {
1294 sal_Int32 nActiveId = 0;
1295 VclBuilder::stringmap::iterator aFind = rMap.find(OString("active"));
1296 if (aFind != rMap.end())
1297 {
1298 nActiveId = aFind->second.toInt32();
1299 rMap.erase(aFind);
1300 }
1301 return nActiveId;
1302 }
1303
1304 bool extractSelectable(VclBuilder::stringmap &rMap)
1305 {
1306 bool bSelectable = false;
1307 VclBuilder::stringmap::iterator aFind = rMap.find(OString("selectable"));
1308 if (aFind != rMap.end())
1309 {
1310 bSelectable = toBool(aFind->second);
1311 rMap.erase(aFind);
1312 }
1313 return bSelectable;
1314 }
1315
1316 OUString extractAdjustment(VclBuilder::stringmap &rMap)
1317 {
1318 OUString sAdjustment;
1319 VclBuilder::stringmap::iterator aFind = rMap.find(OString("adjustment"));
1320 if (aFind != rMap.end())
1321 {
1322 sAdjustment= aFind->second;
1323 rMap.erase(aFind);
1324 return sAdjustment;
1325 }
1326 return sAdjustment;
1327 }
1328
1329 bool extractDrawIndicator(VclBuilder::stringmap &rMap)
1330 {
1331 bool bDrawIndicator = false;
1332 VclBuilder::stringmap::iterator aFind = rMap.find(OString("draw-indicator"));
1333 if (aFind != rMap.end())
1334 {
1335 bDrawIndicator = toBool(aFind->second);
1336 rMap.erase(aFind);
1337 }
1338 return bDrawIndicator;
1339 }
1340}
1341
1342void VclBuilder::extractModel(const OString &id, stringmap &rMap)
1343{
1344 VclBuilder::stringmap::iterator aFind = rMap.find(OString("model"));
1345 if (aFind != rMap.end())
1346 {
1347 m_pParserState->m_aModelMaps.emplace_back(id, aFind->second,
1348 extractActive(rMap));
1349 rMap.erase(aFind);
1350 }
1351}
1352
1353void VclBuilder::extractBuffer(const OString &id, stringmap &rMap)
1354{
1355 VclBuilder::stringmap::iterator aFind = rMap.find(OString("buffer"));
1356 if (aFind != rMap.end())
1357 {
1358 m_pParserState->m_aTextBufferMaps.emplace_back(id, aFind->second);
1359 rMap.erase(aFind);
1360 }
1361}
1362
1364{
1365 int nSize = 4;
1366 auto aFind = rMap.find(OString("icon-size"));
1367 if (aFind != rMap.end())
1368 nSize = aFind->second.toInt32();
1369 return nSize;
1370}
1371
1372void VclBuilder::extractButtonImage(const OString &id, stringmap &rMap, bool bRadio)
1373{
1374 VclBuilder::stringmap::iterator aFind = rMap.find(OString("image"));
1375 if (aFind != rMap.end())
1376 {
1377 m_pParserState->m_aButtonImageWidgetMaps.emplace_back(id, aFind->second, bRadio);
1378 rMap.erase(aFind);
1379 }
1380}
1381
1382void VclBuilder::extractMnemonicWidget(const OString &rLabelID, stringmap &rMap)
1383{
1384 VclBuilder::stringmap::iterator aFind = rMap.find(OString("mnemonic-widget"));
1385 if (aFind != rMap.end())
1386 {
1387 OUString sID = aFind->second;
1388 sal_Int32 nDelim = sID.indexOf(':');
1389 if (nDelim != -1)
1390 sID = sID.copy(0, nDelim);
1391 m_pParserState->m_aMnemonicWidgetMaps.emplace_back(rLabelID, sID);
1392 rMap.erase(aFind);
1393 }
1394}
1395
1397{
1398 //For Widgets that manage their own scrolling, if one appears as a child of
1399 //a scrolling window shoehorn that scrolling settings to this widget and
1400 //return the real parent to use
1401 if (pParent && pParent->GetType() == WindowType::SCROLLWINDOW)
1402 {
1403 WinBits nScrollBits = pParent->GetStyle();
1405 rWinStyle |= nScrollBits;
1406 if (static_cast<VclScrolledWindow*>(pParent)->HasVisibleBorder())
1407 rWinStyle |= WB_BORDER;
1408 pParent = pParent->GetParent();
1409 }
1410
1411 return pParent;
1412}
1413
1415{
1416 //remove the redundant scrolling parent
1417 sal_Int32 nWidthReq = pScrollParent->get_width_request();
1418 rMap[OString("width-request")] = OUString::number(nWidthReq);
1419 sal_Int32 nHeightReq = pScrollParent->get_height_request();
1420 rMap[OString("height-request")] = OUString::number(nHeightReq);
1421
1422 m_pParserState->m_aRedundantParentWidgets[pScrollParent] = pWindow;
1423}
1424
1425#ifndef DISABLE_DYNLOADING
1426
1427extern "C" { static void thisModule() {} }
1428
1429namespace {
1430
1431// Don't unload the module on destruction
1432class NoAutoUnloadModule : public osl::Module
1433{
1434public:
1435 ~NoAutoUnloadModule() { release(); }
1436};
1437
1438}
1439
1440typedef std::map<OUString, std::shared_ptr<NoAutoUnloadModule>> ModuleMap;
1442
1443#if ENABLE_MERGELIBS
1444static std::shared_ptr<NoAutoUnloadModule> g_pMergedLib = std::make_shared<NoAutoUnloadModule>();
1445#endif
1446
1447#ifndef SAL_DLLPREFIX
1448# define SAL_DLLPREFIX ""
1449#endif
1450
1451#endif
1452
1453namespace vcl {
1454
1456{
1457#ifndef DISABLE_DYNLOADING
1458
1459#if ENABLE_MERGELIBS
1460 g_pMergedLib->loadRelative(&thisModule, SVLIBRARY("merged"));
1461#else
1462// find -name '*ui*' | xargs grep 'class=".*lo-' |
1463// sed 's/.*class="//' | sed 's/-.*$//' | sort | uniq
1464 static const char *aWidgetLibs[] = {
1465 "sfxlo", "svtlo"
1466 };
1467 for (const auto & lib : aWidgetLibs)
1468 {
1469 std::unique_ptr<NoAutoUnloadModule> pModule(new NoAutoUnloadModule);
1470 OUString sModule = SAL_DLLPREFIX + OUString::createFromAscii(lib) + SAL_DLLEXTENSION;
1471 if (pModule->loadRelative(&thisModule, sModule))
1472 g_aModuleMap.insert(std::make_pair(sModule, std::move(pModule)));
1473 }
1474#endif // ENABLE_MERGELIBS
1475#endif // DISABLE_DYNLOADING
1476}
1477
1478}
1479
1480#if defined DISABLE_DYNLOADING && !HAVE_FEATURE_DESKTOP
1481
1482// This ifdef branch is mainly for building for the Collabora Online
1483// -based mobile apps for Android and iOS.
1484
1485extern "C" VclBuilder::customMakeWidget lo_get_custom_widget_func(const char* name);
1486
1487#elif defined EMSCRIPTEN && !ENABLE_QT5
1488
1489// This branch is mainly for building for WASM, and especially for
1490// Collabora Online in the browser, where code from core and Collabora
1491// Online is compiled to WASM and linked into a single WASM binary.
1492// (Not for Allotropia's Qt-based LibreOffice in the browser.)
1493
1494// When building core for WASM it doesn't use the same
1495// solenv/bin/native-code.py thing as the mobile apps, even if in both
1496// cases everything is linked statically. So there is no generated
1497// native-code.h, and we can't use lo_get_custom_widget_func() from
1498// that. So cheat and duplicate the code from an existing generated
1499// native-code.h. It's just a handful of lines anyway.
1500
1501extern "C" void makeNotebookbarTabControl(VclPtr<vcl::Window> &rRet, const VclPtr<vcl::Window> &pParent, VclBuilder::stringmap &rVec);
1502extern "C" void makeNotebookbarToolBox(VclPtr<vcl::Window> &rRet, const VclPtr<vcl::Window> &pParent, VclBuilder::stringmap &rVec);
1503
1504static struct { const char *name; VclBuilder::customMakeWidget func; } custom_widgets[] = {
1505 { "makeNotebookbarTabControl", makeNotebookbarTabControl },
1506 { "makeNotebookbarToolBox", makeNotebookbarToolBox },
1507};
1508
1509static VclBuilder::customMakeWidget lo_get_custom_widget_func(const char* name)
1510{
1511 for (size_t i = 0; i < sizeof(custom_widgets) / sizeof(custom_widgets[0]); i++)
1512 if (strcmp(name, custom_widgets[i].name) == 0)
1513 return custom_widgets[i].func;
1514 return nullptr;
1515}
1516
1517#endif
1518
1519namespace
1520{
1521// Takes a string like "sfxlo-NotebookbarToolBox"
1522VclBuilder::customMakeWidget GetCustomMakeWidget(const OString& rName)
1523{
1524 const OString name = rName == "sfxlo-SidebarToolBox" ? "sfxlo-NotebookbarToolBox" : rName;
1525 VclBuilder::customMakeWidget pFunction = nullptr;
1526 if (sal_Int32 nDelim = name.indexOf('-'); nDelim != -1)
1527 {
1528 const OString aFunction(OString::Concat("make") + name.subView(nDelim + 1));
1529 const OUString sFunction(OStringToOUString(aFunction, RTL_TEXTENCODING_UTF8));
1530
1531#ifndef DISABLE_DYNLOADING
1532 const OUString sModule = SAL_DLLPREFIX
1533 + OStringToOUString(name.subView(0, nDelim), RTL_TEXTENCODING_UTF8)
1535 ModuleMap::iterator aI = g_aModuleMap.find(sModule);
1536 if (aI == g_aModuleMap.end())
1537 {
1538 std::shared_ptr<NoAutoUnloadModule> pModule;
1539#if ENABLE_MERGELIBS
1540 if (!g_pMergedLib->is())
1541 g_pMergedLib->loadRelative(&thisModule, SVLIBRARY("merged"));
1542 if ((pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(
1543 g_pMergedLib->getFunctionSymbol(sFunction))))
1544 pModule = g_pMergedLib;
1545#endif
1546 if (!pFunction)
1547 {
1548 pModule = std::make_shared<NoAutoUnloadModule>();
1549 bool ok = pModule->loadRelative(&thisModule, sModule);
1550 if (!ok)
1551 {
1552#ifdef LINUX
1553 // in the case of preloading, we don't have eg. the
1554 // libcuilo.so, but still need to dlsym the symbols -
1555 // which are already in-process
1557 {
1558 pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(dlsym(RTLD_DEFAULT, aFunction.getStr()));
1559 ok = !!pFunction;
1560 assert(ok && "couldn't even directly dlsym the sFunction (available via preload)");
1561 }
1562#endif
1563 assert(ok && "bad module name in .ui");
1564 }
1565 else
1566 {
1567 pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(
1568 pModule->getFunctionSymbol(sFunction));
1569 }
1570 }
1571 g_aModuleMap.insert(std::make_pair(sModule, pModule));
1572 }
1573 else
1574 pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(
1575 aI->second->getFunctionSymbol(sFunction));
1576#elif !HAVE_FEATURE_DESKTOP || (defined EMSCRIPTEN && !ENABLE_QT5)
1577 // This ifdef branch is mainly for building for either the
1578 // Android or iOS apps, or the Collabora Online as WASM thing.
1579 pFunction = lo_get_custom_widget_func(sFunction.toUtf8().getStr());
1580 SAL_WARN_IF(!pFunction, "vcl.builder", "Could not find " << sFunction);
1581 assert(pFunction);
1582#else
1583 pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(
1584 osl_getFunctionSymbol((oslModule)RTLD_DEFAULT, sFunction.pData));
1585#endif
1586 }
1587 return pFunction;
1588}
1589}
1590
1591VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString &name, const OString &id,
1592 stringmap &rMap)
1593{
1594 bool bIsPlaceHolder = name.isEmpty();
1595 bool bVertical = false;
1596
1597 if (pParent && (pParent->GetType() == WindowType::TABCONTROL ||
1599 {
1600 bool bTopLevel(name == "GtkDialog" || name == "GtkMessageDialog" ||
1601 name == "GtkWindow" || name == "GtkPopover" || name == "GtkAssistant");
1602 if (!bTopLevel)
1603 {
1604 if (pParent->GetType() == WindowType::TABCONTROL)
1605 {
1606 //We have to add a page
1607 //make default pageid == position
1608 TabControl *pTabControl = static_cast<TabControl*>(pParent);
1609 sal_uInt16 nNewPageCount = pTabControl->GetPageCount()+1;
1610 sal_uInt16 nNewPageId = nNewPageCount;
1611 pTabControl->InsertPage(nNewPageId, OUString());
1612 pTabControl->SetCurPageId(nNewPageId);
1613 SAL_WARN_IF(bIsPlaceHolder, "vcl.builder", "we should have no placeholders for tabpages");
1614 if (!bIsPlaceHolder)
1615 {
1616 VclPtrInstance<TabPage> pPage(pTabControl);
1617 pPage->Show();
1618
1619 //Make up a name for it
1620 OString sTabPageId = get_by_window(pParent) +
1621 "-page" +
1622 OString::number(nNewPageCount);
1623 m_aChildren.emplace_back(sTabPageId, pPage, false);
1624 pPage->SetHelpId(m_sHelpRoot + sTabPageId);
1625
1626 pParent = pPage;
1627
1628 pTabControl->SetTabPage(nNewPageId, pPage);
1629 }
1630 }
1631 else
1632 {
1633 VerticalTabControl *pTabControl = static_cast<VerticalTabControl*>(pParent);
1634 SAL_WARN_IF(bIsPlaceHolder, "vcl.builder", "we should have no placeholders for tabpages");
1635 if (!bIsPlaceHolder)
1636 pParent = pTabControl->GetPageParent();
1637 }
1638 }
1639 }
1640
1641 if (bIsPlaceHolder || name == "GtkTreeSelection")
1642 return nullptr;
1643
1644 ToolBox *pToolBox = (pParent && pParent->GetType() == WindowType::TOOLBOX) ? static_cast<ToolBox*>(pParent) : nullptr;
1645
1646 extractButtonImage(id, rMap, name == "GtkRadioButton");
1647
1648 VclPtr<vcl::Window> xWindow;
1649 if (name == "GtkDialog" || name == "GtkAssistant")
1650 {
1651 // WB_ALLOWMENUBAR because we don't know in advance if we will encounter
1652 // a menubar, and menubars need a BorderWindow in the toplevel, and
1653 // such border windows need to be in created during the dialog ctor
1655 if (extractResizable(rMap))
1656 nBits |= WB_SIZEABLE;
1657 if (extractCloseable(rMap))
1658 nBits |= WB_CLOSEABLE;
1660 if (name == "GtkAssistant")
1661 xWindow = VclPtr<vcl::RoadmapWizard>::Create(pParent, nBits, eInit);
1662 else
1663 xWindow = VclPtr<Dialog>::Create(pParent, nBits, eInit);
1664#if HAVE_FEATURE_DESKTOP
1665 if (!extractModal(rMap))
1667#endif
1668 }
1669 else if (name == "GtkMessageDialog")
1670 {
1672 if (extractResizable(rMap))
1673 nBits |= WB_SIZEABLE;
1675 m_pParserState->m_aMessageDialogs.push_back(xDialog);
1676 xWindow = xDialog;
1677#if defined _WIN32
1678 xWindow->set_border_width(3);
1679#else
1680 xWindow->set_border_width(12);
1681#endif
1682 }
1683 else if (name == "GtkBox" || name == "GtkStatusbar")
1684 {
1685 bVertical = extractOrientation(rMap);
1686 if (bVertical)
1687 xWindow = VclPtr<VclVBox>::Create(pParent);
1688 else
1689 xWindow = VclPtr<VclHBox>::Create(pParent);
1690 }
1691 else if (name == "GtkPaned")
1692 {
1693 bVertical = extractOrientation(rMap);
1694 if (bVertical)
1695 xWindow = VclPtr<VclVPaned>::Create(pParent);
1696 else
1697 xWindow = VclPtr<VclHPaned>::Create(pParent);
1698 }
1699 else if (name == "GtkHBox")
1700 xWindow = VclPtr<VclHBox>::Create(pParent);
1701 else if (name == "GtkVBox")
1702 xWindow = VclPtr<VclVBox>::Create(pParent);
1703 else if (name == "GtkButtonBox")
1704 {
1705 bVertical = extractOrientation(rMap);
1706 if (bVertical)
1707 xWindow = VclPtr<VclVButtonBox>::Create(pParent);
1708 else
1709 xWindow = VclPtr<VclHButtonBox>::Create(pParent);
1710 }
1711 else if (name == "GtkHButtonBox")
1712 xWindow = VclPtr<VclHButtonBox>::Create(pParent);
1713 else if (name == "GtkVButtonBox")
1714 xWindow = VclPtr<VclVButtonBox>::Create(pParent);
1715 else if (name == "GtkGrid")
1716 xWindow = VclPtr<VclGrid>::Create(pParent);
1717 else if (name == "GtkFrame")
1718 xWindow = VclPtr<VclFrame>::Create(pParent);
1719 else if (name == "GtkExpander")
1720 {
1721 VclPtrInstance<VclExpander> pExpander(pParent);
1722 m_pParserState->m_aExpanderWidgets.push_back(pExpander);
1723 xWindow = pExpander;
1724 }
1725 else if (name == "GtkButton" || (!m_bLegacy && name == "GtkToggleButton"))
1726 {
1727 VclPtr<Button> xButton;
1728 OUString sMenu = BuilderUtils::extractCustomProperty(rMap);
1729 if (sMenu.isEmpty())
1730 xButton = extractStockAndBuildPushButton(pParent, rMap, name == "GtkToggleButton");
1731 else
1732 {
1733 assert(m_bLegacy && "use GtkMenuButton");
1734 xButton = extractStockAndBuildMenuButton(pParent, rMap);
1735 m_pParserState->m_aButtonMenuMaps.emplace_back(id, sMenu);
1736 }
1737 xButton->SetImageAlign(ImageAlign::Left); //default to left
1738 setupFromActionName(xButton, rMap, m_xFrame);
1739 xWindow = xButton;
1740 }
1741 else if (name == "GtkMenuButton")
1742 {
1743 VclPtr<MenuButton> xButton;
1744
1745 OUString sMenu = extractPopupMenu(rMap);
1746 if (!sMenu.isEmpty())
1747 m_pParserState->m_aButtonMenuMaps.emplace_back(id, sMenu);
1748
1749 OUString sType = extractWidgetName(rMap);
1750 if (sType.isEmpty())
1751 {
1752 xButton = extractStockAndBuildMenuButton(pParent, rMap);
1753 xButton->SetAccessibleRole(css::accessibility::AccessibleRole::BUTTON_MENU);
1754 }
1755 else
1756 {
1757 xButton = extractStockAndBuildMenuToggleButton(pParent, rMap);
1758 }
1759
1760 xButton->SetImageAlign(ImageAlign::Left); //default to left
1761
1762 if (!extractDrawIndicator(rMap))
1764
1765 setupFromActionName(xButton, rMap, m_xFrame);
1766 xWindow = xButton;
1767 }
1768 else if (name == "GtkToggleButton" && m_bLegacy)
1769 {
1770 VclPtr<Button> xButton;
1771 OUString sMenu = BuilderUtils::extractCustomProperty(rMap);
1772 assert(sMenu.getLength() && "not implemented yet");
1773 xButton = extractStockAndBuildMenuToggleButton(pParent, rMap);
1774 m_pParserState->m_aButtonMenuMaps.emplace_back(id, sMenu);
1775 xButton->SetImageAlign(ImageAlign::Left); //default to left
1776 setupFromActionName(xButton, rMap, m_xFrame);
1777 xWindow = xButton;
1778 }
1779 else if (name == "GtkRadioButton")
1780 {
1781 extractGroup(id, rMap);
1783 VclPtr<RadioButton> xButton = VclPtr<RadioButton>::Create(pParent, true, nBits);
1784 xButton->SetImageAlign(ImageAlign::Left); //default to left
1785 xWindow = xButton;
1786 }
1787 else if (name == "GtkCheckButton")
1788 {
1790 bool bIsTriState = extractInconsistent(rMap);
1791 VclPtr<CheckBox> xCheckBox = VclPtr<CheckBox>::Create(pParent, nBits);
1792 if (bIsTriState)
1793 {
1794 xCheckBox->EnableTriState(true);
1795 xCheckBox->SetState(TRISTATE_INDET);
1796 }
1797 xCheckBox->SetImageAlign(ImageAlign::Left); //default to left
1798
1799 xWindow = xCheckBox;
1800 }
1801 else if (name == "GtkSpinButton")
1802 {
1803 OUString sAdjustment = extractAdjustment(rMap);
1804
1806 if (extractHasFrame(rMap))
1807 nBits |= WB_BORDER;
1808
1809 connectFormattedFormatterAdjustment(id, sAdjustment);
1810 VclPtrInstance<FormattedField> xField(pParent, nBits);
1811 xField->GetFormatter().SetMinValue(0);
1812 xWindow = xField;
1813 }
1814 else if (name == "GtkLinkButton")
1816 else if (name == "GtkComboBox" || name == "GtkComboBoxText")
1817 {
1818 extractModel(id, rMap);
1819
1821
1822 bool bDropdown = BuilderUtils::extractDropdown(rMap);
1823
1824 if (bDropdown)
1825 nBits |= WB_DROPDOWN;
1826
1827 if (extractEntry(rMap))
1828 {
1829 VclPtrInstance<ComboBox> xComboBox(pParent, nBits);
1830 xComboBox->EnableAutoSize(true);
1831 xWindow = xComboBox;
1832 }
1833 else
1834 {
1835 VclPtrInstance<ListBox> xListBox(pParent, nBits|WB_SIMPLEMODE);
1836 xListBox->EnableAutoSize(true);
1837 xWindow = xListBox;
1838 }
1839 }
1840 else if (name == "VclOptionalBox" || name == "sfxlo-OptionalBox")
1841 {
1842 // tdf#135495 fallback sfxlo-OptionalBox to VclOptionalBox as a stopgap
1843 xWindow = VclPtr<OptionalBox>::Create(pParent);
1844 }
1845 else if (name == "svtlo-ManagedMenuButton")
1846 {
1847 // like tdf#135495 keep the name svtlo-ManagedMenuButton even though it's a misnomer
1848 // and is not dlsymed from the svt library
1850 OUString sMenu = BuilderUtils::extractCustomProperty(rMap);
1851 if (!sMenu.isEmpty())
1852 m_pParserState->m_aButtonMenuMaps.emplace_back(id, sMenu);
1853 setupFromActionName(static_cast<Button*>(xWindow.get()), rMap, m_xFrame);
1854 }
1855 else if (name == "sfxlo-PriorityMergedHBox")
1856 {
1857 // like tdf#135495 above, keep the sfxlo-PriorityMergedHBox even though its not in sfx anymore
1858 xWindow = VclPtr<PriorityMergedHBox>::Create(pParent);
1859 }
1860 else if (name == "sfxlo-PriorityHBox")
1861 {
1862 // like tdf#135495 above, keep the sfxlo-PriorityMergedHBox even though its not in sfx anymore
1863 xWindow = VclPtr<PriorityHBox>::Create(pParent);
1864 }
1865 else if (name == "sfxlo-DropdownBox")
1866 {
1867 // like tdf#135495 above, keep the sfxlo-PriorityMergedHBox even though its not in sfx anymore
1868 xWindow = VclPtr<DropdownBox>::Create(pParent);
1869 }
1870 else if (name == "sfxlo-ContextVBox")
1871 {
1872 // like tdf#135495 above, keep the sfxlo-PriorityMergedHBox even though its not in sfx anymore
1873 xWindow = VclPtr<ContextVBox>::Create(pParent);
1874 }
1875 else if (name == "GtkIconView")
1876 {
1877 assert(rMap.find(OString("model")) != rMap.end() && "GtkIconView must have a model");
1878
1879 //window we want to apply the packing props for this GtkIconView to
1880 VclPtr<vcl::Window> xWindowForPackingProps;
1881 extractModel(id, rMap);
1883 //IconView manages its own scrolling,
1884 vcl::Window *pRealParent = prepareWidgetOwnScrolling(pParent, nWinStyle);
1885
1886 VclPtr<IconView> xBox = VclPtr<IconView>::Create(pRealParent, nWinStyle);
1887 xWindowForPackingProps = xBox;
1888
1889 xWindow = xBox;
1890 xBox->SetNoAutoCurEntry(true);
1891 xBox->SetQuickSearch(true);
1892
1893 if (pRealParent != pParent)
1894 cleanupWidgetOwnScrolling(pParent, xWindowForPackingProps, rMap);
1895 }
1896 else if (name == "GtkTreeView")
1897 {
1898 if (!m_bLegacy)
1899 {
1900 assert(rMap.find(OString("model")) != rMap.end() && "GtkTreeView must have a model");
1901 }
1902
1903 //window we want to apply the packing props for this GtkTreeView to
1904 VclPtr<vcl::Window> xWindowForPackingProps;
1905 //To-Do
1906 //a) make SvHeaderTabListBox/SvTabListBox the default target for GtkTreeView
1907 //b) remove the non-drop down mode of ListBox and convert
1908 // everything over to SvHeaderTabListBox/SvTabListBox
1909 extractModel(id, rMap);
1911 if (m_bLegacy)
1912 {
1914 if (!sBorder.isEmpty())
1915 nWinStyle |= WB_BORDER;
1916 }
1917 else
1918 {
1919 nWinStyle |= WB_HASBUTTONS | WB_HASBUTTONSATROOT;
1920 }
1921 //ListBox/SvHeaderTabListBox manages its own scrolling,
1922 vcl::Window *pRealParent = prepareWidgetOwnScrolling(pParent, nWinStyle);
1923 if (m_bLegacy)
1924 {
1925 xWindow = VclPtr<ListBox>::Create(pRealParent, nWinStyle | WB_SIMPLEMODE);
1926 xWindowForPackingProps = xWindow;
1927 }
1928 else
1929 {
1931 bool bHeadersVisible = extractHeadersVisible(rMap);
1932 if (bHeadersVisible)
1933 {
1934 VclPtr<VclVBox> xContainer = VclPtr<VclVBox>::Create(pRealParent);
1935 OString containerid(id + "-container");
1936 xContainer->SetHelpId(m_sHelpRoot + containerid);
1937 m_aChildren.emplace_back(containerid, xContainer, true);
1938
1940 xHeader->set_width_request(0); // let the headerbar width not affect the size request
1941 OString headerid(id + "-header");
1942 xHeader->SetHelpId(m_sHelpRoot + headerid);
1943 m_aChildren.emplace_back(headerid, xHeader, true);
1944
1945 VclPtr<LclHeaderTabListBox> xHeaderBox = VclPtr<LclHeaderTabListBox>::Create(xContainer, nWinStyle);
1946 xHeaderBox->InitHeaderBar(xHeader);
1947 xContainer->set_expand(true);
1948 xHeader->Show();
1949 xContainer->Show();
1950 xBox = xHeaderBox;
1951 xWindowForPackingProps = xContainer;
1952 }
1953 else
1954 {
1955 xBox = VclPtr<LclTabListBox>::Create(pRealParent, nWinStyle);
1956 xWindowForPackingProps = xBox;
1957 }
1958 xWindow = xBox;
1959 xBox->SetNoAutoCurEntry(true);
1960 xBox->SetQuickSearch(true);
1961 xBox->SetSpaceBetweenEntries(3);
1962 xBox->SetEntryHeight(16);
1963 xBox->SetHighlightRange(); // select over the whole width
1964 }
1965 if (pRealParent != pParent)
1966 cleanupWidgetOwnScrolling(pParent, xWindowForPackingProps, rMap);
1967 }
1968 else if (name == "GtkTreeViewColumn")
1969 {
1970 if (!m_bLegacy)
1971 {
1972 SvHeaderTabListBox* pTreeView = dynamic_cast<SvHeaderTabListBox*>(pParent);
1973 if (HeaderBar* pHeaderBar = pTreeView ? pTreeView->GetHeaderBar() : nullptr)
1974 {
1976 if (extractClickable(rMap))
1978 if (extractSortIndicator(rMap))
1980 float fAlign = extractAlignment(rMap);
1981 if (fAlign == 0.0)
1982 nBits |= HeaderBarItemBits::LEFT;
1983 else if (fAlign == 1.0)
1984 nBits |= HeaderBarItemBits::RIGHT;
1985 else if (fAlign == 0.5)
1987 auto nItemId = pHeaderBar->GetItemCount() + 1;
1988 OUString sTitle(extractTitle(rMap));
1989 pHeaderBar->InsertItem(nItemId, sTitle, 100, nBits);
1990 }
1991 }
1992 }
1993 else if (name == "GtkLabel")
1994 {
1996 extractMnemonicWidget(id, rMap);
1997 if (extractSelectable(rMap))
1998 xWindow = VclPtr<SelectableFixedText>::Create(pParent, nWinStyle);
1999 else
2000 xWindow = VclPtr<FixedText>::Create(pParent, nWinStyle);
2001 }
2002 else if (name == "GtkImage")
2003 {
2005 OUString sIconName = extractIconName(rMap);
2006 if (!sIconName.isEmpty())
2007 xFixedImage->SetImage(FixedImage::loadThemeImage(sIconName));
2008 m_pParserState->m_aImageSizeMap[id] = getImageSize(rMap);
2009 xWindow = xFixedImage;
2010 //such parentless GtkImages are temps used to set icons on buttons
2011 //default them to hidden to stop e.g. insert->index entry flicking temp
2012 //full screen windows
2013 if (!pParent)
2014 {
2015 rMap["visible"] = "false";
2016 }
2017 }
2018 else if (name == "GtkSeparator")
2019 {
2020 bVertical = extractOrientation(rMap);
2021 xWindow = VclPtr<FixedLine>::Create(pParent, bVertical ? WB_VERT : WB_HORZ);
2022 }
2023 else if (name == "GtkScrollbar")
2024 {
2025 extractAdjustmentToMap(id, rMap, m_pParserState->m_aScrollAdjustmentMaps);
2026 bVertical = extractOrientation(rMap);
2027 xWindow = VclPtr<ScrollBar>::Create(pParent, bVertical ? WB_VERT : WB_HORZ);
2028 }
2029 else if (name == "GtkProgressBar")
2030 {
2031 extractAdjustmentToMap(id, rMap, m_pParserState->m_aScrollAdjustmentMaps);
2032 bVertical = extractOrientation(rMap);
2033 xWindow = VclPtr<ProgressBar>::Create(pParent, bVertical ? WB_VERT : WB_HORZ);
2034 }
2035 else if (name == "GtkScrolledWindow")
2036 {
2037 xWindow = VclPtr<VclScrolledWindow>::Create(pParent);
2038 }
2039 else if (name == "GtkViewport")
2040 {
2041 xWindow = VclPtr<VclViewport>::Create(pParent);
2042 }
2043 else if (name == "GtkEventBox")
2044 {
2045 xWindow = VclPtr<VclEventBox>::Create(pParent);
2046 }
2047 else if (name == "GtkEntry")
2048 {
2049 WinBits nWinStyle = WB_LEFT|WB_VCENTER|WB_3DLOOK;
2050 if (extractHasFrame(rMap))
2051 nWinStyle |= WB_BORDER;
2052 xWindow = VclPtr<Edit>::Create(pParent, nWinStyle);
2054 }
2055 else if (name == "GtkNotebook")
2056 {
2057 if (!extractVerticalTabPos(rMap))
2059 else
2060 xWindow = VclPtr<VerticalTabControl>::Create(pParent);
2061 }
2062 else if (name == "GtkDrawingArea")
2063 {
2064 xWindow = VclPtr<VclDrawingArea>::Create(pParent, WB_TABSTOP);
2065 }
2066 else if (name == "GtkTextView")
2067 {
2068 extractBuffer(id, rMap);
2069
2070 WinBits nWinStyle = WB_CLIPCHILDREN|WB_LEFT;
2071 //VclMultiLineEdit manages its own scrolling,
2072 vcl::Window *pRealParent = prepareWidgetOwnScrolling(pParent, nWinStyle);
2073 xWindow = VclPtr<VclMultiLineEdit>::Create(pRealParent, nWinStyle);
2074 if (pRealParent != pParent)
2075 cleanupWidgetOwnScrolling(pParent, xWindow, rMap);
2076 }
2077 else if (name == "GtkSpinner")
2078 {
2079 xWindow = VclPtr<Throbber>::Create(pParent, WB_3DLOOK);
2080 }
2081 else if (name == "GtkScale")
2082 {
2083 extractAdjustmentToMap(id, rMap, m_pParserState->m_aSliderAdjustmentMaps);
2084 bool bDrawValue = extractDrawValue(rMap);
2085 if (bDrawValue)
2086 {
2087 OUString sValuePos = extractValuePos(rMap);
2088 (void)sValuePos;
2089 }
2090 bVertical = extractOrientation(rMap);
2091
2092 WinBits nWinStyle = bVertical ? WB_VERT : WB_HORZ;
2093
2094 xWindow = VclPtr<Slider>::Create(pParent, nWinStyle);
2095 }
2096 else if (name == "GtkToolbar")
2097 {
2098 xWindow = VclPtr<ToolBox>::Create(pParent, WB_3DLOOK | WB_TABSTOP);
2099 }
2100 else if(name == "NotebookBarAddonsToolMergePoint")
2101 {
2102 customMakeWidget pFunction = GetCustomMakeWidget("sfxlo-NotebookbarToolBox");
2103 if(pFunction != nullptr)
2105 return nullptr;
2106 }
2107 else if (name == "GtkToolButton" || name == "GtkMenuToolButton" ||
2108 name == "GtkToggleToolButton" || name == "GtkRadioToolButton" || name == "GtkToolItem")
2109 {
2110 if (pToolBox)
2111 {
2112 OUString aCommand(extractActionName(rMap));
2113
2114 ToolBoxItemId nItemId(0);
2116 if (name == "GtkMenuToolButton")
2118 else if (name == "GtkToggleToolButton")
2120 else if (name == "GtkRadioToolButton")
2122
2123 if (!aCommand.isEmpty() && m_xFrame.is())
2124 {
2125 pToolBox->InsertItem(aCommand, m_xFrame, nBits, extractSizeRequest(rMap));
2126 nItemId = pToolBox->GetItemId(aCommand);
2127 }
2128 else
2129 {
2130 nItemId = ToolBoxItemId(pToolBox->GetItemCount() + 1);
2131 //TODO: ImplToolItems::size_type -> sal_uInt16!
2132 if (aCommand.isEmpty() && !m_bLegacy)
2133 aCommand = OUString::fromUtf8(id);
2134 pToolBox->InsertItem(nItemId, extractLabel(rMap), aCommand, nBits);
2135 }
2136
2137 pToolBox->SetHelpId(nItemId, m_sHelpRoot + id);
2138 OUString sTooltip(extractTooltipText(rMap));
2139 if (!sTooltip.isEmpty())
2140 pToolBox->SetQuickHelpText(nItemId, sTooltip);
2141
2142 OUString sIconName(extractIconName(rMap));
2143 if (!sIconName.isEmpty())
2144 pToolBox->SetItemImage(nItemId, FixedImage::loadThemeImage(sIconName));
2145
2146 if (!extractVisible(rMap))
2147 pToolBox->HideItem(nItemId);
2148
2149 m_pParserState->m_nLastToolbarId = nItemId;
2150
2151 return nullptr; // no widget to be created
2152 }
2153 }
2154 else if (name == "GtkSeparatorToolItem")
2155 {
2156 if (pToolBox)
2157 {
2158 pToolBox->InsertSeparator();
2159 return nullptr; // no widget to be created
2160 }
2161 }
2162 else if (name == "GtkWindow")
2163 {
2164 WinBits nBits = extractDeferredBits(rMap);
2165 if (nBits & WB_DOCKABLE)
2166 xWindow = VclPtr<DockingWindow>::Create(pParent, nBits|WB_MOVEABLE);
2167 else
2168 xWindow = VclPtr<FloatingWindow>::Create(pParent, nBits|WB_MOVEABLE);
2169 }
2170 else if (name == "GtkPopover")
2171 {
2172 WinBits nBits = extractDeferredBits(rMap);
2173 xWindow = VclPtr<DockingWindow>::Create(pParent, nBits|WB_DOCKABLE|WB_MOVEABLE);
2174 }
2175 else if (name == "GtkCalendar")
2176 {
2177 WinBits nBits = extractDeferredBits(rMap);
2178 xWindow = VclPtr<Calendar>::Create(pParent, nBits);
2179 }
2180 else
2181 {
2182 if (customMakeWidget pFunction = GetCustomMakeWidget(name))
2183 {
2184 pFunction(xWindow, pParent, rMap);
2185 if (xWindow->GetType() == WindowType::PUSHBUTTON)
2186 setupFromActionName(static_cast<Button*>(xWindow.get()), rMap, m_xFrame);
2187 else if (xWindow->GetType() == WindowType::MENUBUTTON)
2188 {
2189 OUString sMenu = BuilderUtils::extractCustomProperty(rMap);
2190 if (!sMenu.isEmpty())
2191 m_pParserState->m_aButtonMenuMaps.emplace_back(id, sMenu);
2192 setupFromActionName(static_cast<Button*>(xWindow.get()), rMap, m_xFrame);
2193 }
2194 }
2195 }
2196
2197 SAL_INFO_IF(!xWindow, "vcl.builder", "probably need to implement " << name << " or add a make" << name << " function");
2198 if (xWindow)
2199 {
2200 // child windows of disabled windows are made disabled by vcl by default, we don't want that
2201 WindowImpl *pWindowImpl = xWindow->ImplGetWindowImpl();
2202 pWindowImpl->mbDisabled = false;
2203
2204 xWindow->SetHelpId(m_sHelpRoot + id);
2205 SAL_INFO("vcl.builder", "for name '" << name << "' and id '" << id <<
2206 "', created " << xWindow.get() << " child of " <<
2207 pParent << "(" << xWindow->ImplGetWindowImpl()->mpParent.get() << "/" <<
2208 xWindow->ImplGetWindowImpl()->mpRealParent.get() << "/" <<
2209 xWindow->ImplGetWindowImpl()->mpBorderWindow.get() << ") with helpid " <<
2210 xWindow->GetHelpId());
2211 m_aChildren.emplace_back(id, xWindow, bVertical);
2212
2213 // if the parent was a toolbox set it as an itemwindow for the latest itemid
2214 if (pToolBox)
2215 {
2216 Size aSize(xWindow->GetSizePixel());
2217 aSize.setHeight(xWindow->get_preferred_size().Height());
2218 xWindow->SetSizePixel(aSize);
2219 pToolBox->SetItemWindow(m_pParserState->m_nLastToolbarId, xWindow);
2220 pToolBox->SetItemExpand(m_pParserState->m_nLastToolbarId, true);
2221 }
2222 }
2223 return xWindow;
2224}
2225
2226namespace
2227{
2228 //return true for window types which exist in vcl but are not themselves
2229 //represented in the .ui format, i.e. only their children exist.
2230 bool isConsideredGtkPseudo(vcl::Window const *pWindow)
2231 {
2232 return pWindow->GetType() == WindowType::TABPAGE;
2233 }
2234}
2235
2236//Any properties from .ui load we couldn't set because of potential virtual methods
2237//during ctor are applied here
2239{
2241 return;
2242 stringmap aDeferredProperties;
2243 aDeferredProperties.swap(m_aDeferredProperties);
2245 BuilderUtils::set_properties(m_pParent, aDeferredProperties);
2246}
2247
2249{
2251 {
2252 for (auto const& prop : rProps)
2253 {
2254 const OString &rKey = prop.first;
2255 const OUString &rValue = prop.second;
2256 pWindow->set_property(rKey, rValue);
2257 }
2258 }
2259
2260 OUString convertMnemonicMarkup(std::u16string_view rIn)
2261 {
2262 OUStringBuffer aRet(rIn);
2263 for (sal_Int32 nI = 0; nI < aRet.getLength(); ++nI)
2264 {
2265 if (aRet[nI] == '_' && nI+1 < aRet.getLength())
2266 {
2267 if (aRet[nI+1] != '_')
2268 aRet[nI] = MNEMONIC_CHAR;
2269 else
2270 aRet.remove(nI, 1);
2271 ++nI;
2272 }
2273 }
2274 return aRet.makeStringAndClear();
2275 }
2276
2278 {
2279 OUString sCustomProperty;
2280 VclBuilder::stringmap::iterator aFind = rMap.find(OString("customproperty"));
2281 if (aFind != rMap.end())
2282 {
2283 sCustomProperty = aFind->second;
2284 rMap.erase(aFind);
2285 }
2286 return sCustomProperty;
2287 }
2288
2290 {
2291 OString sWidthChars("width-chars");
2292 VclBuilder::stringmap::iterator aFind = rMap.find(sWidthChars);
2293 if (aFind == rMap.end())
2294 rMap[sWidthChars] = "20";
2295 }
2296
2298 {
2299 bool bDropdown = true;
2300 VclBuilder::stringmap::iterator aFind = rMap.find(OString("dropdown"));
2301 if (aFind != rMap.end())
2302 {
2303 bDropdown = toBool(aFind->second);
2304 rMap.erase(aFind);
2305 }
2306 return bDropdown;
2307 }
2308
2309 void reorderWithinParent(vcl::Window &rWindow, sal_uInt16 nNewPosition)
2310 {
2311 WindowImpl *pWindowImpl = rWindow.ImplGetWindowImpl();
2312 if (pWindowImpl->mpParent != pWindowImpl->mpRealParent)
2313 {
2314 assert(pWindowImpl->mpBorderWindow == pWindowImpl->mpParent);
2315 assert(pWindowImpl->mpBorderWindow->ImplGetWindowImpl()->mpParent == pWindowImpl->mpRealParent);
2316 reorderWithinParent(*pWindowImpl->mpBorderWindow, nNewPosition);
2317 return;
2318 }
2319 rWindow.reorderWithinParent(nNewPosition);
2320 }
2321
2322 void reorderWithinParent(std::vector<vcl::Window*>& rChilds, bool bIsButtonBox)
2323 {
2324 for (size_t i = 0; i < rChilds.size(); ++i)
2325 {
2326 reorderWithinParent(*rChilds[i], i);
2327
2328 if (!bIsButtonBox)
2329 continue;
2330
2331 //The first member of the group for legacy code needs WB_GROUP set and the
2332 //others not
2333 WinBits nBits = rChilds[i]->GetStyle();
2334 nBits &= ~WB_GROUP;
2335 if (i == 0)
2336 nBits |= WB_GROUP;
2337 rChilds[i]->SetStyle(nBits);
2338 }
2339 }
2340
2341 sal_Int16 getRoleFromName(const OString& roleName)
2342 {
2343 using namespace com::sun::star::accessibility;
2344
2345 static const std::unordered_map<OString, sal_Int16> aAtkRoleToAccessibleRole = {
2346 /* This is in atkobject.h's AtkRole order */
2347 { "invalid", AccessibleRole::UNKNOWN },
2348 { "accelerator label", AccessibleRole::UNKNOWN },
2349 { "alert", AccessibleRole::ALERT },
2350 { "animation", AccessibleRole::UNKNOWN },
2351 { "arrow", AccessibleRole::UNKNOWN },
2352 { "calendar", AccessibleRole::UNKNOWN },
2353 { "canvas", AccessibleRole::CANVAS },
2354 { "check box", AccessibleRole::CHECK_BOX },
2355 { "check menu item", AccessibleRole::CHECK_MENU_ITEM },
2356 { "color chooser", AccessibleRole::COLOR_CHOOSER },
2357 { "column header", AccessibleRole::COLUMN_HEADER },
2358 { "combo box", AccessibleRole::COMBO_BOX },
2359 { "date editor", AccessibleRole::DATE_EDITOR },
2360 { "desktop icon", AccessibleRole::DESKTOP_ICON },
2361 { "desktop frame", AccessibleRole::DESKTOP_PANE }, // ?
2362 { "dial", AccessibleRole::UNKNOWN },
2363 { "dialog", AccessibleRole::DIALOG },
2364 { "directory pane", AccessibleRole::DIRECTORY_PANE },
2365 { "drawing area", AccessibleRole::UNKNOWN },
2366 { "file chooser", AccessibleRole::FILE_CHOOSER },
2367 { "filler", AccessibleRole::FILLER },
2368 { "font chooser", AccessibleRole::FONT_CHOOSER },
2369 { "frame", AccessibleRole::FRAME },
2370 { "glass pane", AccessibleRole::GLASS_PANE },
2371 { "html container", AccessibleRole::UNKNOWN },
2372 { "icon", AccessibleRole::ICON },
2373 { "image", AccessibleRole::GRAPHIC },
2374 { "internal frame", AccessibleRole::INTERNAL_FRAME },
2375 { "label", AccessibleRole::LABEL },
2376 { "layered pane", AccessibleRole::LAYERED_PANE },
2377 { "list", AccessibleRole::LIST },
2378 { "list item", AccessibleRole::LIST_ITEM },
2379 { "menu", AccessibleRole::MENU },
2380 { "menu bar", AccessibleRole::MENU_BAR },
2381 { "menu item", AccessibleRole::MENU_ITEM },
2382 { "option pane", AccessibleRole::OPTION_PANE },
2383 { "page tab", AccessibleRole::PAGE_TAB },
2384 { "page tab list", AccessibleRole::PAGE_TAB_LIST },
2385 { "panel", AccessibleRole::PANEL }, // or SHAPE or TEXT_FRAME ?
2386 { "password text", AccessibleRole::PASSWORD_TEXT },
2387 { "popup menu", AccessibleRole::POPUP_MENU },
2388 { "progress bar", AccessibleRole::PROGRESS_BAR },
2389 { "push button", AccessibleRole::PUSH_BUTTON }, // or BUTTON_DROPDOWN or BUTTON_MENU
2390 { "radio button", AccessibleRole::RADIO_BUTTON },
2391 { "radio menu item", AccessibleRole::RADIO_MENU_ITEM },
2392 { "root pane", AccessibleRole::ROOT_PANE },
2393 { "row header", AccessibleRole::ROW_HEADER },
2394 { "scroll bar", AccessibleRole::SCROLL_BAR },
2395 { "scroll pane", AccessibleRole::SCROLL_PANE },
2396 { "separator", AccessibleRole::SEPARATOR },
2397 { "slider", AccessibleRole::SLIDER },
2398 { "split pane", AccessibleRole::SPLIT_PANE },
2399 { "spin button", AccessibleRole::SPIN_BOX }, // ?
2400 { "statusbar", AccessibleRole::STATUS_BAR },
2401 { "table", AccessibleRole::TABLE },
2402 { "table cell", AccessibleRole::TABLE_CELL },
2403 { "table column header", AccessibleRole::COLUMN_HEADER }, // approximate
2404 { "table row header", AccessibleRole::ROW_HEADER }, // approximate
2405 { "tear off menu item", AccessibleRole::UNKNOWN },
2406 { "terminal", AccessibleRole::UNKNOWN },
2407 { "text", AccessibleRole::TEXT },
2408 { "toggle button", AccessibleRole::TOGGLE_BUTTON },
2409 { "tool bar", AccessibleRole::TOOL_BAR },
2410 { "tool tip", AccessibleRole::TOOL_TIP },
2411 { "tree", AccessibleRole::TREE },
2412 { "tree table", AccessibleRole::TREE_TABLE },
2413 { "unknown", AccessibleRole::UNKNOWN },
2414 { "viewport", AccessibleRole::VIEW_PORT },
2415 { "window", AccessibleRole::WINDOW },
2416 { "header", AccessibleRole::HEADER },
2417 { "footer", AccessibleRole::FOOTER },
2418 { "paragraph", AccessibleRole::PARAGRAPH },
2419 { "ruler", AccessibleRole::RULER },
2420 { "application", AccessibleRole::UNKNOWN },
2421 { "autocomplete", AccessibleRole::UNKNOWN },
2422 { "edit bar", AccessibleRole::EDIT_BAR },
2423 { "embedded", AccessibleRole::EMBEDDED_OBJECT },
2424 { "entry", AccessibleRole::UNKNOWN },
2425 { "chart", AccessibleRole::CHART },
2426 { "caption", AccessibleRole::CAPTION },
2427 { "document frame", AccessibleRole::DOCUMENT },
2428 { "heading", AccessibleRole::HEADING },
2429 { "page", AccessibleRole::PAGE },
2430 { "section", AccessibleRole::SECTION },
2431 { "redundant object", AccessibleRole::UNKNOWN },
2432 { "form", AccessibleRole::FORM },
2433 { "link", AccessibleRole::HYPER_LINK },
2434 { "input method window", AccessibleRole::UNKNOWN },
2435 { "table row", AccessibleRole::UNKNOWN },
2436 { "tree item", AccessibleRole::TREE_ITEM },
2437 { "document spreadsheet", AccessibleRole::DOCUMENT_SPREADSHEET },
2438 { "document presentation", AccessibleRole::DOCUMENT_PRESENTATION },
2439 { "document text", AccessibleRole::DOCUMENT_TEXT },
2440 { "document web", AccessibleRole::DOCUMENT }, // approximate
2441 { "document email", AccessibleRole::DOCUMENT }, // approximate
2442 { "comment", AccessibleRole::COMMENT }, // or NOTE or END_NOTE or FOOTNOTE or SCROLL_PANE
2443 { "list box", AccessibleRole::UNKNOWN },
2444 { "grouping", AccessibleRole::GROUP_BOX },
2445 { "image map", AccessibleRole::IMAGE_MAP },
2446 { "notification", AccessibleRole::NOTIFICATION },
2447 { "info bar", AccessibleRole::UNKNOWN },
2448 { "level bar", AccessibleRole::UNKNOWN },
2449 { "title bar", AccessibleRole::UNKNOWN },
2450 { "block quote", AccessibleRole::UNKNOWN },
2451 { "audio", AccessibleRole::UNKNOWN },
2452 { "video", AccessibleRole::UNKNOWN },
2453 { "definition", AccessibleRole::UNKNOWN },
2454 { "article", AccessibleRole::UNKNOWN },
2455 { "landmark", AccessibleRole::UNKNOWN },
2456 { "log", AccessibleRole::UNKNOWN },
2457 { "marquee", AccessibleRole::UNKNOWN },
2458 { "math", AccessibleRole::UNKNOWN },
2459 { "rating", AccessibleRole::UNKNOWN },
2460 { "timer", AccessibleRole::UNKNOWN },
2461 { "description list", AccessibleRole::UNKNOWN },
2462 { "description term", AccessibleRole::UNKNOWN },
2463 { "description value", AccessibleRole::UNKNOWN },
2464 { "static", AccessibleRole::STATIC },
2465 { "math fraction", AccessibleRole::UNKNOWN },
2466 { "math root", AccessibleRole::UNKNOWN },
2467 { "subscript", AccessibleRole::UNKNOWN },
2468 { "superscript", AccessibleRole::UNKNOWN },
2469 { "footnote", AccessibleRole::FOOTNOTE },
2470 };
2471
2472 auto it = aAtkRoleToAccessibleRole.find(roleName);
2473 if (it == aAtkRoleToAccessibleRole.end())
2474 return AccessibleRole::UNKNOWN;
2475 return it->second;
2476 }
2477}
2478
2480 const OString &rID, stringmap &rProps, stringmap &rPango, stringmap &rAtk)
2481{
2482 VclPtr<vcl::Window> pCurrentChild;
2483
2484 if (m_pParent && !isConsideredGtkPseudo(m_pParent) && !m_sID.isEmpty() && rID == m_sID)
2485 {
2486 pCurrentChild = m_pParent;
2487
2488 //toplevels default to resizable and apparently you can't change them
2489 //afterwards, so we need to wait until now before we can truly
2490 //initialize the dialog.
2491 if (pParent && pParent->IsSystemWindow())
2492 {
2493 SystemWindow *pSysWin = static_cast<SystemWindow*>(pCurrentChild.get());
2494 pSysWin->doDeferredInit(extractDeferredBits(rProps));
2496 }
2497 else if (pParent && pParent->IsDockingWindow())
2498 {
2499 DockingWindow *pDockWin = static_cast<DockingWindow*>(pCurrentChild.get());
2500 pDockWin->doDeferredInit(extractDeferredBits(rProps));
2502 }
2503
2504 if (pCurrentChild->GetHelpId().isEmpty())
2505 {
2506 pCurrentChild->SetHelpId(m_sHelpRoot + m_sID);
2507 SAL_INFO("vcl.builder", "for toplevel dialog " << this << " " <<
2508 rID << ", set helpid " << pCurrentChild->GetHelpId());
2509 }
2511 }
2512 else
2513 {
2514 //if we're being inserting under a toplevel dialog whose init is
2515 //deferred due to waiting to encounter it in this .ui, and it hasn't
2516 //been seen yet, then make unattached widgets parent-less toplevels
2517 if (pParent == m_pParent.get() && m_bToplevelHasDeferredInit)
2518 pParent = nullptr;
2519 pCurrentChild = makeObject(pParent, rClass, rID, rProps);
2520 }
2521
2522 if (pCurrentChild)
2523 {
2524 pCurrentChild->set_id(OStringToOUString(rID, RTL_TEXTENCODING_UTF8));
2525 if (pCurrentChild == m_pParent.get() && m_bToplevelHasDeferredProperties)
2526 m_aDeferredProperties = rProps;
2527 else
2528 BuilderUtils::set_properties(pCurrentChild, rProps);
2529
2530 // tdf#119827 handle size before scale so we can trivially
2531 // scale on the current font size whether size is present
2532 // or not.
2533 VclBuilder::stringmap::iterator aSize = rPango.find(OString("size"));
2534 if (aSize != rPango.end())
2535 {
2536 pCurrentChild->set_font_attribute(aSize->first, aSize->second);
2537 rPango.erase(aSize);
2538 }
2539 for (auto const& elem : rPango)
2540 {
2541 const OString &rKey = elem.first;
2542 const OUString &rValue = elem.second;
2543 pCurrentChild->set_font_attribute(rKey, rValue);
2544 }
2545
2546 m_pParserState->m_aAtkInfo[pCurrentChild] = rAtk;
2547 }
2548
2549 rProps.clear();
2550 rPango.clear();
2551 rAtk.clear();
2552
2553 if (!pCurrentChild)
2554 {
2555 bool bToolbarParent = (pParent && pParent->GetType() == WindowType::TOOLBOX);
2556 pCurrentChild = (m_aChildren.empty() || bToolbarParent) ? pParent : m_aChildren.back().m_pWindow.get();
2557 }
2558 return pCurrentChild;
2559}
2560
2562{
2563 TabControl *pTabControl = pParent && pParent->GetType() == WindowType::TABCONTROL ?
2564 static_cast<TabControl*>(pParent) : nullptr;
2565
2566 std::vector<OString> sIDs;
2567
2568 int nLevel = 1;
2570 stringmap aAtkProperties;
2571 std::vector<vcl::EnumContext::Context> context;
2572
2573 while(true)
2574 {
2576 int nsId;
2577
2579 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2580
2581 if (res == xmlreader::XmlReader::Result::Begin)
2582 {
2583 ++nLevel;
2584 if (name == "object")
2585 {
2586 while (reader.nextAttribute(&nsId, &name))
2587 {
2588 if (name == "id")
2589 {
2590 name = reader.getAttributeValue(false);
2591 OString sID(name.begin, name.length);
2592 sal_Int32 nDelim = sID.indexOf(':');
2593 if (nDelim != -1)
2594 {
2595 OString sPattern = sID.copy(nDelim+1);
2596 aProperties[OString("customproperty")] = OUString::fromUtf8(sPattern);
2597 sID = sID.copy(0, nDelim);
2598 }
2599 sIDs.push_back(sID);
2600 }
2601 }
2602 }
2603 else if (name == "style")
2604 {
2605 int nPriority = 0;
2606 context = handleStyle(reader, nPriority);
2607 --nLevel;
2608 }
2609 else if (name == "property")
2611 else if (pTabControl && name == "child")
2612 {
2613 // just to collect the atk properties (if any) for the label
2614 handleChild(nullptr, &aAtkProperties, reader);
2615 --nLevel;
2616 }
2617 }
2618
2619 if (res == xmlreader::XmlReader::Result::End)
2620 --nLevel;
2621
2622 if (!nLevel)
2623 break;
2624
2625 if (res == xmlreader::XmlReader::Result::Done)
2626 break;
2627 }
2628
2629 if (!pParent)
2630 return;
2631
2632 VerticalTabControl *pVerticalTabControl = pParent->GetType() == WindowType::VERTICALTABCONTROL ?
2633 static_cast<VerticalTabControl*>(pParent) : nullptr;
2634 assert(pTabControl || pVerticalTabControl);
2635 VclBuilder::stringmap::iterator aFind = aProperties.find(OString("label"));
2636 if (aFind != aProperties.end())
2637 {
2638 OUString sTooltip(extractTooltipText(aProperties));
2639 if (pTabControl)
2640 {
2641 sal_uInt16 nPageId = pTabControl->GetCurPageId();
2642 pTabControl->SetPageText(nPageId, aFind->second);
2643 pTabControl->SetPageName(nPageId, sIDs.back());
2644 pTabControl->SetHelpText(nPageId, sTooltip);
2645 if (!context.empty())
2646 {
2647 TabPage* pPage = pTabControl->GetTabPage(nPageId);
2648 pPage->SetContext(std::move(context));
2649 }
2650
2651 for (auto const& prop : aAtkProperties)
2652 {
2653 const OString &rKey = prop.first;
2654 const OUString &rValue = prop.second;
2655
2656 if (rKey == "AtkObject::accessible-name")
2657 pTabControl->SetAccessibleName(nPageId, rValue);
2658 else if (rKey == "AtkObject::accessible-description")
2659 pTabControl->SetAccessibleDescription(nPageId, rValue);
2660 else
2661 SAL_INFO("vcl.builder", "unhandled atk property: " << rKey);
2662 }
2663
2664 }
2665 else
2666 {
2667 OUString sLabel(BuilderUtils::convertMnemonicMarkup(aFind->second));
2668 OUString sIconName(extractIconName(aProperties));
2669 pVerticalTabControl->InsertPage(sIDs.front(), sLabel, FixedImage::loadThemeImage(sIconName), sTooltip,
2670 pVerticalTabControl->GetPageParent()->GetWindow(GetWindowType::LastChild));
2671 }
2672 }
2673 else
2674 {
2675 if (pTabControl)
2676 pTabControl->RemovePage(pTabControl->GetCurPageId());
2677 }
2678}
2679
2680//so that tabbing between controls goes in a visually sensible sequence
2681//we sort these into a best-tab-order sequence
2683{
2684 //sort child order within parent list by grid position
2685 sal_Int32 nTopA = pA->get_grid_top_attach();
2686 sal_Int32 nTopB = pB->get_grid_top_attach();
2687 if (nTopA < nTopB)
2688 return true;
2689 if (nTopA > nTopB)
2690 return false;
2691 sal_Int32 nLeftA = pA->get_grid_left_attach();
2692 sal_Int32 nLeftB = pB->get_grid_left_attach();
2693 if (nLeftA < nLeftB)
2694 return true;
2695 if (nLeftA > nLeftB)
2696 return false;
2697 //sort into two groups of pack start and pack end
2698 VclPackType ePackA = pA->get_pack_type();
2699 VclPackType ePackB = pB->get_pack_type();
2700 if (ePackA < ePackB)
2701 return true;
2702 if (ePackA > ePackB)
2703 return false;
2704 bool bVerticalContainer = m_pBuilder->get_window_packing_data(pA->GetParent()).m_bVerticalOrient;
2705 bool bPackA = pA->get_secondary();
2706 bool bPackB = pB->get_secondary();
2707 if (!bVerticalContainer)
2708 {
2709 //for horizontal boxes group secondaries before primaries
2710 if (bPackA > bPackB)
2711 return true;
2712 if (bPackA < bPackB)
2713 return false;
2714 }
2715 else
2716 {
2717 //for vertical boxes group secondaries after primaries
2718 if (bPackA < bPackB)
2719 return true;
2720 if (bPackA > bPackB)
2721 return false;
2722 }
2723 //honour relative box positions with pack group, (numerical order is reversed
2724 //for VclPackType::End, they are packed from the end back, but here we need
2725 //them in visual layout order so that tabbing works as expected)
2726 sal_Int32 nPackA = m_pBuilder->get_window_packing_data(pA).m_nPosition;
2727 sal_Int32 nPackB = m_pBuilder->get_window_packing_data(pB).m_nPosition;
2728 if (nPackA < nPackB)
2729 return ePackA == VclPackType::Start;
2730 if (nPackA > nPackB)
2731 return ePackA != VclPackType::Start;
2732 //sort labels of Frames before body
2733 if (pA->GetParent() == pB->GetParent())
2734 {
2735 const VclFrame *pFrameParent = dynamic_cast<const VclFrame*>(pA->GetParent());
2736 if (pFrameParent)
2737 {
2738 const vcl::Window *pLabel = pFrameParent->get_label_widget();
2739 int nFramePosA = (pA == pLabel) ? 0 : 1;
2740 int nFramePosB = (pB == pLabel) ? 0 : 1;
2741 return nFramePosA < nFramePosB;
2742 }
2743 }
2744 return false;
2745}
2746
2748{
2749 vcl::Window *pCurrentChild = nullptr;
2750
2752 int nsId;
2753 OString sType, sInternalChild;
2754
2755 while (reader.nextAttribute(&nsId, &name))
2756 {
2757 if (name == "type")
2758 {
2759 name = reader.getAttributeValue(false);
2760 sType = OString(name.begin, name.length);
2761 }
2762 else if (name == "internal-child")
2763 {
2764 name = reader.getAttributeValue(false);
2765 sInternalChild = OString(name.begin, name.length);
2766 }
2767 }
2768
2769 if (sType == "tab")
2770 {
2771 handleTabChild(pParent, reader);
2772 return;
2773 }
2774
2775 int nLevel = 1;
2776 while(true)
2777 {
2779 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2780
2781 if (res == xmlreader::XmlReader::Result::Begin)
2782 {
2783 if (name == "object" || name == "placeholder")
2784 {
2785 pCurrentChild = handleObject(pParent, pAtkProps, reader).get();
2786
2787 bool bObjectInserted = pCurrentChild && pParent != pCurrentChild;
2788
2789 if (bObjectInserted)
2790 {
2791 //Internal-children default in glade to not having their visible bits set
2792 //even though they are visible (generally anyway)
2793 if (!sInternalChild.isEmpty())
2794 pCurrentChild->Show();
2795
2796 //Select the first page if it's a notebook
2797 if (pCurrentChild->GetType() == WindowType::TABCONTROL)
2798 {
2799 TabControl *pTabControl = static_cast<TabControl*>(pCurrentChild);
2800 pTabControl->SetCurPageId(pTabControl->GetPageId(0));
2801
2802 //To-Do add reorder capability to the TabControl
2803 }
2804 else
2805 {
2806 // We want to sort labels before contents of frames
2807 // for keyboard traversal, especially if there
2808 // are multiple widgets using the same mnemonic
2809 if (sType == "label")
2810 {
2811 if (VclFrame *pFrameParent = dynamic_cast<VclFrame*>(pParent))
2812 pFrameParent->designate_label(pCurrentChild);
2813 }
2814 if (sInternalChild.startsWith("vbox") || sInternalChild.startsWith("messagedialog-vbox"))
2815 {
2816 if (Dialog *pBoxParent = dynamic_cast<Dialog*>(pParent))
2817 pBoxParent->set_content_area(static_cast<VclBox*>(pCurrentChild)); // FIXME-VCLPTR
2818 }
2819 else if (sInternalChild.startsWith("action_area") || sInternalChild.startsWith("messagedialog-action_area"))
2820 {
2821 vcl::Window *pContentArea = pCurrentChild->GetParent();
2822 if (Dialog *pBoxParent = dynamic_cast<Dialog*>(pContentArea ? pContentArea->GetParent() : nullptr))
2823 {
2824 pBoxParent->set_action_area(static_cast<VclButtonBox*>(pCurrentChild)); // FIXME-VCLPTR
2825 }
2826 }
2827
2828 bool bIsButtonBox = dynamic_cast<VclButtonBox*>(pCurrentChild) != nullptr;
2829
2830 //To-Do make reorder a virtual in Window, move this foo
2831 //there and see above
2832 std::vector<vcl::Window*> aChilds;
2833 for (vcl::Window* pChild = pCurrentChild->GetWindow(GetWindowType::FirstChild); pChild;
2834 pChild = pChild->GetWindow(GetWindowType::Next))
2835 {
2836 if (bIsButtonBox)
2837 {
2838 if (PushButton* pPushButton = dynamic_cast<PushButton*>(pChild))
2839 pPushButton->setAction(true);
2840 }
2841
2842 aChilds.push_back(pChild);
2843 }
2844
2845 //sort child order within parent so that tabbing
2846 //between controls goes in a visually sensible sequence
2847 std::stable_sort(aChilds.begin(), aChilds.end(), sortIntoBestTabTraversalOrder(this));
2848 BuilderUtils::reorderWithinParent(aChilds, bIsButtonBox);
2849 }
2850 }
2851 }
2852 else if (name == "packing")
2853 {
2854 handlePacking(pCurrentChild, pParent, reader);
2855 }
2856 else if (name == "interface")
2857 {
2858 while (reader.nextAttribute(&nsId, &name))
2859 {
2860 if (name == "domain")
2861 {
2862 name = reader.getAttributeValue(false);
2863 sType = OString(name.begin, name.length);
2864 m_pParserState->m_aResLocale = Translate::Create(sType);
2865 }
2866 }
2867 ++nLevel;
2868 }
2869 else
2870 ++nLevel;
2871 }
2872
2873 if (res == xmlreader::XmlReader::Result::End)
2874 --nLevel;
2875
2876 if (!nLevel)
2877 break;
2878
2879 if (res == xmlreader::XmlReader::Result::Done)
2880 break;
2881 }
2882}
2883
2885{
2886 xmlreader::Span span;
2887 int nsId;
2888
2889 OString sProperty;
2890 OString sValue;
2891
2892 while (reader.nextAttribute(&nsId, &span))
2893 {
2894 if (span == "name")
2895 {
2896 span = reader.getAttributeValue(false);
2897 sProperty = OString(span.begin, span.length);
2898 }
2899 else if (span == "value")
2900 {
2901 span = reader.getAttributeValue(false);
2902 sValue = OString(span.begin, span.length);
2903 }
2904 }
2905
2906 if (!sProperty.isEmpty())
2907 rMap[sProperty] = OUString::fromUtf8(sValue);
2908}
2909
2911{
2912 xmlreader::Span span;
2913 int nsId;
2914
2915 OString sProperty;
2916 OString sValue;
2917
2918 while (reader.nextAttribute(&nsId, &span))
2919 {
2920 if (span == "type")
2921 {
2922 span = reader.getAttributeValue(false);
2923 sProperty = OString(span.begin, span.length);
2924 }
2925 else if (span == "target")
2926 {
2927 span = reader.getAttributeValue(false);
2928 sValue = OString(span.begin, span.length);
2929 sal_Int32 nDelim = sValue.indexOf(':');
2930 if (nDelim != -1)
2931 sValue = sValue.copy(0, nDelim);
2932 }
2933 }
2934
2935 if (!sProperty.isEmpty())
2936 rMap[sProperty] = OUString::fromUtf8(sValue);
2937}
2938
2940{
2941 xmlreader::Span span;
2942 int nsId;
2943
2944 OString sProperty;
2945
2946 while (reader.nextAttribute(&nsId, &span))
2947 {
2948 if (span == "type")
2949 {
2950 span = reader.getAttributeValue(false);
2951 sProperty = OString(span.begin, span.length);
2952 }
2953 }
2954
2955 if (!sProperty.isEmpty())
2956 rMap["role"] = OUString::fromUtf8(sProperty);
2957}
2958
2959void VclBuilder::handleRow(xmlreader::XmlReader &reader, const OString &rID)
2960{
2961 int nLevel = 1;
2962
2963 ListStore::row aRow;
2964
2965 while(true)
2966 {
2968 int nsId;
2969
2971 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2972
2973 if (res == xmlreader::XmlReader::Result::Done)
2974 break;
2975
2976 if (res == xmlreader::XmlReader::Result::Begin)
2977 {
2978 ++nLevel;
2979 if (name == "col")
2980 {
2981 bool bTranslated = false;
2982 sal_uInt32 nId = 0;
2983 OString sContext;
2984
2985 while (reader.nextAttribute(&nsId, &name))
2986 {
2987 if (name == "id")
2988 {
2989 name = reader.getAttributeValue(false);
2990 nId = OString(name.begin, name.length).toUInt32();
2991 }
2992 else if (nId == 0 && name == "translatable" && reader.getAttributeValue(false) == "yes")
2993 {
2994 bTranslated = true;
2995 }
2996 else if (name == "context")
2997 {
2998 name = reader.getAttributeValue(false);
2999 sContext = OString(name.begin, name.length);
3000 }
3001 }
3002
3003 (void)reader.nextItem(
3004 xmlreader::XmlReader::Text::Raw, &name, &nsId);
3005
3006 OString sValue(name.begin, name.length);
3007 OUString sFinalValue;
3008 if (bTranslated)
3009 {
3010 sFinalValue = Translate::get(TranslateId{sContext.getStr(), sValue.getStr()}, m_pParserState->m_aResLocale);
3011 }
3012 else
3013 sFinalValue = OUString::fromUtf8(sValue);
3014
3015
3016 if (aRow.size() < nId+1)
3017 aRow.resize(nId+1);
3018 aRow[nId] = sFinalValue;
3019 }
3020 }
3021
3022 if (res == xmlreader::XmlReader::Result::End)
3023 {
3024 --nLevel;
3025 }
3026
3027 if (!nLevel)
3028 break;
3029 }
3030
3031 m_pParserState->m_aModels[rID].m_aEntries.push_back(aRow);
3032}
3033
3034void VclBuilder::handleListStore(xmlreader::XmlReader &reader, const OString &rID, std::string_view rClass)
3035{
3036 int nLevel = 1;
3037
3038 while(true)
3039 {
3041 int nsId;
3042
3044 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3045
3046 if (res == xmlreader::XmlReader::Result::Done)
3047 break;
3048
3049 if (res == xmlreader::XmlReader::Result::Begin)
3050 {
3051 if (name == "row")
3052 {
3053 bool bNotTreeStore = rClass != "GtkTreeStore";
3054 if (bNotTreeStore)
3055 handleRow(reader, rID);
3056 assert(bNotTreeStore && "gtk, as the time of writing, doesn't support data in GtkTreeStore serialization");
3057 }
3058 else
3059 ++nLevel;
3060 }
3061
3062 if (res == xmlreader::XmlReader::Result::End)
3063 {
3064 --nLevel;
3065 }
3066
3067 if (!nLevel)
3068 break;
3069 }
3070}
3071
3073{
3074 int nLevel = 1;
3075
3077
3078 while (true)
3079 {
3081 int nsId;
3082
3084 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3085
3086 if (res == xmlreader::XmlReader::Result::Done)
3087 break;
3088
3089 if (res == xmlreader::XmlReader::Result::Begin)
3090 {
3091 ++nLevel;
3092 if (name == "property")
3094 }
3095
3096 if (res == xmlreader::XmlReader::Result::End)
3097 {
3098 --nLevel;
3099 }
3100
3101 if (!nLevel)
3102 break;
3103 }
3104
3105 return aProperties;
3106}
3107
3108void VclBuilder::applyAtkProperties(vcl::Window *pWindow, const stringmap& rProperties)
3109{
3110 assert(pWindow);
3111 for (auto const& prop : rProperties)
3112 {
3113 const OString &rKey = prop.first;
3114 const OUString &rValue = prop.second;
3115
3116 if (pWindow && rKey.match("AtkObject::"))
3117 pWindow->set_property(rKey.copy(RTL_CONSTASCII_LENGTH("AtkObject::")), rValue);
3118 else
3119 SAL_WARN("vcl.builder", "unhandled atk prop: " << rKey);
3120 }
3121}
3122
3123std::vector<ComboBoxTextItem> VclBuilder::handleItems(xmlreader::XmlReader &reader) const
3124{
3125 int nLevel = 1;
3126
3127 std::vector<ComboBoxTextItem> aItems;
3128
3129 while(true)
3130 {
3132 int nsId;
3133
3135 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3136
3137 if (res == xmlreader::XmlReader::Result::Done)
3138 break;
3139
3140 if (res == xmlreader::XmlReader::Result::Begin)
3141 {
3142 ++nLevel;
3143 if (name == "item")
3144 {
3145 bool bTranslated = false;
3146 OString sContext, sId;
3147
3148 while (reader.nextAttribute(&nsId, &name))
3149 {
3150 if (name == "translatable" && reader.getAttributeValue(false) == "yes")
3151 {
3152 bTranslated = true;
3153 }
3154 else if (name == "context")
3155 {
3156 name = reader.getAttributeValue(false);
3157 sContext = OString(name.begin, name.length);
3158 }
3159 else if (name == "id")
3160 {
3161 name = reader.getAttributeValue(false);
3162 sId = OString(name.begin, name.length);
3163 }
3164 }
3165
3166 (void)reader.nextItem(
3167 xmlreader::XmlReader::Text::Raw, &name, &nsId);
3168
3169 OString sValue(name.begin, name.length);
3170 OUString sFinalValue;
3171 if (bTranslated)
3172 {
3173 sFinalValue = Translate::get(TranslateId{sContext.getStr(), sValue.getStr()}, m_pParserState->m_aResLocale);
3174 }
3175 else
3176 sFinalValue = OUString::fromUtf8(sValue);
3177
3178 if (m_pStringReplace)
3179 sFinalValue = (*m_pStringReplace)(sFinalValue);
3180
3181 aItems.emplace_back(sFinalValue, sId);
3182 }
3183 }
3184
3185 if (res == xmlreader::XmlReader::Result::End)
3186 {
3187 --nLevel;
3188 }
3189
3190 if (!nLevel)
3191 break;
3192 }
3193
3194 return aItems;
3195}
3196
3197VclPtr<Menu> VclBuilder::handleMenu(xmlreader::XmlReader &reader, const OString &rID, bool bMenuBar)
3198{
3199 VclPtr<Menu> pCurrentMenu;
3200 if (bMenuBar)
3201 pCurrentMenu = VclPtr<MenuBar>::Create();
3202 else
3203 pCurrentMenu = VclPtr<PopupMenu>::Create();
3204
3205 pCurrentMenu->set_id(OStringToOUString(rID, RTL_TEXTENCODING_UTF8));
3206
3207 int nLevel = 1;
3208
3210
3211 while(true)
3212 {
3214 int nsId;
3215
3217 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3218
3219 if (res == xmlreader::XmlReader::Result::Done)
3220 break;
3221
3222 if (res == xmlreader::XmlReader::Result::Begin)
3223 {
3224 if (name == "child")
3225 {
3226 handleMenuChild(pCurrentMenu, reader);
3227 }
3228 else
3229 {
3230 ++nLevel;
3231 if (name == "property")
3233 }
3234 }
3235
3236 if (res == xmlreader::XmlReader::Result::End)
3237 {
3238 --nLevel;
3239 }
3240
3241 if (!nLevel)
3242 break;
3243 }
3244
3245 m_aMenus.emplace_back(rID, pCurrentMenu);
3246
3247 return pCurrentMenu;
3248}
3249
3251{
3253 int nsId;
3254
3255 int nLevel = 1;
3256 while(true)
3257 {
3259 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3260
3261 if (res == xmlreader::XmlReader::Result::Begin)
3262 {
3263 if (name == "object" || name == "placeholder")
3264 {
3265 handleMenuObject(pParent, reader);
3266 }
3267 else
3268 ++nLevel;
3269 }
3270
3271 if (res == xmlreader::XmlReader::Result::End)
3272 --nLevel;
3273
3274 if (!nLevel)
3275 break;
3276
3277 if (res == xmlreader::XmlReader::Result::Done)
3278 break;
3279 }
3280}
3281
3283{
3284 OString sClass;
3285 OString sID;
3286 OUString sCustomProperty;
3287 PopupMenu *pSubMenu = nullptr;
3288
3290 int nsId;
3291
3292 while (reader.nextAttribute(&nsId, &name))
3293 {
3294 if (name == "class")
3295 {
3296 name = reader.getAttributeValue(false);
3297 sClass = OString(name.begin, name.length);
3298 }
3299 else if (name == "id")
3300 {
3301 name = reader.getAttributeValue(false);
3302 sID = OString(name.begin, name.length);
3303 if (m_bLegacy)
3304 {
3305 sal_Int32 nDelim = sID.indexOf(':');
3306 if (nDelim != -1)
3307 {
3308 sCustomProperty = OUString::fromUtf8(sID.subView(nDelim+1));
3309 sID = sID.copy(0, nDelim);
3310 }
3311 }
3312 }
3313 }
3314
3315 int nLevel = 1;
3316
3318 stringmap aAtkProperties;
3319 accelmap aAccelerators;
3320
3321 if (!sCustomProperty.isEmpty())
3322 aProperties[OString("customproperty")] = sCustomProperty;
3323
3324 while(true)
3325 {
3327 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3328
3329 if (res == xmlreader::XmlReader::Result::Done)
3330 break;
3331
3332 if (res == xmlreader::XmlReader::Result::Begin)
3333 {
3334 if (name == "child")
3335 {
3336 size_t nChildMenuIdx = m_aMenus.size();
3337 handleChild(nullptr, &aAtkProperties, reader);
3338 bool bSubMenuInserted = m_aMenus.size() > nChildMenuIdx;
3339 if (bSubMenuInserted)
3340 pSubMenu = dynamic_cast<PopupMenu*>(m_aMenus[nChildMenuIdx].m_pMenu.get());
3341 }
3342 else
3343 {
3344 ++nLevel;
3345 if (name == "property")
3347 else if (name == "accelerator")
3348 collectAccelerator(reader, aAccelerators);
3349 }
3350 }
3351
3352 if (res == xmlreader::XmlReader::Result::End)
3353 {
3354 --nLevel;
3355 }
3356
3357 if (!nLevel)
3358 break;
3359 }
3360
3361 insertMenuObject(pParent, pSubMenu, sClass, sID, aProperties, aAtkProperties, aAccelerators);
3362}
3363
3365{
3366 m_pParserState->m_aSizeGroups.emplace_back();
3367 SizeGroup &rSizeGroup = m_pParserState->m_aSizeGroups.back();
3368
3369 int nLevel = 1;
3370
3371 while(true)
3372 {
3374 int nsId;
3375
3377 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3378
3379 if (res == xmlreader::XmlReader::Result::Done)
3380 break;
3381
3382 if (res == xmlreader::XmlReader::Result::Begin)
3383 {
3384 ++nLevel;
3385 if (name == "widget")
3386 {
3387 while (reader.nextAttribute(&nsId, &name))
3388 {
3389 if (name == "name")
3390 {
3391 name = reader.getAttributeValue(false);
3392 OString sWidget(name.begin, name.length);
3393 sal_Int32 nDelim = sWidget.indexOf(':');
3394 if (nDelim != -1)
3395 sWidget = sWidget.copy(0, nDelim);
3396 rSizeGroup.m_aWidgets.push_back(sWidget);
3397 }
3398 }
3399 }
3400 else
3401 {
3402 if (name == "property")
3403 collectProperty(reader, rSizeGroup.m_aProperties);
3404 }
3405 }
3406
3407 if (res == xmlreader::XmlReader::Result::End)
3408 {
3409 --nLevel;
3410 }
3411
3412 if (!nLevel)
3413 break;
3414 }
3415}
3416
3417namespace
3418{
3419 vcl::KeyCode makeKeyCode(const std::pair<OString,OString> &rKey)
3420 {
3421 bool bShift = rKey.second.indexOf("GDK_SHIFT_MASK") != -1;
3422 bool bMod1 = rKey.second.indexOf("GDK_CONTROL_MASK") != -1;
3423 bool bMod2 = rKey.second.indexOf("GDK_ALT_MASK") != -1;
3424 bool bMod3 = rKey.second.indexOf("GDK_MOD2_MASK") != -1;
3425
3426 if (rKey.first == "Insert")
3427 return vcl::KeyCode(KEY_INSERT, bShift, bMod1, bMod2, bMod3);
3428 else if (rKey.first == "Delete")
3429 return vcl::KeyCode(KEY_DELETE, bShift, bMod1, bMod2, bMod3);
3430 else if (rKey.first == "Return")
3431 return vcl::KeyCode(KEY_RETURN, bShift, bMod1, bMod2, bMod3);
3432 else if (rKey.first == "Up")
3433 return vcl::KeyCode(KEY_UP, bShift, bMod1, bMod2, bMod3);
3434 else if (rKey.first == "Down")
3435 return vcl::KeyCode(KEY_DOWN, bShift, bMod1, bMod2, bMod3);
3436 else if (rKey.first == "Left")
3437 return vcl::KeyCode(KEY_LEFT, bShift, bMod1, bMod2, bMod3);
3438 else if (rKey.first == "Right")
3439 return vcl::KeyCode(KEY_RIGHT, bShift, bMod1, bMod2, bMod3);
3440 else if (rKey.first == "asterisk")
3441 return vcl::KeyCode(KEY_MULTIPLY, bShift, bMod1, bMod2, bMod3);
3442 else if (rKey.first.getLength() > 1 && rKey.first[0] == 'F')
3443 {
3444 sal_uInt32 nIndex = o3tl::toUInt32(rKey.first.subView(1));
3445 assert(nIndex >= 1 && nIndex <= 26);
3446 return vcl::KeyCode(KEY_F1 + nIndex - 1, bShift, bMod1, bMod2, bMod3);
3447 }
3448
3449 assert (rKey.first.getLength() == 1);
3450 char cChar = rKey.first.toChar();
3451
3452 if (cChar >= 'a' && cChar <= 'z')
3453 return vcl::KeyCode(KEY_A + (cChar - 'a'), bShift, bMod1, bMod2, bMod3);
3454 else if (cChar >= 'A' && cChar <= 'Z')
3455 return vcl::KeyCode(KEY_A + (cChar - 'A'), bShift, bMod1, bMod2, bMod3);
3456 else if (cChar >= '0' && cChar <= '9')
3457 return vcl::KeyCode(KEY_0 + (cChar - 'A'), bShift, bMod1, bMod2, bMod3);
3458
3459 return vcl::KeyCode(cChar, bShift, bMod1, bMod2, bMod3);
3460 }
3461}
3462
3463void VclBuilder::insertMenuObject(Menu *pParent, PopupMenu *pSubMenu, const OString &rClass, const OString &rID,
3464 stringmap &rProps, stringmap &rAtkProps, accelmap &rAccels)
3465{
3466 sal_uInt16 nOldCount = pParent->GetItemCount();
3467 sal_uInt16 nNewId = ++m_pParserState->m_nLastMenuItemId;
3468
3469 if(rClass == "NotebookBarAddonsMenuMergePoint")
3470 {
3472 m_pParserState->m_nLastMenuItemId = pParent->GetItemCount();
3473 }
3474 else if (rClass == "GtkMenuItem")
3475 {
3476 OUString sLabel(BuilderUtils::convertMnemonicMarkup(extractLabel(rProps)));
3477 OUString aCommand(extractActionName(rProps));
3478 pParent->InsertItem(nNewId, sLabel, MenuItemBits::NONE , rID);
3479 pParent->SetItemCommand(nNewId, aCommand);
3480 if (pSubMenu)
3481 pParent->SetPopupMenu(nNewId, pSubMenu);
3482 }
3483 else if (rClass == "GtkCheckMenuItem")
3484 {
3485 OUString sLabel(BuilderUtils::convertMnemonicMarkup(extractLabel(rProps)));
3486 OUString aCommand(extractActionName(rProps));
3487 pParent->InsertItem(nNewId, sLabel, MenuItemBits::CHECKABLE, rID);
3488 pParent->SetItemCommand(nNewId, aCommand);
3489 }
3490 else if (rClass == "GtkRadioMenuItem")
3491 {
3492 OUString sLabel(BuilderUtils::convertMnemonicMarkup(extractLabel(rProps)));
3493 OUString aCommand(extractActionName(rProps));
3494 pParent->InsertItem(nNewId, sLabel, MenuItemBits::AUTOCHECK | MenuItemBits::RADIOCHECK, rID);
3495 pParent->SetItemCommand(nNewId, aCommand);
3496 }
3497 else if (rClass == "GtkSeparatorMenuItem")
3498 {
3499 pParent->InsertSeparator(rID);
3500 }
3501
3502 SAL_WARN_IF(nOldCount == pParent->GetItemCount(), "vcl.builder", "probably need to implement " << rClass);
3503
3504 if (nOldCount != pParent->GetItemCount())
3505 {
3506 pParent->SetHelpId(nNewId, m_sHelpRoot + rID);
3507 if (!extractVisible(rProps))
3508 pParent->HideItem(nNewId);
3509
3510 for (auto const& prop : rProps)
3511 {
3512 const OString &rKey = prop.first;
3513 const OUString &rValue = prop.second;
3514
3515 if (rKey == "tooltip-markup")
3516 pParent->SetTipHelpText(nNewId, rValue);
3517 else if (rKey == "tooltip-text")
3518 pParent->SetTipHelpText(nNewId, rValue);
3519 else
3520 SAL_INFO("vcl.builder", "unhandled property: " << rKey);
3521 }
3522
3523 for (auto const& prop : rAtkProps)
3524 {
3525 const OString &rKey = prop.first;
3526 const OUString &rValue = prop.second;
3527
3528 if (rKey == "AtkObject::accessible-name")
3529 pParent->SetAccessibleName(nNewId, rValue);
3530 else if (rKey == "AtkObject::accessible-description")
3531 pParent->SetAccessibleDescription(nNewId, rValue);
3532 else
3533 SAL_INFO("vcl.builder", "unhandled atk property: " << rKey);
3534 }
3535
3536 for (auto const& accel : rAccels)
3537 {
3538 const OString &rSignal = accel.first;
3539 const auto &rValue = accel.second;
3540
3541 if (rSignal == "activate")
3542 pParent->SetAccelKey(nNewId, makeKeyCode(rValue));
3543 else
3544 SAL_INFO("vcl.builder", "unhandled accelerator for: " << rSignal);
3545 }
3546 }
3547
3548 rProps.clear();
3549}
3550
3553template<typename T> static bool insertItems(vcl::Window *pWindow, VclBuilder::stringmap &rMap,
3554 std::vector<std::unique_ptr<OUString>>& rUserData,
3555 const std::vector<ComboBoxTextItem> &rItems)
3556{
3557 T *pContainer = dynamic_cast<T*>(pWindow);
3558 if (!pContainer)
3559 return false;
3560
3561 sal_uInt16 nActiveId = extractActive(rMap);
3562 for (auto const& item : rItems)
3563 {
3564 sal_Int32 nPos = pContainer->InsertEntry(item.m_sItem);
3565 if (!item.m_sId.isEmpty())
3566 {
3567 rUserData.emplace_back(std::make_unique<OUString>(OUString::fromUtf8(item.m_sId)));
3568 pContainer->SetEntryData(nPos, rUserData.back().get());
3569 }
3570 }
3571 if (nActiveId < rItems.size())
3572 pContainer->SelectEntryPos(nActiveId);
3573
3574 return true;
3575}
3576
3578{
3579 OString sClass;
3580 OString sID;
3581 OUString sCustomProperty;
3582
3584 int nsId;
3585
3586 while (reader.nextAttribute(&nsId, &name))
3587 {
3588 if (name == "class")
3589 {
3590 name = reader.getAttributeValue(false);
3591 sClass = OString(name.begin, name.length);
3592 }
3593 else if (name == "id")
3594 {
3595 name = reader.getAttributeValue(false);
3596 sID = OString(name.begin, name.length);
3597 if (m_bLegacy)
3598 {
3599 sal_Int32 nDelim = sID.indexOf(':');
3600 if (nDelim != -1)
3601 {
3602 sCustomProperty = OUString::fromUtf8(sID.subView(nDelim+1));
3603 sID = sID.copy(0, nDelim);
3604 }
3605 }
3606 }
3607 }
3608
3609 if (sClass == "GtkListStore" || sClass == "GtkTreeStore")
3610 {
3611 handleListStore(reader, sID, sClass);
3612 return nullptr;
3613 }
3614 else if (sClass == "GtkMenu")
3615 {
3616 handleMenu(reader, sID, false);
3617 return nullptr;
3618 }
3619 else if (sClass == "GtkMenuBar")
3620 {
3621 VclPtr<Menu> xMenu = handleMenu(reader, sID, true);
3622 if (SystemWindow* pTopLevel = pParent ? pParent->GetSystemWindow() : nullptr)
3623 pTopLevel->SetMenuBar(dynamic_cast<MenuBar*>(xMenu.get()));
3624 return nullptr;
3625 }
3626 else if (sClass == "GtkSizeGroup")
3627 {
3628 handleSizeGroup(reader);
3629 return nullptr;
3630 }
3631 else if (sClass == "AtkObject")
3632 {
3633 assert((pParent || pAtkProps) && "must have one set");
3634 assert(!(pParent && pAtkProps) && "must not have both");
3635 auto aAtkProperties = handleAtkObject(reader);
3636 if (pParent)
3637 applyAtkProperties(pParent, aAtkProperties);
3638 if (pAtkProps)
3639 *pAtkProps = aAtkProperties;
3640 return nullptr;
3641 }
3642
3643 int nLevel = 1;
3644
3645 stringmap aProperties, aPangoAttributes;
3646 stringmap aAtkAttributes;
3647 std::vector<ComboBoxTextItem> aItems;
3648
3649 if (!sCustomProperty.isEmpty())
3650 aProperties[OString("customproperty")] = sCustomProperty;
3651
3652 VclPtr<vcl::Window> pCurrentChild;
3653 while(true)
3654 {
3656 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3657
3658 if (res == xmlreader::XmlReader::Result::Done)
3659 break;
3660
3661 if (res == xmlreader::XmlReader::Result::Begin)
3662 {
3663 if (name == "child")
3664 {
3665 if (!pCurrentChild)
3666 {
3667 pCurrentChild = insertObject(pParent, sClass, sID,
3668 aProperties, aPangoAttributes, aAtkAttributes);
3669 }
3670 handleChild(pCurrentChild, nullptr, reader);
3671 }
3672 else if (name == "items")
3673 aItems = handleItems(reader);
3674 else if (name == "style")
3675 {
3676 int nPriority = 0;
3677 std::vector<vcl::EnumContext::Context> aContext = handleStyle(reader, nPriority);
3678 if (nPriority != 0)
3679 {
3680 vcl::IPrioritable* pPrioritable = dynamic_cast<vcl::IPrioritable*>(pCurrentChild.get());
3681 SAL_WARN_IF(!pPrioritable, "vcl", "priority set for not supported item");
3682 if (pPrioritable)
3683 pPrioritable->SetPriority(nPriority);
3684 }
3685 if (!aContext.empty())
3686 {
3687 vcl::IContext* pContextControl = dynamic_cast<vcl::IContext*>(pCurrentChild.get());
3688 SAL_WARN_IF(!pContextControl, "vcl", "context set for not supported item");
3689 if (pContextControl)
3690 pContextControl->SetContext(std::move(aContext));
3691 }
3692 }
3693 else
3694 {
3695 ++nLevel;
3696 if (name == "property")
3698 else if (name == "attribute")
3699 collectPangoAttribute(reader, aPangoAttributes);
3700 else if (name == "relation")
3701 collectAtkRelationAttribute(reader, aAtkAttributes);
3702 else if (name == "role")
3703 collectAtkRoleAttribute(reader, aAtkAttributes);
3704 else if (name == "action-widget")
3705 handleActionWidget(reader);
3706 }
3707 }
3708
3709 if (res == xmlreader::XmlReader::Result::End)
3710 {
3711 --nLevel;
3712 }
3713
3714 if (!nLevel)
3715 break;
3716 }
3717
3718 if (sClass == "GtkAdjustment")
3719 {
3720 m_pParserState->m_aAdjustments[sID] = aProperties;
3721 return nullptr;
3722 }
3723 else if (sClass == "GtkTextBuffer")
3724 {
3725 m_pParserState->m_aTextBuffers[sID] = aProperties;
3726 return nullptr;
3727 }
3728
3729 if (!pCurrentChild)
3730 {
3731 pCurrentChild = insertObject(pParent, sClass, sID, aProperties,
3732 aPangoAttributes, aAtkAttributes);
3733 }
3734
3735 if (!aItems.empty())
3736 {
3737 // try to fill-in the items
3738 if (!insertItems<ComboBox>(pCurrentChild, aProperties, m_aUserData, aItems))
3739 insertItems<ListBox>(pCurrentChild, aProperties, m_aUserData, aItems);
3740 }
3741
3742 return pCurrentChild;
3743}
3744
3746{
3748 int nsId;
3749
3750 int nLevel = 1;
3751
3752 while(true)
3753 {
3755 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3756
3757 if (res == xmlreader::XmlReader::Result::Done)
3758 break;
3759
3760 if (res == xmlreader::XmlReader::Result::Begin)
3761 {
3762 ++nLevel;
3763 if (name == "property")
3764 applyPackingProperty(pCurrent, pParent, reader);
3765 }
3766
3767 if (res == xmlreader::XmlReader::Result::End)
3768 {
3769 --nLevel;
3770 }
3771
3772 if (!nLevel)
3773 break;
3774 }
3775}
3776
3778 vcl::Window *pParent,
3779 xmlreader::XmlReader &reader)
3780{
3781 if (!pCurrent)
3782 return;
3783
3784 //ToolBoxItems are not true widgets just elements
3785 //of the ToolBox itself
3786 ToolBox *pToolBoxParent = nullptr;
3787 if (pCurrent == pParent)
3788 pToolBoxParent = dynamic_cast<ToolBox*>(pParent);
3789
3791 int nsId;
3792
3793 if (pCurrent->GetType() == WindowType::SCROLLWINDOW)
3794 {
3795 auto aFind = m_pParserState->m_aRedundantParentWidgets.find(VclPtr<vcl::Window>(pCurrent));
3796 if (aFind != m_pParserState->m_aRedundantParentWidgets.end())
3797 {
3798 pCurrent = aFind->second;
3799 assert(pCurrent);
3800 }
3801 }
3802
3803 while (reader.nextAttribute(&nsId, &name))
3804 {
3805 if (name == "name")
3806 {
3807 name = reader.getAttributeValue(false);
3808 OString sKey(name.begin, name.length);
3809 sKey = sKey.replace('_', '-');
3810 (void)reader.nextItem(
3811 xmlreader::XmlReader::Text::Raw, &name, &nsId);
3812 OString sValue(name.begin, name.length);
3813
3814 if (sKey == "expand" || sKey == "resize")
3815 {
3816 bool bTrue = (!sValue.isEmpty() && (sValue[0] == 't' || sValue[0] == 'T' || sValue[0] == '1'));
3817 if (pToolBoxParent)
3818 pToolBoxParent->SetItemExpand(m_pParserState->m_nLastToolbarId, bTrue);
3819 else
3820 pCurrent->set_expand(bTrue);
3821 continue;
3822 }
3823
3824 if (pToolBoxParent)
3825 continue;
3826
3827 if (sKey == "fill")
3828 {
3829 bool bTrue = (!sValue.isEmpty() && (sValue[0] == 't' || sValue[0] == 'T' || sValue[0] == '1'));
3830 pCurrent->set_fill(bTrue);
3831 }
3832 else if (sKey == "pack-type")
3833 {
3834 VclPackType ePackType = (!sValue.isEmpty() && (sValue[0] == 'e' || sValue[0] == 'E')) ? VclPackType::End : VclPackType::Start;
3835 pCurrent->set_pack_type(ePackType);
3836 }
3837 else if (sKey == "left-attach")
3838 {
3839 pCurrent->set_grid_left_attach(sValue.toInt32());
3840 }
3841 else if (sKey == "top-attach")
3842 {
3843 pCurrent->set_grid_top_attach(sValue.toInt32());
3844 }
3845 else if (sKey == "width")
3846 {
3847 pCurrent->set_grid_width(sValue.toInt32());
3848 }
3849 else if (sKey == "height")
3850 {
3851 pCurrent->set_grid_height(sValue.toInt32());
3852 }
3853 else if (sKey == "padding")
3854 {
3855 pCurrent->set_padding(sValue.toInt32());
3856 }
3857 else if (sKey == "position")
3858 {
3859 set_window_packing_position(pCurrent, sValue.toInt32());
3860 }
3861 else if (sKey == "secondary")
3862 {
3863 pCurrent->set_secondary(toBool(sValue));
3864 }
3865 else if (sKey == "non-homogeneous")
3866 {
3867 pCurrent->set_non_homogeneous(toBool(sValue));
3868 }
3869 else if (sKey == "homogeneous")
3870 {
3871 pCurrent->set_non_homogeneous(!toBool(sValue));
3872 }
3873 else
3874 {
3875 SAL_WARN_IF(sKey != "shrink", "vcl.builder", "unknown packing: " << sKey);
3876 }
3877 }
3878 }
3879}
3880
3881std::vector<vcl::EnumContext::Context> VclBuilder::handleStyle(xmlreader::XmlReader &reader, int &nPriority)
3882{
3883 std::vector<vcl::EnumContext::Context> aContext;
3884
3886 int nsId;
3887
3888 int nLevel = 1;
3889
3890 while(true)
3891 {
3893 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3894
3895 if (res == xmlreader::XmlReader::Result::Done)
3896 break;
3897
3898 if (res == xmlreader::XmlReader::Result::Begin)
3899 {
3900 ++nLevel;
3901 if (name == "class")
3902 {
3903 OString classStyle = getStyleClass(reader);
3904
3905 if (classStyle.startsWith("context-"))
3906 {
3907 OString sContext = classStyle.copy(classStyle.indexOf('-') + 1);
3908 OUString sContext2(sContext.getStr(), sContext.getLength(), RTL_TEXTENCODING_UTF8);
3909 aContext.push_back(vcl::EnumContext::GetContextEnum(sContext2));
3910 }
3911 else if (classStyle.startsWith("priority-"))
3912 {
3913 OString aPriority = classStyle.copy(classStyle.indexOf('-') + 1);
3914 OUString aPriority2(aPriority.getStr(), aPriority.getLength(), RTL_TEXTENCODING_UTF8);
3915 nPriority = aPriority2.toInt32();
3916 }
3917 else if (classStyle != "small-button" && classStyle != "destructive-action" && classStyle != "suggested-action")
3918 {
3919 SAL_WARN("vcl.builder", "unknown class: " << classStyle);
3920 }
3921 }
3922 }
3923
3924 if (res == xmlreader::XmlReader::Result::End)
3925 {
3926 --nLevel;
3927 }
3928
3929 if (!nLevel)
3930 break;
3931 }
3932
3933 return aContext;
3934}
3935
3937{
3939 int nsId;
3940 OString aRet;
3941
3942 while (reader.nextAttribute(&nsId, &name))
3943 {
3944 if (name == "name")
3945 {
3946 name = reader.getAttributeValue(false);
3947 aRet = OString (name.begin, name.length);
3948 }
3949 }
3950
3951 return aRet;
3952}
3953
3955{
3957 int nsId;
3958
3959 OString sProperty, sContext;
3960
3961 bool bTranslated = false;
3962
3963 while (reader.nextAttribute(&nsId, &name))
3964 {
3965 if (name == "name")
3966 {
3967 name = reader.getAttributeValue(false);
3968 sProperty = OString(name.begin, name.length);
3969 }
3970 else if (name == "context")
3971 {
3972 name = reader.getAttributeValue(false);
3973 sContext = OString(name.begin, name.length);
3974 }
3975 else if (name == "translatable" && reader.getAttributeValue(false) == "yes")
3976 {
3977 bTranslated = true;
3978 }
3979 }
3980
3981 (void)reader.nextItem(xmlreader::XmlReader::Text::Raw, &name, &nsId);
3982 OString sValue(name.begin, name.length);
3983 OUString sFinalValue;
3984 if (bTranslated)
3985 {
3986 sFinalValue = Translate::get(TranslateId{sContext.getStr(), sValue.getStr()}, m_pParserState->m_aResLocale);
3987 }
3988 else
3989 sFinalValue = OUString::fromUtf8(sValue);
3990
3991 if (!sProperty.isEmpty())
3992 {
3993 sProperty = sProperty.replace('_', '-');
3994 if (m_pStringReplace)
3995 sFinalValue = (*m_pStringReplace)(sFinalValue);
3996 rMap[sProperty] = sFinalValue;
3997 }
3998}
3999
4001{
4003 int nsId;
4004
4005 OString sResponse;
4006
4007 while (reader.nextAttribute(&nsId, &name))
4008 {
4009 if (name == "response")
4010 {
4011 name = reader.getAttributeValue(false);
4012 sResponse = OString(name.begin, name.length);
4013 }
4014 }
4015
4016 (void)reader.nextItem(xmlreader::XmlReader::Text::Raw, &name, &nsId);
4017 OString sID(name.begin, name.length);
4018 sal_Int32 nDelim = sID.indexOf(':');
4019 if (nDelim != -1)
4020 sID = sID.copy(0, nDelim);
4021 set_response(sID, sResponse.toInt32());
4022}
4023
4025{
4027 int nsId;
4028
4029 OString sProperty;
4030 OString sValue;
4031 OString sModifiers;
4032
4033 while (reader.nextAttribute(&nsId, &name))
4034 {
4035 if (name == "key")
4036 {
4037 name = reader.getAttributeValue(false);
4038 sValue = OString(name.begin, name.length);
4039 }
4040 else if (name == "signal")
4041 {
4042 name = reader.getAttributeValue(false);
4043 sProperty = OString(name.begin, name.length);
4044 }
4045 else if (name == "modifiers")
4046 {
4047 name = reader.getAttributeValue(false);
4048 sModifiers = OString(name.begin, name.length);
4049 }
4050 }
4051
4052 if (!sProperty.isEmpty() && !sValue.isEmpty())
4053 {
4054 rMap[sProperty] = std::make_pair(sValue, sModifiers);
4055 }
4056}
4057
4059{
4060 return m_aChildren.empty() ? nullptr : m_aChildren[0].m_pWindow.get();
4061}
4062
4064{
4065 for (auto const& child : m_aChildren)
4066 {
4067 if (child.m_sID == sID)
4068 return child.m_pWindow;
4069 }
4070
4071 return nullptr;
4072}
4073
4074PopupMenu *VclBuilder::get_menu(std::string_view sID)
4075{
4076 for (auto const& menu : m_aMenus)
4077 {
4078 if (menu.m_sID == sID)
4079 return dynamic_cast<PopupMenu*>(menu.m_pMenu.get());
4080 }
4081
4082 return nullptr;
4083}
4084
4085void VclBuilder::set_response(std::string_view sID, short nResponse)
4086{
4087 switch (nResponse)
4088 {
4089 case -5:
4090 nResponse = RET_OK;
4091 break;
4092 case -6:
4093 nResponse = RET_CANCEL;
4094 break;
4095 case -7:
4096 nResponse = RET_CLOSE;
4097 break;
4098 case -8:
4099 nResponse = RET_YES;
4100 break;
4101 case -9:
4102 nResponse = RET_NO;
4103 break;
4104 case -11:
4105 nResponse = RET_HELP;
4106 break;
4107 default:
4108 assert(nResponse >= 100 && "keep non-canned responses in range 100+ to avoid collision with vcl RET_*");
4109 break;
4110 }
4111
4112 for (const auto & child : m_aChildren)
4113 {
4114 if (child.m_sID == sID)
4115 {
4116 PushButton* pPushButton = dynamic_cast<PushButton*>(child.m_pWindow.get());
4117 assert(pPushButton);
4118 Dialog* pDialog = pPushButton->GetParentDialog();
4119 assert(pDialog);
4120 pDialog->add_button(pPushButton, nResponse, false);
4121 return;
4122 }
4123 }
4124
4125 assert(false);
4126}
4127
4128void VclBuilder::delete_by_name(const OString& sID)
4129{
4130 auto aI = std::find_if(m_aChildren.begin(), m_aChildren.end(),
4131 [&sID](WinAndId& rItem) { return rItem.m_sID == sID; });
4132 if (aI != m_aChildren.end())
4133 {
4134 aI->m_pWindow.disposeAndClear();
4135 m_aChildren.erase(aI);
4136 }
4137}
4138
4140{
4141 drop_ownership(pWindow);
4142 pWindow->disposeOnce();
4143}
4144
4146{
4147 auto aI = std::find_if(m_aChildren.begin(), m_aChildren.end(),
4148 [&pWindow](WinAndId& rItem) { return rItem.m_pWindow == pWindow; });
4149 if (aI != m_aChildren.end())
4150 m_aChildren.erase(aI);
4151}
4152
4153OString VclBuilder::get_by_window(const vcl::Window *pWindow) const
4154{
4155 for (auto const& child : m_aChildren)
4156 {
4157 if (child.m_pWindow == pWindow)
4158 return child.m_sID;
4159 }
4160
4161 return OString();
4162}
4163
4165{
4166 //We've stored the return of new Control, some of these get
4167 //border windows placed around them which are what you get
4168 //from GetChild, so scoot up a level if necessary to get the
4169 //window whose position value we have
4170 const vcl::Window *pPropHolder = pWindow->ImplGetWindow();
4171
4172 for (auto const& child : m_aChildren)
4173 {
4174 if (child.m_pWindow == pPropHolder)
4175 return child.m_aPackingData;
4176 }
4177
4178 return PackingData();
4179}
4180
4181void VclBuilder::set_window_packing_position(const vcl::Window *pWindow, sal_Int32 nPosition)
4182{
4183 for (auto & child : m_aChildren)
4184 {
4185 if (child.m_pWindow == pWindow)
4186 child.m_aPackingData.m_nPosition = nPosition;
4187 }
4188}
4189
4191{
4192 std::map<OString, ListStore>::const_iterator aI = m_pParserState->m_aModels.find(sID);
4193 if (aI != m_pParserState->m_aModels.end())
4194 return &(aI->second);
4195 return nullptr;
4196}
4197
4199{
4200 std::map<OString, TextBuffer>::const_iterator aI = m_pParserState->m_aTextBuffers.find(sID);
4201 if (aI != m_pParserState->m_aTextBuffers.end())
4202 return &(aI->second);
4203 return nullptr;
4204}
4205
4207{
4208 std::map<OString, Adjustment>::const_iterator aI = m_pParserState->m_aAdjustments.find(sID);
4209 if (aI != m_pParserState->m_aAdjustments.end())
4210 return &(aI->second);
4211 return nullptr;
4212}
4213
4214void VclBuilder::mungeModel(ComboBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId)
4215{
4216 for (auto const& entry : rStore.m_aEntries)
4217 {
4218 const ListStore::row &rRow = entry;
4219 sal_uInt16 nEntry = rTarget.InsertEntry(rRow[0]);
4220 if (rRow.size() > 1)
4221 {
4222 if (m_bLegacy)
4223 {
4224 sal_Int32 nValue = rRow[1].toInt32();
4225 rTarget.SetEntryData(nEntry, reinterpret_cast<void*>(nValue));
4226 }
4227 else
4228 {
4229 if (!rRow[1].isEmpty())
4230 {
4231 m_aUserData.emplace_back(std::make_unique<OUString>(rRow[1]));
4232 rTarget.SetEntryData(nEntry, m_aUserData.back().get());
4233 }
4234 }
4235 }
4236 }
4237 if (nActiveId < rStore.m_aEntries.size())
4238 rTarget.SelectEntryPos(nActiveId);
4239}
4240
4241void VclBuilder::mungeModel(ListBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId)
4242{
4243 for (auto const& entry : rStore.m_aEntries)
4244 {
4245 const ListStore::row &rRow = entry;
4246 sal_uInt16 nEntry = rTarget.InsertEntry(rRow[0]);
4247 if (rRow.size() > 1)
4248 {
4249 if (m_bLegacy)
4250 {
4251 sal_Int32 nValue = rRow[1].toInt32();
4252 rTarget.SetEntryData(nEntry, reinterpret_cast<void*>(nValue));
4253 }
4254 else
4255 {
4256 if (!rRow[1].isEmpty())
4257 {
4258 m_aUserData.emplace_back(std::make_unique<OUString>(rRow[1]));
4259 rTarget.SetEntryData(nEntry, m_aUserData.back().get());
4260 }
4261 }
4262 }
4263 }
4264 if (nActiveId < rStore.m_aEntries.size())
4265 rTarget.SelectEntryPos(nActiveId);
4266}
4267
4268void VclBuilder::mungeModel(SvTabListBox& rTarget, const ListStore &rStore, sal_uInt16 nActiveId)
4269{
4270 for (auto const& entry : rStore.m_aEntries)
4271 {
4272 const ListStore::row &rRow = entry;
4273 auto pEntry = rTarget.InsertEntry(rRow[0]);
4274 if (rRow.size() > 1)
4275 {
4276 if (m_bLegacy)
4277 {
4278 sal_Int32 nValue = rRow[1].toInt32();
4279 pEntry->SetUserData(reinterpret_cast<void*>(nValue));
4280 }
4281 else
4282 {
4283 if (!rRow[1].isEmpty())
4284 {
4285 m_aUserData.emplace_back(std::make_unique<OUString>(rRow[1]));
4286 pEntry->SetUserData(m_aUserData.back().get());
4287 }
4288 }
4289 }
4290 }
4291 if (nActiveId < rStore.m_aEntries.size())
4292 {
4293 SvTreeListEntry* pEntry = rTarget.GetEntry(nullptr, nActiveId);
4294 rTarget.Select(pEntry);
4295 }
4296}
4297
4298void VclBuilder::mungeAdjustment(NumericFormatter &rTarget, const Adjustment &rAdjustment)
4299{
4300 int nMul = rtl_math_pow10Exp(1, rTarget.GetDecimalDigits());
4301
4302 for (auto const& elem : rAdjustment)
4303 {
4304 const OString &rKey = elem.first;
4305 const OUString &rValue = elem.second;
4306
4307 if (rKey == "upper")
4308 {
4309 sal_Int64 nUpper = rValue.toDouble() * nMul;
4310 rTarget.SetMax(nUpper);
4311 rTarget.SetLast(nUpper);
4312 }
4313 else if (rKey == "lower")
4314 {
4315 sal_Int64 nLower = rValue.toDouble() * nMul;
4316 rTarget.SetMin(nLower);
4317 rTarget.SetFirst(nLower);
4318 }
4319 else if (rKey == "value")
4320 {
4321 sal_Int64 nValue = rValue.toDouble() * nMul;
4322 rTarget.SetValue(nValue);
4323 }
4324 else if (rKey == "step-increment")
4325 {
4326 sal_Int64 nSpinSize = rValue.toDouble() * nMul;
4327 rTarget.SetSpinSize(nSpinSize);
4328 }
4329 else
4330 {
4331 SAL_INFO("vcl.builder", "unhandled property :" << rKey);
4332 }
4333 }
4334}
4335
4337{
4338 double nMaxValue = 0, nMinValue = 0, nValue = 0, nSpinSize = 0;
4339
4340 for (auto const& elem : rAdjustment)
4341 {
4342 const OString &rKey = elem.first;
4343 const OUString &rValue = elem.second;
4344
4345 if (rKey == "upper")
4346 nMaxValue = rValue.toDouble();
4347 else if (rKey == "lower")
4348 nMinValue = rValue.toDouble();
4349 else if (rKey == "value")
4350 nValue = rValue.toDouble();
4351 else if (rKey == "step-increment")
4352 nSpinSize = rValue.toDouble();
4353 else
4354 SAL_INFO("vcl.builder", "unhandled property :" << rKey);
4355 }
4356
4357 Formatter& rFormatter = rTarget.GetFormatter();
4358 rFormatter.SetMinValue(nMinValue);
4359 rFormatter.SetMaxValue(nMaxValue);
4360 rFormatter.SetValue(nValue);
4361 rFormatter.SetSpinSize(nSpinSize);
4362}
4363
4364void VclBuilder::mungeAdjustment(ScrollBar &rTarget, const Adjustment &rAdjustment)
4365{
4366 for (auto const& elem : rAdjustment)
4367 {
4368 const OString &rKey = elem.first;
4369 const OUString &rValue = elem.second;
4370
4371 if (rKey == "upper")
4372 rTarget.SetRangeMax(rValue.toInt32());
4373 else if (rKey == "lower")
4374 rTarget.SetRangeMin(rValue.toInt32());
4375 else if (rKey == "value")
4376 rTarget.SetThumbPos(rValue.toInt32());
4377 else if (rKey == "step-increment")
4378 rTarget.SetLineSize(rValue.toInt32());
4379 else if (rKey == "page-increment")
4380 rTarget.SetPageSize(rValue.toInt32());
4381 else
4382 {
4383 SAL_INFO("vcl.builder", "unhandled property :" << rKey);
4384 }
4385 }
4386}
4387
4388void VclBuilder::mungeAdjustment(Slider& rTarget, const Adjustment& rAdjustment)
4389{
4390 for (auto const& elem : rAdjustment)
4391 {
4392 const OString &rKey = elem.first;
4393 const OUString &rValue = elem.second;
4394
4395 if (rKey == "upper")
4396 rTarget.SetRangeMax(rValue.toInt32());
4397 else if (rKey == "lower")
4398 rTarget.SetRangeMin(rValue.toInt32());
4399 else if (rKey == "value")
4400 rTarget.SetThumbPos(rValue.toInt32());
4401 else if (rKey == "step-increment")
4402 rTarget.SetLineSize(rValue.toInt32());
4403 else if (rKey == "page-increment")
4404 rTarget.SetPageSize(rValue.toInt32());
4405 else
4406 {
4407 SAL_INFO("vcl.builder", "unhandled property :" << rKey);
4408 }
4409 }
4410}
4411
4413{
4414 for (auto const& elem : rTextBuffer)
4415 {
4416 const OString &rKey = elem.first;
4417 const OUString &rValue = elem.second;
4418
4419 if (rKey == "text")
4420 rTarget.SetText(rValue);
4421 else
4422 {
4423 SAL_INFO("vcl.builder", "unhandled property :" << rKey);
4424 }
4425 }
4426}
4427
4429 : m_nLastToolbarId(0)
4430 , m_nLastMenuItemId(0)
4431{}
4432
4434 : m_sID(std::move(aId))
4435 , m_pMenu(pMenu)
4436{}
4437
4438/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OptionalString sType
PropertiesInfo aProperties
css::uno::Reference< css::lang::XComponent > m_xFrame
sal_uInt16 nPageId
static bool insertItems(vcl::Window *pWindow, VclBuilder::stringmap &rMap, std::vector< std::unique_ptr< OUString > > &rUserData, const std::vector< ComboBoxTextItem > &rItems)
Insert items to a ComboBox or a ListBox.
Definition: builder.cxx:3553
std::map< OUString, std::shared_ptr< NoAutoUnloadModule > > ModuleMap
Definition: builder.cxx:1440
static ModuleMap g_aModuleMap
Definition: builder.cxx:1441
#define SAL_DLLPREFIX
Definition: builder.cxx:1448
static void thisModule()
Definition: builder.cxx:1427
static bool toBool(std::string_view rValue)
Definition: builder.cxx:92
static OUString GetUIRootDir()
Definition: dialog.cxx:557
const LocaleDataWrapper & GetLocaleDataWrapper() const
static weld::Window * GetFrameWeld(const css::uno::Reference< css::awt::XWindow > &rWindow)
Definition: builder.cxx:224
static std::unique_ptr< weld::Builder > CreateInterimBuilder(vcl::Window *pParent, const OUString &rUIFile, bool bAllowCycleFocusOut, sal_uInt64 nLOKWindowId=0)
Definition: builder.cxx:201
static const AllSettings & GetSettings()
Gets the application's settings.
Definition: svapp.cxx:761
static std::unique_ptr< weld::Builder > CreateBuilder(weld::Widget *pParent, const OUString &rUIFile, bool bMobile=false, sal_uInt64 nLOKWindowId=0)
Definition: builder.cxx:186
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage)
Definition: builder.cxx:215
void SetSmallSymbol()
Definition: button.cxx:533
void SetImageAlign(ImageAlign eAlign)
Definition: button.cxx:153
void SetCommandHandler(const OUString &aCommand, const css::uno::Reference< css::frame::XFrame > &rFrame)
Setup handler for UNO commands so that commands like .uno:Something are handled automagically by this...
Definition: button.cxx:119
void SetModeImage(const Image &rImage)
Definition: button.cxx:133
void EnableTriState(bool bTriState=true)
Definition: button.cxx:3617
void SetState(TriState eState)
Definition: button.cxx:3595
A widget used to choose from a list of items and which has an entry.
Definition: combobox.hxx:39
virtual void SetText(const OUString &rStr) override
Definition: ctrl.cxx:96
virtual Size GetOptimalSize() const override
Definition: ctrl.cxx:370
static void addKeyValue(SAL_UNUSED_PARAMETER const OUString &, SAL_UNUSED_PARAMETER const OUString &, SAL_UNUSED_PARAMETER tAddKeyHandling)
InitFlag
Definition: dialog.hxx:44
@ NoParent
No Parent.
@ Default
Use given parent or get a default one using GetDefaultParent(...)
void add_button(PushButton *pButton, int nResponse, bool bTransferOwnership)
Definition: dialog.cxx:1442
virtual void doDeferredInit(WinBits nBits)
Definition: dockwin.cxx:363
const Image & GetImage() const
Definition: fixed.hxx:171
static Image loadThemeImage(const OUString &rFileName)
Definition: fixed.cxx:956
void SetImage(const Image &rImage)
Definition: fixed.cxx:946
void set_mnemonic_widget(vcl::Window *pWindow)
Definition: fixed.cxx:406
void SetValue(double dVal)
Definition: fmtfield.cxx:856
virtual void SetMaxValue(double dMax)
Definition: fmtfield.cxx:713
virtual void SetMinValue(double dMin)
Definition: fmtfield.cxx:703
virtual void SetSpinSize(double dStep)
Definition: formatter.hxx:226
Definition: image.hxx:40
OUString GetStock() const
Definition: Image.cxx:81
Size GetSizePixel() const
Definition: Image.cxx:88
static std::unique_ptr< JSInstanceBuilder > CreateSidebarBuilder(weld::Widget *pParent, const OUString &rUIRoot, const OUString &rUIFile, sal_uInt64 nLOKWindowId=0)
static std::unique_ptr< JSInstanceBuilder > CreateNotebookbarBuilder(vcl::Window *pParent, const OUString &rUIRoot, const OUString &rUIFile, const css::uno::Reference< css::frame::XFrame > &rFrame, sal_uInt64 nWindowId=0)
static std::unique_ptr< JSInstanceBuilder > CreateFormulabarBuilder(vcl::Window *pParent, const OUString &rUIRoot, const OUString &rUIFile, sal_uInt64 nLOKWindowId)
static std::unique_ptr< JSInstanceBuilder > CreatePopupBuilder(weld::Widget *pParent, const OUString &rUIRoot, const OUString &rUIFile)
static std::unique_ptr< JSInstanceBuilder > CreateDialogBuilder(weld::Widget *pParent, const OUString &rUIRoot, const OUString &rUIFile)
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage)
A widget used to choose from a list of items and which has no entry.
Definition: lstbox.hxx:83
OUString getNum(sal_Int64 nNumber, sal_uInt16 nDecimals, bool bUseThousandSep=true, bool bTrailingZeros=true) const
const LanguageTag & getLanguageTag() const
void SetPopupMenu(PopupMenu *pNewMenu)
Definition: menubtn.cxx:241
Definition: menu.hxx:116
void set_id(const OUString &rID)
Sets an ID.
Definition: menu.hxx:393
void InsertSeparator(const OString &rIdent=OString(), sal_uInt16 nPos=MENU_APPEND)
Definition: menu.cxx:472
void InsertItem(sal_uInt16 nItemId, const OUString &rStr, MenuItemBits nItemBits=MenuItemBits::NONE, const OString &rIdent=OString(), sal_uInt16 nPos=MENU_APPEND)
Definition: menu.cxx:432
void SetAccessibleName(sal_uInt16 nItemId, const OUString &rStr)
Definition: menu.cxx:2273
void SetAccessibleDescription(sal_uInt16 nItemId, const OUString &rStr)
Definition: menu.cxx:2295
void SetAccelKey(sal_uInt16 nItemId, const vcl::KeyCode &rKeyCode)
Definition: menu.cxx:760
void SetTipHelpText(sal_uInt16 nItemId, const OUString &rString)
Definition: menu.cxx:1102
void SetItemCommand(sal_uInt16 nItemId, const OUString &rCommand)
Definition: menu.cxx:1029
void SetPopupMenu(sal_uInt16 nItemId, PopupMenu *pMenu)
Definition: menu.cxx:713
void HideItem(sal_uInt16 nItemId)
Definition: menu.hxx:288
sal_uInt16 GetItemCount() const
Definition: menu.cxx:577
void SetHelpId(sal_uInt16 nItemId, const OString &rHelpId)
Definition: menu.cxx:1120
void SetDropDown(PushButtonDropdownStyle nStyle)
Definition: button.cxx:1644
void SetSymbol(SymbolType eSymbol)
Definition: button.cxx:1630
std::shared_ptr< std::vector< VclPtr< RadioButton > > > m_xGroup
Definition: button.hxx:379
void group(RadioButton &rOther)
Definition: button.cxx:2274
void SetModeRadioImage(const Image &rImage)
Definition: button.cxx:2714
virtual std::unique_ptr< weld::Builder > CreateBuilder(weld::Widget *pParent, const OUString &rUIRoot, const OUString &rUIFile)
virtual weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage)
virtual std::unique_ptr< weld::Builder > CreateInterimBuilder(vcl::Window *pParent, const OUString &rUIRoot, const OUString &rUIFile, bool bAllowCycleFocusOut, sal_uInt64 nLOKWindowId=0)
virtual weld::Window * GetFrameWeld(const css::uno::Reference< css::awt::XWindow > &rWindow)
constexpr tools::Long Height() const
tools::Long AdjustHeight(tools::Long n)
tools::Long AdjustWidth(tools::Long n)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
HeaderBar * GetHeaderBar()
Definition: svtabbx.cxx:522
void SetSpaceBetweenEntries(short nSpace)
void SetEntryHeight(short nHeight)
void SetHighlightRange(sal_uInt16 nFirstTab=0, sal_uInt16 nLastTab=0xffff)
void SetNoAutoCurEntry(bool b)
void SetQuickSearch(bool bEnable)
virtual void doDeferredInit(WinBits nBits)
Definition: syswin.cxx:1111
sal_uInt16 GetPageCount() const
Definition: tabctrl.cxx:1789
void SetPageName(sal_uInt16 nPageId, const OString &rName) const
Definition: tabctrl.cxx:2009
void SetAccessibleDescription(sal_uInt16 nItemId, const OUString &rStr)
Definition: tabctrl.cxx:1993
void SetTabPage(sal_uInt16 nPageId, TabPage *pPage)
Definition: tabctrl.cxx:1895
void SetAccessibleName(sal_uInt16 nItemId, const OUString &rStr)
Definition: tabctrl.cxx:1977
TabPage * GetTabPage(sal_uInt16 nPageId) const
Definition: tabctrl.cxx:1921
void SetCurPageId(sal_uInt16 nPageId)
Definition: tabctrl.cxx:1831
void InsertPage(sal_uInt16 nPageId, const OUString &rText, sal_uInt16 nPos=TAB_APPEND)
Definition: tabctrl.cxx:1647
sal_uInt16 GetCurPageId() const
Definition: tabctrl.cxx:1865
sal_uInt16 GetPageId(sal_uInt16 nPos) const
Definition: tabctrl.cxx:1794
void SetHelpText(sal_uInt16 nPageId, const OUString &rText)
Definition: tabctrl.cxx:1961
void SetPageText(sal_uInt16 nPageId, const OUString &rText)
Definition: tabctrl.cxx:1931
void RemovePage(sal_uInt16 nPageId)
Definition: tabctrl.cxx:1697
A toolbar: contains all those icons, typically below the menu bar.
Definition: toolbox.hxx:74
ToolBoxItemId GetItemId(ImplToolItems::size_type nPos) const
Definition: toolbox2.cxx:746
void SetQuickHelpText(ToolBoxItemId nItemId, const OUString &rText)
Definition: toolbox2.cxx:1321
void InsertSeparator(ImplToolItems::size_type nPos=APPEND, sal_uInt16 nPixSize=0)
Definition: toolbox2.cxx:503
void SetHelpId(ToolBoxItemId nItemId, const OString &rHelpId)
Definition: toolbox2.cxx:1352
ImplToolItems::size_type GetItemCount() const
Definition: toolbox2.cxx:712
void SetItemExpand(ToolBoxItemId nItemId, bool bExpand)
Definition: toolbox2.cxx:914
void SetItemWindow(ToolBoxItemId nItemId, vcl::Window *pNewWindow)
Definition: toolbox2.cxx:1058
virtual void InsertItem(const OUString &rCommand, const css::uno::Reference< css::frame::XFrame > &rFrame, ToolBoxItemBits nBits, const Size &rRequestedSize, ImplToolItems::size_type nPos=APPEND)
Insert a command (like '.uno:Save').
Definition: toolbox2.cxx:440
void HideItem(ToolBoxItemId nItemId)
Convenience method to hide items (via ShowItem).
Definition: toolbox.hxx:396
void SetItemImage(ToolBoxItemId nItemId, const Image &rImage)
Definition: toolbox2.cxx:966
bool operator()(const vcl::Window *pA, const vcl::Window *pB) const
Definition: builder.cxx:2682
static OString getStyleClass(xmlreader::XmlReader &reader)
Definition: builder.cxx:3936
void handleListStore(xmlreader::XmlReader &reader, const OString &rID, std::string_view rClass)
Definition: builder.cxx:3034
stringmap m_aDeferredProperties
Definition: builder.hxx:126
static std::vector< vcl::EnumContext::Context > handleStyle(xmlreader::XmlReader &reader, int &nPriority)
Definition: builder.cxx:3881
void handleActionWidget(xmlreader::XmlReader &reader)
Definition: builder.cxx:4000
void connectNumericFormatterAdjustment(const OString &id, const OUString &rAdjustment)
Definition: builder.cxx:1266
VclBuilder(vcl::Window *pParent, const OUString &sUIRootDir, const OUString &sUIFile, OString sID=OString(), css::uno::Reference< css::frame::XFrame > xFrame=css::uno::Reference< css::frame::XFrame >(), bool bLegacy=true, const NotebookBarAddonsItem *pNotebookBarAddonsItem=nullptr)
Definition: builder.cxx:445
static vcl::Window * prepareWidgetOwnScrolling(vcl::Window *pParent, WinBits &rWinStyle)
Definition: builder.cxx:1396
void(* customMakeWidget)(VclPtr< vcl::Window > &rRet, const VclPtr< vcl::Window > &pParent, stringmap &rVec)
These functions create a new widget with parent pParent and return it in rRet.
Definition: builder.hxx:74
PackingData get_window_packing_data(const vcl::Window *pWindow) const
Definition: builder.cxx:4164
VclPtr< vcl::Window > m_pParent
Definition: builder.hxx:298
void mungeModel(ListBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId)
Definition: builder.cxx:4241
const TextBuffer * get_buffer_by_name(const OString &sID) const
Definition: builder.cxx:4198
OString m_sHelpRoot
Definition: builder.hxx:296
vcl::Window * get_widget_root()
Definition: builder.cxx:4058
css::uno::Reference< css::frame::XFrame > m_xFrame
XFrame to be able to extract labels and other properties of the UNO commands (like of ....
Definition: builder.hxx:321
VclPtr< vcl::Window > handleObject(vcl::Window *pParent, stringmap *pAtkProps, xmlreader::XmlReader &reader)
Definition: builder.cxx:3577
void extractGroup(const OString &id, stringmap &rVec)
Definition: builder.cxx:1252
void extractBuffer(const OString &id, stringmap &rVec)
Definition: builder.cxx:1353
static void applyAtkProperties(vcl::Window *pWindow, const stringmap &rProperties)
Definition: builder.cxx:3108
void extractButtonImage(const OString &id, stringmap &rMap, bool bRadio)
Definition: builder.cxx:1372
const Adjustment * get_adjustment_by_name(const OString &sID) const
Definition: builder.cxx:4206
void extractModel(const OString &id, stringmap &rVec)
Definition: builder.cxx:1342
static void collectAtkRelationAttribute(xmlreader::XmlReader &reader, stringmap &rMap)
Definition: builder.cxx:2910
bool m_bToplevelHasDeferredInit
Definition: builder.hxx:299
static void mungeTextBuffer(VclMultiLineEdit &rTarget, const TextBuffer &rTextBuffer)
Definition: builder.cxx:4412
void insertMenuObject(Menu *pParent, PopupMenu *pSubMenu, const OString &rClass, const OString &rID, stringmap &rProps, stringmap &rAtkProps, accelmap &rAccels)
Definition: builder.cxx:3463
VclPtr< vcl::Window > insertObject(vcl::Window *pParent, const OString &rClass, const OString &rID, stringmap &rProps, stringmap &rPangoAttributes, stringmap &rAtkProps)
Definition: builder.cxx:2479
std::vector< WinAndId > m_aChildren
Definition: builder.hxx:153
std::map< OString, OUString > stringmap
Definition: builder.hxx:71
bool m_bToplevelHasDeferredProperties
Definition: builder.hxx:300
void set_response(std::string_view sID, short nResponse)
Definition: builder.cxx:4085
void cleanupWidgetOwnScrolling(vcl::Window *pScrollParent, vcl::Window *pWindow, stringmap &rMap)
Definition: builder.cxx:1414
std::vector< std::unique_ptr< OUString > > m_aUserData
Definition: builder.hxx:119
ResHookProc m_pStringReplace
Definition: builder.hxx:297
bool m_bToplevelParentFound
Definition: builder.hxx:301
std::map< OString, std::pair< OString, OString > > accelmap
Definition: builder.hxx:72
static void collectAccelerator(xmlreader::XmlReader &reader, accelmap &rMap)
Definition: builder.cxx:4024
OString m_sID
Definition: builder.hxx:295
void set_window_packing_position(const vcl::Window *pWindow, sal_Int32 nPosition)
Definition: builder.cxx:4181
void collectProperty(xmlreader::XmlReader &reader, stringmap &rVec) const
Definition: builder.cxx:3954
static void collectAtkRoleAttribute(xmlreader::XmlReader &reader, stringmap &rMap)
Definition: builder.cxx:2939
T * get(VclPtr< T > &ret, const OString &sID)
Definition: builder.hxx:421
void extractMnemonicWidget(const OString &id, stringmap &rMap)
Definition: builder.cxx:1382
static int getImageSize(const stringmap &rMap)
Definition: builder.cxx:1363
std::vector< MenuAndId > m_aMenus
Definition: builder.hxx:161
vcl::Window * get_by_name(std::string_view sID)
Definition: builder.cxx:4063
std::unique_ptr< ParserState > m_pParserState
Definition: builder.hxx:303
static bool extractAdjustmentToMap(const OString &id, stringmap &rVec, std::vector< WidgetAdjustmentMap > &rAdjustmentMap)
Definition: builder.cxx:1278
OString get_by_window(const vcl::Window *pWindow) const
Definition: builder.cxx:4153
const ListStore * get_model_by_name(const OString &sID) const
Definition: builder.cxx:4190
stringmap handleAtkObject(xmlreader::XmlReader &reader) const
Definition: builder.cxx:3072
void handleRow(xmlreader::XmlReader &reader, const OString &rID)
Definition: builder.cxx:2959
void handleChild(vcl::Window *pParent, stringmap *pAtkProps, xmlreader::XmlReader &reader)
Definition: builder.cxx:2747
void handleMenuObject(Menu *pParent, xmlreader::XmlReader &reader)
Definition: builder.cxx:3282
void drop_ownership(const vcl::Window *pWindow)
Definition: builder.cxx:4145
void setDeferredProperties()
Definition: builder.cxx:2238
void handleSizeGroup(xmlreader::XmlReader &reader)
Definition: builder.cxx:3364
bool m_bLegacy
Definition: builder.hxx:302
void delete_by_window(vcl::Window *pWindow)
Definition: builder.cxx:4139
static void mungeAdjustment(NumericFormatter &rTarget, const Adjustment &rAdjustment)
Definition: builder.cxx:4298
stringmap Adjustment
Definition: builder.hxx:234
void applyPackingProperty(vcl::Window *pCurrent, vcl::Window *pParent, xmlreader::XmlReader &reader)
Definition: builder.cxx:3777
void disposeBuilder()
releases references and disposes all children.
Definition: builder.cxx:813
void delete_by_name(const OString &sID)
Definition: builder.cxx:4128
void handleTabChild(vcl::Window *pParent, xmlreader::XmlReader &reader)
Definition: builder.cxx:2561
static SymbolType mapStockToSymbol(std::u16string_view icon_name)
Definition: builder.cxx:126
void handleMenuChild(Menu *pParent, xmlreader::XmlReader &reader)
Definition: builder.cxx:3250
static void collectPangoAttribute(xmlreader::XmlReader &reader, stringmap &rMap)
Definition: builder.cxx:2884
VclPtr< Menu > handleMenu(xmlreader::XmlReader &reader, const OString &rID, bool bMenuBar)
Definition: builder.cxx:3197
void handlePacking(vcl::Window *pCurrent, vcl::Window *pParent, xmlreader::XmlReader &reader)
Definition: builder.cxx:3745
VclPtr< vcl::Window > makeObject(vcl::Window *pParent, const OString &rClass, const OString &rID, stringmap &rVec)
Definition: builder.cxx:1591
std::vector< ComboBoxTextItem > handleItems(xmlreader::XmlReader &reader) const
Definition: builder.cxx:3123
stringmap TextBuffer
Definition: builder.hxx:229
void connectFormattedFormatterAdjustment(const OString &id, const OUString &rAdjustment)
Definition: builder.cxx:1272
std::unique_ptr< NotebookBarAddonsItem > m_pNotebookBarAddonsItem
Definition: builder.hxx:128
PopupMenu * get_menu(std::string_view sID)
Definition: builder.cxx:4074
vcl::Window * get_label_widget()
Definition: layout.cxx:1516
A construction helper for a temporary VclPtr.
Definition: vclptr.hxx:276
void clear()
Definition: vclptr.hxx:190
reference_type * get() const
Get the body.
Definition: vclptr.hxx:143
static VclPtr< reference_type > Create(Arg &&... arg)
A construction helper for VclPtr.
Definition: vclptr.hxx:127
bool HasVisibleBorder() const
Definition: layout.hxx:493
void InsertPage(const OString &rPageId, const OUString &rLabel, const Image &rImage, const OUString &rTooltip, VclPtr< vcl::Window > xPage, int nPos=-1)
Definition: ivctrl.cxx:555
vcl::Window * GetPageParent()
bool mbDisabled
Definition: window.h:328
VclPtr< vcl::Window > mpRealParent
Definition: window.h:236
VclPtr< vcl::Window > mpBorderWindow
Definition: window.h:233
VclPtr< vcl::Window > mpParent
Definition: window.h:235
std::pair< const_iterator, bool > insert(Value &&x)
static OUString formatPercent(double dNumber, const LanguageTag &rLangTag)
static Context GetContextEnum(const OUString &rsContextName)
void SetStyle(WinBits nStyle)
Definition: window.cxx:1966
vcl::Window * GetParent() const
Definition: window2.cxx:1128
bool IsControlFont() const
Definition: window2.cxx:1098
void SetControlFont()
Definition: window2.cxx:433
WindowType GetType() const
Definition: window2.cxx:1005
void set_padding(sal_Int32 nPadding)
Definition: window2.cxx:1808
virtual void SetSizePixel(const Size &rNewSize)
Definition: window2.cxx:1293
Size get_preferred_size() const
Definition: window2.cxx:1699
vcl::Window * GetWindow(GetWindowType nType) const
Definition: stacking.cxx:1035
void set_border_width(sal_Int32 nBorderWidth)
Definition: window2.cxx:1874
void set_grid_left_attach(sal_Int32 nAttach)
Definition: window2.cxx:1844
Dialog * GetParentDialog() const
Definition: window2.cxx:1013
void set_height_request(sal_Int32 nHeightRequest)
Definition: window2.cxx:1649
void set_id(const OUString &rID)
Sets an ID.
Definition: window.cxx:3931
VclPackType get_pack_type() const
Definition: window2.cxx:1790
void reorderWithinParent(sal_uInt16 nNewPosition)
Definition: stacking.cxx:162
void set_grid_height(sal_Int32 nRows)
Definition: window2.cxx:1856
bool set_font_attribute(const OString &rKey, std::u16string_view rValue)
Definition: window2.cxx:1417
WinBits GetStyle() const
Definition: window2.cxx:984
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
Definition: window.cxx:2191
const OString & GetHelpId() const
Definition: window2.cxx:854
vcl::Font GetControlFont() const
Definition: window2.cxx:462
bool IsDialog() const
Definition: window2.cxx:1033
void set_pack_type(VclPackType ePackType)
Definition: window2.cxx:1796
bool get_secondary() const
Definition: window2.cxx:1962
SystemWindow * GetSystemWindow() const
Definition: stacking.cxx:806
void SetAccessibleRole(sal_uInt16 nRole)
bool IsDockingWindow() const
Definition: window2.cxx:937
SAL_DLLPRIVATE WindowImpl * ImplGetWindowImpl() const
Definition: window.hxx:528
void SetHelpId(const OString &)
Definition: window2.cxx:849
sal_Int32 get_height_request() const
Definition: window2.cxx:1950
void add_to_size_group(const std::shared_ptr< VclSizeGroup > &xGroup)
Definition: window2.cxx:1986
sal_Int32 get_grid_left_attach() const
Definition: window2.cxx:1838
sal_Int32 get_grid_top_attach() const
Definition: window2.cxx:1862
void set_width_request(sal_Int32 nWidthRequest)
Definition: window2.cxx:1663
bool IsSystemWindow() const
Definition: window2.cxx:1028
virtual Size GetSizePixel() const
Definition: window.cxx:2406
virtual bool set_property(const OString &rKey, const OUString &rValue)
Definition: window2.cxx:1483
sal_Int32 get_width_request() const
Definition: window2.cxx:1956
void set_secondary(bool bSecondary)
Definition: window2.cxx:1968
void set_expand(bool bExpand)
Definition: window2.cxx:1784
void set_grid_top_attach(sal_Int32 nAttach)
Definition: window2.cxx:1868
void SetQuickHelpText(const OUString &rHelpText)
Definition: window2.cxx:1257
virtual OUString GetText() const
Definition: window.cxx:3062
void set_fill(bool bFill)
Definition: window2.cxx:1820
void SetAccessibleRelationLabelFor(vcl::Window *pLabelFor)
vcl::Window * ImplGetWindow() const
if this is a proxy return the client, otherwise itself
Definition: window2.cxx:861
void set_non_homogeneous(bool bNonHomogeneous)
Definition: window2.cxx:1980
void SetType(WindowType nType)
Definition: window2.cxx:999
void set_grid_width(sal_Int32 nCols)
Definition: window2.cxx:1832
void SetAccessibleRelationLabeledBy(vcl::Window *pLabeledBy)
std::unique_ptr< Entry > m_xEntry
Definition: weld.hxx:1897
EntryTreeView(std::unique_ptr< Entry > xEntry, std::unique_ptr< TreeView > xTreeView)
Definition: builder.cxx:382
void set_height_request_by_rows(int nRows)
Definition: builder.cxx:401
std::unique_ptr< TreeView > m_xTreeView
Definition: weld.hxx:1898
void get_increments(int &step, int &page, FieldUnit eDestUnit) const
Definition: weld.hxx:2094
FieldUnit m_eSrcUnit
Definition: weld.hxx:1986
static OUString MetricToString(FieldUnit rUnit)
Definition: builder.cxx:231
void set_increments(int step, int page, FieldUnit eValueUnit)
Definition: weld.hxx:2087
void set_unit(FieldUnit eUnit)
Definition: builder.cxx:346
sal_Int64 ConvertValue(sal_Int64 nValue, FieldUnit eInUnit, FieldUnit eOutUnit) const
Definition: builder.cxx:361
void set_digits(unsigned int digits)
Definition: builder.cxx:335
void set_value(sal_Int64 nValue, FieldUnit eValueUnit)
Definition: weld.hxx:2029
OUString format_number(sal_Int64 nValue) const
Definition: builder.cxx:291
std::unique_ptr< weld::SpinButton > m_xSpinButton
Definition: weld.hxx:1987
sal_Int64 get_value(FieldUnit eDestUnit) const
Definition: weld.hxx:2034
sal_Int64 denormalize(sal_Int64 nValue) const
Definition: builder.cxx:274
virtual unsigned int get_digits() const =0
static unsigned int Power10(unsigned int n)
Definition: builder.cxx:266
virtual std::unique_ptr< TreeIter > make_iterator(const TreeIter *pOrig=nullptr) const =0
virtual bool get_row_expanded(const TreeIter &rIter) const =0
virtual bool get_iter_first(TreeIter &rIter) const =0
virtual bool iter_parent(TreeIter &rIter) const =0
virtual bool iter_next(TreeIter &rIter) const =0
virtual int iter_compare(const TreeIter &a, const TreeIter &b) const =0
virtual int get_iter_depth(const TreeIter &rIter) const =0
Result nextItem(Text reportText, Span *data, int *nsId)
bool nextAttribute(int *nsId, Span *localName)
Span getAttributeValue(bool fullyNormalize)
Any value
#define SAL_DLLEXTENSION
#define DBG_UNHANDLED_EXCEPTION(...)
float u
#define max(a, b)
FilterGroup & rTarget
FieldUnit
sal_Int16 nValue
TRISTATE_INDET
HeaderBarItemBits
Definition: headbar.hxx:181
#define WB_BUTTONSTYLE
Definition: headbar.hxx:177
const char sBorder[]
const char * name
sal_Int32 nIndex
sal_Int64 n
constexpr sal_uInt16 KEY_RETURN
Definition: keycodes.hxx:119
constexpr sal_uInt16 KEY_0
Definition: keycodes.hxx:45
constexpr sal_uInt16 KEY_LEFT
Definition: keycodes.hxx:112
constexpr sal_uInt16 KEY_UP
Definition: keycodes.hxx:111
constexpr sal_uInt16 KEY_F1
Definition: keycodes.hxx:83
constexpr sal_uInt16 KEY_A
Definition: keycodes.hxx:56
constexpr sal_uInt16 KEY_RIGHT
Definition: keycodes.hxx:113
constexpr sal_uInt16 KEY_DELETE
Definition: keycodes.hxx:125
constexpr sal_uInt16 KEY_DOWN
Definition: keycodes.hxx:110
constexpr sal_uInt16 KEY_INSERT
Definition: keycodes.hxx:124
constexpr sal_uInt16 KEY_MULTIPLY
Definition: keycodes.hxx:129
sal_uInt16 nPos
#define SAL_INFO_IF(condition, area, stream)
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
aStr
#define MNEMONIC_CHAR
Definition: mnemonic.hxx:48
void ensureDefaultWidthChars(VclBuilder::stringmap &rMap)
Definition: builder.cxx:2289
sal_Int16 getRoleFromName(const OString &roleName)
Definition: builder.cxx:2341
void set_properties(vcl::Window *pWindow, const VclBuilder::stringmap &rProps)
Definition: builder.cxx:2250
OUString convertMnemonicMarkup(std::u16string_view rIn)
Definition: builder.cxx:2260
bool extractDropdown(VclBuilder::stringmap &rMap)
Definition: builder.cxx:2297
OUString extractCustomProperty(VclBuilder::stringmap &rMap)
Definition: builder.cxx:2277
void reorderWithinParent(vcl::Window &rWindow, sal_uInt16 nNewPosition)
Definition: builder.cxx:2309
void MergeNotebookBarAddons(vcl::Window *pParent, const VclBuilder::customMakeWidget &pFunction, const css::uno::Reference< css::frame::XFrame > &m_xFrame, const NotebookBarAddonsItem &aNotebookBarAddonsItem, VclBuilder::stringmap &rMap)
void MergeNotebookBarMenuAddons(Menu *pPopupMenu, sal_Int16 nItemId, const OString &sItemIdName, NotebookBarAddonsItem &aNotebookBarAddonsItem)
ResHookProc GetReadStringHook()
std::locale Create(std::string_view aPrefixName, const LanguageTag &rLocale)
OUString get(TranslateId sContextAndId, const std::locale &loc)
int i
bool isInterimBuilderEnabledForNotebookbar(std::u16string_view rUIFile)
bool isBuilderEnabledForSidebar(std::u16string_view rUIFile)
bool isBuilderEnabled(std::u16string_view rUIFile, bool bMobile)
bool isBuilderEnabledForPopup(std::u16string_view rUIFile)
sal_uInt32 toUInt32(std::u16string_view str, sal_Int16 radix=10)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
@ eSymbol
Definition: ppdparser.hxx:44
SAL_DLLPUBLIC_EXPORT void makeNotebookbarToolBox(VclPtr< vcl::Window > &rRet, const VclPtr< vcl::Window > &pParent, VclBuilder::stringmap &rMap)
Sequence< beans::PropertyValue > GetCommandProperties(const OUString &rsCommandName, const OUString &rsModuleName)
Return a label for the given command.
OUString GetTooltipForCommand(const OUString &rsCommandName, const css::uno::Sequence< css::beans::PropertyValue > &rProperties, const Reference< frame::XFrame > &rxFrame)
OUString GetModuleIdentifier(const Reference< frame::XFrame > &rxFrame)
Image GetImageForCommand(const OUString &rsCommandName, const Reference< frame::XFrame > &rxFrame, vcl::ImageType eImageType)
OUString GetLabelForCommand(const css::uno::Sequence< css::beans::PropertyValue > &rProperties)
Return a label for the given command.
void VclBuilderPreload()
Pre-loads all modules containing UI information.
Definition: builder.cxx:1455
bool TextToValue(const OUString &rStr, double &rValue, sal_Int64 nBaseValue, sal_uInt16 nDecDigits, const LocaleDataWrapper &rLocaleDataWrapper, FieldUnit eUnit)
Definition: field.cxx:1201
sal_Int64 ConvertValue(sal_Int64 nValue, sal_Int64 mnBaseValue, sal_uInt16 nDecDigits, FieldUnit eInUnit, FieldUnit eOutUnit)
Definition: field.cxx:1030
IMPL_LINK_NOARG(HexColorControl, OnAsyncModifyHdl, void *, void)
size_t GetAbsPos(const weld::TreeView &rTreeView, const weld::TreeIter &rIter)
Definition: builder.cxx:407
bool IsEntryVisible(const weld::TreeView &rTreeView, const weld::TreeIter &rIter)
Definition: builder.cxx:425
IMPL_LINK(CustomWeld, DoResize, const Size &, rSize, void)
Definition: customweld.cxx:46
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
sal_Int16 nId
QPRO_FUNC_TYPE nType
SalInstance * mpDefInst
Definition: svdata.hxx:393
std::vector< row > m_aEntries
Definition: builder.hxx:221
std::vector< OUString > row
Definition: builder.hxx:220
MenuAndId(OString sId, Menu *pMenu)
Definition: builder.cxx:4433
std::vector< OString > m_aWidgets
Definition: builder.hxx:246
stringmap m_aProperties
Definition: builder.hxx:247
char const * begin
sal_Int32 length
Reference< XFrame > xFrame
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:76
const FieldUnitStringList & ImplGetFieldUnits()
Definition: svdata.cxx:265
std::vector< std::pair< OUString, FieldUnit > > FieldUnitStringList
Definition: svdata.hxx:275
#define SVLIBRARY(Base)
OUString aCommand
o3tl::strong_int< sal_uInt16, struct ToolBoxItemIdTag > ToolBoxItemId
Definition: toolboxid.hxx:14
#define SAL_MAX_INT32
#define SAL_MIN_INT32
Any result
OUString aLabel
OUString sId
SymbolType
Definition: vclenum.hxx:74