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