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
13#include <memory>
14#include <string_view>
15#include <unordered_map>
16#include <com/sun/star/accessibility/AccessibleRole.hpp>
17
18#include <comphelper/lok.hxx>
19#include <i18nutil/unicode.hxx>
20#include <jsdialog/enabled.hxx>
21#include <o3tl/string_view.hxx>
22#include <officecfg/Office/Common.hxx>
23#include <osl/module.hxx>
24#include <sal/log.hxx>
26#include <unotools/resmgr.hxx>
27#include <utility>
28#include <vcl/builder.hxx>
29#include <vcl/dialoghelper.hxx>
30#include <vcl/menu.hxx>
33#include <vcl/toolkit/edit.hxx>
34#include <vcl/toolkit/field.hxx>
35#include <vcl/fieldvalues.hxx>
37#include <vcl/toolkit/fixed.hxx>
39#include <vcl/headbar.hxx>
42#include <vcl/layout.hxx>
45#include <vcl/mnemonic.hxx>
48#include <vcl/split.hxx>
49#include <vcl/svapp.hxx>
51#include <vcl/tabctrl.hxx>
52#include <vcl/tabpage.hxx>
54#include <vcl/toolbox.hxx>
57#include <vcl/settings.hxx>
58#include <slider.hxx>
59#include <vcl/weld.hxx>
60#include <vcl/weldutils.hxx>
62#include <iconview.hxx>
63#include <svdata.hxx>
64#include <bitmaps.hlst>
65#include <managedmenubutton.hxx>
66#include <messagedialog.hxx>
67#include <ContextVBox.hxx>
68#include <DropdownBox.hxx>
69#include <IPrioritable.hxx>
70#include <OptionalBox.hxx>
72#include <PriorityHBox.hxx>
73#include <window.h>
76#include <calendar.hxx>
77#include <menutogglebutton.hxx>
78#include <salinst.hxx>
79#include <strings.hrc>
80#include <treeglue.hxx>
82#include <verticaltabctrl.hxx>
83#include <wizdlg.hxx>
84#include <tools/svlibrary.h>
86
87#if defined(DISABLE_DYNLOADING) || defined(LINUX)
88#include <dlfcn.h>
89#endif
90
91static bool toBool(std::string_view rValue)
92{
93 return (!rValue.empty() && (rValue[0] == 't' || rValue[0] == 'T' || rValue[0] == '1'));
94}
95
96namespace
97{
98 OUString mapStockToImageResource(std::u16string_view sType)
99 {
100 if (sType == u"view-refresh")
101 return SV_RESID_BITMAP_REFRESH;
102 else if (sType == u"dialog-error")
103 return IMG_ERROR;
104 else if (sType == u"list-add")
105 return IMG_ADD;
106 else if (sType == u"list-remove")
107 return IMG_REMOVE;
108 else if (sType == u"edit-copy")
109 return IMG_COPY;
110 else if (sType == u"edit-paste")
111 return IMG_PASTE;
112 else if (sType == u"document-open")
113 return IMG_OPEN;
114 else if (sType == u"open-menu-symbolic")
115 return IMG_MENU;
116 else if (sType == u"window-close-symbolic")
117 return SV_RESID_BITMAP_CLOSEDOC;
118 else if (sType == u"x-office-calendar")
119 return IMG_CALENDAR;
120 return OUString();
121 }
122
123}
124
125SymbolType VclBuilder::mapStockToSymbol(std::u16string_view sType)
126{
128 if (sType == u"media-skip-forward")
129 eRet = SymbolType::NEXT;
130 else if (sType == u"media-skip-backward")
131 eRet = SymbolType::PREV;
132 else if (sType == u"media-playback-start")
133 eRet = SymbolType::PLAY;
134 else if (sType == u"media-playback-stop")
135 eRet = SymbolType::STOP;
136 else if (sType == u"go-first")
137 eRet = SymbolType::FIRST;
138 else if (sType == u"go-last")
139 eRet = SymbolType::LAST;
140 else if (sType == u"go-previous")
142 else if (sType == u"go-next")
144 else if (sType == u"go-up")
146 else if (sType == u"go-down")
148 else if (sType == u"missing-image")
149 eRet = SymbolType::IMAGE;
150 else if (sType == u"help-browser" || sType == u"help-browser-symbolic")
151 eRet = SymbolType::HELP;
152 else if (sType == u"window-close")
153 eRet = SymbolType::CLOSE;
154 else if (sType == u"document-new")
155 eRet = SymbolType::PLUS;
156 else if (sType == u"pan-down-symbolic")
158 else if (sType == u"pan-up-symbolic")
159 eRet = SymbolType::SPIN_UP;
160 else if (!mapStockToImageResource(sType).isEmpty())
161 eRet = SymbolType::IMAGE;
162 return eRet;
163}
164
165namespace
166{
167 void setupFromActionName(Button *pButton, VclBuilder::stringmap &rMap, const css::uno::Reference<css::frame::XFrame>& rFrame);
168
169#if defined SAL_LOG_WARN
170 bool isButtonType(WindowType nType)
171 {
172 return nType == WindowType::PUSHBUTTON ||
180 }
181#endif
182
183}
184
185std::unique_ptr<weld::Builder> Application::CreateBuilder(weld::Widget* pParent, const OUString &rUIFile, bool bMobile, sal_uInt64 nLOKWindowId)
186{
188 {
190 return JSInstanceBuilder::CreateSidebarBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile, nLOKWindowId);
191 else if (jsdialog::isBuilderEnabledForPopup(rUIFile))
193 else if (jsdialog::isBuilderEnabled(rUIFile, bMobile))
195 }
196
197 return ImplGetSVData()->mpDefInst->CreateBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile);
198}
199
200std::unique_ptr<weld::Builder> Application::CreateInterimBuilder(vcl::Window* pParent, const OUString &rUIFile, bool bAllowCycleFocusOut, sal_uInt64 nLOKWindowId)
201{
203 {
204 // Notebookbar sub controls
206 return JSInstanceBuilder::CreateNotebookbarBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile, css::uno::Reference<css::frame::XFrame>(), nLOKWindowId);
207 else if (rUIFile == u"modules/scalc/ui/inputbar.ui")
208 return JSInstanceBuilder::CreateFormulabarBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile, nLOKWindowId);
209 }
210
211 return ImplGetSVData()->mpDefInst->CreateInterimBuilder(pParent, AllSettings::GetUIRootDir(), rUIFile, bAllowCycleFocusOut, nLOKWindowId);
212}
213
215 VclButtonsType eButtonType, const OUString& rPrimaryMessage,
216 bool /*bMobile*/)
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 if (aFind->second == "half")
1037 nBits = WB_FLATBUTTON | WB_BEVELBUTTON;
1038 else if (aFind->second == "none")
1039 nBits = WB_FLATBUTTON;
1040 rMap.erase(aFind);
1041 }
1042 return nBits;
1043 }
1044
1045 OUString extractLabel(VclBuilder::stringmap &rMap)
1046 {
1047 OUString sType;
1048 VclBuilder::stringmap::iterator aFind = rMap.find(OString("label"));
1049 if (aFind != rMap.end())
1050 {
1051 sType = aFind->second;
1052 rMap.erase(aFind);
1053 }
1054 return sType;
1055 }
1056
1057 OUString extractActionName(VclBuilder::stringmap &rMap)
1058 {
1059 OUString sActionName;
1060 VclBuilder::stringmap::iterator aFind = rMap.find(OString("action-name"));
1061 if (aFind != rMap.end())
1062 {
1063 sActionName = aFind->second;
1064 rMap.erase(aFind);
1065 }
1066 return sActionName;
1067 }
1068
1069 bool extractVisible(VclBuilder::stringmap &rMap)
1070 {
1071 bool bRet = false;
1072 VclBuilder::stringmap::iterator aFind = rMap.find(OString("visible"));
1073 if (aFind != rMap.end())
1074 {
1075 bRet = toBool(aFind->second);
1076 rMap.erase(aFind);
1077 }
1078 return bRet;
1079 }
1080
1081 Size extractSizeRequest(VclBuilder::stringmap &rMap)
1082 {
1083 OUString sWidthRequest("0");
1084 OUString sHeightRequest("0");
1085 VclBuilder::stringmap::iterator aFind = rMap.find(OString("width-request"));
1086 if (aFind != rMap.end())
1087 {
1088 sWidthRequest = aFind->second;
1089 rMap.erase(aFind);
1090 }
1091 aFind = rMap.find("height-request");
1092 if (aFind != rMap.end())
1093 {
1094 sHeightRequest = aFind->second;
1095 rMap.erase(aFind);
1096 }
1097 return Size(sWidthRequest.toInt32(), sHeightRequest.toInt32());
1098 }
1099
1100 OUString extractTooltipText(VclBuilder::stringmap &rMap)
1101 {
1102 OUString sTooltipText;
1103 VclBuilder::stringmap::iterator aFind = rMap.find(OString("tooltip-text"));
1104 if (aFind == rMap.end())
1105 aFind = rMap.find(OString("tooltip-markup"));
1106 if (aFind != rMap.end())
1107 {
1108 sTooltipText = aFind->second;
1109 rMap.erase(aFind);
1110 }
1111 return sTooltipText;
1112 }
1113
1114 float extractAlignment(VclBuilder::stringmap &rMap)
1115 {
1116 float f = 0.0;
1117 VclBuilder::stringmap::iterator aFind = rMap.find(OString("alignment"));
1118 if (aFind != rMap.end())
1119 {
1120 f = aFind->second.toFloat();
1121 rMap.erase(aFind);
1122 }
1123 return f;
1124 }
1125
1126 OUString extractTitle(VclBuilder::stringmap &rMap)
1127 {
1128 OUString sTitle;
1129 VclBuilder::stringmap::iterator aFind = rMap.find(OString("title"));
1130 if (aFind != rMap.end())
1131 {
1132 sTitle = aFind->second;
1133 rMap.erase(aFind);
1134 }
1135 return sTitle;
1136 }
1137
1138 bool extractHeadersVisible(VclBuilder::stringmap &rMap)
1139 {
1140 bool bHeadersVisible = true;
1141 VclBuilder::stringmap::iterator aFind = rMap.find(OString("headers-visible"));
1142 if (aFind != rMap.end())
1143 {
1144 bHeadersVisible = toBool(aFind->second);
1145 rMap.erase(aFind);
1146 }
1147 return bHeadersVisible;
1148 }
1149
1150 bool extractSortIndicator(VclBuilder::stringmap &rMap)
1151 {
1152 bool bSortIndicator = false;
1153 VclBuilder::stringmap::iterator aFind = rMap.find(OString("sort-indicator"));
1154 if (aFind != rMap.end())
1155 {
1156 bSortIndicator = toBool(aFind->second);
1157 rMap.erase(aFind);
1158 }
1159 return bSortIndicator;
1160 }
1161
1162 bool extractClickable(VclBuilder::stringmap &rMap)
1163 {
1164 bool bClickable = false;
1165 VclBuilder::stringmap::iterator aFind = rMap.find(OString("clickable"));
1166 if (aFind != rMap.end())
1167 {
1168 bClickable = toBool(aFind->second);
1169 rMap.erase(aFind);
1170 }
1171 return bClickable;
1172 }
1173
1174 void setupFromActionName(Button *pButton, VclBuilder::stringmap &rMap, const css::uno::Reference<css::frame::XFrame>& rFrame)
1175 {
1176 if (!rFrame.is())
1177 return;
1178
1179 OUString aCommand(extractActionName(rMap));
1180 if (aCommand.isEmpty())
1181 return;
1182
1183 OUString aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(rFrame));
1184 auto aProperties = vcl::CommandInfoProvider::GetCommandProperties(aCommand, aModuleName);
1186 if (!aLabel.isEmpty())
1187 pButton->SetText(aLabel);
1188
1189 OUString aTooltip(vcl::CommandInfoProvider::GetTooltipForCommand(aCommand, aProperties, rFrame));
1190 if (!aTooltip.isEmpty())
1191 pButton->SetQuickHelpText(aTooltip);
1192
1193 Image aImage(vcl::CommandInfoProvider::GetImageForCommand(aCommand, rFrame));
1194 pButton->SetModeImage(aImage);
1195
1196 pButton->SetCommandHandler(aCommand, rFrame);
1197 }
1198
1199 VclPtr<Button> extractStockAndBuildPushButton(vcl::Window *pParent, VclBuilder::stringmap &rMap, bool bToggle)
1200 {
1202 if (bToggle)
1203 nBits |= WB_TOGGLE;
1204
1205 nBits |= extractRelief(rMap);
1206
1207 VclPtr<Button> xWindow = VclPtr<PushButton>::Create(pParent, nBits);
1208 return xWindow;
1209 }
1210
1211 VclPtr<MenuButton> extractStockAndBuildMenuButton(vcl::Window *pParent, VclBuilder::stringmap &rMap)
1212 {
1214
1215 nBits |= extractRelief(rMap);
1216
1217 VclPtr<MenuButton> xWindow = VclPtr<MenuButton>::Create(pParent, nBits);
1218 return xWindow;
1219 }
1220
1221 VclPtr<MenuButton> extractStockAndBuildMenuToggleButton(vcl::Window *pParent, VclBuilder::stringmap &rMap)
1222 {
1224
1225 nBits |= extractRelief(rMap);
1226
1227 VclPtr<MenuButton> xWindow = VclPtr<MenuToggleButton>::Create(pParent, nBits);
1228 return xWindow;
1229 }
1230
1231 WinBits extractDeferredBits(VclBuilder::stringmap &rMap)
1232 {
1233 WinBits nBits = WB_3DLOOK|WB_HIDE;
1234 if (extractResizable(rMap))
1235 nBits |= WB_SIZEABLE;
1236 if (extractCloseable(rMap))
1237 nBits |= WB_CLOSEABLE;
1238 if (!extractDecorated(rMap))
1239 nBits |= WB_OWNERDRAWDECORATION;
1240 OUString sType(extractTypeHint(rMap));
1241 if (sType == "utility")
1243 else if (sType == "popup-menu")
1245 else if (sType == "dock")
1246 nBits |= WB_DOCKABLE | WB_MOVEABLE;
1247 else
1248 nBits |= WB_MOVEABLE;
1249 return nBits;
1250 }
1251}
1252
1253void VclBuilder::extractGroup(const OString &id, stringmap &rMap)
1254{
1255 VclBuilder::stringmap::iterator aFind = rMap.find(OString("group"));
1256 if (aFind != rMap.end())
1257 {
1258 OUString sID = aFind->second;
1259 sal_Int32 nDelim = sID.indexOf(':');
1260 if (nDelim != -1)
1261 sID = sID.copy(0, nDelim);
1262 m_pParserState->m_aGroupMaps.emplace_back(id, sID.toUtf8());
1263 rMap.erase(aFind);
1264 }
1265}
1266
1267void VclBuilder::connectNumericFormatterAdjustment(const OString &id, const OUString &rAdjustment)
1268{
1269 if (!rAdjustment.isEmpty())
1270 m_pParserState->m_aNumericFormatterAdjustmentMaps.emplace_back(id, rAdjustment);
1271}
1272
1273void VclBuilder::connectFormattedFormatterAdjustment(const OString &id, const OUString &rAdjustment)
1274{
1275 if (!rAdjustment.isEmpty())
1276 m_pParserState->m_aFormattedFormatterAdjustmentMaps.emplace_back(id, rAdjustment);
1277}
1278
1279bool VclBuilder::extractAdjustmentToMap(const OString& id, VclBuilder::stringmap& rMap, std::vector<WidgetAdjustmentMap>& rAdjustmentMap)
1280{
1281 VclBuilder::stringmap::iterator aFind = rMap.find(OString("adjustment"));
1282 if (aFind != rMap.end())
1283 {
1284 rAdjustmentMap.emplace_back(id, aFind->second);
1285 rMap.erase(aFind);
1286 return true;
1287 }
1288 return false;
1289}
1290
1291namespace
1292{
1293 sal_Int32 extractActive(VclBuilder::stringmap &rMap)
1294 {
1295 sal_Int32 nActiveId = 0;
1296 VclBuilder::stringmap::iterator aFind = rMap.find(OString("active"));
1297 if (aFind != rMap.end())
1298 {
1299 nActiveId = aFind->second.toInt32();
1300 rMap.erase(aFind);
1301 }
1302 return nActiveId;
1303 }
1304
1305 bool extractSelectable(VclBuilder::stringmap &rMap)
1306 {
1307 bool bSelectable = false;
1308 VclBuilder::stringmap::iterator aFind = rMap.find(OString("selectable"));
1309 if (aFind != rMap.end())
1310 {
1311 bSelectable = toBool(aFind->second);
1312 rMap.erase(aFind);
1313 }
1314 return bSelectable;
1315 }
1316
1317 OUString extractAdjustment(VclBuilder::stringmap &rMap)
1318 {
1319 OUString sAdjustment;
1320 VclBuilder::stringmap::iterator aFind = rMap.find(OString("adjustment"));
1321 if (aFind != rMap.end())
1322 {
1323 sAdjustment= aFind->second;
1324 rMap.erase(aFind);
1325 return sAdjustment;
1326 }
1327 return sAdjustment;
1328 }
1329
1330 bool extractDrawIndicator(VclBuilder::stringmap &rMap)
1331 {
1332 bool bDrawIndicator = false;
1333 VclBuilder::stringmap::iterator aFind = rMap.find(OString("draw-indicator"));
1334 if (aFind != rMap.end())
1335 {
1336 bDrawIndicator = toBool(aFind->second);
1337 rMap.erase(aFind);
1338 }
1339 return bDrawIndicator;
1340 }
1341}
1342
1343void VclBuilder::extractModel(const OString &id, stringmap &rMap)
1344{
1345 VclBuilder::stringmap::iterator aFind = rMap.find(OString("model"));
1346 if (aFind != rMap.end())
1347 {
1348 m_pParserState->m_aModelMaps.emplace_back(id, aFind->second,
1349 extractActive(rMap));
1350 rMap.erase(aFind);
1351 }
1352}
1353
1354void VclBuilder::extractBuffer(const OString &id, stringmap &rMap)
1355{
1356 VclBuilder::stringmap::iterator aFind = rMap.find(OString("buffer"));
1357 if (aFind != rMap.end())
1358 {
1359 m_pParserState->m_aTextBufferMaps.emplace_back(id, aFind->second);
1360 rMap.erase(aFind);
1361 }
1362}
1363
1365{
1366 int nSize = 4;
1367 auto aFind = rMap.find(OString("icon-size"));
1368 if (aFind != rMap.end())
1369 nSize = aFind->second.toInt32();
1370 return nSize;
1371}
1372
1373void VclBuilder::extractButtonImage(const OString &id, stringmap &rMap, bool bRadio)
1374{
1375 VclBuilder::stringmap::iterator aFind = rMap.find(OString("image"));
1376 if (aFind != rMap.end())
1377 {
1378 m_pParserState->m_aButtonImageWidgetMaps.emplace_back(id, aFind->second, bRadio);
1379 rMap.erase(aFind);
1380 }
1381}
1382
1383void VclBuilder::extractMnemonicWidget(const OString &rLabelID, stringmap &rMap)
1384{
1385 VclBuilder::stringmap::iterator aFind = rMap.find(OString("mnemonic-widget"));
1386 if (aFind != rMap.end())
1387 {
1388 OUString sID = aFind->second;
1389 sal_Int32 nDelim = sID.indexOf(':');
1390 if (nDelim != -1)
1391 sID = sID.copy(0, nDelim);
1392 m_pParserState->m_aMnemonicWidgetMaps.emplace_back(rLabelID, sID);
1393 rMap.erase(aFind);
1394 }
1395}
1396
1398{
1399 //For Widgets that manage their own scrolling, if one appears as a child of
1400 //a scrolling window shoehorn that scrolling settings to this widget and
1401 //return the real parent to use
1402 if (pParent && pParent->GetType() == WindowType::SCROLLWINDOW)
1403 {
1404 WinBits nScrollBits = pParent->GetStyle();
1406 rWinStyle |= nScrollBits;
1407 if (static_cast<VclScrolledWindow*>(pParent)->HasVisibleBorder())
1408 rWinStyle |= WB_BORDER;
1409 pParent = pParent->GetParent();
1410 }
1411
1412 return pParent;
1413}
1414
1416{
1417 //remove the redundant scrolling parent
1418 sal_Int32 nWidthReq = pScrollParent->get_width_request();
1419 rMap[OString("width-request")] = OUString::number(nWidthReq);
1420 sal_Int32 nHeightReq = pScrollParent->get_height_request();
1421 rMap[OString("height-request")] = OUString::number(nHeightReq);
1422
1423 m_pParserState->m_aRedundantParentWidgets[pScrollParent] = pWindow;
1424}
1425
1426#ifndef DISABLE_DYNLOADING
1427
1428extern "C" { static void thisModule() {} }
1429
1430namespace {
1431
1432// Don't unload the module on destruction
1433class NoAutoUnloadModule : public osl::Module
1434{
1435public:
1436 ~NoAutoUnloadModule() { release(); }
1437};
1438
1439}
1440
1441typedef std::map<OUString, std::shared_ptr<NoAutoUnloadModule>> ModuleMap;
1443
1444#if ENABLE_MERGELIBS
1445static std::shared_ptr<NoAutoUnloadModule> g_pMergedLib = std::make_shared<NoAutoUnloadModule>();
1446#endif
1447
1448#ifndef SAL_DLLPREFIX
1449# define SAL_DLLPREFIX ""
1450#endif
1451
1452#endif
1453
1454namespace vcl {
1455
1457{
1458#ifndef DISABLE_DYNLOADING
1459
1460#if ENABLE_MERGELIBS
1461 g_pMergedLib->loadRelative(&thisModule, SVLIBRARY("merged"));
1462#else
1463// find -name '*ui*' | xargs grep 'class=".*lo-' |
1464// sed 's/.*class="//' | sed 's/-.*$//' | sort | uniq
1465 static const char *aWidgetLibs[] = {
1466 "sfxlo", "svtlo"
1467 };
1468 for (const auto & lib : aWidgetLibs)
1469 {
1470 std::unique_ptr<NoAutoUnloadModule> pModule(new NoAutoUnloadModule);
1471 OUString sModule = SAL_DLLPREFIX + OUString::createFromAscii(lib) + SAL_DLLEXTENSION;
1472 if (pModule->loadRelative(&thisModule, sModule))
1473 g_aModuleMap.insert(std::make_pair(sModule, std::move(pModule)));
1474 }
1475#endif // ENABLE_MERGELIBS
1476#endif // DISABLE_DYNLOADING
1477}
1478
1479}
1480
1481#if defined DISABLE_DYNLOADING && !HAVE_FEATURE_DESKTOP
1482extern "C" VclBuilder::customMakeWidget lo_get_custom_widget_func(const char* name);
1483#endif
1484
1485namespace
1486{
1487// Takes a string like "sfxlo-NotebookbarToolBox"
1488VclBuilder::customMakeWidget GetCustomMakeWidget(const OString& rName)
1489{
1490 const OString name = rName == "sfxlo-SidebarToolBox" ? "sfxlo-NotebookbarToolBox" : rName;
1491 VclBuilder::customMakeWidget pFunction = nullptr;
1492 if (sal_Int32 nDelim = name.indexOf('-'); nDelim != -1)
1493 {
1494 const OString aFunction(OString::Concat("make") + name.subView(nDelim + 1));
1495 const OUString sFunction(OStringToOUString(aFunction, RTL_TEXTENCODING_UTF8));
1496
1497#ifndef DISABLE_DYNLOADING
1498 const OUString sModule = SAL_DLLPREFIX
1499 + OStringToOUString(name.subView(0, nDelim), RTL_TEXTENCODING_UTF8)
1501 ModuleMap::iterator aI = g_aModuleMap.find(sModule);
1502 if (aI == g_aModuleMap.end())
1503 {
1504 std::shared_ptr<NoAutoUnloadModule> pModule;
1505#if ENABLE_MERGELIBS
1506 if (!g_pMergedLib->is())
1507 g_pMergedLib->loadRelative(&thisModule, SVLIBRARY("merged"));
1508 if ((pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(
1509 g_pMergedLib->getFunctionSymbol(sFunction))))
1510 pModule = g_pMergedLib;
1511#endif
1512 if (!pFunction)
1513 {
1514 pModule = std::make_shared<NoAutoUnloadModule>();
1515 bool ok = pModule->loadRelative(&thisModule, sModule);
1516 if (!ok)
1517 {
1518#ifdef LINUX
1519 // in the case of preloading, we don't have eg. the
1520 // libcuilo.so, but still need to dlsym the symbols -
1521 // which are already in-process
1523 {
1524 pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(dlsym(RTLD_DEFAULT, aFunction.getStr()));
1525 ok = !!pFunction;
1526 assert(ok && "couldn't even directly dlsym the sFunction (available via preload)");
1527 }
1528#endif
1529 assert(ok && "bad module name in .ui");
1530 }
1531 else
1532 {
1533 pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(
1534 pModule->getFunctionSymbol(sFunction));
1535 }
1536 }
1537 g_aModuleMap.insert(std::make_pair(sModule, pModule));
1538 }
1539 else
1540 pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(
1541 aI->second->getFunctionSymbol(sFunction));
1542#elif !HAVE_FEATURE_DESKTOP
1543 pFunction = lo_get_custom_widget_func(sFunction.toUtf8().getStr());
1544 SAL_WARN_IF(!pFunction, "vcl.builder", "Could not find " << sFunction);
1545 assert(pFunction);
1546#else
1547 pFunction = reinterpret_cast<VclBuilder::customMakeWidget>(
1548 osl_getFunctionSymbol((oslModule)RTLD_DEFAULT, sFunction.pData));
1549#endif
1550 }
1551 return pFunction;
1552}
1553}
1554
1555VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString &name, const OString &id,
1556 stringmap &rMap)
1557{
1558 bool bIsPlaceHolder = name.isEmpty();
1559 bool bVertical = false;
1560
1561 if (pParent && (pParent->GetType() == WindowType::TABCONTROL ||
1563 {
1564 bool bTopLevel(name == "GtkDialog" || name == "GtkMessageDialog" ||
1565 name == "GtkWindow" || name == "GtkPopover" || name == "GtkAssistant");
1566 if (!bTopLevel)
1567 {
1568 if (pParent->GetType() == WindowType::TABCONTROL)
1569 {
1570 //We have to add a page
1571 //make default pageid == position
1572 TabControl *pTabControl = static_cast<TabControl*>(pParent);
1573 sal_uInt16 nNewPageCount = pTabControl->GetPageCount()+1;
1574 sal_uInt16 nNewPageId = nNewPageCount;
1575 pTabControl->InsertPage(nNewPageId, OUString());
1576 pTabControl->SetCurPageId(nNewPageId);
1577 SAL_WARN_IF(bIsPlaceHolder, "vcl.builder", "we should have no placeholders for tabpages");
1578 if (!bIsPlaceHolder)
1579 {
1580 VclPtrInstance<TabPage> pPage(pTabControl);
1581 pPage->Show();
1582
1583 //Make up a name for it
1584 OString sTabPageId = get_by_window(pParent) +
1585 "-page" +
1586 OString::number(nNewPageCount);
1587 m_aChildren.emplace_back(sTabPageId, pPage, false);
1588 pPage->SetHelpId(m_sHelpRoot + sTabPageId);
1589
1590 pParent = pPage;
1591
1592 pTabControl->SetTabPage(nNewPageId, pPage);
1593 }
1594 }
1595 else
1596 {
1597 VerticalTabControl *pTabControl = static_cast<VerticalTabControl*>(pParent);
1598 SAL_WARN_IF(bIsPlaceHolder, "vcl.builder", "we should have no placeholders for tabpages");
1599 if (!bIsPlaceHolder)
1600 pParent = pTabControl->GetPageParent();
1601 }
1602 }
1603 }
1604
1605 if (bIsPlaceHolder || name == "GtkTreeSelection")
1606 return nullptr;
1607
1608 ToolBox *pToolBox = (pParent && pParent->GetType() == WindowType::TOOLBOX) ? static_cast<ToolBox*>(pParent) : nullptr;
1609
1610 extractButtonImage(id, rMap, name == "GtkRadioButton");
1611
1612 VclPtr<vcl::Window> xWindow;
1613 if (name == "GtkDialog" || name == "GtkAssistant")
1614 {
1615 // WB_ALLOWMENUBAR because we don't know in advance if we will encounter
1616 // a menubar, and menubars need a BorderWindow in the toplevel, and
1617 // such border windows need to be in created during the dialog ctor
1619 if (extractResizable(rMap))
1620 nBits |= WB_SIZEABLE;
1621 if (extractCloseable(rMap))
1622 nBits |= WB_CLOSEABLE;
1624 if (name == "GtkAssistant")
1625 xWindow = VclPtr<vcl::RoadmapWizard>::Create(pParent, nBits, eInit);
1626 else
1627 xWindow = VclPtr<Dialog>::Create(pParent, nBits, eInit);
1628#if HAVE_FEATURE_DESKTOP
1629 if (!extractModal(rMap))
1631#endif
1632 }
1633 else if (name == "GtkMessageDialog")
1634 {
1636 if (extractResizable(rMap))
1637 nBits |= WB_SIZEABLE;
1639 m_pParserState->m_aMessageDialogs.push_back(xDialog);
1640 xWindow = xDialog;
1641#if defined _WIN32
1642 xWindow->set_border_width(3);
1643#else
1644 xWindow->set_border_width(12);
1645#endif
1646 }
1647 else if (name == "GtkBox" || name == "GtkStatusbar")
1648 {
1649 bVertical = extractOrientation(rMap);
1650 if (bVertical)
1651 xWindow = VclPtr<VclVBox>::Create(pParent);
1652 else
1653 xWindow = VclPtr<VclHBox>::Create(pParent);
1654 }
1655 else if (name == "GtkPaned")
1656 {
1657 bVertical = extractOrientation(rMap);
1658 if (bVertical)
1659 xWindow = VclPtr<VclVPaned>::Create(pParent);
1660 else
1661 xWindow = VclPtr<VclHPaned>::Create(pParent);
1662 }
1663 else if (name == "GtkHBox")
1664 xWindow = VclPtr<VclHBox>::Create(pParent);
1665 else if (name == "GtkVBox")
1666 xWindow = VclPtr<VclVBox>::Create(pParent);
1667 else if (name == "GtkButtonBox")
1668 {
1669 bVertical = extractOrientation(rMap);
1670 if (bVertical)
1671 xWindow = VclPtr<VclVButtonBox>::Create(pParent);
1672 else
1673 xWindow = VclPtr<VclHButtonBox>::Create(pParent);
1674 }
1675 else if (name == "GtkHButtonBox")
1676 xWindow = VclPtr<VclHButtonBox>::Create(pParent);
1677 else if (name == "GtkVButtonBox")
1678 xWindow = VclPtr<VclVButtonBox>::Create(pParent);
1679 else if (name == "GtkGrid")
1680 xWindow = VclPtr<VclGrid>::Create(pParent);
1681 else if (name == "GtkFrame")
1682 xWindow = VclPtr<VclFrame>::Create(pParent);
1683 else if (name == "GtkExpander")
1684 {
1685 VclPtrInstance<VclExpander> pExpander(pParent);
1686 m_pParserState->m_aExpanderWidgets.push_back(pExpander);
1687 xWindow = pExpander;
1688 }
1689 else if (name == "GtkButton" || (!m_bLegacy && name == "GtkToggleButton"))
1690 {
1691 VclPtr<Button> xButton;
1692 OUString sMenu = BuilderUtils::extractCustomProperty(rMap);
1693 if (sMenu.isEmpty())
1694 xButton = extractStockAndBuildPushButton(pParent, rMap, name == "GtkToggleButton");
1695 else
1696 {
1697 assert(m_bLegacy && "use GtkMenuButton");
1698 xButton = extractStockAndBuildMenuButton(pParent, rMap);
1699 m_pParserState->m_aButtonMenuMaps.emplace_back(id, sMenu);
1700 }
1701 xButton->SetImageAlign(ImageAlign::Left); //default to left
1702 setupFromActionName(xButton, rMap, m_xFrame);
1703 xWindow = xButton;
1704 }
1705 else if (name == "GtkMenuButton")
1706 {
1707 VclPtr<MenuButton> xButton;
1708
1709 OUString sMenu = extractPopupMenu(rMap);
1710 if (!sMenu.isEmpty())
1711 m_pParserState->m_aButtonMenuMaps.emplace_back(id, sMenu);
1712
1713 OUString sType = extractWidgetName(rMap);
1714 if (sType.isEmpty())
1715 {
1716 xButton = extractStockAndBuildMenuButton(pParent, rMap);
1717 xButton->SetAccessibleRole(css::accessibility::AccessibleRole::BUTTON_MENU);
1718 }
1719 else
1720 {
1721 xButton = extractStockAndBuildMenuToggleButton(pParent, rMap);
1722 }
1723
1724 xButton->SetImageAlign(ImageAlign::Left); //default to left
1725
1726 if (!extractDrawIndicator(rMap))
1728
1729 setupFromActionName(xButton, rMap, m_xFrame);
1730 xWindow = xButton;
1731 }
1732 else if (name == "GtkToggleButton" && m_bLegacy)
1733 {
1734 VclPtr<Button> xButton;
1735 OUString sMenu = BuilderUtils::extractCustomProperty(rMap);
1736 assert(sMenu.getLength() && "not implemented yet");
1737 xButton = extractStockAndBuildMenuToggleButton(pParent, rMap);
1738 m_pParserState->m_aButtonMenuMaps.emplace_back(id, sMenu);
1739 xButton->SetImageAlign(ImageAlign::Left); //default to left
1740 setupFromActionName(xButton, rMap, m_xFrame);
1741 xWindow = xButton;
1742 }
1743 else if (name == "GtkRadioButton")
1744 {
1745 extractGroup(id, rMap);
1747 VclPtr<RadioButton> xButton = VclPtr<RadioButton>::Create(pParent, true, nBits);
1748 xButton->SetImageAlign(ImageAlign::Left); //default to left
1749 xWindow = xButton;
1750 }
1751 else if (name == "GtkCheckButton")
1752 {
1754 bool bIsTriState = extractInconsistent(rMap);
1755 VclPtr<CheckBox> xCheckBox = VclPtr<CheckBox>::Create(pParent, nBits);
1756 if (bIsTriState)
1757 {
1758 xCheckBox->EnableTriState(true);
1759 xCheckBox->SetState(TRISTATE_INDET);
1760 }
1761 xCheckBox->SetImageAlign(ImageAlign::Left); //default to left
1762
1763 xWindow = xCheckBox;
1764 }
1765 else if (name == "GtkSpinButton")
1766 {
1767 OUString sAdjustment = extractAdjustment(rMap);
1768
1770 if (extractHasFrame(rMap))
1771 nBits |= WB_BORDER;
1772
1773 connectFormattedFormatterAdjustment(id, sAdjustment);
1774 VclPtrInstance<FormattedField> xField(pParent, nBits);
1775 xField->GetFormatter().SetMinValue(0);
1776 xWindow = xField;
1777 }
1778 else if (name == "GtkLinkButton")
1780 else if (name == "GtkComboBox" || name == "GtkComboBoxText")
1781 {
1782 extractModel(id, rMap);
1783
1785
1786 bool bDropdown = BuilderUtils::extractDropdown(rMap);
1787
1788 if (bDropdown)
1789 nBits |= WB_DROPDOWN;
1790
1791 if (extractEntry(rMap))
1792 {
1793 VclPtrInstance<ComboBox> xComboBox(pParent, nBits);
1794 xComboBox->EnableAutoSize(true);
1795 xWindow = xComboBox;
1796 }
1797 else
1798 {
1799 VclPtrInstance<ListBox> xListBox(pParent, nBits|WB_SIMPLEMODE);
1800 xListBox->EnableAutoSize(true);
1801 xWindow = xListBox;
1802 }
1803 }
1804 else if (name == "VclOptionalBox" || name == "sfxlo-OptionalBox")
1805 {
1806 // tdf#135495 fallback sfxlo-OptionalBox to VclOptionalBox as a stopgap
1807 xWindow = VclPtr<OptionalBox>::Create(pParent);
1808 }
1809 else if (name == "svtlo-ManagedMenuButton")
1810 {
1811 // like tdf#135495 keep the name svtlo-ManagedMenuButton even though it's a misnomer
1812 // and is not dlsymed from the svt library
1814 OUString sMenu = BuilderUtils::extractCustomProperty(rMap);
1815 if (!sMenu.isEmpty())
1816 m_pParserState->m_aButtonMenuMaps.emplace_back(id, sMenu);
1817 setupFromActionName(static_cast<Button*>(xWindow.get()), rMap, m_xFrame);
1818 }
1819 else if (name == "sfxlo-PriorityMergedHBox")
1820 {
1821 // like tdf#135495 above, keep the sfxlo-PriorityMergedHBox even though its not in sfx anymore
1822 xWindow = VclPtr<PriorityMergedHBox>::Create(pParent);
1823 }
1824 else if (name == "sfxlo-PriorityHBox")
1825 {
1826 // like tdf#135495 above, keep the sfxlo-PriorityMergedHBox even though its not in sfx anymore
1827 xWindow = VclPtr<PriorityHBox>::Create(pParent);
1828 }
1829 else if (name == "sfxlo-DropdownBox")
1830 {
1831 // like tdf#135495 above, keep the sfxlo-PriorityMergedHBox even though its not in sfx anymore
1832 xWindow = VclPtr<DropdownBox>::Create(pParent);
1833 }
1834 else if (name == "sfxlo-ContextVBox")
1835 {
1836 // like tdf#135495 above, keep the sfxlo-PriorityMergedHBox even though its not in sfx anymore
1837 xWindow = VclPtr<ContextVBox>::Create(pParent);
1838 }
1839 else if (name == "GtkIconView")
1840 {
1841 assert(rMap.find(OString("model")) != rMap.end() && "GtkIconView must have a model");
1842
1843 //window we want to apply the packing props for this GtkIconView to
1844 VclPtr<vcl::Window> xWindowForPackingProps;
1845 extractModel(id, rMap);
1847 //IconView manages its own scrolling,
1848 vcl::Window *pRealParent = prepareWidgetOwnScrolling(pParent, nWinStyle);
1849
1850 VclPtr<IconView> xBox = VclPtr<IconView>::Create(pRealParent, nWinStyle);
1851 xWindowForPackingProps = xBox;
1852
1853 xWindow = xBox;
1854 xBox->SetNoAutoCurEntry(true);
1855 xBox->SetQuickSearch(true);
1856
1857 if (pRealParent != pParent)
1858 cleanupWidgetOwnScrolling(pParent, xWindowForPackingProps, rMap);
1859 }
1860 else if (name == "GtkTreeView")
1861 {
1862 if (!m_bLegacy)
1863 {
1864 assert(rMap.find(OString("model")) != rMap.end() && "GtkTreeView must have a model");
1865 }
1866
1867 //window we want to apply the packing props for this GtkTreeView to
1868 VclPtr<vcl::Window> xWindowForPackingProps;
1869 //To-Do
1870 //a) make SvHeaderTabListBox/SvTabListBox the default target for GtkTreeView
1871 //b) remove the non-drop down mode of ListBox and convert
1872 // everything over to SvHeaderTabListBox/SvTabListBox
1873 extractModel(id, rMap);
1875 if (m_bLegacy)
1876 {
1878 if (!sBorder.isEmpty())
1879 nWinStyle |= WB_BORDER;
1880 }
1881 else
1882 {
1883 nWinStyle |= WB_HASBUTTONS | WB_HASBUTTONSATROOT;
1884 }
1885 //ListBox/SvHeaderTabListBox manages its own scrolling,
1886 vcl::Window *pRealParent = prepareWidgetOwnScrolling(pParent, nWinStyle);
1887 if (m_bLegacy)
1888 {
1889 xWindow = VclPtr<ListBox>::Create(pRealParent, nWinStyle | WB_SIMPLEMODE);
1890 xWindowForPackingProps = xWindow;
1891 }
1892 else
1893 {
1895 bool bHeadersVisible = extractHeadersVisible(rMap);
1896 if (bHeadersVisible)
1897 {
1898 VclPtr<VclVBox> xContainer = VclPtr<VclVBox>::Create(pRealParent);
1899 OString containerid(id + "-container");
1900 xContainer->SetHelpId(m_sHelpRoot + containerid);
1901 m_aChildren.emplace_back(containerid, xContainer, true);
1902
1904 xHeader->set_width_request(0); // let the headerbar width not affect the size request
1905 OString headerid(id + "-header");
1906 xHeader->SetHelpId(m_sHelpRoot + headerid);
1907 m_aChildren.emplace_back(headerid, xHeader, true);
1908
1909 VclPtr<LclHeaderTabListBox> xHeaderBox = VclPtr<LclHeaderTabListBox>::Create(xContainer, nWinStyle);
1910 xHeaderBox->InitHeaderBar(xHeader);
1911 xContainer->set_expand(true);
1912 xHeader->Show();
1913 xContainer->Show();
1914 xBox = xHeaderBox;
1915 xWindowForPackingProps = xContainer;
1916 }
1917 else
1918 {
1919 xBox = VclPtr<LclTabListBox>::Create(pRealParent, nWinStyle);
1920 xWindowForPackingProps = xBox;
1921 }
1922 xWindow = xBox;
1923 xBox->SetNoAutoCurEntry(true);
1924 xBox->SetQuickSearch(true);
1925 xBox->SetSpaceBetweenEntries(3);
1926 xBox->SetEntryHeight(16);
1927 xBox->SetHighlightRange(); // select over the whole width
1928 }
1929 if (pRealParent != pParent)
1930 cleanupWidgetOwnScrolling(pParent, xWindowForPackingProps, rMap);
1931 }
1932 else if (name == "GtkTreeViewColumn")
1933 {
1934 if (!m_bLegacy)
1935 {
1936 SvHeaderTabListBox* pTreeView = dynamic_cast<SvHeaderTabListBox*>(pParent);
1937 if (HeaderBar* pHeaderBar = pTreeView ? pTreeView->GetHeaderBar() : nullptr)
1938 {
1940 if (extractClickable(rMap))
1942 if (extractSortIndicator(rMap))
1944 float fAlign = extractAlignment(rMap);
1945 if (fAlign == 0.0)
1946 nBits |= HeaderBarItemBits::LEFT;
1947 else if (fAlign == 1.0)
1948 nBits |= HeaderBarItemBits::RIGHT;
1949 else if (fAlign == 0.5)
1951 auto nItemId = pHeaderBar->GetItemCount() + 1;
1952 OUString sTitle(extractTitle(rMap));
1953 pHeaderBar->InsertItem(nItemId, sTitle, 100, nBits);
1954 }
1955 }
1956 }
1957 else if (name == "GtkLabel")
1958 {
1960 extractMnemonicWidget(id, rMap);
1961 if (extractSelectable(rMap))
1962 xWindow = VclPtr<SelectableFixedText>::Create(pParent, nWinStyle);
1963 else
1964 xWindow = VclPtr<FixedText>::Create(pParent, nWinStyle);
1965 }
1966 else if (name == "GtkImage")
1967 {
1969 OUString sIconName = extractIconName(rMap);
1970 if (!sIconName.isEmpty())
1971 xFixedImage->SetImage(FixedImage::loadThemeImage(sIconName));
1972 m_pParserState->m_aImageSizeMap[id] = getImageSize(rMap);
1973 xWindow = xFixedImage;
1974 //such parentless GtkImages are temps used to set icons on buttons
1975 //default them to hidden to stop e.g. insert->index entry flicking temp
1976 //full screen windows
1977 if (!pParent)
1978 {
1979 rMap["visible"] = "false";
1980 }
1981 }
1982 else if (name == "GtkSeparator")
1983 {
1984 bVertical = extractOrientation(rMap);
1985 xWindow = VclPtr<FixedLine>::Create(pParent, bVertical ? WB_VERT : WB_HORZ);
1986 }
1987 else if (name == "GtkScrollbar")
1988 {
1989 extractAdjustmentToMap(id, rMap, m_pParserState->m_aScrollAdjustmentMaps);
1990 bVertical = extractOrientation(rMap);
1991 xWindow = VclPtr<ScrollBar>::Create(pParent, bVertical ? WB_VERT : WB_HORZ);
1992 }
1993 else if (name == "GtkProgressBar")
1994 {
1995 extractAdjustmentToMap(id, rMap, m_pParserState->m_aScrollAdjustmentMaps);
1996 bVertical = extractOrientation(rMap);
1997 xWindow = VclPtr<ProgressBar>::Create(pParent, bVertical ? WB_VERT : WB_HORZ);
1998 }
1999 else if (name == "GtkScrolledWindow")
2000 {
2001 xWindow = VclPtr<VclScrolledWindow>::Create(pParent);
2002 }
2003 else if (name == "GtkViewport")
2004 {
2005 xWindow = VclPtr<VclViewport>::Create(pParent);
2006 }
2007 else if (name == "GtkEventBox")
2008 {
2009 xWindow = VclPtr<VclEventBox>::Create(pParent);
2010 }
2011 else if (name == "GtkEntry")
2012 {
2013 WinBits nWinStyle = WB_LEFT|WB_VCENTER|WB_3DLOOK;
2014 if (extractHasFrame(rMap))
2015 nWinStyle |= WB_BORDER;
2016 xWindow = VclPtr<Edit>::Create(pParent, nWinStyle);
2018 }
2019 else if (name == "GtkNotebook")
2020 {
2021 if (!extractVerticalTabPos(rMap))
2023 else
2024 xWindow = VclPtr<VerticalTabControl>::Create(pParent);
2025 }
2026 else if (name == "GtkDrawingArea")
2027 {
2028 xWindow = VclPtr<VclDrawingArea>::Create(pParent, WB_TABSTOP);
2029 }
2030 else if (name == "GtkTextView")
2031 {
2032 extractBuffer(id, rMap);
2033
2034 WinBits nWinStyle = WB_CLIPCHILDREN|WB_LEFT;
2035 //VclMultiLineEdit manages its own scrolling,
2036 vcl::Window *pRealParent = prepareWidgetOwnScrolling(pParent, nWinStyle);
2037 xWindow = VclPtr<VclMultiLineEdit>::Create(pRealParent, nWinStyle);
2038 if (pRealParent != pParent)
2039 cleanupWidgetOwnScrolling(pParent, xWindow, rMap);
2040 }
2041 else if (name == "GtkSpinner")
2042 {
2043 xWindow = VclPtr<Throbber>::Create(pParent, WB_3DLOOK);
2044 }
2045 else if (name == "GtkScale")
2046 {
2047 extractAdjustmentToMap(id, rMap, m_pParserState->m_aSliderAdjustmentMaps);
2048 bool bDrawValue = extractDrawValue(rMap);
2049 if (bDrawValue)
2050 {
2051 OUString sValuePos = extractValuePos(rMap);
2052 (void)sValuePos;
2053 }
2054 bVertical = extractOrientation(rMap);
2055
2056 WinBits nWinStyle = bVertical ? WB_VERT : WB_HORZ;
2057
2058 xWindow = VclPtr<Slider>::Create(pParent, nWinStyle);
2059 }
2060 else if (name == "GtkToolbar")
2061 {
2062 xWindow = VclPtr<ToolBox>::Create(pParent, WB_3DLOOK | WB_TABSTOP);
2063 }
2064 else if(name == "NotebookBarAddonsToolMergePoint")
2065 {
2066 customMakeWidget pFunction = GetCustomMakeWidget("sfxlo-NotebookbarToolBox");
2067 if(pFunction != nullptr)
2069 return nullptr;
2070 }
2071 else if (name == "GtkToolButton" || name == "GtkMenuToolButton" ||
2072 name == "GtkToggleToolButton" || name == "GtkRadioToolButton" || name == "GtkToolItem")
2073 {
2074 if (pToolBox)
2075 {
2076 OUString aCommand(extractActionName(rMap));
2077
2078 ToolBoxItemId nItemId(0);
2080 if (name == "GtkMenuToolButton")
2082 else if (name == "GtkToggleToolButton")
2084 else if (name == "GtkRadioToolButton")
2086
2087 if (!aCommand.isEmpty() && m_xFrame.is())
2088 {
2089 pToolBox->InsertItem(aCommand, m_xFrame, nBits, extractSizeRequest(rMap));
2090 nItemId = pToolBox->GetItemId(aCommand);
2091 }
2092 else
2093 {
2094 nItemId = ToolBoxItemId(pToolBox->GetItemCount() + 1);
2095 //TODO: ImplToolItems::size_type -> sal_uInt16!
2096 if (aCommand.isEmpty() && !m_bLegacy)
2097 aCommand = OUString::fromUtf8(id);
2098 pToolBox->InsertItem(nItemId, extractLabel(rMap), aCommand, nBits);
2099 }
2100
2101 pToolBox->SetHelpId(nItemId, m_sHelpRoot + id);
2102 OUString sTooltip(extractTooltipText(rMap));
2103 if (!sTooltip.isEmpty())
2104 pToolBox->SetQuickHelpText(nItemId, sTooltip);
2105
2106 OUString sIconName(extractIconName(rMap));
2107 if (!sIconName.isEmpty())
2108 pToolBox->SetItemImage(nItemId, FixedImage::loadThemeImage(sIconName));
2109
2110 if (!extractVisible(rMap))
2111 pToolBox->HideItem(nItemId);
2112
2113 m_pParserState->m_nLastToolbarId = nItemId;
2114
2115 return nullptr; // no widget to be created
2116 }
2117 }
2118 else if (name == "GtkSeparatorToolItem")
2119 {
2120 if (pToolBox)
2121 {
2122 pToolBox->InsertSeparator();
2123 return nullptr; // no widget to be created
2124 }
2125 }
2126 else if (name == "GtkWindow")
2127 {
2128 WinBits nBits = extractDeferredBits(rMap);
2129 if (nBits & WB_DOCKABLE)
2130 xWindow = VclPtr<DockingWindow>::Create(pParent, nBits|WB_MOVEABLE);
2131 else
2132 xWindow = VclPtr<FloatingWindow>::Create(pParent, nBits|WB_MOVEABLE);
2133 }
2134 else if (name == "GtkPopover")
2135 {
2136 WinBits nBits = extractDeferredBits(rMap);
2137 xWindow = VclPtr<DockingWindow>::Create(pParent, nBits|WB_DOCKABLE|WB_MOVEABLE);
2138 }
2139 else if (name == "GtkCalendar")
2140 {
2141 WinBits nBits = extractDeferredBits(rMap);
2142 xWindow = VclPtr<Calendar>::Create(pParent, nBits);
2143 }
2144 else
2145 {
2146 if (customMakeWidget pFunction = GetCustomMakeWidget(name))
2147 {
2148 pFunction(xWindow, pParent, rMap);
2149 if (xWindow->GetType() == WindowType::PUSHBUTTON)
2150 setupFromActionName(static_cast<Button*>(xWindow.get()), rMap, m_xFrame);
2151 else if (xWindow->GetType() == WindowType::MENUBUTTON)
2152 {
2153 OUString sMenu = BuilderUtils::extractCustomProperty(rMap);
2154 if (!sMenu.isEmpty())
2155 m_pParserState->m_aButtonMenuMaps.emplace_back(id, sMenu);
2156 setupFromActionName(static_cast<Button*>(xWindow.get()), rMap, m_xFrame);
2157 }
2158 }
2159 }
2160
2161 SAL_INFO_IF(!xWindow, "vcl.builder", "probably need to implement " << name << " or add a make" << name << " function");
2162 if (xWindow)
2163 {
2164 // child windows of disabled windows are made disabled by vcl by default, we don't want that
2165 WindowImpl *pWindowImpl = xWindow->ImplGetWindowImpl();
2166 pWindowImpl->mbDisabled = false;
2167
2168 xWindow->SetHelpId(m_sHelpRoot + id);
2169 SAL_INFO("vcl.builder", "for name '" << name << "' and id '" << id <<
2170 "', created " << xWindow.get() << " child of " <<
2171 pParent << "(" << xWindow->ImplGetWindowImpl()->mpParent.get() << "/" <<
2172 xWindow->ImplGetWindowImpl()->mpRealParent.get() << "/" <<
2173 xWindow->ImplGetWindowImpl()->mpBorderWindow.get() << ") with helpid " <<
2174 xWindow->GetHelpId());
2175 m_aChildren.emplace_back(id, xWindow, bVertical);
2176
2177 // if the parent was a toolbox set it as an itemwindow for the latest itemid
2178 if (pToolBox)
2179 {
2180 Size aSize(xWindow->GetSizePixel());
2181 aSize.setHeight(xWindow->get_preferred_size().Height());
2182 xWindow->SetSizePixel(aSize);
2183 pToolBox->SetItemWindow(m_pParserState->m_nLastToolbarId, xWindow);
2184 pToolBox->SetItemExpand(m_pParserState->m_nLastToolbarId, true);
2185 }
2186 }
2187 return xWindow;
2188}
2189
2190namespace
2191{
2192 //return true for window types which exist in vcl but are not themselves
2193 //represented in the .ui format, i.e. only their children exist.
2194 bool isConsideredGtkPseudo(vcl::Window const *pWindow)
2195 {
2196 return pWindow->GetType() == WindowType::TABPAGE;
2197 }
2198}
2199
2200//Any properties from .ui load we couldn't set because of potential virtual methods
2201//during ctor are applied here
2203{
2205 return;
2206 stringmap aDeferredProperties;
2207 aDeferredProperties.swap(m_aDeferredProperties);
2209 BuilderUtils::set_properties(m_pParent, aDeferredProperties);
2210}
2211
2213{
2215 {
2216 for (auto const& prop : rProps)
2217 {
2218 const OString &rKey = prop.first;
2219 const OUString &rValue = prop.second;
2220 pWindow->set_property(rKey, rValue);
2221 }
2222 }
2223
2224 OUString convertMnemonicMarkup(std::u16string_view rIn)
2225 {
2226 OUStringBuffer aRet(rIn);
2227 for (sal_Int32 nI = 0; nI < aRet.getLength(); ++nI)
2228 {
2229 if (aRet[nI] == '_' && nI+1 < aRet.getLength())
2230 {
2231 if (aRet[nI+1] != '_')
2232 aRet[nI] = MNEMONIC_CHAR;
2233 else
2234 aRet.remove(nI, 1);
2235 ++nI;
2236 }
2237 }
2238 return aRet.makeStringAndClear();
2239 }
2240
2242 {
2243 OUString sCustomProperty;
2244 VclBuilder::stringmap::iterator aFind = rMap.find(OString("customproperty"));
2245 if (aFind != rMap.end())
2246 {
2247 sCustomProperty = aFind->second;
2248 rMap.erase(aFind);
2249 }
2250 return sCustomProperty;
2251 }
2252
2254 {
2255 OString sWidthChars("width-chars");
2256 VclBuilder::stringmap::iterator aFind = rMap.find(sWidthChars);
2257 if (aFind == rMap.end())
2258 rMap[sWidthChars] = "20";
2259 }
2260
2262 {
2263 bool bDropdown = true;
2264 VclBuilder::stringmap::iterator aFind = rMap.find(OString("dropdown"));
2265 if (aFind != rMap.end())
2266 {
2267 bDropdown = toBool(aFind->second);
2268 rMap.erase(aFind);
2269 }
2270 return bDropdown;
2271 }
2272
2273 void reorderWithinParent(vcl::Window &rWindow, sal_uInt16 nNewPosition)
2274 {
2275 WindowImpl *pWindowImpl = rWindow.ImplGetWindowImpl();
2276 if (pWindowImpl->mpParent != pWindowImpl->mpRealParent)
2277 {
2278 assert(pWindowImpl->mpBorderWindow == pWindowImpl->mpParent);
2279 assert(pWindowImpl->mpBorderWindow->ImplGetWindowImpl()->mpParent == pWindowImpl->mpRealParent);
2280 reorderWithinParent(*pWindowImpl->mpBorderWindow, nNewPosition);
2281 return;
2282 }
2283 rWindow.reorderWithinParent(nNewPosition);
2284 }
2285
2286 void reorderWithinParent(std::vector<vcl::Window*>& rChilds, bool bIsButtonBox)
2287 {
2288 for (size_t i = 0; i < rChilds.size(); ++i)
2289 {
2290 reorderWithinParent(*rChilds[i], i);
2291
2292 if (!bIsButtonBox)
2293 continue;
2294
2295 //The first member of the group for legacy code needs WB_GROUP set and the
2296 //others not
2297 WinBits nBits = rChilds[i]->GetStyle();
2298 nBits &= ~WB_GROUP;
2299 if (i == 0)
2300 nBits |= WB_GROUP;
2301 rChilds[i]->SetStyle(nBits);
2302 }
2303 }
2304
2305 sal_Int16 getRoleFromName(const OString& roleName)
2306 {
2307 using namespace com::sun::star::accessibility;
2308
2309 static const std::unordered_map<OString, sal_Int16> aAtkRoleToAccessibleRole = {
2310 /* This is in atkobject.h's AtkRole order */
2311 { "invalid", AccessibleRole::UNKNOWN },
2312 { "accelerator label", AccessibleRole::UNKNOWN },
2313 { "alert", AccessibleRole::ALERT },
2314 { "animation", AccessibleRole::UNKNOWN },
2315 { "arrow", AccessibleRole::UNKNOWN },
2316 { "calendar", AccessibleRole::UNKNOWN },
2317 { "canvas", AccessibleRole::CANVAS },
2318 { "check box", AccessibleRole::CHECK_BOX },
2319 { "check menu item", AccessibleRole::CHECK_MENU_ITEM },
2320 { "color chooser", AccessibleRole::COLOR_CHOOSER },
2321 { "column header", AccessibleRole::COLUMN_HEADER },
2322 { "combo box", AccessibleRole::COMBO_BOX },
2323 { "date editor", AccessibleRole::DATE_EDITOR },
2324 { "desktop icon", AccessibleRole::DESKTOP_ICON },
2325 { "desktop frame", AccessibleRole::DESKTOP_PANE }, // ?
2326 { "dial", AccessibleRole::UNKNOWN },
2327 { "dialog", AccessibleRole::DIALOG },
2328 { "directory pane", AccessibleRole::DIRECTORY_PANE },
2329 { "drawing area", AccessibleRole::UNKNOWN },
2330 { "file chooser", AccessibleRole::FILE_CHOOSER },
2331 { "filler", AccessibleRole::FILLER },
2332 { "font chooser", AccessibleRole::FONT_CHOOSER },
2333 { "frame", AccessibleRole::FRAME },
2334 { "glass pane", AccessibleRole::GLASS_PANE },
2335 { "html container", AccessibleRole::UNKNOWN },
2336 { "icon", AccessibleRole::ICON },
2337 { "image", AccessibleRole::GRAPHIC },
2338 { "internal frame", AccessibleRole::INTERNAL_FRAME },
2339 { "label", AccessibleRole::LABEL },
2340 { "layered pane", AccessibleRole::LAYERED_PANE },
2341 { "list", AccessibleRole::LIST },
2342 { "list item", AccessibleRole::LIST_ITEM },
2343 { "menu", AccessibleRole::MENU },
2344 { "menu bar", AccessibleRole::MENU_BAR },
2345 { "menu item", AccessibleRole::MENU_ITEM },
2346 { "option pane", AccessibleRole::OPTION_PANE },
2347 { "page tab", AccessibleRole::PAGE_TAB },
2348 { "page tab list", AccessibleRole::PAGE_TAB_LIST },
2349 { "panel", AccessibleRole::PANEL }, // or SHAPE or TEXT_FRAME ?
2350 { "password text", AccessibleRole::PASSWORD_TEXT },
2351 { "popup menu", AccessibleRole::POPUP_MENU },
2352 { "progress bar", AccessibleRole::PROGRESS_BAR },
2353 { "push button", AccessibleRole::PUSH_BUTTON }, // or BUTTON_DROPDOWN or BUTTON_MENU
2354 { "radio button", AccessibleRole::RADIO_BUTTON },
2355 { "radio menu item", AccessibleRole::RADIO_MENU_ITEM },
2356 { "root pane", AccessibleRole::ROOT_PANE },
2357 { "row header", AccessibleRole::ROW_HEADER },
2358 { "scroll bar", AccessibleRole::SCROLL_BAR },
2359 { "scroll pane", AccessibleRole::SCROLL_PANE },
2360 { "separator", AccessibleRole::SEPARATOR },
2361 { "slider", AccessibleRole::SLIDER },
2362 { "split pane", AccessibleRole::SPLIT_PANE },
2363 { "spin button", AccessibleRole::SPIN_BOX }, // ?
2364 { "statusbar", AccessibleRole::STATUS_BAR },
2365 { "table", AccessibleRole::TABLE },
2366 { "table cell", AccessibleRole::TABLE_CELL },
2367 { "table column header", AccessibleRole::COLUMN_HEADER }, // approximate
2368 { "table row header", AccessibleRole::ROW_HEADER }, // approximate
2369 { "tear off menu item", AccessibleRole::UNKNOWN },
2370 { "terminal", AccessibleRole::UNKNOWN },
2371 { "text", AccessibleRole::TEXT },
2372 { "toggle button", AccessibleRole::TOGGLE_BUTTON },
2373 { "tool bar", AccessibleRole::TOOL_BAR },
2374 { "tool tip", AccessibleRole::TOOL_TIP },
2375 { "tree", AccessibleRole::TREE },
2376 { "tree table", AccessibleRole::TREE_TABLE },
2377 { "unknown", AccessibleRole::UNKNOWN },
2378 { "viewport", AccessibleRole::VIEW_PORT },
2379 { "window", AccessibleRole::WINDOW },
2380 { "header", AccessibleRole::HEADER },
2381 { "footer", AccessibleRole::FOOTER },
2382 { "paragraph", AccessibleRole::PARAGRAPH },
2383 { "ruler", AccessibleRole::RULER },
2384 { "application", AccessibleRole::UNKNOWN },
2385 { "autocomplete", AccessibleRole::UNKNOWN },
2386 { "edit bar", AccessibleRole::EDIT_BAR },
2387 { "embedded", AccessibleRole::EMBEDDED_OBJECT },
2388 { "entry", AccessibleRole::UNKNOWN },
2389 { "chart", AccessibleRole::CHART },
2390 { "caption", AccessibleRole::CAPTION },
2391 { "document frame", AccessibleRole::DOCUMENT },
2392 { "heading", AccessibleRole::HEADING },
2393 { "page", AccessibleRole::PAGE },
2394 { "section", AccessibleRole::SECTION },
2395 { "redundant object", AccessibleRole::UNKNOWN },
2396 { "form", AccessibleRole::FORM },
2397 { "link", AccessibleRole::HYPER_LINK },
2398 { "input method window", AccessibleRole::UNKNOWN },
2399 { "table row", AccessibleRole::UNKNOWN },
2400 { "tree item", AccessibleRole::TREE_ITEM },
2401 { "document spreadsheet", AccessibleRole::DOCUMENT_SPREADSHEET },
2402 { "document presentation", AccessibleRole::DOCUMENT_PRESENTATION },
2403 { "document text", AccessibleRole::DOCUMENT_TEXT },
2404 { "document web", AccessibleRole::DOCUMENT }, // approximate
2405 { "document email", AccessibleRole::DOCUMENT }, // approximate
2406 { "comment", AccessibleRole::COMMENT }, // or NOTE or END_NOTE or FOOTNOTE or SCROLL_PANE
2407 { "list box", AccessibleRole::UNKNOWN },
2408 { "grouping", AccessibleRole::GROUP_BOX },
2409 { "image map", AccessibleRole::IMAGE_MAP },
2410 { "notification", AccessibleRole::UNKNOWN },
2411 { "info bar", AccessibleRole::UNKNOWN },
2412 { "level bar", AccessibleRole::UNKNOWN },
2413 { "title bar", AccessibleRole::UNKNOWN },
2414 { "block quote", AccessibleRole::UNKNOWN },
2415 { "audio", AccessibleRole::UNKNOWN },
2416 { "video", AccessibleRole::UNKNOWN },
2417 { "definition", AccessibleRole::UNKNOWN },
2418 { "article", AccessibleRole::UNKNOWN },
2419 { "landmark", AccessibleRole::UNKNOWN },
2420 { "log", AccessibleRole::UNKNOWN },
2421 { "marquee", AccessibleRole::UNKNOWN },
2422 { "math", AccessibleRole::UNKNOWN },
2423 { "rating", AccessibleRole::UNKNOWN },
2424 { "timer", AccessibleRole::UNKNOWN },
2425 { "description list", AccessibleRole::UNKNOWN },
2426 { "description term", AccessibleRole::UNKNOWN },
2427 { "description value", AccessibleRole::UNKNOWN },
2428 { "static", AccessibleRole::STATIC },
2429 { "math fraction", AccessibleRole::UNKNOWN },
2430 { "math root", AccessibleRole::UNKNOWN },
2431 { "subscript", AccessibleRole::UNKNOWN },
2432 { "superscript", AccessibleRole::UNKNOWN },
2433 { "footnote", AccessibleRole::FOOTNOTE },
2434 };
2435
2436 auto it = aAtkRoleToAccessibleRole.find(roleName);
2437 if (it == aAtkRoleToAccessibleRole.end())
2438 return AccessibleRole::UNKNOWN;
2439 return it->second;
2440 }
2441}
2442
2444 const OString &rID, stringmap &rProps, stringmap &rPango, stringmap &rAtk)
2445{
2446 VclPtr<vcl::Window> pCurrentChild;
2447
2448 if (m_pParent && !isConsideredGtkPseudo(m_pParent) && !m_sID.isEmpty() && rID == m_sID)
2449 {
2450 pCurrentChild = m_pParent;
2451
2452 //toplevels default to resizable and apparently you can't change them
2453 //afterwards, so we need to wait until now before we can truly
2454 //initialize the dialog.
2455 if (pParent && pParent->IsSystemWindow())
2456 {
2457 SystemWindow *pSysWin = static_cast<SystemWindow*>(pCurrentChild.get());
2458 pSysWin->doDeferredInit(extractDeferredBits(rProps));
2460 }
2461 else if (pParent && pParent->IsDockingWindow())
2462 {
2463 DockingWindow *pDockWin = static_cast<DockingWindow*>(pCurrentChild.get());
2464 pDockWin->doDeferredInit(extractDeferredBits(rProps));
2466 }
2467
2468 if (pCurrentChild->GetHelpId().isEmpty())
2469 {
2470 pCurrentChild->SetHelpId(m_sHelpRoot + m_sID);
2471 SAL_INFO("vcl.builder", "for toplevel dialog " << this << " " <<
2472 rID << ", set helpid " << pCurrentChild->GetHelpId());
2473 }
2475 }
2476 else
2477 {
2478 //if we're being inserting under a toplevel dialog whose init is
2479 //deferred due to waiting to encounter it in this .ui, and it hasn't
2480 //been seen yet, then make unattached widgets parent-less toplevels
2481 if (pParent == m_pParent.get() && m_bToplevelHasDeferredInit)
2482 pParent = nullptr;
2483 pCurrentChild = makeObject(pParent, rClass, rID, rProps);
2484 }
2485
2486 if (pCurrentChild)
2487 {
2488 pCurrentChild->set_id(OStringToOUString(rID, RTL_TEXTENCODING_UTF8));
2489 if (pCurrentChild == m_pParent.get() && m_bToplevelHasDeferredProperties)
2490 m_aDeferredProperties = rProps;
2491 else
2492 BuilderUtils::set_properties(pCurrentChild, rProps);
2493
2494 // tdf#119827 handle size before scale so we can trivially
2495 // scale on the current font size whether size is present
2496 // or not.
2497 VclBuilder::stringmap::iterator aSize = rPango.find(OString("size"));
2498 if (aSize != rPango.end())
2499 {
2500 pCurrentChild->set_font_attribute(aSize->first, aSize->second);
2501 rPango.erase(aSize);
2502 }
2503 for (auto const& elem : rPango)
2504 {
2505 const OString &rKey = elem.first;
2506 const OUString &rValue = elem.second;
2507 pCurrentChild->set_font_attribute(rKey, rValue);
2508 }
2509
2510 m_pParserState->m_aAtkInfo[pCurrentChild] = rAtk;
2511 }
2512
2513 rProps.clear();
2514 rPango.clear();
2515 rAtk.clear();
2516
2517 if (!pCurrentChild)
2518 {
2519 bool bToolbarParent = (pParent && pParent->GetType() == WindowType::TOOLBOX);
2520 pCurrentChild = (m_aChildren.empty() || bToolbarParent) ? pParent : m_aChildren.back().m_pWindow.get();
2521 }
2522 return pCurrentChild;
2523}
2524
2526{
2527 TabControl *pTabControl = pParent && pParent->GetType() == WindowType::TABCONTROL ?
2528 static_cast<TabControl*>(pParent) : nullptr;
2529
2530 std::vector<OString> sIDs;
2531
2532 int nLevel = 1;
2534 stringmap aAtkProperties;
2535 std::vector<vcl::EnumContext::Context> context;
2536
2537 while(true)
2538 {
2540 int nsId;
2541
2543 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2544
2545 if (res == xmlreader::XmlReader::Result::Begin)
2546 {
2547 ++nLevel;
2548 if (name == "object")
2549 {
2550 while (reader.nextAttribute(&nsId, &name))
2551 {
2552 if (name == "id")
2553 {
2554 name = reader.getAttributeValue(false);
2555 OString sID(name.begin, name.length);
2556 sal_Int32 nDelim = sID.indexOf(':');
2557 if (nDelim != -1)
2558 {
2559 OString sPattern = sID.copy(nDelim+1);
2560 aProperties[OString("customproperty")] = OUString::fromUtf8(sPattern);
2561 sID = sID.copy(0, nDelim);
2562 }
2563 sIDs.push_back(sID);
2564 }
2565 }
2566 }
2567 else if (name == "style")
2568 {
2569 int nPriority = 0;
2570 context = handleStyle(reader, nPriority);
2571 --nLevel;
2572 }
2573 else if (name == "property")
2575 else if (pTabControl && name == "child")
2576 {
2577 // just to collect the atk properties (if any) for the label
2578 handleChild(nullptr, &aAtkProperties, reader);
2579 --nLevel;
2580 }
2581 }
2582
2583 if (res == xmlreader::XmlReader::Result::End)
2584 --nLevel;
2585
2586 if (!nLevel)
2587 break;
2588
2589 if (res == xmlreader::XmlReader::Result::Done)
2590 break;
2591 }
2592
2593 if (!pParent)
2594 return;
2595
2596 VerticalTabControl *pVerticalTabControl = pParent->GetType() == WindowType::VERTICALTABCONTROL ?
2597 static_cast<VerticalTabControl*>(pParent) : nullptr;
2598 assert(pTabControl || pVerticalTabControl);
2599 VclBuilder::stringmap::iterator aFind = aProperties.find(OString("label"));
2600 if (aFind != aProperties.end())
2601 {
2602 OUString sTooltip(extractTooltipText(aProperties));
2603 if (pTabControl)
2604 {
2605 sal_uInt16 nPageId = pTabControl->GetCurPageId();
2606 pTabControl->SetPageText(nPageId, aFind->second);
2607 pTabControl->SetPageName(nPageId, sIDs.back());
2608 pTabControl->SetHelpText(nPageId, sTooltip);
2609 if (!context.empty())
2610 {
2611 TabPage* pPage = pTabControl->GetTabPage(nPageId);
2612 pPage->SetContext(std::move(context));
2613 }
2614
2615 for (auto const& prop : aAtkProperties)
2616 {
2617 const OString &rKey = prop.first;
2618 const OUString &rValue = prop.second;
2619
2620 if (rKey == "AtkObject::accessible-name")
2621 pTabControl->SetAccessibleName(nPageId, rValue);
2622 else if (rKey == "AtkObject::accessible-description")
2623 pTabControl->SetAccessibleDescription(nPageId, rValue);
2624 else
2625 SAL_INFO("vcl.builder", "unhandled atk property: " << rKey);
2626 }
2627
2628 }
2629 else
2630 {
2631 OUString sLabel(BuilderUtils::convertMnemonicMarkup(aFind->second));
2632 OUString sIconName(extractIconName(aProperties));
2633 pVerticalTabControl->InsertPage(sIDs.front(), sLabel, FixedImage::loadThemeImage(sIconName), sTooltip,
2634 pVerticalTabControl->GetPageParent()->GetWindow(GetWindowType::LastChild));
2635 }
2636 }
2637 else
2638 {
2639 if (pTabControl)
2640 pTabControl->RemovePage(pTabControl->GetCurPageId());
2641 }
2642}
2643
2644//so that tabbing between controls goes in a visually sensible sequence
2645//we sort these into a best-tab-order sequence
2647{
2648 //sort child order within parent list by grid position
2649 sal_Int32 nTopA = pA->get_grid_top_attach();
2650 sal_Int32 nTopB = pB->get_grid_top_attach();
2651 if (nTopA < nTopB)
2652 return true;
2653 if (nTopA > nTopB)
2654 return false;
2655 sal_Int32 nLeftA = pA->get_grid_left_attach();
2656 sal_Int32 nLeftB = pB->get_grid_left_attach();
2657 if (nLeftA < nLeftB)
2658 return true;
2659 if (nLeftA > nLeftB)
2660 return false;
2661 //sort into two groups of pack start and pack end
2662 VclPackType ePackA = pA->get_pack_type();
2663 VclPackType ePackB = pB->get_pack_type();
2664 if (ePackA < ePackB)
2665 return true;
2666 if (ePackA > ePackB)
2667 return false;
2668 bool bVerticalContainer = m_pBuilder->get_window_packing_data(pA->GetParent()).m_bVerticalOrient;
2669 bool bPackA = pA->get_secondary();
2670 bool bPackB = pB->get_secondary();
2671 if (!bVerticalContainer)
2672 {
2673 //for horizontal boxes group secondaries before primaries
2674 if (bPackA > bPackB)
2675 return true;
2676 if (bPackA < bPackB)
2677 return false;
2678 }
2679 else
2680 {
2681 //for vertical boxes group secondaries after primaries
2682 if (bPackA < bPackB)
2683 return true;
2684 if (bPackA > bPackB)
2685 return false;
2686 }
2687 //honour relative box positions with pack group, (numerical order is reversed
2688 //for VclPackType::End, they are packed from the end back, but here we need
2689 //them in visual layout order so that tabbing works as expected)
2690 sal_Int32 nPackA = m_pBuilder->get_window_packing_data(pA).m_nPosition;
2691 sal_Int32 nPackB = m_pBuilder->get_window_packing_data(pB).m_nPosition;
2692 if (nPackA < nPackB)
2693 return ePackA == VclPackType::Start;
2694 if (nPackA > nPackB)
2695 return ePackA != VclPackType::Start;
2696 //sort labels of Frames before body
2697 if (pA->GetParent() == pB->GetParent())
2698 {
2699 const VclFrame *pFrameParent = dynamic_cast<const VclFrame*>(pA->GetParent());
2700 if (pFrameParent)
2701 {
2702 const vcl::Window *pLabel = pFrameParent->get_label_widget();
2703 int nFramePosA = (pA == pLabel) ? 0 : 1;
2704 int nFramePosB = (pB == pLabel) ? 0 : 1;
2705 return nFramePosA < nFramePosB;
2706 }
2707 }
2708 return false;
2709}
2710
2712{
2713 vcl::Window *pCurrentChild = nullptr;
2714
2716 int nsId;
2717 OString sType, sInternalChild;
2718
2719 while (reader.nextAttribute(&nsId, &name))
2720 {
2721 if (name == "type")
2722 {
2723 name = reader.getAttributeValue(false);
2724 sType = OString(name.begin, name.length);
2725 }
2726 else if (name == "internal-child")
2727 {
2728 name = reader.getAttributeValue(false);
2729 sInternalChild = OString(name.begin, name.length);
2730 }
2731 }
2732
2733 if (sType == "tab")
2734 {
2735 handleTabChild(pParent, reader);
2736 return;
2737 }
2738
2739 int nLevel = 1;
2740 while(true)
2741 {
2743 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2744
2745 if (res == xmlreader::XmlReader::Result::Begin)
2746 {
2747 if (name == "object" || name == "placeholder")
2748 {
2749 pCurrentChild = handleObject(pParent, pAtkProps, reader).get();
2750
2751 bool bObjectInserted = pCurrentChild && pParent != pCurrentChild;
2752
2753 if (bObjectInserted)
2754 {
2755 //Internal-children default in glade to not having their visible bits set
2756 //even though they are visible (generally anyway)
2757 if (!sInternalChild.isEmpty())
2758 pCurrentChild->Show();
2759
2760 //Select the first page if it's a notebook
2761 if (pCurrentChild->GetType() == WindowType::TABCONTROL)
2762 {
2763 TabControl *pTabControl = static_cast<TabControl*>(pCurrentChild);
2764 pTabControl->SetCurPageId(pTabControl->GetPageId(0));
2765
2766 //To-Do add reorder capability to the TabControl
2767 }
2768 else
2769 {
2770 // We want to sort labels before contents of frames
2771 // for keyboard traversal, especially if there
2772 // are multiple widgets using the same mnemonic
2773 if (sType == "label")
2774 {
2775 if (VclFrame *pFrameParent = dynamic_cast<VclFrame*>(pParent))
2776 pFrameParent->designate_label(pCurrentChild);
2777 }
2778 if (sInternalChild.startsWith("vbox") || sInternalChild.startsWith("messagedialog-vbox"))
2779 {
2780 if (Dialog *pBoxParent = dynamic_cast<Dialog*>(pParent))
2781 pBoxParent->set_content_area(static_cast<VclBox*>(pCurrentChild)); // FIXME-VCLPTR
2782 }
2783 else if (sInternalChild.startsWith("action_area") || sInternalChild.startsWith("messagedialog-action_area"))
2784 {
2785 vcl::Window *pContentArea = pCurrentChild->GetParent();
2786 if (Dialog *pBoxParent = dynamic_cast<Dialog*>(pContentArea ? pContentArea->GetParent() : nullptr))
2787 {
2788 pBoxParent->set_action_area(static_cast<VclButtonBox*>(pCurrentChild)); // FIXME-VCLPTR
2789 }
2790 }
2791
2792 bool bIsButtonBox = dynamic_cast<VclButtonBox*>(pCurrentChild) != nullptr;
2793
2794 //To-Do make reorder a virtual in Window, move this foo
2795 //there and see above
2796 std::vector<vcl::Window*> aChilds;
2797 for (vcl::Window* pChild = pCurrentChild->GetWindow(GetWindowType::FirstChild); pChild;
2798 pChild = pChild->GetWindow(GetWindowType::Next))
2799 {
2800 if (bIsButtonBox)
2801 {
2802 if (PushButton* pPushButton = dynamic_cast<PushButton*>(pChild))
2803 pPushButton->setAction(true);
2804 }
2805
2806 aChilds.push_back(pChild);
2807 }
2808
2809 //sort child order within parent so that tabbing
2810 //between controls goes in a visually sensible sequence
2811 std::stable_sort(aChilds.begin(), aChilds.end(), sortIntoBestTabTraversalOrder(this));
2812 BuilderUtils::reorderWithinParent(aChilds, bIsButtonBox);
2813 }
2814 }
2815 }
2816 else if (name == "packing")
2817 {
2818 handlePacking(pCurrentChild, pParent, reader);
2819 }
2820 else if (name == "interface")
2821 {
2822 while (reader.nextAttribute(&nsId, &name))
2823 {
2824 if (name == "domain")
2825 {
2826 name = reader.getAttributeValue(false);
2827 sType = OString(name.begin, name.length);
2828 m_pParserState->m_aResLocale = Translate::Create(sType);
2829 }
2830 }
2831 ++nLevel;
2832 }
2833 else
2834 ++nLevel;
2835 }
2836
2837 if (res == xmlreader::XmlReader::Result::End)
2838 --nLevel;
2839
2840 if (!nLevel)
2841 break;
2842
2843 if (res == xmlreader::XmlReader::Result::Done)
2844 break;
2845 }
2846}
2847
2849{
2850 xmlreader::Span span;
2851 int nsId;
2852
2853 OString sProperty;
2854 OString sValue;
2855
2856 while (reader.nextAttribute(&nsId, &span))
2857 {
2858 if (span == "name")
2859 {
2860 span = reader.getAttributeValue(false);
2861 sProperty = OString(span.begin, span.length);
2862 }
2863 else if (span == "value")
2864 {
2865 span = reader.getAttributeValue(false);
2866 sValue = OString(span.begin, span.length);
2867 }
2868 }
2869
2870 if (!sProperty.isEmpty())
2871 rMap[sProperty] = OUString::fromUtf8(sValue);
2872}
2873
2875{
2876 xmlreader::Span span;
2877 int nsId;
2878
2879 OString sProperty;
2880 OString sValue;
2881
2882 while (reader.nextAttribute(&nsId, &span))
2883 {
2884 if (span == "type")
2885 {
2886 span = reader.getAttributeValue(false);
2887 sProperty = OString(span.begin, span.length);
2888 }
2889 else if (span == "target")
2890 {
2891 span = reader.getAttributeValue(false);
2892 sValue = OString(span.begin, span.length);
2893 sal_Int32 nDelim = sValue.indexOf(':');
2894 if (nDelim != -1)
2895 sValue = sValue.copy(0, nDelim);
2896 }
2897 }
2898
2899 if (!sProperty.isEmpty())
2900 rMap[sProperty] = OUString::fromUtf8(sValue);
2901}
2902
2904{
2905 xmlreader::Span span;
2906 int nsId;
2907
2908 OString sProperty;
2909
2910 while (reader.nextAttribute(&nsId, &span))
2911 {
2912 if (span == "type")
2913 {
2914 span = reader.getAttributeValue(false);
2915 sProperty = OString(span.begin, span.length);
2916 }
2917 }
2918
2919 if (!sProperty.isEmpty())
2920 rMap["role"] = OUString::fromUtf8(sProperty);
2921}
2922
2923void VclBuilder::handleRow(xmlreader::XmlReader &reader, const OString &rID)
2924{
2925 int nLevel = 1;
2926
2927 ListStore::row aRow;
2928
2929 while(true)
2930 {
2932 int nsId;
2933
2935 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2936
2937 if (res == xmlreader::XmlReader::Result::Done)
2938 break;
2939
2940 if (res == xmlreader::XmlReader::Result::Begin)
2941 {
2942 ++nLevel;
2943 if (name == "col")
2944 {
2945 bool bTranslated = false;
2946 sal_uInt32 nId = 0;
2947 OString sContext;
2948
2949 while (reader.nextAttribute(&nsId, &name))
2950 {
2951 if (name == "id")
2952 {
2953 name = reader.getAttributeValue(false);
2954 nId = OString(name.begin, name.length).toUInt32();
2955 }
2956 else if (nId == 0 && name == "translatable" && reader.getAttributeValue(false) == "yes")
2957 {
2958 bTranslated = true;
2959 }
2960 else if (name == "context")
2961 {
2962 name = reader.getAttributeValue(false);
2963 sContext = OString(name.begin, name.length);
2964 }
2965 }
2966
2967 (void)reader.nextItem(
2968 xmlreader::XmlReader::Text::Raw, &name, &nsId);
2969
2970 OString sValue(name.begin, name.length);
2971 OUString sFinalValue;
2972 if (bTranslated)
2973 {
2974 sFinalValue = Translate::get(TranslateId{sContext.getStr(), sValue.getStr()}, m_pParserState->m_aResLocale);
2975 }
2976 else
2977 sFinalValue = OUString::fromUtf8(sValue);
2978
2979
2980 if (aRow.size() < nId+1)
2981 aRow.resize(nId+1);
2982 aRow[nId] = sFinalValue;
2983 }
2984 }
2985
2986 if (res == xmlreader::XmlReader::Result::End)
2987 {
2988 --nLevel;
2989 }
2990
2991 if (!nLevel)
2992 break;
2993 }
2994
2995 m_pParserState->m_aModels[rID].m_aEntries.push_back(aRow);
2996}
2997
2998void VclBuilder::handleListStore(xmlreader::XmlReader &reader, const OString &rID, std::string_view rClass)
2999{
3000 int nLevel = 1;
3001
3002 while(true)
3003 {
3005 int nsId;
3006
3008 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3009
3010 if (res == xmlreader::XmlReader::Result::Done)
3011 break;
3012
3013 if (res == xmlreader::XmlReader::Result::Begin)
3014 {
3015 if (name == "row")
3016 {
3017 bool bNotTreeStore = rClass != "GtkTreeStore";
3018 if (bNotTreeStore)
3019 handleRow(reader, rID);
3020 assert(bNotTreeStore && "gtk, as the time of writing, doesn't support data in GtkTreeStore serialization");
3021 }
3022 else
3023 ++nLevel;
3024 }
3025
3026 if (res == xmlreader::XmlReader::Result::End)
3027 {
3028 --nLevel;
3029 }
3030
3031 if (!nLevel)
3032 break;
3033 }
3034}
3035
3037{
3038 int nLevel = 1;
3039
3041
3042 while (true)
3043 {
3045 int nsId;
3046
3048 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3049
3050 if (res == xmlreader::XmlReader::Result::Done)
3051 break;
3052
3053 if (res == xmlreader::XmlReader::Result::Begin)
3054 {
3055 ++nLevel;
3056 if (name == "property")
3058 }
3059
3060 if (res == xmlreader::XmlReader::Result::End)
3061 {
3062 --nLevel;
3063 }
3064
3065 if (!nLevel)
3066 break;
3067 }
3068
3069 return aProperties;
3070}
3071
3072void VclBuilder::applyAtkProperties(vcl::Window *pWindow, const stringmap& rProperties)
3073{
3074 assert(pWindow);
3075 for (auto const& prop : rProperties)
3076 {
3077 const OString &rKey = prop.first;
3078 const OUString &rValue = prop.second;
3079
3080 if (pWindow && rKey.match("AtkObject::"))
3081 pWindow->set_property(rKey.copy(RTL_CONSTASCII_LENGTH("AtkObject::")), rValue);
3082 else
3083 SAL_WARN("vcl.builder", "unhandled atk prop: " << rKey);
3084 }
3085}
3086
3087std::vector<ComboBoxTextItem> VclBuilder::handleItems(xmlreader::XmlReader &reader) const
3088{
3089 int nLevel = 1;
3090
3091 std::vector<ComboBoxTextItem> aItems;
3092
3093 while(true)
3094 {
3096 int nsId;
3097
3099 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3100
3101 if (res == xmlreader::XmlReader::Result::Done)
3102 break;
3103
3104 if (res == xmlreader::XmlReader::Result::Begin)
3105 {
3106 ++nLevel;
3107 if (name == "item")
3108 {
3109 bool bTranslated = false;
3110 OString sContext, sId;
3111
3112 while (reader.nextAttribute(&nsId, &name))
3113 {
3114 if (name == "translatable" && reader.getAttributeValue(false) == "yes")
3115 {
3116 bTranslated = true;
3117 }
3118 else if (name == "context")
3119 {
3120 name = reader.getAttributeValue(false);
3121 sContext = OString(name.begin, name.length);
3122 }
3123 else if (name == "id")
3124 {
3125 name = reader.getAttributeValue(false);
3126 sId = OString(name.begin, name.length);
3127 }
3128 }
3129
3130 (void)reader.nextItem(
3131 xmlreader::XmlReader::Text::Raw, &name, &nsId);
3132
3133 OString sValue(name.begin, name.length);
3134 OUString sFinalValue;
3135 if (bTranslated)
3136 {
3137 sFinalValue = Translate::get(TranslateId{sContext.getStr(), sValue.getStr()}, m_pParserState->m_aResLocale);
3138 }
3139 else
3140 sFinalValue = OUString::fromUtf8(sValue);
3141
3142 if (m_pStringReplace)
3143 sFinalValue = (*m_pStringReplace)(sFinalValue);
3144
3145 aItems.emplace_back(sFinalValue, sId);
3146 }
3147 }
3148
3149 if (res == xmlreader::XmlReader::Result::End)
3150 {
3151 --nLevel;
3152 }
3153
3154 if (!nLevel)
3155 break;
3156 }
3157
3158 return aItems;
3159}
3160
3161VclPtr<Menu> VclBuilder::handleMenu(xmlreader::XmlReader &reader, const OString &rID, bool bMenuBar)
3162{
3163 VclPtr<Menu> pCurrentMenu;
3164 if (bMenuBar)
3165 pCurrentMenu = VclPtr<MenuBar>::Create();
3166 else
3167 pCurrentMenu = VclPtr<PopupMenu>::Create();
3168
3169 pCurrentMenu->set_id(OStringToOUString(rID, RTL_TEXTENCODING_UTF8));
3170
3171 int nLevel = 1;
3172
3174
3175 while(true)
3176 {
3178 int nsId;
3179
3181 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3182
3183 if (res == xmlreader::XmlReader::Result::Done)
3184 break;
3185
3186 if (res == xmlreader::XmlReader::Result::Begin)
3187 {
3188 if (name == "child")
3189 {
3190 handleMenuChild(pCurrentMenu, reader);
3191 }
3192 else
3193 {
3194 ++nLevel;
3195 if (name == "property")
3197 }
3198 }
3199
3200 if (res == xmlreader::XmlReader::Result::End)
3201 {
3202 --nLevel;
3203 }
3204
3205 if (!nLevel)
3206 break;
3207 }
3208
3209 m_aMenus.emplace_back(rID, pCurrentMenu);
3210
3211 return pCurrentMenu;
3212}
3213
3215{
3217 int nsId;
3218
3219 int nLevel = 1;
3220 while(true)
3221 {
3223 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3224
3225 if (res == xmlreader::XmlReader::Result::Begin)
3226 {
3227 if (name == "object" || name == "placeholder")
3228 {
3229 handleMenuObject(pParent, reader);
3230 }
3231 else
3232 ++nLevel;
3233 }
3234
3235 if (res == xmlreader::XmlReader::Result::End)
3236 --nLevel;
3237
3238 if (!nLevel)
3239 break;
3240
3241 if (res == xmlreader::XmlReader::Result::Done)
3242 break;
3243 }
3244}
3245
3247{
3248 OString sClass;
3249 OString sID;
3250 OUString sCustomProperty;
3251 PopupMenu *pSubMenu = nullptr;
3252
3254 int nsId;
3255
3256 while (reader.nextAttribute(&nsId, &name))
3257 {
3258 if (name == "class")
3259 {
3260 name = reader.getAttributeValue(false);
3261 sClass = OString(name.begin, name.length);
3262 }
3263 else if (name == "id")
3264 {
3265 name = reader.getAttributeValue(false);
3266 sID = OString(name.begin, name.length);
3267 if (m_bLegacy)
3268 {
3269 sal_Int32 nDelim = sID.indexOf(':');
3270 if (nDelim != -1)
3271 {
3272 sCustomProperty = OUString::fromUtf8(sID.subView(nDelim+1));
3273 sID = sID.copy(0, nDelim);
3274 }
3275 }
3276 }
3277 }
3278
3279 int nLevel = 1;
3280
3282 stringmap aAtkProperties;
3283 accelmap aAccelerators;
3284
3285 if (!sCustomProperty.isEmpty())
3286 aProperties[OString("customproperty")] = sCustomProperty;
3287
3288 while(true)
3289 {
3291 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3292
3293 if (res == xmlreader::XmlReader::Result::Done)
3294 break;
3295
3296 if (res == xmlreader::XmlReader::Result::Begin)
3297 {
3298 if (name == "child")
3299 {
3300 size_t nChildMenuIdx = m_aMenus.size();
3301 handleChild(nullptr, &aAtkProperties, reader);
3302 bool bSubMenuInserted = m_aMenus.size() > nChildMenuIdx;
3303 if (bSubMenuInserted)
3304 pSubMenu = dynamic_cast<PopupMenu*>(m_aMenus[nChildMenuIdx].m_pMenu.get());
3305 }
3306 else
3307 {
3308 ++nLevel;
3309 if (name == "property")
3311 else if (name == "accelerator")
3312 collectAccelerator(reader, aAccelerators);
3313 }
3314 }
3315
3316 if (res == xmlreader::XmlReader::Result::End)
3317 {
3318 --nLevel;
3319 }
3320
3321 if (!nLevel)
3322 break;
3323 }
3324
3325 insertMenuObject(pParent, pSubMenu, sClass, sID, aProperties, aAtkProperties, aAccelerators);
3326}
3327
3329{
3330 m_pParserState->m_aSizeGroups.emplace_back();
3331 SizeGroup &rSizeGroup = m_pParserState->m_aSizeGroups.back();
3332
3333 int nLevel = 1;
3334
3335 while(true)
3336 {
3338 int nsId;
3339
3341 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3342
3343 if (res == xmlreader::XmlReader::Result::Done)
3344 break;
3345
3346 if (res == xmlreader::XmlReader::Result::Begin)
3347 {
3348 ++nLevel;
3349 if (name == "widget")
3350 {
3351 while (reader.nextAttribute(&nsId, &name))
3352 {
3353 if (name == "name")
3354 {
3355 name = reader.getAttributeValue(false);
3356 OString sWidget(name.begin, name.length);
3357 sal_Int32 nDelim = sWidget.indexOf(':');
3358 if (nDelim != -1)
3359 sWidget = sWidget.copy(0, nDelim);
3360 rSizeGroup.m_aWidgets.push_back(sWidget);
3361 }
3362 }
3363 }
3364 else
3365 {
3366 if (name == "property")
3367 collectProperty(reader, rSizeGroup.m_aProperties);
3368 }
3369 }
3370
3371 if (res == xmlreader::XmlReader::Result::End)
3372 {
3373 --nLevel;
3374 }
3375
3376 if (!nLevel)
3377 break;
3378 }
3379}
3380
3381namespace
3382{
3383 vcl::KeyCode makeKeyCode(const std::pair<OString,OString> &rKey)
3384 {
3385 bool bShift = rKey.second.indexOf("GDK_SHIFT_MASK") != -1;
3386 bool bMod1 = rKey.second.indexOf("GDK_CONTROL_MASK") != -1;
3387 bool bMod2 = rKey.second.indexOf("GDK_ALT_MASK") != -1;
3388 bool bMod3 = rKey.second.indexOf("GDK_MOD2_MASK") != -1;
3389
3390 if (rKey.first == "Insert")
3391 return vcl::KeyCode(KEY_INSERT, bShift, bMod1, bMod2, bMod3);
3392 else if (rKey.first == "Delete")
3393 return vcl::KeyCode(KEY_DELETE, bShift, bMod1, bMod2, bMod3);
3394 else if (rKey.first == "Return")
3395 return vcl::KeyCode(KEY_RETURN, bShift, bMod1, bMod2, bMod3);
3396 else if (rKey.first == "Up")
3397 return vcl::KeyCode(KEY_UP, bShift, bMod1, bMod2, bMod3);
3398 else if (rKey.first == "Down")
3399 return vcl::KeyCode(KEY_DOWN, bShift, bMod1, bMod2, bMod3);
3400 else if (rKey.first == "Left")
3401 return vcl::KeyCode(KEY_LEFT, bShift, bMod1, bMod2, bMod3);
3402 else if (rKey.first == "Right")
3403 return vcl::KeyCode(KEY_RIGHT, bShift, bMod1, bMod2, bMod3);
3404 else if (rKey.first == "asterisk")
3405 return vcl::KeyCode(KEY_MULTIPLY, bShift, bMod1, bMod2, bMod3);
3406 else if (rKey.first.getLength() > 1 && rKey.first[0] == 'F')
3407 {
3408 sal_uInt32 nIndex = o3tl::toUInt32(rKey.first.subView(1));
3409 assert(nIndex >= 1 && nIndex <= 26);
3410 return vcl::KeyCode(KEY_F1 + nIndex - 1, bShift, bMod1, bMod2, bMod3);
3411 }
3412
3413 assert (rKey.first.getLength() == 1);
3414 char cChar = rKey.first.toChar();
3415
3416 if (cChar >= 'a' && cChar <= 'z')
3417 return vcl::KeyCode(KEY_A + (cChar - 'a'), bShift, bMod1, bMod2, bMod3);
3418 else if (cChar >= 'A' && cChar <= 'Z')
3419 return vcl::KeyCode(KEY_A + (cChar - 'A'), bShift, bMod1, bMod2, bMod3);
3420 else if (cChar >= '0' && cChar <= '9')
3421 return vcl::KeyCode(KEY_0 + (cChar - 'A'), bShift, bMod1, bMod2, bMod3);
3422
3423 return vcl::KeyCode(cChar, bShift, bMod1, bMod2, bMod3);
3424 }
3425}
3426
3427void VclBuilder::insertMenuObject(Menu *pParent, PopupMenu *pSubMenu, const OString &rClass, const OString &rID,
3428 stringmap &rProps, stringmap &rAtkProps, accelmap &rAccels)
3429{
3430 sal_uInt16 nOldCount = pParent->GetItemCount();
3431 sal_uInt16 nNewId = ++m_pParserState->m_nLastMenuItemId;
3432
3433 if(rClass == "NotebookBarAddonsMenuMergePoint")
3434 {
3436 m_pParserState->m_nLastMenuItemId = pParent->GetItemCount();
3437 }
3438 else if (rClass == "GtkMenuItem")
3439 {
3440 OUString sLabel(BuilderUtils::convertMnemonicMarkup(extractLabel(rProps)));
3441 OUString aCommand(extractActionName(rProps));
3442 pParent->InsertItem(nNewId, sLabel, MenuItemBits::NONE , rID);
3443 pParent->SetItemCommand(nNewId, aCommand);
3444 if (pSubMenu)
3445 pParent->SetPopupMenu(nNewId, pSubMenu);
3446 }
3447 else if (rClass == "GtkCheckMenuItem")
3448 {
3449 OUString sLabel(BuilderUtils::convertMnemonicMarkup(extractLabel(rProps)));
3450 OUString aCommand(extractActionName(rProps));
3451 pParent->InsertItem(nNewId, sLabel, MenuItemBits::CHECKABLE, rID);
3452 pParent->SetItemCommand(nNewId, aCommand);
3453 }
3454 else if (rClass == "GtkRadioMenuItem")
3455 {
3456 OUString sLabel(BuilderUtils::convertMnemonicMarkup(extractLabel(rProps)));
3457 OUString aCommand(extractActionName(rProps));
3458 pParent->InsertItem(nNewId, sLabel, MenuItemBits::AUTOCHECK | MenuItemBits::RADIOCHECK, rID);
3459 pParent->SetItemCommand(nNewId, aCommand);
3460 }
3461 else if (rClass == "GtkSeparatorMenuItem")
3462 {
3463 pParent->InsertSeparator(rID);
3464 }
3465
3466 SAL_WARN_IF(nOldCount == pParent->GetItemCount(), "vcl.builder", "probably need to implement " << rClass);
3467
3468 if (nOldCount != pParent->GetItemCount())
3469 {
3470 pParent->SetHelpId(nNewId, m_sHelpRoot + rID);
3471 if (!extractVisible(rProps))
3472 pParent->HideItem(nNewId);
3473
3474 for (auto const& prop : rProps)
3475 {
3476 const OString &rKey = prop.first;
3477 const OUString &rValue = prop.second;
3478
3479 if (rKey == "tooltip-markup")
3480 pParent->SetTipHelpText(nNewId, rValue);
3481 else if (rKey == "tooltip-text")
3482 pParent->SetTipHelpText(nNewId, rValue);
3483 else
3484 SAL_INFO("vcl.builder", "unhandled property: " << rKey);
3485 }
3486
3487 for (auto const& prop : rAtkProps)
3488 {
3489 const OString &rKey = prop.first;
3490 const OUString &rValue = prop.second;
3491
3492 if (rKey == "AtkObject::accessible-name")
3493 pParent->SetAccessibleName(nNewId, rValue);
3494 else if (rKey == "AtkObject::accessible-description")
3495 pParent->SetAccessibleDescription(nNewId, rValue);
3496 else
3497 SAL_INFO("vcl.builder", "unhandled atk property: " << rKey);
3498 }
3499
3500 for (auto const& accel : rAccels)
3501 {
3502 const OString &rSignal = accel.first;
3503 const auto &rValue = accel.second;
3504
3505 if (rSignal == "activate")
3506 pParent->SetAccelKey(nNewId, makeKeyCode(rValue));
3507 else
3508 SAL_INFO("vcl.builder", "unhandled accelerator for: " << rSignal);
3509 }
3510 }
3511
3512 rProps.clear();
3513}
3514
3517template<typename T> static bool insertItems(vcl::Window *pWindow, VclBuilder::stringmap &rMap,
3518 std::vector<std::unique_ptr<OUString>>& rUserData,
3519 const std::vector<ComboBoxTextItem> &rItems)
3520{
3521 T *pContainer = dynamic_cast<T*>(pWindow);
3522 if (!pContainer)
3523 return false;
3524
3525 sal_uInt16 nActiveId = extractActive(rMap);
3526 for (auto const& item : rItems)
3527 {
3528 sal_Int32 nPos = pContainer->InsertEntry(item.m_sItem);
3529 if (!item.m_sId.isEmpty())
3530 {
3531 rUserData.emplace_back(std::make_unique<OUString>(OUString::fromUtf8(item.m_sId)));
3532 pContainer->SetEntryData(nPos, rUserData.back().get());
3533 }
3534 }
3535 if (nActiveId < rItems.size())
3536 pContainer->SelectEntryPos(nActiveId);
3537
3538 return true;
3539}
3540
3542{
3543 OString sClass;
3544 OString sID;
3545 OUString sCustomProperty;
3546
3548 int nsId;
3549
3550 while (reader.nextAttribute(&nsId, &name))
3551 {
3552 if (name == "class")
3553 {
3554 name = reader.getAttributeValue(false);
3555 sClass = OString(name.begin, name.length);
3556 }
3557 else if (name == "id")
3558 {
3559 name = reader.getAttributeValue(false);
3560 sID = OString(name.begin, name.length);
3561 if (m_bLegacy)
3562 {
3563 sal_Int32 nDelim = sID.indexOf(':');
3564 if (nDelim != -1)
3565 {
3566 sCustomProperty = OUString::fromUtf8(sID.subView(nDelim+1));
3567 sID = sID.copy(0, nDelim);
3568 }
3569 }
3570 }
3571 }
3572
3573 if (sClass == "GtkListStore" || sClass == "GtkTreeStore")
3574 {
3575 handleListStore(reader, sID, sClass);
3576 return nullptr;
3577 }
3578 else if (sClass == "GtkMenu")
3579 {
3580 handleMenu(reader, sID, false);
3581 return nullptr;
3582 }
3583 else if (sClass == "GtkMenuBar")
3584 {
3585 VclPtr<Menu> xMenu = handleMenu(reader, sID, true);
3586 if (SystemWindow* pTopLevel = pParent ? pParent->GetSystemWindow() : nullptr)
3587 pTopLevel->SetMenuBar(dynamic_cast<MenuBar*>(xMenu.get()));
3588 return nullptr;
3589 }
3590 else if (sClass == "GtkSizeGroup")
3591 {
3592 handleSizeGroup(reader);
3593 return nullptr;
3594 }
3595 else if (sClass == "AtkObject")
3596 {
3597 assert((pParent || pAtkProps) && "must have one set");
3598 assert(!(pParent && pAtkProps) && "must not have both");
3599 auto aAtkProperties = handleAtkObject(reader);
3600 if (pParent)
3601 applyAtkProperties(pParent, aAtkProperties);
3602 if (pAtkProps)
3603 *pAtkProps = aAtkProperties;
3604 return nullptr;
3605 }
3606
3607 int nLevel = 1;
3608
3609 stringmap aProperties, aPangoAttributes;
3610 stringmap aAtkAttributes;
3611 std::vector<ComboBoxTextItem> aItems;
3612
3613 if (!sCustomProperty.isEmpty())
3614 aProperties[OString("customproperty")] = sCustomProperty;
3615
3616 VclPtr<vcl::Window> pCurrentChild;
3617 while(true)
3618 {
3620 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3621
3622 if (res == xmlreader::XmlReader::Result::Done)
3623 break;
3624
3625 if (res == xmlreader::XmlReader::Result::Begin)
3626 {
3627 if (name == "child")
3628 {
3629 if (!pCurrentChild)
3630 {
3631 pCurrentChild = insertObject(pParent, sClass, sID,
3632 aProperties, aPangoAttributes, aAtkAttributes);
3633 }
3634 handleChild(pCurrentChild, nullptr, reader);
3635 }
3636 else if (name == "items")
3637 aItems = handleItems(reader);
3638 else if (name == "style")
3639 {
3640 int nPriority = 0;
3641 std::vector<vcl::EnumContext::Context> aContext = handleStyle(reader, nPriority);
3642 if (nPriority != 0)
3643 {
3644 vcl::IPrioritable* pPrioritable = dynamic_cast<vcl::IPrioritable*>(pCurrentChild.get());
3645 SAL_WARN_IF(!pPrioritable, "vcl", "priority set for not supported item");
3646 if (pPrioritable)
3647 pPrioritable->SetPriority(nPriority);
3648 }
3649 if (!aContext.empty())
3650 {
3651 vcl::IContext* pContextControl = dynamic_cast<vcl::IContext*>(pCurrentChild.get());
3652 SAL_WARN_IF(!pContextControl, "vcl", "context set for not supported item");
3653 if (pContextControl)
3654 pContextControl->SetContext(std::move(aContext));
3655 }
3656 }
3657 else
3658 {
3659 ++nLevel;
3660 if (name == "property")
3662 else if (name == "attribute")
3663 collectPangoAttribute(reader, aPangoAttributes);
3664 else if (name == "relation")
3665 collectAtkRelationAttribute(reader, aAtkAttributes);
3666 else if (name == "role")
3667 collectAtkRoleAttribute(reader, aAtkAttributes);
3668 else if (name == "action-widget")
3669 handleActionWidget(reader);
3670 }
3671 }
3672
3673 if (res == xmlreader::XmlReader::Result::End)
3674 {
3675 --nLevel;
3676 }
3677
3678 if (!nLevel)
3679 break;
3680 }
3681
3682 if (sClass == "GtkAdjustment")
3683 {
3684 m_pParserState->m_aAdjustments[sID] = aProperties;
3685 return nullptr;
3686 }
3687 else if (sClass == "GtkTextBuffer")
3688 {
3689 m_pParserState->m_aTextBuffers[sID] = aProperties;
3690 return nullptr;
3691 }
3692
3693 if (!pCurrentChild)
3694 {
3695 pCurrentChild = insertObject(pParent, sClass, sID, aProperties,
3696 aPangoAttributes, aAtkAttributes);
3697 }
3698
3699 if (!aItems.empty())
3700 {
3701 // try to fill-in the items
3702 if (!insertItems<ComboBox>(pCurrentChild, aProperties, m_aUserData, aItems))
3703 insertItems<ListBox>(pCurrentChild, aProperties, m_aUserData, aItems);
3704 }
3705
3706 return pCurrentChild;
3707}
3708
3710{
3712 int nsId;
3713
3714 int nLevel = 1;
3715
3716 while(true)
3717 {
3719 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3720
3721 if (res == xmlreader::XmlReader::Result::Done)
3722 break;
3723
3724 if (res == xmlreader::XmlReader::Result::Begin)
3725 {
3726 ++nLevel;
3727 if (name == "property")
3728 applyPackingProperty(pCurrent, pParent, reader);
3729 }
3730
3731 if (res == xmlreader::XmlReader::Result::End)
3732 {
3733 --nLevel;
3734 }
3735
3736 if (!nLevel)
3737 break;
3738 }
3739}
3740
3742 vcl::Window *pParent,
3743 xmlreader::XmlReader &reader)
3744{
3745 if (!pCurrent)
3746 return;
3747
3748 //ToolBoxItems are not true widgets just elements
3749 //of the ToolBox itself
3750 ToolBox *pToolBoxParent = nullptr;
3751 if (pCurrent == pParent)
3752 pToolBoxParent = dynamic_cast<ToolBox*>(pParent);
3753
3755 int nsId;
3756
3757 if (pCurrent->GetType() == WindowType::SCROLLWINDOW)
3758 {
3759 auto aFind = m_pParserState->m_aRedundantParentWidgets.find(VclPtr<vcl::Window>(pCurrent));
3760 if (aFind != m_pParserState->m_aRedundantParentWidgets.end())
3761 {
3762 pCurrent = aFind->second;
3763 assert(pCurrent);
3764 }
3765 }
3766
3767 while (reader.nextAttribute(&nsId, &name))
3768 {
3769 if (name == "name")
3770 {
3771 name = reader.getAttributeValue(false);
3772 OString sKey(name.begin, name.length);
3773 sKey = sKey.replace('_', '-');
3774 (void)reader.nextItem(
3775 xmlreader::XmlReader::Text::Raw, &name, &nsId);
3776 OString sValue(name.begin, name.length);
3777
3778 if (sKey == "expand" || sKey == "resize")
3779 {
3780 bool bTrue = (!sValue.isEmpty() && (sValue[0] == 't' || sValue[0] == 'T' || sValue[0] == '1'));
3781 if (pToolBoxParent)
3782 pToolBoxParent->SetItemExpand(m_pParserState->m_nLastToolbarId, bTrue);
3783 else
3784 pCurrent->set_expand(bTrue);
3785 continue;
3786 }
3787
3788 if (pToolBoxParent)
3789 continue;
3790
3791 if (sKey == "fill")
3792 {
3793 bool bTrue = (!sValue.isEmpty() && (sValue[0] == 't' || sValue[0] == 'T' || sValue[0] == '1'));
3794 pCurrent->set_fill(bTrue);
3795 }
3796 else if (sKey == "pack-type")
3797 {
3798 VclPackType ePackType = (!sValue.isEmpty() && (sValue[0] == 'e' || sValue[0] == 'E')) ? VclPackType::End : VclPackType::Start;
3799 pCurrent->set_pack_type(ePackType);
3800 }
3801 else if (sKey == "left-attach")
3802 {
3803 pCurrent->set_grid_left_attach(sValue.toInt32());
3804 }
3805 else if (sKey == "top-attach")
3806 {
3807 pCurrent->set_grid_top_attach(sValue.toInt32());
3808 }
3809 else if (sKey == "width")
3810 {
3811 pCurrent->set_grid_width(sValue.toInt32());
3812 }
3813 else if (sKey == "height")
3814 {
3815 pCurrent->set_grid_height(sValue.toInt32());
3816 }
3817 else if (sKey == "padding")
3818 {
3819 pCurrent->set_padding(sValue.toInt32());
3820 }
3821 else if (sKey == "position")
3822 {
3823 set_window_packing_position(pCurrent, sValue.toInt32());
3824 }
3825 else if (sKey == "secondary")
3826 {
3827 pCurrent->set_secondary(toBool(sValue));
3828 }
3829 else if (sKey == "non-homogeneous")
3830 {
3831 pCurrent->set_non_homogeneous(toBool(sValue));
3832 }
3833 else if (sKey == "homogeneous")
3834 {
3835 pCurrent->set_non_homogeneous(!toBool(sValue));
3836 }
3837 else
3838 {
3839 SAL_WARN_IF(sKey != "shrink", "vcl.builder", "unknown packing: " << sKey);
3840 }
3841 }
3842 }
3843}
3844
3845std::vector<vcl::EnumContext::Context> VclBuilder::handleStyle(xmlreader::XmlReader &reader, int &nPriority)
3846{
3847 std::vector<vcl::EnumContext::Context> aContext;
3848
3850 int nsId;
3851
3852 int nLevel = 1;
3853
3854 while(true)
3855 {
3857 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3858
3859 if (res == xmlreader::XmlReader::Result::Done)
3860 break;
3861
3862 if (res == xmlreader::XmlReader::Result::Begin)
3863 {
3864 ++nLevel;
3865 if (name == "class")
3866 {
3867 OString classStyle = getStyleClass(reader);
3868
3869 if (classStyle.startsWith("context-"))
3870 {
3871 OString sContext = classStyle.copy(classStyle.indexOf('-') + 1);
3872 OUString sContext2(sContext.getStr(), sContext.getLength(), RTL_TEXTENCODING_UTF8);
3873 aContext.push_back(vcl::EnumContext::GetContextEnum(sContext2));
3874 }
3875 else if (classStyle.startsWith("priority-"))
3876 {
3877 OString aPriority = classStyle.copy(classStyle.indexOf('-') + 1);
3878 OUString aPriority2(aPriority.getStr(), aPriority.getLength(), RTL_TEXTENCODING_UTF8);
3879 nPriority = aPriority2.toInt32();
3880 }
3881 else if (classStyle != "small-button" && classStyle != "destructive-action" && classStyle != "suggested-action")
3882 {
3883 SAL_WARN("vcl.builder", "unknown class: " << classStyle);
3884 }
3885 }
3886 }
3887
3888 if (res == xmlreader::XmlReader::Result::End)
3889 {
3890 --nLevel;
3891 }
3892
3893 if (!nLevel)
3894 break;
3895 }
3896
3897 return aContext;
3898}
3899
3901{
3903 int nsId;
3904 OString aRet;
3905
3906 while (reader.nextAttribute(&nsId, &name))
3907 {
3908 if (name == "name")
3909 {
3910 name = reader.getAttributeValue(false);
3911 aRet = OString (name.begin, name.length);
3912 }
3913 }
3914
3915 return aRet;
3916}
3917
3919{
3921 int nsId;
3922
3923 OString sProperty, sContext;
3924
3925 bool bTranslated = false;
3926
3927 while (reader.nextAttribute(&nsId, &name))
3928 {
3929 if (name == "name")
3930 {
3931 name = reader.getAttributeValue(false);
3932 sProperty = OString(name.begin, name.length);
3933 }
3934 else if (name == "context")
3935 {
3936 name = reader.getAttributeValue(false);
3937 sContext = OString(name.begin, name.length);
3938 }
3939 else if (name == "translatable" && reader.getAttributeValue(false) == "yes")
3940 {
3941 bTranslated = true;
3942 }
3943 }
3944
3945 (void)reader.nextItem(xmlreader::XmlReader::Text::Raw, &name, &nsId);
3946 OString sValue(name.begin, name.length);
3947 OUString sFinalValue;
3948 if (bTranslated)
3949 {
3950 sFinalValue = Translate::get(TranslateId{sContext.getStr(), sValue.getStr()}, m_pParserState->m_aResLocale);
3951 }
3952 else
3953 sFinalValue = OUString::fromUtf8(sValue);
3954
3955 if (!sProperty.isEmpty())
3956 {
3957 sProperty = sProperty.replace('_', '-');
3958 if (m_pStringReplace)
3959 sFinalValue = (*m_pStringReplace)(sFinalValue);
3960 rMap[sProperty] = sFinalValue;
3961 }
3962}
3963
3965{
3967 int nsId;
3968
3969 OString sResponse;
3970
3971 while (reader.nextAttribute(&nsId, &name))
3972 {
3973 if (name == "response")
3974 {
3975 name = reader.getAttributeValue(false);
3976 sResponse = OString(name.begin, name.length);
3977 }
3978 }
3979
3980 (void)reader.nextItem(xmlreader::XmlReader::Text::Raw, &name, &nsId);
3981 OString sID(name.begin, name.length);
3982 sal_Int32 nDelim = sID.indexOf(':');
3983 if (nDelim != -1)
3984 sID = sID.copy(0, nDelim);
3985 set_response(sID, sResponse.toInt32());
3986}
3987
3989{
3991 int nsId;
3992
3993 OString sProperty;
3994 OString sValue;
3995 OString sModifiers;
3996
3997 while (reader.nextAttribute(&nsId, &name))
3998 {
3999 if (name == "key")
4000 {
4001 name = reader.getAttributeValue(false);
4002 sValue = OString(name.begin, name.length);
4003 }
4004 else if (name == "signal")
4005 {
4006 name = reader.getAttributeValue(false);
4007 sProperty = OString(name.begin, name.length);
4008 }
4009 else if (name == "modifiers")
4010 {
4011 name = reader.getAttributeValue(false);
4012 sModifiers = OString(name.begin, name.length);
4013 }
4014 }
4015
4016 if (!sProperty.isEmpty() && !sValue.isEmpty())
4017 {
4018 rMap[sProperty] = std::make_pair(sValue, sModifiers);
4019 }
4020}
4021
4023{
4024 return m_aChildren.empty() ? nullptr : m_aChildren[0].m_pWindow.get();
4025}
4026
4028{
4029 for (auto const& child : m_aChildren)
4030 {
4031 if (child.m_sID == sID)
4032 return child.m_pWindow;
4033 }
4034
4035 return nullptr;
4036}
4037
4038PopupMenu *VclBuilder::get_menu(std::string_view sID)
4039{
4040 for (auto const& menu : m_aMenus)
4041 {
4042 if (menu.m_sID == sID)
4043 return dynamic_cast<PopupMenu*>(menu.m_pMenu.get());
4044 }
4045
4046 return nullptr;
4047}
4048
4049void VclBuilder::set_response(std::string_view sID, short nResponse)
4050{
4051 switch (nResponse)
4052 {
4053 case -5:
4054 nResponse = RET_OK;
4055 break;
4056 case -6:
4057 nResponse = RET_CANCEL;
4058 break;
4059 case -7:
4060 nResponse = RET_CLOSE;
4061 break;
4062 case -8:
4063 nResponse = RET_YES;
4064 break;
4065 case -9:
4066 nResponse = RET_NO;
4067 break;
4068 case -11:
4069 nResponse = RET_HELP;
4070 break;
4071 default:
4072 assert(nResponse >= 100 && "keep non-canned responses in range 100+ to avoid collision with vcl RET_*");
4073 break;
4074 }
4075
4076 for (const auto & child : m_aChildren)
4077 {
4078 if (child.m_sID == sID)
4079 {
4080 PushButton* pPushButton = dynamic_cast<PushButton*>(child.m_pWindow.get());
4081 assert(pPushButton);
4082 Dialog* pDialog = pPushButton->GetParentDialog();
4083 assert(pDialog);
4084 pDialog->add_button(pPushButton, nResponse, false);
4085 return;
4086 }
4087 }
4088
4089 assert(false);
4090}
4091
4092void VclBuilder::delete_by_name(const OString& sID)
4093{
4094 auto aI = std::find_if(m_aChildren.begin(), m_aChildren.end(),
4095 [&sID](WinAndId& rItem) { return rItem.m_sID == sID; });
4096 if (aI != m_aChildren.end())
4097 {
4098 aI->m_pWindow.disposeAndClear();
4099 m_aChildren.erase(aI);
4100 }
4101}
4102
4104{
4105 drop_ownership(pWindow);
4106 pWindow->disposeOnce();
4107}
4108
4110{
4111 auto aI = std::find_if(m_aChildren.begin(), m_aChildren.end(),
4112 [&pWindow](WinAndId& rItem) { return rItem.m_pWindow == pWindow; });
4113 if (aI != m_aChildren.end())
4114 m_aChildren.erase(aI);
4115}
4116
4117OString VclBuilder::get_by_window(const vcl::Window *pWindow) const
4118{
4119 for (auto const& child : m_aChildren)
4120 {
4121 if (child.m_pWindow == pWindow)
4122 return child.m_sID;
4123 }
4124
4125 return OString();
4126}
4127
4129{
4130 //We've stored the return of new Control, some of these get
4131 //border windows placed around them which are what you get
4132 //from GetChild, so scoot up a level if necessary to get the
4133 //window whose position value we have
4134 const vcl::Window *pPropHolder = pWindow->ImplGetWindow();
4135
4136 for (auto const& child : m_aChildren)
4137 {
4138 if (child.m_pWindow == pPropHolder)
4139 return child.m_aPackingData;
4140 }
4141
4142 return PackingData();
4143}
4144
4145void VclBuilder::set_window_packing_position(const vcl::Window *pWindow, sal_Int32 nPosition)
4146{
4147 for (auto & child : m_aChildren)
4148 {
4149 if (child.m_pWindow == pWindow)
4150 child.m_aPackingData.m_nPosition = nPosition;
4151 }
4152}
4153
4155{
4156 std::map<OString, ListStore>::const_iterator aI = m_pParserState->m_aModels.find(sID);
4157 if (aI != m_pParserState->m_aModels.end())
4158 return &(aI->second);
4159 return nullptr;
4160}
4161
4163{
4164 std::map<OString, TextBuffer>::const_iterator aI = m_pParserState->m_aTextBuffers.find(sID);
4165 if (aI != m_pParserState->m_aTextBuffers.end())
4166 return &(aI->second);
4167 return nullptr;
4168}
4169
4171{
4172 std::map<OString, Adjustment>::const_iterator aI = m_pParserState->m_aAdjustments.find(sID);
4173 if (aI != m_pParserState->m_aAdjustments.end())
4174 return &(aI->second);
4175 return nullptr;
4176}
4177
4178void VclBuilder::mungeModel(ComboBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId)
4179{
4180 for (auto const& entry : rStore.m_aEntries)
4181 {
4182 const ListStore::row &rRow = entry;
4183 sal_uInt16 nEntry = rTarget.InsertEntry(rRow[0]);
4184 if (rRow.size() > 1)
4185 {
4186 if (m_bLegacy)
4187 {
4188 sal_Int32 nValue = rRow[1].toInt32();
4189 rTarget.SetEntryData(nEntry, reinterpret_cast<void*>(nValue));
4190 }
4191 else
4192 {
4193 if (!rRow[1].isEmpty())
4194 {
4195 m_aUserData.emplace_back(std::make_unique<OUString>(rRow[1]));
4196 rTarget.SetEntryData(nEntry, m_aUserData.back().get());
4197 }
4198 }
4199 }
4200 }
4201 if (nActiveId < rStore.m_aEntries.size())
4202 rTarget.SelectEntryPos(nActiveId);
4203}
4204
4205void VclBuilder::mungeModel(ListBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId)
4206{
4207 for (auto const& entry : rStore.m_aEntries)
4208 {
4209 const ListStore::row &rRow = entry;
4210 sal_uInt16 nEntry = rTarget.InsertEntry(rRow[0]);
4211 if (rRow.size() > 1)
4212 {
4213 if (m_bLegacy)
4214 {
4215 sal_Int32 nValue = rRow[1].toInt32();
4216 rTarget.SetEntryData(nEntry, reinterpret_cast<void*>(nValue));
4217 }
4218 else
4219 {
4220 if (!rRow[1].isEmpty())
4221 {
4222 m_aUserData.emplace_back(std::make_unique<OUString>(rRow[1]));
4223 rTarget.SetEntryData(nEntry, m_aUserData.back().get());
4224 }
4225 }
4226 }
4227 }
4228 if (nActiveId < rStore.m_aEntries.size())
4229 rTarget.SelectEntryPos(nActiveId);
4230}
4231
4232void VclBuilder::mungeModel(SvTabListBox& rTarget, const ListStore &rStore, sal_uInt16 nActiveId)
4233{
4234 for (auto const& entry : rStore.m_aEntries)
4235 {
4236 const ListStore::row &rRow = entry;
4237 auto pEntry = rTarget.InsertEntry(rRow[0]);
4238 if (rRow.size() > 1)
4239 {
4240 if (m_bLegacy)
4241 {
4242 sal_Int32 nValue = rRow[1].toInt32();
4243 pEntry->SetUserData(reinterpret_cast<void*>(nValue));
4244 }
4245 else
4246 {
4247 if (!rRow[1].isEmpty())
4248 {
4249 m_aUserData.emplace_back(std::make_unique<OUString>(rRow[1]));
4250 pEntry->SetUserData(m_aUserData.back().get());
4251 }
4252 }
4253 }
4254 }
4255 if (nActiveId < rStore.m_aEntries.size())
4256 {
4257 SvTreeListEntry* pEntry = rTarget.GetEntry(nullptr, nActiveId);
4258 rTarget.Select(pEntry);
4259 }
4260}
4261
4263{
4264 int nMul = rtl_math_pow10Exp(1, rTarget.GetDecimalDigits());
4265
4266 for (auto const& elem : rAdjustment)
4267 {
4268 const OString &rKey = elem.first;
4269 const OUString &rValue = elem.second;
4270
4271 if (rKey == "upper")
4272 {
4273 sal_Int64 nUpper = rValue.toDouble() * nMul;
4274 rTarget.SetMax(nUpper);
4275 rTarget.SetLast(nUpper);
4276 }
4277 else if (rKey == "lower")
4278 {
4279 sal_Int64 nLower = rValue.toDouble() * nMul;
4280 rTarget.SetMin(nLower);
4281 rTarget.SetFirst(nLower);
4282 }
4283 else if (rKey == "value")
4284 {
4285 sal_Int64 nValue = rValue.toDouble() * nMul;
4286 rTarget.SetValue(nValue);
4287 }
4288 else if (rKey == "step-increment")
4289 {
4290 sal_Int64 nSpinSize = rValue.toDouble() * nMul;
4291 rTarget.SetSpinSize(nSpinSize);
4292 }
4293 else
4294 {
4295 SAL_INFO("vcl.builder", "unhandled property :" << rKey);
4296 }
4297 }
4298}
4299
4301{
4302 double nMaxValue = 0, nMinValue = 0, nValue = 0, nSpinSize = 0;
4303
4304 for (auto const& elem : rAdjustment)
4305 {
4306 const OString &rKey = elem.first;
4307 const OUString &rValue = elem.second;
4308
4309 if (rKey == "upper")
4310 nMaxValue = rValue.toDouble();
4311 else if (rKey == "lower")
4312 nMinValue = rValue.toDouble();
4313 else if (rKey == "value")
4314 nValue = rValue.toDouble();
4315 else if (rKey == "step-increment")
4316 nSpinSize = rValue.toDouble();
4317 else
4318 SAL_INFO("vcl.builder", "unhandled property :" << rKey);
4319 }
4320
4321 Formatter& rFormatter = rTarget.GetFormatter();
4322 rFormatter.SetMinValue(nMinValue);
4323 rFormatter.SetMaxValue(nMaxValue);
4324 rFormatter.SetValue(nValue);
4325 rFormatter.SetSpinSize(nSpinSize);
4326}
4327
4328void VclBuilder::mungeAdjustment(ScrollBar &rTarget, const Adjustment &rAdjustment)
4329{
4330 for (auto const& elem : rAdjustment)
4331 {
4332 const OString &rKey = elem.first;
4333 const OUString &rValue = elem.second;
4334
4335 if (rKey == "upper")
4336 rTarget.SetRangeMax(rValue.toInt32());
4337 else if (rKey == "lower")
4338 rTarget.SetRangeMin(rValue.toInt32());
4339 else if (rKey == "value")
4340 rTarget.SetThumbPos(rValue.toInt32());
4341 else if (rKey == "step-increment")
4342 rTarget.SetLineSize(rValue.toInt32());
4343 else if (rKey == "page-increment")
4344 rTarget.SetPageSize(rValue.toInt32());
4345 else
4346 {
4347 SAL_INFO("vcl.builder", "unhandled property :" << rKey);
4348 }
4349 }
4350}
4351
4352void VclBuilder::mungeAdjustment(Slider& rTarget, const Adjustment& rAdjustment)
4353{
4354 for (auto const& elem : rAdjustment)
4355 {
4356 const OString &rKey = elem.first;
4357 const OUString &rValue = elem.second;
4358
4359 if (rKey == "upper")
4360 rTarget.SetRangeMax(rValue.toInt32());
4361 else if (rKey == "lower")
4362 rTarget.SetRangeMin(rValue.toInt32());
4363 else if (rKey == "value")
4364 rTarget.SetThumbPos(rValue.toInt32());
4365 else if (rKey == "step-increment")
4366 rTarget.SetLineSize(rValue.toInt32());
4367 else if (rKey == "page-increment")
4368 rTarget.SetPageSize(rValue.toInt32());
4369 else
4370 {
4371 SAL_INFO("vcl.builder", "unhandled property :" << rKey);
4372 }
4373 }
4374}
4375
4377{
4378 for (auto const& elem : rTextBuffer)
4379 {
4380 const OString &rKey = elem.first;
4381 const OUString &rValue = elem.second;
4382
4383 if (rKey == "text")
4384 rTarget.SetText(rValue);
4385 else
4386 {
4387 SAL_INFO("vcl.builder", "unhandled property :" << rKey);
4388 }
4389 }
4390}
4391
4393 : m_nLastToolbarId(0)
4394 , m_nLastMenuItemId(0)
4395{}
4396
4398 : m_sID(std::move(aId))
4399 , m_pMenu(pMenu)
4400{}
4401
4402/* 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:3517
std::map< OUString, std::shared_ptr< NoAutoUnloadModule > > ModuleMap
Definition: builder.cxx:1441
static ModuleMap g_aModuleMap
Definition: builder.cxx:1442
#define SAL_DLLPREFIX
Definition: builder.cxx:1449
static void thisModule()
Definition: builder.cxx:1428
static bool toBool(std::string_view rValue)
Definition: builder.cxx:91
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:200
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:185
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
Definition: builder.cxx:214
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:3598
void SetState(TriState eState)
Definition: button.cxx:3576
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:1439
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:79
Size GetSizePixel() const
Definition: Image.cxx:86
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:1625
void SetSymbol(SymbolType eSymbol)
Definition: button.cxx:1611
std::shared_ptr< std::vector< VclPtr< RadioButton > > > m_xGroup
Definition: button.hxx:379
void group(RadioButton &rOther)
Definition: button.cxx:2255
void SetModeRadioImage(const Image &rImage)
Definition: button.cxx:2695
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:505
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:1783
void SetPageName(sal_uInt16 nPageId, const OString &rName) const
Definition: tabctrl.cxx:2003
void SetAccessibleDescription(sal_uInt16 nItemId, const OUString &rStr)
Definition: tabctrl.cxx:1987
void SetTabPage(sal_uInt16 nPageId, TabPage *pPage)
Definition: tabctrl.cxx:1889
void SetAccessibleName(sal_uInt16 nItemId, const OUString &rStr)
Definition: tabctrl.cxx:1971
TabPage * GetTabPage(sal_uInt16 nPageId) const
Definition: tabctrl.cxx:1915
void SetCurPageId(sal_uInt16 nPageId)
Definition: tabctrl.cxx:1825
void InsertPage(sal_uInt16 nPageId, const OUString &rText, sal_uInt16 nPos=TAB_APPEND)
Definition: tabctrl.cxx:1641
sal_uInt16 GetCurPageId() const
Definition: tabctrl.cxx:1859
sal_uInt16 GetPageId(sal_uInt16 nPos) const
Definition: tabctrl.cxx:1788
void SetHelpText(sal_uInt16 nPageId, const OUString &rText)
Definition: tabctrl.cxx:1955
void SetPageText(sal_uInt16 nPageId, const OUString &rText)
Definition: tabctrl.cxx:1925
void RemovePage(sal_uInt16 nPageId)
Definition: tabctrl.cxx:1691
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:2646
static OString getStyleClass(xmlreader::XmlReader &reader)
Definition: builder.cxx:3900
void handleListStore(xmlreader::XmlReader &reader, const OString &rID, std::string_view rClass)
Definition: builder.cxx:2998
stringmap m_aDeferredProperties
Definition: builder.hxx:126
static std::vector< vcl::EnumContext::Context > handleStyle(xmlreader::XmlReader &reader, int &nPriority)
Definition: builder.cxx:3845
void handleActionWidget(xmlreader::XmlReader &reader)
Definition: builder.cxx:3964
void connectNumericFormatterAdjustment(const OString &id, const OUString &rAdjustment)
Definition: builder.cxx:1267
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:1397
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:4128
VclPtr< vcl::Window > m_pParent
Definition: builder.hxx:298
void mungeModel(ListBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId)
Definition: builder.cxx:4205
const TextBuffer * get_buffer_by_name(const OString &sID) const
Definition: builder.cxx:4162
OString m_sHelpRoot
Definition: builder.hxx:296
vcl::Window * get_widget_root()
Definition: builder.cxx:4022
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:3541
void extractGroup(const OString &id, stringmap &rVec)
Definition: builder.cxx:1253
void extractBuffer(const OString &id, stringmap &rVec)
Definition: builder.cxx:1354
static void applyAtkProperties(vcl::Window *pWindow, const stringmap &rProperties)
Definition: builder.cxx:3072
void extractButtonImage(const OString &id, stringmap &rMap, bool bRadio)
Definition: builder.cxx:1373
const Adjustment * get_adjustment_by_name(const OString &sID) const
Definition: builder.cxx:4170
void extractModel(const OString &id, stringmap &rVec)
Definition: builder.cxx:1343
static void collectAtkRelationAttribute(xmlreader::XmlReader &reader, stringmap &rMap)
Definition: builder.cxx:2874
bool m_bToplevelHasDeferredInit
Definition: builder.hxx:299
static void mungeTextBuffer(VclMultiLineEdit &rTarget, const TextBuffer &rTextBuffer)
Definition: builder.cxx:4376
void insertMenuObject(Menu *pParent, PopupMenu *pSubMenu, const OString &rClass, const OString &rID, stringmap &rProps, stringmap &rAtkProps, accelmap &rAccels)
Definition: builder.cxx:3427
VclPtr< vcl::Window > insertObject(vcl::Window *pParent, const OString &rClass, const OString &rID, stringmap &rProps, stringmap &rPangoAttributes, stringmap &rAtkProps)
Definition: builder.cxx:2443
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:4049
void cleanupWidgetOwnScrolling(vcl::Window *pScrollParent, vcl::Window *pWindow, stringmap &rMap)
Definition: builder.cxx:1415
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:3988
OString m_sID
Definition: builder.hxx:295
void set_window_packing_position(const vcl::Window *pWindow, sal_Int32 nPosition)
Definition: builder.cxx:4145
void collectProperty(xmlreader::XmlReader &reader, stringmap &rVec) const
Definition: builder.cxx:3918
static void collectAtkRoleAttribute(xmlreader::XmlReader &reader, stringmap &rMap)
Definition: builder.cxx:2903
T * get(VclPtr< T > &ret, const OString &sID)
Definition: builder.hxx:421
void extractMnemonicWidget(const OString &id, stringmap &rMap)
Definition: builder.cxx:1383
static int getImageSize(const stringmap &rMap)
Definition: builder.cxx:1364
std::vector< MenuAndId > m_aMenus
Definition: builder.hxx:161
vcl::Window * get_by_name(std::string_view sID)
Definition: builder.cxx:4027
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:1279
OString get_by_window(const vcl::Window *pWindow) const
Definition: builder.cxx:4117
const ListStore * get_model_by_name(const OString &sID) const
Definition: builder.cxx:4154
stringmap handleAtkObject(xmlreader::XmlReader &reader) const
Definition: builder.cxx:3036
void handleRow(xmlreader::XmlReader &reader, const OString &rID)
Definition: builder.cxx:2923
void handleChild(vcl::Window *pParent, stringmap *pAtkProps, xmlreader::XmlReader &reader)
Definition: builder.cxx:2711
void handleMenuObject(Menu *pParent, xmlreader::XmlReader &reader)
Definition: builder.cxx:3246
void drop_ownership(const vcl::Window *pWindow)
Definition: builder.cxx:4109
void setDeferredProperties()
Definition: builder.cxx:2202
void handleSizeGroup(xmlreader::XmlReader &reader)
Definition: builder.cxx:3328
bool m_bLegacy
Definition: builder.hxx:302
void delete_by_window(vcl::Window *pWindow)
Definition: builder.cxx:4103
static void mungeAdjustment(NumericFormatter &rTarget, const Adjustment &rAdjustment)
Definition: builder.cxx:4262
stringmap Adjustment
Definition: builder.hxx:234
void applyPackingProperty(vcl::Window *pCurrent, vcl::Window *pParent, xmlreader::XmlReader &reader)
Definition: builder.cxx:3741
void disposeBuilder()
releases references and disposes all children.
Definition: builder.cxx:813
void delete_by_name(const OString &sID)
Definition: builder.cxx:4092
void handleTabChild(vcl::Window *pParent, xmlreader::XmlReader &reader)
Definition: builder.cxx:2525
static SymbolType mapStockToSymbol(std::u16string_view icon_name)
Definition: builder.cxx:125
void handleMenuChild(Menu *pParent, xmlreader::XmlReader &reader)
Definition: builder.cxx:3214
static void collectPangoAttribute(xmlreader::XmlReader &reader, stringmap &rMap)
Definition: builder.cxx:2848
VclPtr< Menu > handleMenu(xmlreader::XmlReader &reader, const OString &rID, bool bMenuBar)
Definition: builder.cxx:3161
void handlePacking(vcl::Window *pCurrent, vcl::Window *pParent, xmlreader::XmlReader &reader)
Definition: builder.cxx:3709
VclPtr< vcl::Window > makeObject(vcl::Window *pParent, const OString &rClass, const OString &rID, stringmap &rVec)
Definition: builder.cxx:1555
std::vector< ComboBoxTextItem > handleItems(xmlreader::XmlReader &reader) const
Definition: builder.cxx:3087
stringmap TextBuffer
Definition: builder.hxx:229
void connectFormattedFormatterAdjustment(const OString &id, const OUString &rAdjustment)
Definition: builder.cxx:1273
std::unique_ptr< NotebookBarAddonsItem > m_pNotebookBarAddonsItem
Definition: builder.hxx:128
PopupMenu * get_menu(std::string_view sID)
Definition: builder.cxx:4038
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:326
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 SetContext(std::vector< vcl::EnumContext::Context > &&aContext)
Definition: IContext.hxx:25
void SetPriority(int nPriority)
void SetStyle(WinBits nStyle)
Definition: window.cxx:1964
vcl::Window * GetParent() const
Definition: window2.cxx:1121
bool IsControlFont() const
Definition: window2.cxx:1091
void SetControlFont()
Definition: window2.cxx:433
WindowType GetType() const
Definition: window2.cxx:998
void set_padding(sal_Int32 nPadding)
Definition: window2.cxx:1801
virtual void SetSizePixel(const Size &rNewSize)
Definition: window2.cxx:1286
Size get_preferred_size() const
Definition: window2.cxx:1692
vcl::Window * GetWindow(GetWindowType nType) const
Definition: stacking.cxx:1035
void set_border_width(sal_Int32 nBorderWidth)
Definition: window2.cxx:1867
void set_grid_left_attach(sal_Int32 nAttach)
Definition: window2.cxx:1837
Dialog * GetParentDialog() const
Definition: window2.cxx:1006
void set_height_request(sal_Int32 nHeightRequest)
Definition: window2.cxx:1642
void set_id(const OUString &rID)
Sets an ID.
Definition: window.cxx:3929
VclPackType get_pack_type() const
Definition: window2.cxx:1783
void reorderWithinParent(sal_uInt16 nNewPosition)
Definition: stacking.cxx:162
void set_grid_height(sal_Int32 nRows)
Definition: window2.cxx:1849
bool set_font_attribute(const OString &rKey, std::u16string_view rValue)
Definition: window2.cxx:1410
WinBits GetStyle() const
Definition: window2.cxx:977
void Show(bool bVisible=true, ShowFlags nFlags=ShowFlags::NONE)
Definition: window.cxx:2189
const OString & GetHelpId() const
Definition: window2.cxx:847
vcl::Font GetControlFont() const
Definition: window2.cxx:462
bool IsDialog() const
Definition: window2.cxx:1026
void set_pack_type(VclPackType ePackType)
Definition: window2.cxx:1789
bool get_secondary() const
Definition: window2.cxx:1955
SystemWindow * GetSystemWindow() const
Definition: stacking.cxx:806
void SetAccessibleRole(sal_uInt16 nRole)
bool IsDockingWindow() const
Definition: window2.cxx:930
SAL_DLLPRIVATE WindowImpl * ImplGetWindowImpl() const
Definition: window.hxx:528
void SetHelpId(const OString &)
Definition: window2.cxx:842
sal_Int32 get_height_request() const
Definition: window2.cxx:1943
void add_to_size_group(const std::shared_ptr< VclSizeGroup > &xGroup)
Definition: window2.cxx:1979
sal_Int32 get_grid_left_attach() const
Definition: window2.cxx:1831
sal_Int32 get_grid_top_attach() const
Definition: window2.cxx:1855
void set_width_request(sal_Int32 nWidthRequest)
Definition: window2.cxx:1656
bool IsSystemWindow() const
Definition: window2.cxx:1021
virtual Size GetSizePixel() const
Definition: window.cxx:2404
virtual bool set_property(const OString &rKey, const OUString &rValue)
Definition: window2.cxx:1476
sal_Int32 get_width_request() const
Definition: window2.cxx:1949
void set_secondary(bool bSecondary)
Definition: window2.cxx:1961
void set_expand(bool bExpand)
Definition: window2.cxx:1777
void set_grid_top_attach(sal_Int32 nAttach)
Definition: window2.cxx:1861
void SetQuickHelpText(const OUString &rHelpText)
Definition: window2.cxx:1250
virtual OUString GetText() const
Definition: window.cxx:3060
void set_fill(bool bFill)
Definition: window2.cxx:1813
void SetAccessibleRelationLabelFor(vcl::Window *pLabelFor)
vcl::Window * ImplGetWindow() const
if this is a proxy return the client, otherwise itself
Definition: window2.cxx:854
void set_non_homogeneous(bool bNonHomogeneous)
Definition: window2.cxx:1973
void SetType(WindowType nType)
Definition: window2.cxx:992
void set_grid_width(sal_Int32 nCols)
Definition: window2.cxx:1825
void SetAccessibleRelationLabeledBy(vcl::Window *pLabeledBy)
std::unique_ptr< Entry > m_xEntry
Definition: weld.hxx:1889
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:1890
void get_increments(int &step, int &page, FieldUnit eDestUnit) const
Definition: weld.hxx:2086
FieldUnit m_eSrcUnit
Definition: weld.hxx:1978
static OUString MetricToString(FieldUnit rUnit)
Definition: builder.cxx:231
void set_increments(int step, int page, FieldUnit eValueUnit)
Definition: weld.hxx:2079
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:2021
OUString format_number(sal_Int64 nValue) const
Definition: builder.cxx:291
std::unique_ptr< weld::SpinButton > m_xSpinButton
Definition: weld.hxx:1979
sal_Int64 get_value(FieldUnit eDestUnit) const
Definition: weld.hxx:2026
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:2253
sal_Int16 getRoleFromName(const OString &roleName)
Definition: builder.cxx:2305
void set_properties(vcl::Window *pWindow, const VclBuilder::stringmap &rProps)
Definition: builder.cxx:2214
OUString convertMnemonicMarkup(std::u16string_view rIn)
Definition: builder.cxx:2224
bool extractDropdown(VclBuilder::stringmap &rMap)
Definition: builder.cxx:2261
OUString extractCustomProperty(VclBuilder::stringmap &rMap)
Definition: builder.cxx:2241
void reorderWithinParent(vcl::Window &rWindow, sal_uInt16 nNewPosition)
Definition: builder.cxx:2273
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:42
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:1456
void(* f)(TrueTypeTable *)
Definition: ttcr.cxx:466
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:392
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:4397
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:274
#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
@ RET_HELP
Definition: vclenum.hxx:219
@ RET_OK
Definition: vclenum.hxx:213
@ RET_CLOSE
Definition: vclenum.hxx:218
@ RET_CANCEL
Definition: vclenum.hxx:212
@ RET_NO
Definition: vclenum.hxx:215
@ RET_YES
Definition: vclenum.hxx:214
VclMessageType
Definition: vclenum.hxx:233
VclPackType
Definition: vclenum.hxx:201
VclButtonsType
Definition: vclenum.hxx:223
ToolBoxItemBits
Definition: vclenum.hxx:51