build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / window / builder.cxx
blob5202bbfd0b29b5dae051d96d0d69c91509e6eecb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include <com/sun/star/packages/zip/ZipFileAccess.hpp>
12 #include <comphelper/lok.hxx>
13 #include <comphelper/processfactory.hxx>
14 #include <osl/module.hxx>
15 #include <sal/log.hxx>
16 #include <unotools/configmgr.hxx>
17 #include <vcl/builder.hxx>
18 #include <vcl/button.hxx>
19 #include <vcl/dialog.hxx>
20 #include <vcl/edit.hxx>
21 #include <vcl/field.hxx>
22 #include <vcl/fixed.hxx>
23 #include <vcl/fixedhyper.hxx>
24 #include <vcl/IPrioritable.hxx>
25 #include <vcl/layout.hxx>
26 #include <vcl/lstbox.hxx>
27 #include <vcl/menubtn.hxx>
28 #include <vcl/mnemonic.hxx>
29 #include <vcl/prgsbar.hxx>
30 #include <vcl/scrbar.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/tabctrl.hxx>
33 #include <vcl/tabpage.hxx>
34 #include <vcl/throbber.hxx>
35 #include <vcl/toolbox.hxx>
36 #include <vcl/vclmedit.hxx>
37 #include <vcl/settings.hxx>
38 #include <vcl/slider.hxx>
39 #include <vcl/commandinfoprovider.hxx>
40 #include <svdata.hxx>
41 #include <svids.hrc>
42 #include <window.h>
43 #include <xmlreader/xmlreader.hxx>
45 #ifdef DISABLE_DYNLOADING
46 #include <dlfcn.h>
47 #endif
49 namespace
51 sal_uInt16 mapStockToImageResource(const OString& sType)
53 sal_uInt16 nRet = 0;
54 if (sType == "gtk-index")
55 nRet = SV_RESID_BITMAP_INDEX;
56 else if (sType == "gtk-refresh")
57 nRet = SV_RESID_BITMAP_REFRESH;
58 return nRet;
61 SymbolType mapStockToSymbol(const OString& sType)
63 SymbolType eRet = SymbolType::DONTKNOW;
64 if (sType == "gtk-media-next")
65 eRet = SymbolType::NEXT;
66 else if (sType == "gtk-media-previous")
67 eRet = SymbolType::PREV;
68 else if (sType == "gtk-media-play")
69 eRet = SymbolType::PLAY;
70 else if (sType == "gtk-media-stop")
71 eRet = SymbolType::STOP;
72 else if (sType == "gtk-goto-first")
73 eRet = SymbolType::FIRST;
74 else if (sType == "gtk-goto-last")
75 eRet = SymbolType::LAST;
76 else if (sType == "gtk-go-back")
77 eRet = SymbolType::ARROW_LEFT;
78 else if (sType == "gtk-go-forward")
79 eRet = SymbolType::ARROW_RIGHT;
80 else if (sType == "gtk-go-up")
81 eRet = SymbolType::ARROW_UP;
82 else if (sType == "gtk-go-down")
83 eRet = SymbolType::ARROW_DOWN;
84 else if (sType == "gtk-missing-image")
85 eRet = SymbolType::IMAGE;
86 else if (sType == "gtk-help")
87 eRet = SymbolType::HELP;
88 else if (sType == "gtk-close")
89 eRet = SymbolType::CLOSE;
90 else if (mapStockToImageResource(sType))
91 eRet = SymbolType::IMAGE;
92 return eRet;
95 void setupFromActionName(Button *pButton, VclBuilder::stringmap &rMap, const css::uno::Reference<css::frame::XFrame>& rFrame);
98 void VclBuilder::loadTranslations(const LanguageTag &rLanguageTag, const OUString& rUri)
100 /* FIXME-BCP47: support language tags with
101 * LanguageTag::getFallbackStrings() ? */
102 for (int i = rLanguageTag.getCountry().isEmpty() ? 1 : 0; i < 2; ++i)
104 OUStringBuffer aTransBuf;
105 sal_Int32 nLastSlash = rUri.lastIndexOf('/');
106 if (nLastSlash != -1)
107 aTransBuf.append(rUri.copy(0, nLastSlash));
108 else
110 aTransBuf.append('.');
111 nLastSlash = 0;
113 aTransBuf.append("/res/");
114 OUString sLang(rLanguageTag.getLanguage());
115 switch (i)
117 case 0:
118 sLang = sLang + "-" + rLanguageTag.getCountry();
119 break;
120 default:
121 break;
123 aTransBuf.append(sLang);
124 aTransBuf.append(".zip");
125 sal_Int32 nEndName = rUri.lastIndexOf('.');
126 if (nEndName == -1)
127 nEndName = rUri.getLength();
128 OUString sZippedFile(rUri.copy(nLastSlash + 1, nEndName - nLastSlash - 1) + "/" + sLang + ".ui");
131 css::uno::Reference<css::packages::zip::XZipFileAccess2> xNameAccess =
132 css::packages::zip::ZipFileAccess::createWithURL(
133 comphelper::getProcessComponentContext(), aTransBuf.makeStringAndClear());
134 if (!xNameAccess.is())
135 continue;
136 css::uno::Reference<css::io::XInputStream> xInputStream(xNameAccess->getByName(sZippedFile), css::uno::UNO_QUERY);
137 if (!xInputStream.is())
138 continue;
139 OStringBuffer sStr;
140 for (;;)
142 sal_Int32 const size = 2048;
143 css::uno::Sequence< sal_Int8 > data(size);
144 sal_Int32 n = xInputStream->readBytes(data, size);
145 sStr.append(reinterpret_cast<const sal_Char *>(data.getConstArray()), n);
146 if (n < size)
147 break;
150 xmlreader::XmlReader reader(sStr.getStr(), sStr.getLength());
151 handleTranslations(reader);
152 break;
154 catch (const css::uno::Exception &)
160 #if defined SAL_LOG_WARN
161 namespace
163 bool isButtonType(WindowType nType)
165 return nType == WINDOW_PUSHBUTTON ||
166 nType == WINDOW_OKBUTTON ||
167 nType == WINDOW_CANCELBUTTON ||
168 nType == WINDOW_HELPBUTTON ||
169 nType == WINDOW_IMAGEBUTTON ||
170 nType == WINDOW_MENUBUTTON ||
171 nType == WINDOW_MOREBUTTON ||
172 nType == WINDOW_SPINBUTTON;
175 #endif
177 VclBuilder::VclBuilder(vcl::Window *pParent, const OUString& sUIDir, const OUString& sUIFile, const OString& sID, const css::uno::Reference<css::frame::XFrame>& rFrame)
178 : m_sID(sID)
179 , m_sHelpRoot(OUStringToOString(sUIFile, RTL_TEXTENCODING_UTF8))
180 , m_pStringReplace(ResMgr::GetReadStringHook())
181 , m_pParent(pParent)
182 , m_bToplevelParentFound(false)
183 , m_pParserState(new ParserState)
184 , m_xFrame(rFrame)
186 m_bToplevelHasDeferredInit = pParent &&
187 ((pParent->IsSystemWindow() && static_cast<SystemWindow*>(pParent)->isDeferredInit()) ||
188 (pParent->IsDockingWindow() && static_cast<DockingWindow*>(pParent)->isDeferredInit()));
189 m_bToplevelHasDeferredProperties = m_bToplevelHasDeferredInit;
191 sal_Int32 nIdx = m_sHelpRoot.lastIndexOf('.');
192 if (nIdx != -1)
193 m_sHelpRoot = m_sHelpRoot.copy(0, nIdx);
194 m_sHelpRoot = m_sHelpRoot + OString('/');
196 OUString sUri = sUIDir + sUIFile;
198 const LanguageTag& rLanguageTag = Application::GetSettings().GetUILanguageTag();
199 bool bEN_US = (rLanguageTag.getBcp47() == "en-US");
200 if (!bEN_US)
201 loadTranslations(rLanguageTag, sUri);
205 xmlreader::XmlReader reader(sUri);
207 handleChild(pParent, reader);
209 catch (const css::uno::Exception &rExcept)
211 SAL_WARN("vcl.layout", "Unable to read .ui file: " << rExcept.Message);
212 throw;
215 //Set Mnemonic widgets when everything has been imported
216 for (std::vector<MnemonicWidgetMap>::iterator aI = m_pParserState->m_aMnemonicWidgetMaps.begin(),
217 aEnd = m_pParserState->m_aMnemonicWidgetMaps.end(); aI != aEnd; ++aI)
219 FixedText *pOne = get<FixedText>(aI->m_sID);
220 vcl::Window *pOther = get<vcl::Window>(aI->m_sValue);
221 SAL_WARN_IF(!pOne || !pOther, "vcl", "missing either source " << aI->m_sID << " or target " << aI->m_sValue << " member of Mnemonic Widget Mapping");
222 if (pOne && pOther)
223 pOne->set_mnemonic_widget(pOther);
226 //Set a11y relations when everything has been imported
227 for (AtkMap::iterator aI = m_pParserState->m_aAtkInfo.begin(),
228 aEnd = m_pParserState->m_aAtkInfo.end(); aI != aEnd; ++aI)
230 vcl::Window *pSource = aI->first;
231 const stringmap &rMap = aI->second;
233 for (stringmap::const_iterator aP = rMap.begin(),
234 aEndP = rMap.end(); aP != aEndP; ++aP)
236 const OString &rTarget = aP->second;
237 vcl::Window *pTarget = get<vcl::Window>(rTarget);
238 SAL_WARN_IF(!pTarget, "vcl", "missing member of a11y relation: "
239 << rTarget.getStr());
240 if (!pTarget)
241 continue;
242 const OString &rType = aP->first;
243 if (rType == "labelled-by")
244 pSource->SetAccessibleRelationLabeledBy(pTarget);
245 else if (rType == "label-for")
246 pSource->SetAccessibleRelationLabelFor(pTarget);
247 else if (rType == "member-of")
248 pSource->SetAccessibleRelationMemberOf(pTarget);
249 else
251 SAL_INFO("vcl.layout", "unhandled a11y relation :" << rType.getStr());
256 //Set radiobutton groups when everything has been imported
257 for (std::vector<RadioButtonGroupMap>::iterator aI = m_pParserState->m_aGroupMaps.begin(),
258 aEnd = m_pParserState->m_aGroupMaps.end(); aI != aEnd; ++aI)
260 RadioButton *pOne = get<RadioButton>(aI->m_sID);
261 RadioButton *pOther = get<RadioButton>(aI->m_sValue);
262 SAL_WARN_IF(!pOne || !pOther, "vcl", "missing member of radiobutton group");
263 if (pOne && pOther)
264 pOne->group(*pOther);
267 //Set ComboBox models when everything has been imported
268 for (std::vector<ComboBoxModelMap>::iterator aI = m_pParserState->m_aModelMaps.begin(),
269 aEnd = m_pParserState->m_aModelMaps.end(); aI != aEnd; ++aI)
271 ListBox *pTarget = get<ListBox>(aI->m_sID);
272 // pStore may be empty
273 const ListStore *pStore = get_model_by_name(aI->m_sValue);
274 SAL_WARN_IF(!pTarget, "vcl", "missing elements of combobox");
275 if (pTarget && pStore)
276 mungeModel(*pTarget, *pStore, aI->m_nActiveId);
279 //Set TextView buffers when everything has been imported
280 for (std::vector<TextBufferMap>::iterator aI = m_pParserState->m_aTextBufferMaps.begin(),
281 aEnd = m_pParserState->m_aTextBufferMaps.end(); aI != aEnd; ++aI)
283 VclMultiLineEdit *pTarget = get<VclMultiLineEdit>(aI->m_sID);
284 const TextBuffer *pBuffer = get_buffer_by_name(aI->m_sValue);
285 SAL_WARN_IF(!pTarget || !pBuffer, "vcl", "missing elements of textview/textbuffer");
286 if (pTarget && pBuffer)
287 mungeTextBuffer(*pTarget, *pBuffer);
290 //Set SpinButton adjustments when everything has been imported
291 for (std::vector<WidgetAdjustmentMap>::iterator aI = m_pParserState->m_aNumericFormatterAdjustmentMaps.begin(),
292 aEnd = m_pParserState->m_aNumericFormatterAdjustmentMaps.end(); aI != aEnd; ++aI)
294 NumericFormatter *pTarget = dynamic_cast<NumericFormatter*>(get<vcl::Window>(aI->m_sID));
295 const Adjustment *pAdjustment = get_adjustment_by_name(aI->m_sValue);
296 SAL_WARN_IF(!pTarget, "vcl", "missing NumericFormatter element of spinbutton/adjustment");
297 SAL_WARN_IF(!pAdjustment, "vcl", "missing Adjustment element of spinbutton/adjustment");
298 if (pTarget && pAdjustment)
299 mungeAdjustment(*pTarget, *pAdjustment);
302 for (std::vector<WidgetAdjustmentMap>::iterator aI = m_pParserState->m_aTimeFormatterAdjustmentMaps.begin(),
303 aEnd = m_pParserState->m_aTimeFormatterAdjustmentMaps.end(); aI != aEnd; ++aI)
305 TimeField *pTarget = dynamic_cast<TimeField*>(get<vcl::Window>(aI->m_sID));
306 const Adjustment *pAdjustment = get_adjustment_by_name(aI->m_sValue);
307 SAL_WARN_IF(!pTarget || !pAdjustment, "vcl", "missing elements of spinbutton/adjustment");
308 if (pTarget && pAdjustment)
309 mungeAdjustment(*pTarget, *pAdjustment);
312 for (std::vector<WidgetAdjustmentMap>::iterator aI = m_pParserState->m_aDateFormatterAdjustmentMaps.begin(),
313 aEnd = m_pParserState->m_aDateFormatterAdjustmentMaps.end(); aI != aEnd; ++aI)
315 DateField *pTarget = dynamic_cast<DateField*>(get<vcl::Window>(aI->m_sID));
316 const Adjustment *pAdjustment = get_adjustment_by_name(aI->m_sValue);
317 SAL_WARN_IF(!pTarget || !pAdjustment, "vcl", "missing elements of spinbutton/adjustment");
318 if (pTarget && pAdjustment)
319 mungeAdjustment(*pTarget, *pAdjustment);
322 //Set ScrollBar adjustments when everything has been imported
323 for (std::vector<WidgetAdjustmentMap>::iterator aI = m_pParserState->m_aScrollAdjustmentMaps.begin(),
324 aEnd = m_pParserState->m_aScrollAdjustmentMaps.end(); aI != aEnd; ++aI)
326 ScrollBar *pTarget = get<ScrollBar>(aI->m_sID);
327 const Adjustment *pAdjustment = get_adjustment_by_name(aI->m_sValue);
328 SAL_WARN_IF(!pTarget || !pAdjustment, "vcl", "missing elements of scrollbar/adjustment");
329 if (pTarget && pAdjustment)
330 mungeAdjustment(*pTarget, *pAdjustment);
333 //Set Scale(Slider) adjustments
334 std::vector<WidgetAdjustmentMap>::iterator aIterator;
335 for (aIterator = m_pParserState->m_aSliderAdjustmentMaps.begin();
336 aIterator != m_pParserState->m_aSliderAdjustmentMaps.end(); ++aIterator)
338 Slider* pTarget = dynamic_cast<Slider*>(get<vcl::Window>(aIterator->m_sID));
339 const Adjustment* pAdjustment = get_adjustment_by_name(aIterator->m_sValue);
340 SAL_WARN_IF(!pTarget || !pAdjustment, "vcl", "missing elements of scale(slider)/adjustment");
341 if (pTarget && pAdjustment)
343 mungeAdjustment(*pTarget, *pAdjustment);
347 //Set size-groups when all widgets have been imported
348 for (std::vector<SizeGroup>::iterator aI = m_pParserState->m_aSizeGroups.begin(),
349 aEnd = m_pParserState->m_aSizeGroups.end(); aI != aEnd; ++aI)
351 std::shared_ptr<VclSizeGroup> xGroup(std::make_shared<VclSizeGroup>());
353 for (stringmap::iterator aP = aI->m_aProperties.begin(),
354 aEndP = aI->m_aProperties.end(); aP != aEndP; ++aP)
356 const OString &rKey = aP->first;
357 const OString &rValue = aP->second;
358 xGroup->set_property(rKey, rValue);
361 for (std::vector<OString>::iterator aW = aI->m_aWidgets.begin(),
362 aEndW = aI->m_aWidgets.end(); aW != aEndW; ++aW)
364 vcl::Window* pWindow = get<vcl::Window>(aW->getStr());
365 pWindow->add_to_size_group(xGroup);
369 //Set button images when everything has been imported
370 std::set<OString> aImagesToBeRemoved;
371 for (std::vector<ButtonImageWidgetMap>::iterator aI = m_pParserState->m_aButtonImageWidgetMaps.begin(),
372 aEnd = m_pParserState->m_aButtonImageWidgetMaps.end(); aI != aEnd; ++aI)
374 PushButton *pTargetButton = nullptr;
375 RadioButton *pTargetRadio = nullptr;
376 Button *pTarget = nullptr;
378 if (!aI->m_bRadio)
380 pTargetButton = get<PushButton>(aI->m_sID);
381 pTarget = pTargetButton;
383 else
385 pTargetRadio = get<RadioButton>(aI->m_sID);
386 pTarget = pTargetRadio;
389 FixedImage *pImage = get<FixedImage>(aI->m_sValue);
390 SAL_WARN_IF(!pTarget || !pImage,
391 "vcl", "missing elements of button/image/stock");
392 if (!pTarget || !pImage)
393 continue;
394 aImagesToBeRemoved.insert(aI->m_sValue);
396 VclBuilder::StockMap::iterator aFind = m_pParserState->m_aStockMap.find(aI->m_sValue);
397 if (aFind == m_pParserState->m_aStockMap.end())
399 if (!aI->m_bRadio)
400 pTargetButton->SetModeImage(pImage->GetImage());
401 else
402 pTargetRadio->SetModeRadioImage(pImage->GetImage());
404 else
406 const stockinfo &rImageInfo = aFind->second;
407 SymbolType eType = mapStockToSymbol(rImageInfo.m_sStock);
408 SAL_WARN_IF(eType == SymbolType::DONTKNOW, "vcl", "missing stock image element for button");
409 if (eType == SymbolType::DONTKNOW)
410 continue;
411 if (!aI->m_bRadio)
413 pTargetButton->SetSymbol(eType);
414 //fdo#76457 keep symbol images small e.g. tools->customize->menu
415 //but images the right size. Really the PushButton::CalcMinimumSize
416 //and PushButton::ImplDrawPushButton are the better place to handle
417 //this, but its such a train-wreck
418 if (eType != SymbolType::IMAGE)
419 pTargetButton->SetStyle(pTargetButton->GetStyle() | WB_SMALLSTYLE);
421 else
422 SAL_WARN_IF(eType != SymbolType::IMAGE, "vcl.layout", "inimplemented symbol type for radiobuttons");
423 if (eType == SymbolType::IMAGE)
425 Bitmap aBitmap(VclResId(mapStockToImageResource(rImageInfo.m_sStock)));
426 Image const aImage(aBitmap);
427 if (!aI->m_bRadio)
428 pTargetButton->SetModeImage(aImage);
429 else
430 pTargetRadio->SetModeRadioImage(aImage);
432 switch (rImageInfo.m_nSize)
434 case 1:
435 pTarget->SetSmallSymbol();
436 break;
437 case 4:
438 break;
439 default:
440 SAL_WARN("vcl.layout", "unsupported image size " << rImageInfo.m_nSize);
441 break;
446 //There may be duplicate use of an Image, so we used a set to collect and
447 //now we can remove them from the tree after their final munge
448 for (std::set<OString>::iterator aI = aImagesToBeRemoved.begin(),
449 aEnd = aImagesToBeRemoved.end(); aI != aEnd; ++aI)
451 delete_by_name(*aI);
454 //Set button menus when everything has been imported
455 for (std::vector<ButtonMenuMap>::iterator aI = m_pParserState->m_aButtonMenuMaps.begin(),
456 aEnd = m_pParserState->m_aButtonMenuMaps.end(); aI != aEnd; ++aI)
458 MenuButton *pTarget = get<MenuButton>(aI->m_sID);
459 PopupMenu *pMenu = get_menu(aI->m_sValue);
460 SAL_WARN_IF(!pTarget || !pMenu,
461 "vcl", "missing elements of button/menu");
462 if (!pTarget || !pMenu)
463 continue;
464 pTarget->SetPopupMenu(pMenu);
467 //Remove ScrollWindow parent widgets whose children in vcl implement scrolling
468 //internally.
469 for (auto aI = m_pParserState->m_aRedundantParentWidgets.begin(),
470 aEnd = m_pParserState->m_aRedundantParentWidgets.end(); aI != aEnd; ++aI)
472 delete_by_window(aI->first);
475 //fdo#67378 merge the label into the disclosure button
476 for (VclPtr<VclExpander> const & pOne : m_pParserState->m_aExpanderWidgets)
478 vcl::Window *pChild = pOne->get_child();
479 vcl::Window* pLabel = pOne->GetWindow(GetWindowType::LastChild);
480 if (pLabel && pLabel != pChild && pLabel->GetType() == WINDOW_FIXEDTEXT)
482 FixedText *pLabelWidget = static_cast<FixedText*>(pLabel);
483 pOne->set_label(pLabelWidget->GetText());
484 delete_by_window(pLabel);
488 //drop maps, etc. that we don't need again
489 m_pParserState.reset();
491 SAL_WARN_IF(!m_sID.isEmpty() && (!m_bToplevelParentFound && !get_by_name(m_sID)), "vcl.layout",
492 "Requested top level widget \"" << m_sID.getStr() <<
493 "\" not found in " << sUIFile);
495 #if defined SAL_LOG_WARN
496 if (m_bToplevelParentFound && m_pParent->IsDialog())
498 int nButtons = 0;
499 bool bHasDefButton = false;
500 for (std::vector<WinAndId>::iterator aI = m_aChildren.begin(),
501 aEnd = m_aChildren.end(); aI != aEnd; ++aI)
503 if (isButtonType(aI->m_pWindow->GetType()))
505 ++nButtons;
506 if (aI->m_pWindow->GetStyle() & WB_DEFBUTTON)
508 bHasDefButton = true;
509 break;
513 SAL_WARN_IF(nButtons && !bHasDefButton, "vcl.layout", "No default button defined in " << sUIFile);
515 #endif
518 VclBuilder::~VclBuilder()
520 disposeBuilder();
523 void VclBuilder::disposeBuilder()
525 for (std::vector<WinAndId>::reverse_iterator aI = m_aChildren.rbegin(),
526 aEnd = m_aChildren.rend(); aI != aEnd; ++aI)
528 aI->m_pWindow.disposeAndClear();
530 m_aChildren.clear();
532 for (std::vector<MenuAndId>::reverse_iterator aI = m_aMenus.rbegin(),
533 aEnd = m_aMenus.rend(); aI != aEnd; ++aI)
535 aI->m_pMenu.disposeAndClear();
537 m_aMenus.clear();
538 m_pParent.clear();
541 void VclBuilder::handleTranslations(xmlreader::XmlReader &reader)
543 xmlreader::Span name;
544 int nsId;
546 OString sID, sProperty;
548 while(true)
550 xmlreader::XmlReader::Result res = reader.nextItem(
551 xmlreader::XmlReader::Text::Raw, &name, &nsId);
553 if (res == xmlreader::XmlReader::Result::Begin)
555 if (name.equals("e"))
557 while (reader.nextAttribute(&nsId, &name))
559 if (name.equals("g"))
561 name = reader.getAttributeValue(false);
562 sID = OString(name.begin, name.length);
563 sal_Int32 nDelim = sID.indexOf(':');
564 if (nDelim != -1)
565 sID = sID.copy(nDelim);
567 else if (name.equals("i"))
569 name = reader.getAttributeValue(false);
570 sProperty = OString(name.begin, name.length);
576 if (res == xmlreader::XmlReader::Result::Text && !sID.isEmpty())
578 OString sTranslation(name.begin, name.length);
579 m_pParserState->m_aTranslations[sID][sProperty] = sTranslation;
582 if (res == xmlreader::XmlReader::Result::End)
583 sID.clear();
585 if (res == xmlreader::XmlReader::Result::Done)
586 break;
590 OString VclBuilder::extractCustomProperty(VclBuilder::stringmap &rMap)
592 OString sCustomProperty;
593 VclBuilder::stringmap::iterator aFind = rMap.find(OString("customproperty"));
594 if (aFind != rMap.end())
596 sCustomProperty = aFind->second;
597 rMap.erase(aFind);
599 return sCustomProperty;
602 namespace
604 bool extractDrawValue(VclBuilder::stringmap& rMap)
606 bool bDrawValue = true;
607 VclBuilder::stringmap::iterator aFind = rMap.find(OString("draw_value"));
608 if (aFind != rMap.end())
610 bDrawValue = toBool(aFind->second);
611 rMap.erase(aFind);
613 return bDrawValue;
616 OString extractValuePos(VclBuilder::stringmap& rMap)
618 OString sRet("top");
619 VclBuilder::stringmap::iterator aFind = rMap.find(OString("value_pos"));
620 if (aFind != rMap.end())
622 sRet = aFind->second;
623 rMap.erase(aFind);
625 return sRet;
628 OString extractTypeHint(VclBuilder::stringmap &rMap)
630 OString sRet("normal");
631 VclBuilder::stringmap::iterator aFind = rMap.find(OString("type-hint"));
632 if (aFind != rMap.end())
634 sRet = aFind->second;
635 rMap.erase(aFind);
637 return sRet;
640 bool extractResizable(VclBuilder::stringmap &rMap)
642 bool bResizable = true;
643 VclBuilder::stringmap::iterator aFind = rMap.find(OString("resizable"));
644 if (aFind != rMap.end())
646 bResizable = toBool(aFind->second);
647 rMap.erase(aFind);
649 return bResizable;
652 bool extractDecorated(VclBuilder::stringmap &rMap)
654 bool bDecorated = true;
655 VclBuilder::stringmap::iterator aFind = rMap.find(OString("decorated"));
656 if (aFind != rMap.end())
658 bDecorated = toBool(aFind->second);
659 rMap.erase(aFind);
661 return bDecorated;
664 bool extractCloseable(VclBuilder::stringmap &rMap)
666 bool bCloseable = true;
667 VclBuilder::stringmap::iterator aFind = rMap.find(OString("deletable"));
668 if (aFind != rMap.end())
670 bCloseable = toBool(aFind->second);
671 rMap.erase(aFind);
673 return bCloseable;
676 bool extractEntry(VclBuilder::stringmap &rMap)
678 bool bHasEntry = false;
679 VclBuilder::stringmap::iterator aFind = rMap.find(OString("has-entry"));
680 if (aFind != rMap.end())
682 bHasEntry = toBool(aFind->second);
683 rMap.erase(aFind);
685 return bHasEntry;
688 bool extractOrientation(VclBuilder::stringmap &rMap)
690 bool bVertical = false;
691 VclBuilder::stringmap::iterator aFind = rMap.find(OString("orientation"));
692 if (aFind != rMap.end())
694 bVertical = aFind->second.equalsIgnoreAsciiCase("vertical");
695 rMap.erase(aFind);
697 return bVertical;
700 bool extractInconsistent(VclBuilder::stringmap &rMap)
702 bool bInconsistent = false;
703 VclBuilder::stringmap::iterator aFind = rMap.find(OString("inconsistent"));
704 if (aFind != rMap.end())
706 bInconsistent = toBool(aFind->second);
707 rMap.erase(aFind);
709 return bInconsistent;
712 OString extractIconName(VclBuilder::stringmap &rMap)
714 OString sIconName;
715 VclBuilder::stringmap::iterator aFind = rMap.find(OString("icon-name"));
716 if (aFind != rMap.end())
718 sIconName = aFind->second;
719 rMap.erase(aFind);
721 return sIconName;
724 OUString getStockText(const OString &rType)
726 if (rType == "gtk-ok")
727 return (VclResId(SV_BUTTONTEXT_OK).toString());
728 else if (rType == "gtk-cancel")
729 return (VclResId(SV_BUTTONTEXT_CANCEL).toString());
730 else if (rType == "gtk-help")
731 return (VclResId(SV_BUTTONTEXT_HELP).toString());
732 else if (rType == "gtk-close")
733 return (VclResId(SV_BUTTONTEXT_CLOSE).toString());
734 else if (rType == "gtk-revert-to-saved")
735 return (VclResId(SV_BUTTONTEXT_RESET).toString());
736 else if (rType == "gtk-add")
737 return (VclResId(SV_BUTTONTEXT_ADD).toString());
738 else if (rType == "gtk-delete")
739 return (VclResId(SV_BUTTONTEXT_DELETE).toString());
740 else if (rType == "gtk-remove")
741 return (VclResId(SV_BUTTONTEXT_REMOVE).toString());
742 else if (rType == "gtk-new")
743 return (VclResId(SV_BUTTONTEXT_NEW).toString());
744 else if (rType == "gtk-edit")
745 return (VclResId(SV_BUTTONTEXT_EDIT).toString());
746 else if (rType == "gtk-apply")
747 return (VclResId(SV_BUTTONTEXT_APPLY).toString());
748 else if (rType == "gtk-save")
749 return (VclResId(SV_BUTTONTEXT_SAVE).toString());
750 else if (rType == "gtk-open")
751 return (VclResId(SV_BUTTONTEXT_OPEN).toString());
752 else if (rType == "gtk-undo")
753 return (VclResId(SV_BUTTONTEXT_UNDO).toString());
754 else if (rType == "gtk-paste")
755 return (VclResId(SV_BUTTONTEXT_PASTE).toString());
756 else if (rType == "gtk-media-next")
757 return (VclResId(SV_BUTTONTEXT_NEXT).toString());
758 else if (rType == "gtk-go-up")
759 return (VclResId(SV_BUTTONTEXT_GO_UP).toString());
760 else if (rType == "gtk-go-down")
761 return (VclResId(SV_BUTTONTEXT_GO_DOWN).toString());
762 else if (rType == "gtk-clear")
763 return (VclResId(SV_BUTTONTEXT_CLEAR).toString());
764 else if (rType == "gtk-media-play")
765 return (VclResId(SV_BUTTONTEXT_PLAY).toString());
766 else if (rType == "gtk-find")
767 return (VclResId(SV_BUTTONTEXT_FIND).toString());
768 else if (rType == "gtk-stop")
769 return (VclResId(SV_BUTTONTEXT_STOP).toString());
770 else if (rType == "gtk-connect")
771 return (VclResId(SV_BUTTONTEXT_CONNECT).toString());
772 else if (rType == "gtk-yes")
773 return (VclResId(SV_BUTTONTEXT_YES).toString());
774 else if (rType == "gtk-no")
775 return (VclResId(SV_BUTTONTEXT_NO).toString());
776 SAL_WARN("vcl.layout", "unknown stock type: " << rType.getStr());
777 return OUString();
780 bool extractStock(VclBuilder::stringmap &rMap)
782 bool bIsStock = false;
783 VclBuilder::stringmap::iterator aFind = rMap.find(OString("use-stock"));
784 if (aFind != rMap.end())
786 bIsStock = toBool(aFind->second);
787 rMap.erase(aFind);
789 return bIsStock;
792 WinBits extractRelief(VclBuilder::stringmap &rMap)
794 WinBits nBits = WB_3DLOOK;
795 VclBuilder::stringmap::iterator aFind = rMap.find(OString("relief"));
796 if (aFind != rMap.end())
798 if (aFind->second == "half")
799 nBits = WB_FLATBUTTON | WB_BEVELBUTTON;
800 else if (aFind->second == "none")
801 nBits = WB_FLATBUTTON;
802 rMap.erase(aFind);
804 return nBits;
807 OString extractLabel(VclBuilder::stringmap &rMap)
809 OString sType;
810 VclBuilder::stringmap::iterator aFind = rMap.find(OString("label"));
811 if (aFind != rMap.end())
813 sType = aFind->second;
814 rMap.erase(aFind);
816 return sType;
819 OString extractActionName(VclBuilder::stringmap &rMap)
821 OString sActionName;
822 VclBuilder::stringmap::iterator aFind = rMap.find(OString("action-name"));
823 if (aFind != rMap.end())
825 sActionName = aFind->second;
826 rMap.erase(aFind);
828 return sActionName;
831 bool extractVisible(VclBuilder::stringmap &rMap)
833 VclBuilder::stringmap::iterator aFind = rMap.find(OString("visible"));
834 if (aFind != rMap.end())
836 return toBool(aFind->second);
838 return false;
841 Size extractSizeRequest(VclBuilder::stringmap &rMap)
843 OString sWidthRequest("0");
844 OString sHeightRequest("0");
845 VclBuilder::stringmap::iterator aFind = rMap.find(OString("width-request"));
846 if (aFind != rMap.end())
848 sWidthRequest = aFind->second;
849 rMap.erase(aFind);
851 aFind = rMap.find(OString("height-request"));
852 if (aFind != rMap.end())
854 sHeightRequest = aFind->second;
855 rMap.erase(aFind);
857 return Size(sWidthRequest.toInt32(), sHeightRequest.toInt32());
860 OString extractTooltipText(VclBuilder::stringmap &rMap)
862 OString sTooltipText;
863 VclBuilder::stringmap::iterator aFind = rMap.find(OString("tooltip-text"));
864 if (aFind == rMap.end())
865 aFind = rMap.find(OString("tooltip-markup"));
866 if (aFind != rMap.end())
868 sTooltipText = aFind->second;
869 rMap.erase(aFind);
871 return sTooltipText;
874 void setupFromActionName(Button *pButton, VclBuilder::stringmap &rMap, const css::uno::Reference<css::frame::XFrame>& rFrame)
876 if (!rFrame.is())
877 return;
879 OUString aCommand(OStringToOUString(extractActionName(rMap), RTL_TEXTENCODING_UTF8));
880 if (aCommand.isEmpty())
881 return;
883 OUString aLabel(vcl::CommandInfoProvider::Instance().GetLabelForCommand(aCommand, rFrame));
884 if (!aLabel.isEmpty())
885 pButton->SetText(aLabel);
887 OUString aTooltip(vcl::CommandInfoProvider::Instance().GetTooltipForCommand(aCommand, rFrame));
888 if (!aTooltip.isEmpty())
889 pButton->SetQuickHelpText(aTooltip);
891 Image aImage(vcl::CommandInfoProvider::Instance().GetImageForCommand(aCommand, rFrame));
892 pButton->SetModeImage(aImage);
894 pButton->SetCommandHandler(aCommand);
897 VclPtr<Button> extractStockAndBuildPushButton(vcl::Window *pParent, VclBuilder::stringmap &rMap)
899 WinBits nBits = WB_CLIPCHILDREN|WB_CENTER|WB_VCENTER;
901 nBits |= extractRelief(rMap);
903 bool bIsStock = extractStock(rMap);
905 VclPtr<Button> xWindow;
907 if (bIsStock)
909 OString sType = extractLabel(rMap);
910 if (sType == "gtk-ok")
911 xWindow = VclPtr<OKButton>::Create(pParent, nBits);
912 else if (sType == "gtk-cancel")
913 xWindow = VclPtr<CancelButton>::Create(pParent, nBits);
914 else if (sType == "gtk-close")
915 xWindow = VclPtr<CloseButton>::Create(pParent, nBits);
916 else if (sType == "gtk-help")
917 xWindow = VclPtr<HelpButton>::Create(pParent, nBits);
918 else
920 xWindow = VclPtr<PushButton>::Create(pParent, nBits);
921 xWindow->SetText(getStockText(sType));
925 if (!xWindow)
926 xWindow = VclPtr<PushButton>::Create(pParent, nBits);
927 return xWindow;
930 VclPtr<Button> extractStockAndBuildMenuButton(vcl::Window *pParent, VclBuilder::stringmap &rMap)
932 WinBits nBits = WB_CLIPCHILDREN|WB_CENTER|WB_VCENTER|WB_3DLOOK;
934 nBits |= extractRelief(rMap);
936 VclPtr<Button> xWindow = VclPtr<MenuButton>::Create(pParent, nBits);
938 if (extractStock(rMap))
940 xWindow->SetText(getStockText(extractLabel(rMap)));
943 return xWindow;
946 VclPtr<Button> extractStockAndBuildMenuToggleButton(vcl::Window *pParent, VclBuilder::stringmap &rMap)
948 WinBits nBits = WB_CLIPCHILDREN|WB_CENTER|WB_VCENTER|WB_3DLOOK;
950 nBits |= extractRelief(rMap);
952 VclPtr<Button> xWindow = VclPtr<MenuToggleButton>::Create(pParent, nBits);
954 if (extractStock(rMap))
956 xWindow->SetText(getStockText(extractLabel(rMap)));
959 return xWindow;
962 OString extractUnit(const OString& sPattern)
964 OString sUnit(sPattern);
965 for (sal_Int32 i = 0; i < sPattern.getLength(); ++i)
967 if (sPattern[i] != '.' && sPattern[i] != ',' && sPattern[i] != '0')
969 sUnit = sPattern.copy(i);
970 break;
973 return sUnit;
976 int extractDecimalDigits(const OString& sPattern)
978 int nDigits = 0;
979 bool bAfterPoint = false;
980 for (sal_Int32 i = 0; i < sPattern.getLength(); ++i)
982 if (sPattern[i] == '.' || sPattern[i] == ',')
983 bAfterPoint = true;
984 else if (sPattern[i] == '0')
986 if (bAfterPoint)
987 ++nDigits;
989 else
990 break;
992 return nDigits;
995 FieldUnit detectMetricUnit(const OString& sUnit)
997 FieldUnit eUnit = FUNIT_NONE;
999 if (sUnit == "mm")
1000 eUnit = FUNIT_MM;
1001 else if (sUnit == "cm")
1002 eUnit = FUNIT_CM;
1003 else if (sUnit == "m")
1004 eUnit = FUNIT_M;
1005 else if (sUnit == "km")
1006 eUnit = FUNIT_KM;
1007 else if ((sUnit == "twips") || (sUnit == "twip"))
1008 eUnit = FUNIT_TWIP;
1009 else if (sUnit == "pt")
1010 eUnit = FUNIT_POINT;
1011 else if (sUnit == "pc")
1012 eUnit = FUNIT_PICA;
1013 else if (sUnit == "\"" || (sUnit == "in") || (sUnit == "inch"))
1014 eUnit = FUNIT_INCH;
1015 else if ((sUnit == "'") || (sUnit == "ft") || (sUnit == "foot") || (sUnit == "feet"))
1016 eUnit = FUNIT_FOOT;
1017 else if (sUnit == "mile" || (sUnit == "miles"))
1018 eUnit = FUNIT_MILE;
1019 else if (sUnit == "ch")
1020 eUnit = FUNIT_CHAR;
1021 else if (sUnit == "line")
1022 eUnit = FUNIT_LINE;
1023 else if (sUnit == "%")
1024 eUnit = FUNIT_PERCENT;
1025 else if ((sUnit == "pixels") || (sUnit == "pixel") || (sUnit == "px"))
1026 eUnit = FUNIT_PIXEL;
1027 else if ((sUnit == "degrees") || (sUnit == "degree"))
1028 eUnit = FUNIT_DEGREE;
1029 else if ((sUnit == "sec") || (sUnit == "seconds") || (sUnit == "second"))
1030 eUnit = FUNIT_SECOND;
1031 else if ((sUnit == "ms") || (sUnit == "milliseconds") || (sUnit == "millisecond"))
1032 eUnit = FUNIT_MILLISECOND;
1033 else if (sUnit != "0")
1034 eUnit = FUNIT_CUSTOM;
1036 return eUnit;
1039 WinBits extractDeferredBits(VclBuilder::stringmap &rMap)
1041 WinBits nBits = WB_3DLOOK|WB_HIDE;
1042 if (extractResizable(rMap))
1043 nBits |= WB_SIZEABLE;
1044 if (extractCloseable(rMap))
1045 nBits |= WB_CLOSEABLE;
1046 OString sBorder = VclBuilder::extractCustomProperty(rMap);
1047 if (!sBorder.isEmpty())
1048 nBits |= WB_BORDER;
1049 if (!extractDecorated(rMap))
1050 nBits |= WB_OWNERDRAWDECORATION;
1051 OString sType(extractTypeHint(rMap));
1052 if (sType == "utility")
1053 nBits |= WB_SYSTEMWINDOW | WB_DIALOGCONTROL | WB_MOVEABLE;
1054 else if (sType == "popup-menu")
1055 nBits |= WB_SYSTEMWINDOW | WB_DIALOGCONTROL | WB_POPUP;
1056 else if (sType == "dock")
1057 nBits |= WB_DOCKABLE | WB_MOVEABLE;
1058 else
1059 nBits |= WB_MOVEABLE;
1060 return nBits;
1064 FieldUnit VclBuilder::detectUnit(OString const& rString)
1066 OString const unit(extractUnit(rString));
1067 return detectMetricUnit(unit);
1070 void VclBuilder::ensureDefaultWidthChars(VclBuilder::stringmap &rMap)
1072 OString sWidthChars("width-chars");
1073 VclBuilder::stringmap::iterator aFind = rMap.find(sWidthChars);
1074 if (aFind == rMap.end())
1075 rMap[sWidthChars] = "25";
1078 bool VclBuilder::extractGroup(const OString &id, stringmap &rMap)
1080 VclBuilder::stringmap::iterator aFind = rMap.find(OString("group"));
1081 if (aFind != rMap.end())
1083 OString sID = aFind->second;
1084 sal_Int32 nDelim = sID.indexOf(':');
1085 if (nDelim != -1)
1086 sID = sID.copy(0, nDelim);
1087 m_pParserState->m_aGroupMaps.push_back(RadioButtonGroupMap(id, sID));
1088 rMap.erase(aFind);
1089 return true;
1091 return false;
1094 void VclBuilder::connectNumericFormatterAdjustment(const OString &id, const OString &rAdjustment)
1096 if (!rAdjustment.isEmpty())
1097 m_pParserState->m_aNumericFormatterAdjustmentMaps.push_back(WidgetAdjustmentMap(id, rAdjustment));
1100 void VclBuilder::connectTimeFormatterAdjustment(const OString &id, const OString &rAdjustment)
1102 if (!rAdjustment.isEmpty())
1103 m_pParserState->m_aTimeFormatterAdjustmentMaps.push_back(WidgetAdjustmentMap(id, rAdjustment));
1106 void VclBuilder::connectDateFormatterAdjustment(const OString &id, const OString &rAdjustment)
1108 if (!rAdjustment.isEmpty())
1109 m_pParserState->m_aDateFormatterAdjustmentMaps.push_back(WidgetAdjustmentMap(id, rAdjustment));
1112 bool VclBuilder::extractAdjustmentToMap(const OString& id, VclBuilder::stringmap& rMap, std::vector<WidgetAdjustmentMap>& rAdjustmentMap)
1114 VclBuilder::stringmap::iterator aFind = rMap.find(OString("adjustment"));
1115 if (aFind != rMap.end())
1117 rAdjustmentMap.push_back(WidgetAdjustmentMap(id, aFind->second));
1118 rMap.erase(aFind);
1119 return true;
1121 return false;
1124 namespace
1126 sal_Int32 extractActive(VclBuilder::stringmap &rMap)
1128 sal_Int32 nActiveId = 0;
1129 VclBuilder::stringmap::iterator aFind = rMap.find(OString("active"));
1130 if (aFind != rMap.end())
1132 nActiveId = aFind->second.toInt32();
1133 rMap.erase(aFind);
1135 return nActiveId;
1138 bool extractSelectable(VclBuilder::stringmap &rMap)
1140 bool bSelectable = false;
1141 VclBuilder::stringmap::iterator aFind = rMap.find(OString("selectable"));
1142 if (aFind != rMap.end())
1144 bSelectable = toBool(aFind->second);
1145 rMap.erase(aFind);
1147 return bSelectable;
1150 OString extractAdjustment(VclBuilder::stringmap &rMap)
1152 OString sAdjustment;
1153 VclBuilder::stringmap::iterator aFind = rMap.find(OString("adjustment"));
1154 if (aFind != rMap.end())
1156 sAdjustment= aFind->second;
1157 rMap.erase(aFind);
1158 return sAdjustment;
1160 return sAdjustment;
1164 bool VclBuilder::extractModel(const OString &id, stringmap &rMap)
1166 VclBuilder::stringmap::iterator aFind = rMap.find(OString("model"));
1167 if (aFind != rMap.end())
1169 m_pParserState->m_aModelMaps.push_back(ComboBoxModelMap(id, aFind->second,
1170 extractActive(rMap)));
1171 rMap.erase(aFind);
1172 return true;
1174 return false;
1177 bool VclBuilder::extractDropdown(VclBuilder::stringmap &rMap)
1179 bool bDropdown = true;
1180 VclBuilder::stringmap::iterator aFind = rMap.find(OString("dropdown"));
1181 if (aFind != rMap.end())
1183 bDropdown = toBool(aFind->second);
1184 rMap.erase(aFind);
1186 return bDropdown;
1189 bool VclBuilder::extractBuffer(const OString &id, stringmap &rMap)
1191 VclBuilder::stringmap::iterator aFind = rMap.find(OString("buffer"));
1192 if (aFind != rMap.end())
1194 m_pParserState->m_aTextBufferMaps.push_back(TextBufferMap(id, aFind->second));
1195 rMap.erase(aFind);
1196 return true;
1198 return false;
1201 bool VclBuilder::extractStock(const OString &id, stringmap &rMap)
1203 VclBuilder::stringmap::iterator aFind = rMap.find(OString("stock"));
1204 if (aFind != rMap.end())
1206 stockinfo aInfo;
1207 aInfo.m_sStock = aFind->second;
1208 rMap.erase(aFind);
1209 aFind = rMap.find(OString("icon-size"));
1210 if (aFind != rMap.end())
1212 aInfo.m_nSize = aFind->second.toInt32();
1213 rMap.erase(aFind);
1215 m_pParserState->m_aStockMap[id] = aInfo;
1216 return true;
1218 return false;
1221 bool VclBuilder::extractButtonImage(const OString &id, stringmap &rMap, bool bRadio)
1223 VclBuilder::stringmap::iterator aFind = rMap.find(OString("image"));
1224 if (aFind != rMap.end())
1226 m_pParserState->m_aButtonImageWidgetMaps.push_back(ButtonImageWidgetMap(id, aFind->second, bRadio));
1227 rMap.erase(aFind);
1228 return true;
1230 return false;
1233 void VclBuilder::extractMnemonicWidget(const OString &rLabelID, stringmap &rMap)
1235 VclBuilder::stringmap::iterator aFind = rMap.find(OString("mnemonic-widget"));
1236 if (aFind != rMap.end())
1238 OString sID = aFind->second;
1239 sal_Int32 nDelim = sID.indexOf(':');
1240 if (nDelim != -1)
1241 sID = sID.copy(0, nDelim);
1242 m_pParserState->m_aMnemonicWidgetMaps.push_back(MnemonicWidgetMap(rLabelID, sID));
1243 rMap.erase(aFind);
1247 vcl::Window* VclBuilder::prepareWidgetOwnScrolling(vcl::Window *pParent, WinBits &rWinStyle)
1249 //For Widgets that manage their own scrolling, if one appears as a child of
1250 //a scrolling window shoehorn that scrolling settings to this widget and
1251 //return the real parent to use
1252 if (pParent && pParent->GetType() == WINDOW_SCROLLWINDOW)
1254 WinBits nScrollBits = pParent->GetStyle();
1255 nScrollBits &= (WB_AUTOHSCROLL|WB_HSCROLL|WB_AUTOVSCROLL|WB_VSCROLL);
1256 rWinStyle |= nScrollBits;
1257 pParent = pParent->GetParent();
1260 return pParent;
1263 void VclBuilder::cleanupWidgetOwnScrolling(vcl::Window *pScrollParent, vcl::Window *pWindow, stringmap &rMap)
1265 //remove the redundant scrolling parent
1266 sal_Int32 nWidthReq = pScrollParent->get_width_request();
1267 rMap[OString("width-request")] = OString::number(nWidthReq);
1268 sal_Int32 nHeightReq = pScrollParent->get_height_request();
1269 rMap[OString("height-request")] = OString::number(nHeightReq);
1271 m_pParserState->m_aRedundantParentWidgets[pScrollParent] = pWindow;
1274 #ifndef DISABLE_DYNLOADING
1275 extern "C" { static void SAL_CALL thisModule() {} }
1276 #endif
1278 VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString &name, const OString &id,
1279 stringmap &rMap)
1281 bool bIsPlaceHolder = name.isEmpty();
1282 bool bVertical = false;
1284 if (pParent && pParent->GetType() == WINDOW_TABCONTROL)
1286 //We have to add a page
1288 //make default pageid == position
1289 TabControl *pTabControl = static_cast<TabControl*>(pParent);
1290 sal_uInt16 nNewPageCount = pTabControl->GetPageCount()+1;
1291 sal_uInt16 nNewPageId = nNewPageCount;
1292 pTabControl->InsertPage(nNewPageId, OUString());
1293 pTabControl->SetCurPageId(nNewPageId);
1295 if (!bIsPlaceHolder)
1297 VclPtrInstance<TabPage> pPage(pTabControl);
1298 pPage->Show();
1300 //Make up a name for it
1301 OString sTabPageId = get_by_window(pParent) +
1302 OString("-page") +
1303 OString::number(nNewPageCount);
1304 m_aChildren.push_back(WinAndId(sTabPageId, pPage, false));
1305 pPage->SetHelpId(m_sHelpRoot + sTabPageId);
1307 //And give the page one container as a child to make it a layout enabled
1308 //tab page
1309 VclPtrInstance<VclBin> pContainer(pPage);
1310 pContainer->Show();
1311 m_aChildren.push_back(WinAndId(OString(), pContainer, false));
1312 pContainer->SetHelpId(m_sHelpRoot + sTabPageId + OString("-bin"));
1313 pParent = pContainer;
1315 pTabControl->SetTabPage(nNewPageId, pPage);
1319 if (bIsPlaceHolder || name == "GtkTreeSelection")
1320 return nullptr;
1322 extractButtonImage(id, rMap, name == "GtkRadioButton");
1324 VclPtr<vcl::Window> xWindow;
1325 if (name == "GtkDialog")
1327 WinBits nBits = WB_CLIPCHILDREN|WB_MOVEABLE|WB_3DLOOK|WB_CLOSEABLE;
1328 if (extractResizable(rMap))
1329 nBits |= WB_SIZEABLE;
1330 xWindow = VclPtr<Dialog>::Create(pParent, nBits);
1332 else if (name == "GtkMessageDialog")
1334 WinBits nBits = WB_CLIPCHILDREN|WB_MOVEABLE|WB_3DLOOK|WB_CLOSEABLE;
1335 if (extractResizable(rMap))
1336 nBits |= WB_SIZEABLE;
1337 xWindow = VclPtr<MessageDialog>::Create(pParent, nBits);
1339 else if (name == "GtkBox")
1341 bVertical = extractOrientation(rMap);
1342 if (bVertical)
1343 xWindow = VclPtr<VclVBox>::Create(pParent);
1344 else
1345 xWindow = VclPtr<VclHBox>::Create(pParent);
1347 else if (name == "GtkPaned")
1349 bVertical = extractOrientation(rMap);
1350 assert(bVertical && "hori not implemented, shouldn't be hard though");
1351 xWindow = VclPtr<VclVPaned>::Create(pParent);
1353 else if (name == "GtkHBox")
1354 xWindow = VclPtr<VclHBox>::Create(pParent);
1355 else if (name == "GtkVBox")
1356 xWindow = VclPtr<VclVBox>::Create(pParent);
1357 else if (name == "GtkButtonBox")
1359 bVertical = extractOrientation(rMap);
1360 if (bVertical)
1361 xWindow = VclPtr<VclVButtonBox>::Create(pParent);
1362 else
1363 xWindow = VclPtr<VclHButtonBox>::Create(pParent);
1365 else if (name == "GtkHButtonBox")
1366 xWindow = VclPtr<VclHButtonBox>::Create(pParent);
1367 else if (name == "GtkVButtonBox")
1368 xWindow = VclPtr<VclVButtonBox>::Create(pParent);
1369 else if (name == "GtkGrid")
1370 xWindow = VclPtr<VclGrid>::Create(pParent);
1371 else if (name == "GtkFrame")
1372 xWindow = VclPtr<VclFrame>::Create(pParent);
1373 else if (name == "GtkExpander")
1375 VclPtrInstance<VclExpander> pExpander(pParent);
1376 m_pParserState->m_aExpanderWidgets.push_back(pExpander);
1377 xWindow = pExpander;
1379 else if (name == "GtkAlignment")
1380 xWindow = VclPtr<VclAlignment>::Create(pParent);
1381 else if (name == "GtkButton")
1383 VclPtr<Button> xButton;
1384 OString sMenu = extractCustomProperty(rMap);
1385 if (sMenu.isEmpty())
1386 xButton = extractStockAndBuildPushButton(pParent, rMap);
1387 else
1389 xButton = extractStockAndBuildMenuButton(pParent, rMap);
1390 m_pParserState->m_aButtonMenuMaps.push_back(ButtonMenuMap(id, sMenu));
1392 xButton->SetImageAlign(ImageAlign::Left); //default to left
1393 setupFromActionName(xButton, rMap, m_xFrame);
1394 xWindow = xButton;
1396 else if (name == "GtkToggleButton")
1398 VclPtr<Button> xButton;
1399 OString sMenu = extractCustomProperty(rMap);
1400 assert(sMenu.getLength() && "not implemented yet");
1401 xButton = extractStockAndBuildMenuToggleButton(pParent, rMap);
1402 m_pParserState->m_aButtonMenuMaps.push_back(ButtonMenuMap(id, sMenu));
1403 xButton->SetImageAlign(ImageAlign::Left); //default to left
1404 setupFromActionName(xButton, rMap, m_xFrame);
1405 xWindow = xButton;
1407 else if (name == "GtkRadioButton")
1409 extractGroup(id, rMap);
1410 WinBits nBits = WB_CLIPCHILDREN|WB_CENTER|WB_VCENTER|WB_3DLOOK;
1411 OString sWrap = extractCustomProperty(rMap);
1412 if (!sWrap.isEmpty())
1413 nBits |= WB_WORDBREAK;
1414 VclPtr<RadioButton> xButton = VclPtr<RadioButton>::Create(pParent, nBits);
1415 xButton->SetImageAlign(ImageAlign::Left); //default to left
1416 xWindow = xButton;
1418 else if (name == "GtkCheckButton")
1420 WinBits nBits = WB_CLIPCHILDREN|WB_CENTER|WB_VCENTER|WB_3DLOOK;
1421 OString sWrap = extractCustomProperty(rMap);
1422 if (!sWrap.isEmpty())
1423 nBits |= WB_WORDBREAK;
1424 //maybe always import as TriStateBox and enable/disable tristate
1425 bool bIsTriState = extractInconsistent(rMap);
1426 VclPtr<CheckBox> xCheckBox;
1427 if (bIsTriState)
1428 xCheckBox = VclPtr<TriStateBox>::Create(pParent, nBits);
1429 else
1430 xCheckBox = VclPtr<CheckBox>::Create(pParent, nBits);
1431 if (bIsTriState)
1432 xCheckBox->SetState(TRISTATE_INDET);
1433 xCheckBox->SetImageAlign(ImageAlign::Left); //default to left
1434 xWindow = xCheckBox;
1436 else if (name == "GtkSpinButton")
1438 OString sAdjustment = extractAdjustment(rMap);
1439 OString sPattern = extractCustomProperty(rMap);
1440 OString sUnit = extractUnit(sPattern);
1442 WinBits nBits = WB_CLIPCHILDREN|WB_LEFT|WB_BORDER|WB_3DLOOK;
1443 if (!id.endsWith("-nospin"))
1444 nBits |= WB_SPIN | WB_REPEAT;
1446 if (sPattern.isEmpty())
1448 connectNumericFormatterAdjustment(id, sAdjustment);
1449 SAL_INFO("vcl.layout", "making numeric field for " << name.getStr() << " " << sUnit.getStr());
1450 xWindow = VclPtr<NumericField>::Create(pParent, nBits);
1452 else
1454 if (sPattern == "hh:mm")
1456 connectTimeFormatterAdjustment(id, sAdjustment);
1457 SAL_INFO("vcl.layout", "making time field for " << name.getStr() << " " << sUnit.getStr());
1458 xWindow = VclPtr<TimeField>::Create(pParent, nBits);
1460 else if (sPattern == "yy:mm:dd")
1462 connectDateFormatterAdjustment(id, sAdjustment);
1463 SAL_INFO("vcl.layout", "making date field for " << name.getStr() << " " << sUnit.getStr());
1464 xWindow = VclPtr<DateField>::Create(pParent, nBits);
1466 else
1468 connectNumericFormatterAdjustment(id, sAdjustment);
1469 FieldUnit eUnit = detectMetricUnit(sUnit);
1470 SAL_INFO("vcl.layout", "making metric field for " << name.getStr() << " " << sUnit.getStr());
1471 VclPtrInstance<MetricField> xField(pParent, nBits);
1472 xField->SetUnit(eUnit);
1473 if (eUnit == FUNIT_CUSTOM)
1474 xField->SetCustomUnitText(OStringToOUString(sUnit, RTL_TEXTENCODING_UTF8));
1475 xWindow = xField;
1479 else if (name == "GtkLinkButton")
1480 xWindow = VclPtr<FixedHyperlink>::Create(pParent, WB_CENTER|WB_VCENTER|WB_3DLOOK|WB_NOLABEL);
1481 else if ((name == "GtkComboBox") || (name == "GtkComboBoxText") || (name == "VclComboBoxText"))
1483 OString sPattern = extractCustomProperty(rMap);
1484 extractModel(id, rMap);
1486 WinBits nBits = WB_CLIPCHILDREN|WB_LEFT|WB_VCENTER|WB_3DLOOK;
1488 bool bDropdown = VclBuilder::extractDropdown(rMap);
1490 if (bDropdown)
1491 nBits |= WB_DROPDOWN;
1493 if (!sPattern.isEmpty())
1495 OString sAdjustment = extractAdjustment(rMap);
1496 connectNumericFormatterAdjustment(id, sAdjustment);
1497 OString sUnit = extractUnit(sPattern);
1498 FieldUnit eUnit = detectMetricUnit(sUnit);
1499 SAL_WARN("vcl.layout", "making metric box for type: " << name.getStr()
1500 << " unit: " << sUnit.getStr()
1501 << " name: " << id.getStr()
1502 << " use a VclComboBoxNumeric instead");
1503 VclPtrInstance<MetricBox> xBox(pParent, nBits);
1504 xBox->EnableAutoSize(true);
1505 xBox->SetUnit(eUnit);
1506 xBox->SetDecimalDigits(extractDecimalDigits(sPattern));
1507 if (eUnit == FUNIT_CUSTOM)
1508 xBox->SetCustomUnitText(OStringToOUString(sUnit, RTL_TEXTENCODING_UTF8));
1509 xWindow = xBox;
1511 else if (extractEntry(rMap))
1513 VclPtrInstance<ComboBox> xComboBox(pParent, nBits);
1514 xComboBox->EnableAutoSize(true);
1515 xWindow = xComboBox;
1517 else
1519 VclPtrInstance<ListBox> xListBox(pParent, nBits|WB_SIMPLEMODE);
1520 xListBox->EnableAutoSize(true);
1521 xWindow = xListBox;
1524 else if (name == "VclComboBoxNumeric")
1526 OString sPattern = extractCustomProperty(rMap);
1527 OString sAdjustment = extractAdjustment(rMap);
1528 extractModel(id, rMap);
1530 WinBits nBits = WB_CLIPCHILDREN|WB_LEFT|WB_VCENTER|WB_3DLOOK;
1532 bool bDropdown = VclBuilder::extractDropdown(rMap);
1534 if (bDropdown)
1535 nBits |= WB_DROPDOWN;
1537 if (!sPattern.isEmpty())
1539 connectNumericFormatterAdjustment(id, sAdjustment);
1540 OString sUnit = extractUnit(sPattern);
1541 FieldUnit eUnit = detectMetricUnit(sUnit);
1542 SAL_INFO("vcl.layout", "making metric box for " << name.getStr() << " " << sUnit.getStr());
1543 VclPtrInstance<MetricBox> xBox(pParent, nBits);
1544 xBox->EnableAutoSize(true);
1545 xBox->SetUnit(eUnit);
1546 xBox->SetDecimalDigits(extractDecimalDigits(sPattern));
1547 if (eUnit == FUNIT_CUSTOM)
1548 xBox->SetCustomUnitText(OStringToOUString(sUnit, RTL_TEXTENCODING_UTF8));
1549 xWindow = xBox;
1551 else
1553 SAL_INFO("vcl.layout", "making numeric box for " << name.getStr());
1554 connectNumericFormatterAdjustment(id, sAdjustment);
1555 VclPtrInstance<NumericBox> xBox(pParent, nBits);
1556 if (bDropdown)
1557 xBox->EnableAutoSize(true);
1558 xWindow = xBox;
1561 else if (name == "GtkTreeView")
1563 //To-Do
1564 //a) move svtools SvTreeViewBox into vcl
1565 //b) make that the default target for GtkTreeView
1566 //c) remove the non-drop down mode of ListBox and convert
1567 // everything over to SvTreeViewBox
1568 //d) remove the users of makeSvTreeViewBox
1569 extractModel(id, rMap);
1570 WinBits nWinStyle = WB_CLIPCHILDREN|WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_SIMPLEMODE;
1571 OString sBorder = extractCustomProperty(rMap);
1572 if (!sBorder.isEmpty())
1573 nWinStyle |= WB_BORDER;
1574 //ListBox manages its own scrolling,
1575 vcl::Window *pRealParent = prepareWidgetOwnScrolling(pParent, nWinStyle);
1576 xWindow = VclPtr<ListBox>::Create(pRealParent, nWinStyle);
1577 if (pRealParent != pParent)
1578 cleanupWidgetOwnScrolling(pParent, xWindow, rMap);
1580 else if (name == "GtkLabel")
1582 WinBits nWinStyle = WB_CENTER|WB_VCENTER|WB_3DLOOK;
1583 OString sBorder = extractCustomProperty(rMap);
1584 if (!sBorder.isEmpty())
1585 nWinStyle |= WB_BORDER;
1586 extractMnemonicWidget(id, rMap);
1587 if (extractSelectable(rMap))
1588 xWindow = VclPtr<SelectableFixedText>::Create(pParent, nWinStyle);
1589 else
1590 xWindow = VclPtr<FixedText>::Create(pParent, nWinStyle);
1592 else if (name == "GtkImage")
1594 extractStock(id, rMap);
1595 xWindow = VclPtr<FixedImage>::Create(pParent, WB_CENTER|WB_VCENTER|WB_3DLOOK|WB_SCALE);
1596 //such parentless GtkImages are temps used to set icons on buttons
1597 //default them to hidden to stop e.g. insert->index entry flicking temp
1598 //full screen windows
1599 if (!pParent)
1601 rMap["visible"] = "false";
1605 else if (name == "GtkSeparator")
1607 bVertical = extractOrientation(rMap);
1608 xWindow = VclPtr<FixedLine>::Create(pParent, bVertical ? WB_VERT : WB_HORZ);
1610 else if (name == "GtkScrollbar")
1612 extractAdjustmentToMap(id, rMap, m_pParserState->m_aScrollAdjustmentMaps);
1613 bVertical = extractOrientation(rMap);
1614 xWindow = VclPtr<ScrollBar>::Create(pParent, bVertical ? WB_VERT : WB_HORZ);
1616 else if (name == "GtkProgressBar")
1618 extractAdjustmentToMap(id, rMap, m_pParserState->m_aScrollAdjustmentMaps);
1619 bVertical = extractOrientation(rMap);
1620 xWindow = VclPtr<ProgressBar>::Create(pParent, bVertical ? WB_VERT : WB_HORZ);
1622 else if (name == "GtkScrolledWindow")
1624 xWindow = VclPtr<VclScrolledWindow>::Create(pParent);
1626 else if (name == "GtkViewport")
1628 xWindow = VclPtr<VclViewport>::Create(pParent);
1630 else if (name == "GtkEventBox")
1632 xWindow = VclPtr<VclEventBox>::Create(pParent);
1634 else if (name == "GtkEntry")
1636 xWindow = VclPtr<Edit>::Create(pParent, WB_LEFT|WB_VCENTER|WB_BORDER|WB_3DLOOK);
1637 ensureDefaultWidthChars(rMap);
1639 else if (name == "GtkNotebook")
1641 xWindow = VclPtr<TabControl>::Create(pParent, WB_STDTABCONTROL|WB_3DLOOK);
1643 else if (name == "GtkDrawingArea")
1645 OString sBorder = extractCustomProperty(rMap);
1646 xWindow = VclPtr<vcl::Window>::Create(pParent, sBorder.isEmpty() ? 0 : WB_BORDER);
1648 else if (name == "GtkTextView")
1650 extractBuffer(id, rMap);
1652 WinBits nWinStyle = WB_CLIPCHILDREN|WB_LEFT;
1653 OString sBorder = extractCustomProperty(rMap);
1654 if (!sBorder.isEmpty())
1655 nWinStyle |= WB_BORDER;
1656 //VclMultiLineEdit manages its own scrolling,
1657 vcl::Window *pRealParent = prepareWidgetOwnScrolling(pParent, nWinStyle);
1658 xWindow = VclPtr<VclMultiLineEdit>::Create(pRealParent, nWinStyle);
1659 if (pRealParent != pParent)
1660 cleanupWidgetOwnScrolling(pParent, xWindow, rMap);
1662 else if (name == "GtkSpinner")
1664 xWindow = VclPtr<Throbber>::Create(pParent, WB_3DLOOK);
1666 else if (name == "GtkScale")
1668 extractAdjustmentToMap(id, rMap, m_pParserState->m_aSliderAdjustmentMaps);
1669 bool bDrawValue = extractDrawValue(rMap);
1670 if (bDrawValue)
1672 OString sValuePos = extractValuePos(rMap);
1673 (void)sValuePos;
1675 bVertical = extractOrientation(rMap);
1677 WinBits nWinStyle = bVertical ? WB_VERT : WB_HORZ;
1679 xWindow = VclPtr<Slider>::Create(pParent, nWinStyle);
1681 else if (name == "GtkToolbar")
1683 xWindow = VclPtr<ToolBox>::Create(pParent, WB_3DLOOK | WB_TABSTOP);
1685 else if (name == "GtkToolButton" || name == "GtkMenuToolButton" ||
1686 name == "GtkToggleToolButton" || name == "GtkRadioToolButton")
1688 ToolBox *pToolBox = dynamic_cast<ToolBox*>(pParent);
1689 if (pToolBox)
1691 OUString aCommand(OStringToOUString(extractActionName(rMap), RTL_TEXTENCODING_UTF8));
1693 sal_uInt16 nItemId = 0;
1694 ToolBoxItemBits nBits = ToolBoxItemBits::NONE;
1695 if (name == "GtkMenuToolButton")
1696 nBits |= ToolBoxItemBits::DROPDOWN;
1697 else if (name == "GtkToggleToolButton")
1698 nBits |= ToolBoxItemBits::AUTOCHECK | ToolBoxItemBits::CHECKABLE;
1699 else if (name == "GtkRadioToolButton")
1700 nBits |= ToolBoxItemBits::AUTOCHECK | ToolBoxItemBits::RADIOCHECK;
1702 if (!aCommand.isEmpty() && m_xFrame.is())
1704 pToolBox->InsertItem(aCommand, m_xFrame, nBits, extractSizeRequest(rMap));
1705 nItemId = pToolBox->GetItemId(aCommand);
1707 else
1709 nItemId = pToolBox->GetItemCount() + 1;
1710 pToolBox->InsertItem(nItemId, OStringToOUString(extractLabel(rMap), RTL_TEXTENCODING_UTF8), nBits);
1711 pToolBox->SetItemCommand(nItemId, aCommand);
1712 pToolBox->SetHelpId(nItemId, m_sHelpRoot + id);
1715 OString sTooltip(extractTooltipText(rMap));
1716 if (!sTooltip.isEmpty())
1717 pToolBox->SetQuickHelpText(nItemId, OStringToOUString(sTooltip, RTL_TEXTENCODING_UTF8));
1719 OString sIconName(extractIconName(rMap));
1720 if (!sIconName.isEmpty())
1721 pToolBox->SetItemImage(nItemId, FixedImage::loadThemeImage(sIconName));
1723 if (!extractVisible(rMap))
1724 pToolBox->HideItem(nItemId);
1726 m_pParserState->m_nLastToolbarId = nItemId;
1728 return nullptr; // no widget to be created
1731 else if (name == "GtkSeparatorToolItem")
1733 ToolBox *pToolBox = dynamic_cast<ToolBox*>(pParent);
1734 if (pToolBox)
1736 pToolBox->InsertSeparator();
1737 return nullptr; // no widget to be created
1740 else if (name == "GtkWindow")
1742 WinBits nBits = extractDeferredBits(rMap);
1743 if (nBits & WB_DOCKABLE)
1744 xWindow = VclPtr<DockingWindow>::Create(pParent, nBits|WB_MOVEABLE);
1745 else
1746 xWindow = VclPtr<FloatingWindow>::Create(pParent, nBits|WB_MOVEABLE);
1748 else
1750 #ifndef SAL_DLLPREFIX
1751 #define SAL_DLLPREFIX ""
1752 #endif
1753 sal_Int32 nDelim = name.indexOf('-');
1754 if (nDelim != -1)
1756 #ifndef DISABLE_DYNLOADING
1757 OUStringBuffer sModuleBuf;
1758 sModuleBuf.append(SAL_DLLPREFIX);
1759 sModuleBuf.append(OStringToOUString(name.copy(0, nDelim), RTL_TEXTENCODING_UTF8));
1760 sModuleBuf.append(SAL_DLLEXTENSION);
1761 #endif
1762 OUString sFunction(OStringToOUString(OString("make") + name.copy(nDelim+1), RTL_TEXTENCODING_UTF8));
1763 #ifndef DISABLE_DYNLOADING
1764 OUString sModule = sModuleBuf.makeStringAndClear();
1765 ModuleMap::iterator aI = m_aModuleMap.find(sModule);
1766 if (aI == m_aModuleMap.end())
1768 osl::Module* pModule = new osl::Module;
1769 #if ENABLE_MERGELIBS
1770 sModuleBuf.append(SAL_DLLPREFIX);
1771 sModuleBuf.append("mergedlo");
1772 sModuleBuf.append(SAL_DLLEXTENSION);
1773 OUString sMergedModule = sModuleBuf.makeStringAndClear();
1774 pModule->loadRelative(&thisModule, sMergedModule);
1775 if (!pModule->getFunctionSymbol(sFunction))
1777 pModule->loadRelative(&thisModule, sModule);
1779 #else
1780 pModule->loadRelative(&thisModule, sModule);
1781 #endif
1782 aI = m_aModuleMap.insert(std::make_pair(sModule, std::unique_ptr<osl::Module>(pModule))).first;
1784 customMakeWidget pFunction = reinterpret_cast<customMakeWidget>(aI->second->getFunctionSymbol(sFunction));
1785 #else
1786 customMakeWidget pFunction = reinterpret_cast<customMakeWidget>(osl_getFunctionSymbol((oslModule) RTLD_DEFAULT, sFunction.pData));
1787 #endif
1788 if (pFunction)
1790 VclPtr<vcl::Window> xParent(pParent);
1791 pFunction(xWindow, xParent, rMap);
1792 if (xWindow->GetType() == WINDOW_PUSHBUTTON)
1793 setupFromActionName(static_cast<Button*>(xWindow.get()), rMap, m_xFrame);
1797 SAL_WARN_IF(!xWindow, "vcl.layout", "probably need to implement " << name.getStr() << " or add a make" << name.getStr() << " function");
1798 if (xWindow)
1800 xWindow->SetHelpId(m_sHelpRoot + id);
1801 SAL_INFO("vcl.layout", "for " << name.getStr() <<
1802 ", created " << xWindow.get() << " child of " <<
1803 pParent << "(" << xWindow->mpWindowImpl->mpParent.get() << "/" <<
1804 xWindow->mpWindowImpl->mpRealParent.get() << "/" <<
1805 xWindow->mpWindowImpl->mpBorderWindow.get() << ") with helpid " <<
1806 xWindow->GetHelpId().getStr());
1807 m_aChildren.push_back(WinAndId(id, xWindow, bVertical));
1809 return xWindow;
1812 namespace
1814 //return true for window types which exist in vcl but are not themselves
1815 //represented in the .ui format, i.e. only their children exist.
1816 bool isConsideredGtkPseudo(vcl::Window *pWindow)
1818 return pWindow->GetType() == WINDOW_TABPAGE;
1822 //Any properties from .ui load we couldn't set because of potential virtual methods
1823 //during ctor are applied here
1824 void VclBuilder::setDeferredProperties()
1826 if (!m_bToplevelHasDeferredProperties)
1827 return;
1828 stringmap aDeferredProperties;
1829 aDeferredProperties.swap(m_aDeferredProperties);
1830 m_bToplevelHasDeferredProperties = false;
1831 set_properties(m_pParent, aDeferredProperties);
1834 void VclBuilder::set_properties(vcl::Window *pWindow, const stringmap &rProps)
1836 for (stringmap::const_iterator aI = rProps.begin(), aEnd = rProps.end(); aI != aEnd; ++aI)
1838 const OString &rKey = aI->first;
1839 const OString &rValue = aI->second;
1840 pWindow->set_property(rKey, rValue);
1844 VclPtr<vcl::Window> VclBuilder::insertObject(vcl::Window *pParent, const OString &rClass,
1845 const OString &rID, stringmap &rProps, stringmap &rPango, stringmap &rAtk)
1847 VclPtr<vcl::Window> pCurrentChild;
1849 if (m_pParent && !isConsideredGtkPseudo(m_pParent) && !m_sID.isEmpty() && rID.equals(m_sID))
1851 pCurrentChild = m_pParent;
1853 //toplevels default to resizable and apparently you can't change them
1854 //afterwards, so we need to wait until now before we can truly
1855 //initialize the dialog.
1856 if (pParent && pParent->IsSystemWindow())
1858 SystemWindow *pSysWin = static_cast<SystemWindow*>(pCurrentChild.get());
1859 pSysWin->doDeferredInit(extractDeferredBits(rProps));
1860 m_bToplevelHasDeferredInit = false;
1862 else if (pParent && pParent->IsDockingWindow())
1864 DockingWindow *pDockWin = static_cast<DockingWindow*>(pCurrentChild.get());
1865 pDockWin->doDeferredInit(extractDeferredBits(rProps));
1866 m_bToplevelHasDeferredInit = false;
1869 if (pCurrentChild->GetHelpId().isEmpty())
1871 pCurrentChild->SetHelpId(m_sHelpRoot + m_sID);
1872 SAL_INFO("vcl.layout", "for toplevel dialog " << this << " " <<
1873 rID.getStr() << ", set helpid " <<
1874 pCurrentChild->GetHelpId().getStr());
1876 m_bToplevelParentFound = true;
1878 else
1880 //if we're being inserting under a toplevel dialog whose init is
1881 //deferred due to waiting to encounter it in this .ui, and it hasn't
1882 //been seen yet, then make unattached widgets parent-less toplevels
1883 if (pParent == m_pParent.get() && m_bToplevelHasDeferredInit)
1884 pParent = nullptr;
1885 pCurrentChild = makeObject(pParent, rClass, rID, rProps);
1888 if (pCurrentChild)
1890 pCurrentChild->set_id(OStringToOUString(rID, RTL_TEXTENCODING_UTF8));
1891 if (pCurrentChild == m_pParent.get() && m_bToplevelHasDeferredProperties)
1892 m_aDeferredProperties = rProps;
1893 else
1894 set_properties(pCurrentChild, rProps);
1896 for (stringmap::iterator aI = rPango.begin(), aEnd = rPango.end(); aI != aEnd; ++aI)
1898 const OString &rKey = aI->first;
1899 const OString &rValue = aI->second;
1900 pCurrentChild->set_font_attribute(rKey, rValue);
1903 m_pParserState->m_aAtkInfo[VclPtr<vcl::Window>(pCurrentChild)] = rAtk;
1906 rProps.clear();
1907 rPango.clear();
1908 rAtk.clear();
1910 if (!pCurrentChild)
1911 pCurrentChild = m_aChildren.empty() ? pParent : m_aChildren.back().m_pWindow.get();
1912 return pCurrentChild;
1915 void VclBuilder::reorderWithinParent(vcl::Window &rWindow, sal_uInt16 nNewPosition)
1917 if (rWindow.mpWindowImpl->mpParent != rWindow.mpWindowImpl->mpRealParent)
1919 assert(rWindow.mpWindowImpl->mpBorderWindow ==
1920 rWindow.mpWindowImpl->mpParent);
1921 assert(rWindow.mpWindowImpl->mpBorderWindow->mpWindowImpl->mpParent ==
1922 rWindow.mpWindowImpl->mpRealParent);
1923 reorderWithinParent(*rWindow.mpWindowImpl->mpBorderWindow, nNewPosition);
1924 return;
1926 rWindow.reorderWithinParent(nNewPosition);
1929 void VclBuilder::handleTabChild(vcl::Window *pParent, xmlreader::XmlReader &reader)
1931 OString sID;
1933 int nLevel = 1;
1934 stringmap aProperties;
1935 std::vector<vcl::EnumContext::Context> context;
1937 while(true)
1939 xmlreader::Span name;
1940 int nsId;
1942 xmlreader::XmlReader::Result res = reader.nextItem(
1943 xmlreader::XmlReader::Text::NONE, &name, &nsId);
1945 if (res == xmlreader::XmlReader::Result::Begin)
1947 ++nLevel;
1948 if (name.equals("object"))
1950 while (reader.nextAttribute(&nsId, &name))
1952 if (name.equals("id"))
1954 name = reader.getAttributeValue(false);
1955 sID = OString(name.begin, name.length);
1956 sal_Int32 nDelim = sID.indexOf(':');
1957 if (nDelim != -1)
1959 OString sPattern = sID.copy(nDelim+1);
1960 aProperties[OString("customproperty")] = sPattern;
1961 sID = sID.copy(0, nDelim);
1966 else if (name.equals("style"))
1968 int nPriority = 0;
1969 context = handleStyle(reader, nPriority);
1970 --nLevel;
1972 else if (name.equals("property"))
1973 collectProperty(reader, sID, aProperties);
1976 if (res == xmlreader::XmlReader::Result::End)
1977 --nLevel;
1979 if (!nLevel)
1980 break;
1982 if (res == xmlreader::XmlReader::Result::Done)
1983 break;
1986 if (!pParent)
1987 return;
1989 TabControl *pTabControl = static_cast<TabControl*>(pParent);
1990 VclBuilder::stringmap::iterator aFind = aProperties.find(OString("label"));
1991 if (aFind != aProperties.end())
1993 sal_uInt16 nPageId = pTabControl->GetCurPageId();
1994 pTabControl->SetPageText(nPageId,
1995 OStringToOUString(aFind->second, RTL_TEXTENCODING_UTF8));
1996 pTabControl->SetPageName(nPageId, sID);
1997 if (context.size() != 0)
1999 TabPage* pPage = pTabControl->GetTabPage(nPageId);
2000 pPage->SetContext(context);
2003 else
2004 pTabControl->RemovePage(pTabControl->GetCurPageId());
2007 //so that tabbing between controls goes in a visually sensible sequence
2008 //we sort these into a best-tab-order sequence
2009 bool VclBuilder::sortIntoBestTabTraversalOrder::operator()(const vcl::Window *pA, const vcl::Window *pB) const
2011 //sort child order within parent list by grid position
2012 sal_Int32 nTopA = pA->get_grid_top_attach();
2013 sal_Int32 nTopB = pB->get_grid_top_attach();
2014 if (nTopA < nTopB)
2015 return true;
2016 if (nTopA > nTopB)
2017 return false;
2018 sal_Int32 nLeftA = pA->get_grid_left_attach();
2019 sal_Int32 nLeftB = pB->get_grid_left_attach();
2020 if (nLeftA < nLeftB)
2021 return true;
2022 if (nLeftA > nLeftB)
2023 return false;
2024 //sort into two groups of pack start and pack end
2025 VclPackType ePackA = pA->get_pack_type();
2026 VclPackType ePackB = pB->get_pack_type();
2027 if (ePackA < ePackB)
2028 return true;
2029 if (ePackA > ePackB)
2030 return false;
2031 bool bVerticalContainer = m_pBuilder->get_window_packing_data(pA->GetParent()).m_bVerticalOrient;
2032 bool bPackA = pA->get_secondary();
2033 bool bPackB = pB->get_secondary();
2034 if (!bVerticalContainer)
2036 //for horizontal boxes group secondaries before primaries
2037 if (bPackA > bPackB)
2038 return true;
2039 if (bPackA < bPackB)
2040 return false;
2042 else
2044 //for vertical boxes group secondaries after primaries
2045 if (bPackA < bPackB)
2046 return true;
2047 if (bPackA > bPackB)
2048 return false;
2050 //honour relative box positions with pack group, (numerical order is reversed
2051 //for VclPackType::End, they are packed from the end back, but here we need
2052 //them in visual layout order so that tabbing works as expected)
2053 sal_Int32 nPackA = m_pBuilder->get_window_packing_data(pA).m_nPosition;
2054 sal_Int32 nPackB = m_pBuilder->get_window_packing_data(pB).m_nPosition;
2055 if (nPackA < nPackB)
2056 return ePackA == VclPackType::Start;
2057 if (nPackA > nPackB)
2058 return ePackA != VclPackType::Start;
2059 //sort labels of Frames before body
2060 if (pA->GetParent() == pB->GetParent())
2062 const VclFrame *pFrameParent = dynamic_cast<const VclFrame*>(pA->GetParent());
2063 if (pFrameParent)
2065 const vcl::Window *pLabel = pFrameParent->get_label_widget();
2066 int nFramePosA = (pA == pLabel) ? 0 : 1;
2067 int nFramePosB = (pB == pLabel) ? 0 : 1;
2068 return nFramePosA < nFramePosB;
2071 return false;
2074 void VclBuilder::handleChild(vcl::Window *pParent, xmlreader::XmlReader &reader)
2076 vcl::Window *pCurrentChild = nullptr;
2078 xmlreader::Span name;
2079 int nsId;
2080 OString sType, sInternalChild;
2082 while (reader.nextAttribute(&nsId, &name))
2084 if (name.equals("type"))
2086 name = reader.getAttributeValue(false);
2087 sType = OString(name.begin, name.length);
2089 else if (name.equals("internal-child"))
2091 name = reader.getAttributeValue(false);
2092 sInternalChild = OString(name.begin, name.length);
2096 if (sType.equals("tab"))
2098 handleTabChild(pParent, reader);
2099 return;
2102 int nLevel = 1;
2103 while(true)
2105 xmlreader::XmlReader::Result res = reader.nextItem(
2106 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2108 if (res == xmlreader::XmlReader::Result::Begin)
2110 if (name.equals("object") || name.equals("placeholder"))
2112 pCurrentChild = handleObject(pParent, reader).get();
2114 bool bObjectInserted = pCurrentChild && pParent != pCurrentChild;
2116 if (bObjectInserted)
2118 //Internal-children default in glade to not having their visible bits set
2119 //even though they are visible (generally anyway)
2120 if (!sInternalChild.isEmpty())
2121 pCurrentChild->Show();
2123 //Select the first page if it's a notebook
2124 if (pCurrentChild->GetType() == WINDOW_TABCONTROL)
2126 TabControl *pTabControl = static_cast<TabControl*>(pCurrentChild);
2127 pTabControl->SetCurPageId(pTabControl->GetPageId(0));
2129 //To-Do add reorder capability to the TabControl
2131 else
2133 // We want to sort labels before contents of frames
2134 // for keyboard traversal, especially if there
2135 // are multiple widgets using the same mnemonic
2136 if (sType.equals("label"))
2138 if (VclFrame *pFrameParent = dynamic_cast<VclFrame*>(pParent))
2139 pFrameParent->designate_label(pCurrentChild);
2141 if (sInternalChild.startsWith("vbox") || sInternalChild.startsWith("messagedialog-vbox"))
2143 if (Dialog *pBoxParent = dynamic_cast<Dialog*>(pParent))
2144 pBoxParent->set_content_area(static_cast<VclBox*>(pCurrentChild)); // FIXME-VCLPTR
2146 else if (sInternalChild.startsWith("action_area") || sInternalChild.startsWith("messagedialog-action_area"))
2148 vcl::Window *pContentArea = pCurrentChild->GetParent();
2149 if (Dialog *pBoxParent = dynamic_cast<Dialog*>(pContentArea ? pContentArea->GetParent() : nullptr))
2151 pBoxParent->set_action_area(static_cast<VclButtonBox*>(pCurrentChild)); // FIXME-VCLPTR
2155 //To-Do make reorder a virtual in Window, move this foo
2156 //there and see above
2157 std::vector<vcl::Window*> aChilds;
2158 for (vcl::Window* pChild = pCurrentChild->GetWindow(GetWindowType::FirstChild); pChild;
2159 pChild = pChild->GetWindow(GetWindowType::Next))
2161 aChilds.push_back(pChild);
2164 bool bIsButtonBox = dynamic_cast<VclButtonBox*>(pCurrentChild) != nullptr;
2166 //sort child order within parent so that tabbing
2167 //between controls goes in a visually sensible sequence
2168 std::stable_sort(aChilds.begin(), aChilds.end(), sortIntoBestTabTraversalOrder(this));
2169 reorderWithinParent(aChilds, bIsButtonBox);
2173 else if (name.equals("packing"))
2175 handlePacking(pCurrentChild, pParent, reader);
2177 else
2178 ++nLevel;
2181 if (res == xmlreader::XmlReader::Result::End)
2182 --nLevel;
2184 if (!nLevel)
2185 break;
2187 if (res == xmlreader::XmlReader::Result::Done)
2188 break;
2192 void VclBuilder::reorderWithinParent(std::vector<vcl::Window*>& rChilds, bool bIsButtonBox)
2194 for (size_t i = 0; i < rChilds.size(); ++i)
2196 reorderWithinParent(*rChilds[i], i);
2198 if (!bIsButtonBox)
2199 continue;
2201 //The first member of the group for legacy code needs WB_GROUP set and the
2202 //others not
2203 WinBits nBits = rChilds[i]->GetStyle();
2204 nBits &= ~WB_GROUP;
2205 if (i == 0)
2206 nBits |= WB_GROUP;
2207 rChilds[i]->SetStyle(nBits);
2211 void VclBuilder::collectPangoAttribute(xmlreader::XmlReader &reader, stringmap &rMap)
2213 xmlreader::Span span;
2214 int nsId;
2216 OString sProperty;
2217 OString sValue;
2219 while (reader.nextAttribute(&nsId, &span))
2221 if (span.equals("name"))
2223 span = reader.getAttributeValue(false);
2224 sProperty = OString(span.begin, span.length);
2226 else if (span.equals("value"))
2228 span = reader.getAttributeValue(false);
2229 sValue = OString(span.begin, span.length);
2233 if (!sProperty.isEmpty())
2234 rMap[sProperty] = sValue;
2237 void VclBuilder::collectAtkAttribute(xmlreader::XmlReader &reader, stringmap &rMap)
2239 xmlreader::Span span;
2240 int nsId;
2242 OString sProperty;
2243 OString sValue;
2245 while (reader.nextAttribute(&nsId, &span))
2247 if (span.equals("type"))
2249 span = reader.getAttributeValue(false);
2250 sProperty = OString(span.begin, span.length);
2252 else if (span.equals("target"))
2254 span = reader.getAttributeValue(false);
2255 sValue = OString(span.begin, span.length);
2256 sal_Int32 nDelim = sValue.indexOf(':');
2257 if (nDelim != -1)
2258 sValue = sValue.copy(0, nDelim);
2262 if (!sProperty.isEmpty())
2263 rMap[sProperty] = sValue;
2266 void VclBuilder::handleRow(xmlreader::XmlReader &reader, const OString &rID, sal_Int32 nRowIndex)
2268 int nLevel = 1;
2270 ListStore::row aRow;
2272 while(true)
2274 xmlreader::Span name;
2275 int nsId;
2277 xmlreader::XmlReader::Result res = reader.nextItem(
2278 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2280 if (res == xmlreader::XmlReader::Result::Done)
2281 break;
2283 if (res == xmlreader::XmlReader::Result::Begin)
2285 ++nLevel;
2286 if (name.equals("col"))
2288 bool bTranslated = false;
2289 OString sValue;
2290 sal_uInt32 nId = 0;
2292 while (reader.nextAttribute(&nsId, &name))
2294 if (name.equals("id"))
2296 name = reader.getAttributeValue(false);
2297 nId = OString(name.begin, name.length).toInt32();
2299 else if (nId == 0 && name.equals("translatable") && reader.getAttributeValue(false).equals("yes"))
2301 sValue = getTranslation(rID, OString::number(nRowIndex));
2302 bTranslated = !sValue.isEmpty();
2306 reader.nextItem(
2307 xmlreader::XmlReader::Text::Raw, &name, &nsId);
2309 if (!bTranslated)
2310 sValue = OString(name.begin, name.length);
2312 if (aRow.size() < nId+1)
2313 aRow.resize(nId+1);
2314 aRow[nId] = sValue;
2318 if (res == xmlreader::XmlReader::Result::End)
2320 --nLevel;
2323 if (!nLevel)
2324 break;
2327 m_pParserState->m_aModels[rID].m_aEntries.push_back(aRow);
2330 void VclBuilder::handleListStore(xmlreader::XmlReader &reader, const OString &rID)
2332 int nLevel = 1;
2333 sal_Int32 nRowIndex = 0;
2335 while(true)
2337 xmlreader::Span name;
2338 int nsId;
2340 xmlreader::XmlReader::Result res = reader.nextItem(
2341 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2343 if (res == xmlreader::XmlReader::Result::Done)
2344 break;
2346 if (res == xmlreader::XmlReader::Result::Begin)
2348 if (name.equals("row"))
2349 handleRow(reader, rID, nRowIndex++);
2350 else
2351 ++nLevel;
2354 if (res == xmlreader::XmlReader::Result::End)
2356 --nLevel;
2359 if (!nLevel)
2360 break;
2364 void VclBuilder::handleAtkObject(xmlreader::XmlReader &reader, const OString &rID, vcl::Window *pWindow)
2366 assert(pWindow);
2368 int nLevel = 1;
2370 stringmap aProperties;
2372 while(true)
2374 xmlreader::Span name;
2375 int nsId;
2377 xmlreader::XmlReader::Result res = reader.nextItem(
2378 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2380 if (res == xmlreader::XmlReader::Result::Done)
2381 break;
2383 if (res == xmlreader::XmlReader::Result::Begin)
2385 ++nLevel;
2386 if (name.equals("property"))
2387 collectProperty(reader, rID, aProperties);
2390 if (res == xmlreader::XmlReader::Result::End)
2392 --nLevel;
2395 if (!nLevel)
2396 break;
2399 for (stringmap::iterator aI = aProperties.begin(), aEnd = aProperties.end(); aI != aEnd; ++aI)
2401 const OString &rKey = aI->first;
2402 const OString &rValue = aI->second;
2404 if (pWindow && rKey.match("AtkObject::"))
2405 pWindow->set_property(rKey.copy(RTL_CONSTASCII_LENGTH("AtkObject::")), rValue);
2406 else
2407 SAL_WARN("vcl.layout", "unhandled atk prop: " << rKey.getStr());
2411 std::vector<OString> VclBuilder::handleItems(xmlreader::XmlReader &reader, const OString &rID)
2413 int nLevel = 1;
2415 std::vector<OString> aItems;
2416 sal_Int32 nItemIndex = 0;
2418 while(true)
2420 xmlreader::Span name;
2421 int nsId;
2423 xmlreader::XmlReader::Result res = reader.nextItem(
2424 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2426 if (res == xmlreader::XmlReader::Result::Done)
2427 break;
2429 if (res == xmlreader::XmlReader::Result::Begin)
2431 ++nLevel;
2432 if (name.equals("item"))
2434 bool bTranslated = false;
2435 OString sValue;
2437 while (reader.nextAttribute(&nsId, &name))
2439 if (name.equals("translatable") && reader.getAttributeValue(false).equals("yes"))
2441 sValue = getTranslation(rID, OString::number(nItemIndex));
2442 bTranslated = !sValue.isEmpty();
2446 reader.nextItem(
2447 xmlreader::XmlReader::Text::Raw, &name, &nsId);
2449 if (!bTranslated)
2450 sValue = OString(name.begin, name.length);
2452 if (m_pStringReplace)
2454 OUString sTmp = (*m_pStringReplace)(OStringToOUString(sValue, RTL_TEXTENCODING_UTF8));
2455 sValue = OUStringToOString(sTmp, RTL_TEXTENCODING_UTF8);
2458 aItems.push_back(sValue);
2459 ++nItemIndex;
2463 if (res == xmlreader::XmlReader::Result::End)
2465 --nLevel;
2468 if (!nLevel)
2469 break;
2472 return aItems;
2475 void VclBuilder::handleMenu(xmlreader::XmlReader &reader, const OString &rID)
2477 VclPtr<PopupMenu> pCurrentMenu = VclPtr<PopupMenu>::Create();
2479 int nLevel = 1;
2481 stringmap aProperties;
2483 while(true)
2485 xmlreader::Span name;
2486 int nsId;
2488 xmlreader::XmlReader::Result res = reader.nextItem(
2489 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2491 if (res == xmlreader::XmlReader::Result::Done)
2492 break;
2494 if (res == xmlreader::XmlReader::Result::Begin)
2496 if (name.equals("child"))
2498 handleMenuChild(pCurrentMenu, reader);
2500 else
2502 ++nLevel;
2503 if (name.equals("property"))
2504 collectProperty(reader, rID, aProperties);
2508 if (res == xmlreader::XmlReader::Result::End)
2510 --nLevel;
2513 if (!nLevel)
2514 break;
2517 m_aMenus.push_back(MenuAndId(rID, pCurrentMenu));
2520 void VclBuilder::handleMenuChild(PopupMenu *pParent, xmlreader::XmlReader &reader)
2522 xmlreader::Span name;
2523 int nsId;
2525 int nLevel = 1;
2526 while(true)
2528 xmlreader::XmlReader::Result res = reader.nextItem(
2529 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2531 if (res == xmlreader::XmlReader::Result::Begin)
2533 if (name.equals("object") || name.equals("placeholder"))
2535 handleMenuObject(pParent, reader);
2537 else
2538 ++nLevel;
2541 if (res == xmlreader::XmlReader::Result::End)
2542 --nLevel;
2544 if (!nLevel)
2545 break;
2547 if (res == xmlreader::XmlReader::Result::Done)
2548 break;
2552 void VclBuilder::handleMenuObject(PopupMenu *pParent, xmlreader::XmlReader &reader)
2554 OString sClass;
2555 OString sID;
2556 OString sCustomProperty;
2558 xmlreader::Span name;
2559 int nsId;
2561 while (reader.nextAttribute(&nsId, &name))
2563 if (name.equals("class"))
2565 name = reader.getAttributeValue(false);
2566 sClass = OString(name.begin, name.length);
2568 else if (name.equals("id"))
2570 name = reader.getAttributeValue(false);
2571 sID = OString(name.begin, name.length);
2572 sal_Int32 nDelim = sID.indexOf(':');
2573 if (nDelim != -1)
2575 sCustomProperty = sID.copy(nDelim+1);
2576 sID = sID.copy(0, nDelim);
2581 int nLevel = 1;
2583 stringmap aProperties, aAccelerators;
2585 if (!sCustomProperty.isEmpty())
2586 aProperties[OString("customproperty")] = sCustomProperty;
2588 while(true)
2590 xmlreader::XmlReader::Result res = reader.nextItem(
2591 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2593 if (res == xmlreader::XmlReader::Result::Done)
2594 break;
2596 if (res == xmlreader::XmlReader::Result::Begin)
2598 ++nLevel;
2599 if (name.equals("property"))
2600 collectProperty(reader, sID, aProperties);
2601 else if (name.equals("accelerator"))
2602 collectAccelerator(reader, aAccelerators);
2605 if (res == xmlreader::XmlReader::Result::End)
2607 --nLevel;
2610 if (!nLevel)
2611 break;
2614 insertMenuObject(pParent, sClass, sID, aProperties, aAccelerators);
2617 void VclBuilder::handleSizeGroup(xmlreader::XmlReader &reader, const OString &rID)
2619 m_pParserState->m_aSizeGroups.push_back(SizeGroup());
2620 SizeGroup &rSizeGroup = m_pParserState->m_aSizeGroups.back();
2622 int nLevel = 1;
2624 while(true)
2626 xmlreader::Span name;
2627 int nsId;
2629 xmlreader::XmlReader::Result res = reader.nextItem(
2630 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2632 if (res == xmlreader::XmlReader::Result::Done)
2633 break;
2635 if (res == xmlreader::XmlReader::Result::Begin)
2637 ++nLevel;
2638 if (name.equals("widget"))
2640 while (reader.nextAttribute(&nsId, &name))
2642 if (name.equals("name"))
2644 name = reader.getAttributeValue(false);
2645 OString sWidget = OString(name.begin, name.length);
2646 sal_Int32 nDelim = sWidget.indexOf(':');
2647 if (nDelim != -1)
2648 sWidget = sWidget.copy(0, nDelim);
2649 rSizeGroup.m_aWidgets.push_back(sWidget);
2653 else
2655 if (name.equals("property"))
2656 collectProperty(reader, rID, rSizeGroup.m_aProperties);
2660 if (res == xmlreader::XmlReader::Result::End)
2662 --nLevel;
2665 if (!nLevel)
2666 break;
2670 OString VclBuilder::convertMnemonicMarkup(const OString &rIn)
2672 OStringBuffer aRet(rIn);
2673 for (sal_Int32 nI = 0; nI < aRet.getLength(); ++nI)
2675 if (aRet[nI] == '_' && nI+1 < aRet.getLength())
2677 if (aRet[nI+1] != '_')
2678 aRet[nI] = MNEMONIC_CHAR;
2679 else
2680 aRet.remove(nI, 1);
2681 ++nI;
2684 return aRet.makeStringAndClear();
2687 namespace
2689 vcl::KeyCode makeKeyCode(const OString &rKey)
2691 if (rKey == "Insert")
2692 return vcl::KeyCode(KEY_INSERT);
2693 else if (rKey == "Delete")
2694 return vcl::KeyCode(KEY_DELETE);
2696 assert (rKey.getLength() == 1);
2697 sal_Char cChar = rKey.toChar();
2699 if (cChar >= 'a' && cChar <= 'z')
2700 return vcl::KeyCode(KEY_A + (cChar - 'a'));
2701 else if (cChar >= 'A' && cChar <= 'Z')
2702 return vcl::KeyCode(KEY_A + (cChar - 'A'));
2703 else if (cChar >= '0' && cChar <= '9')
2704 return vcl::KeyCode(KEY_0 + (cChar - 'A'));
2706 return vcl::KeyCode(cChar);
2710 void VclBuilder::insertMenuObject(PopupMenu *pParent, const OString &rClass, const OString &rID,
2711 stringmap &rProps, stringmap &rAccels)
2713 sal_uInt16 nOldCount = pParent->GetItemCount();
2714 sal_uInt16 nNewId = nOldCount + 1;
2716 if (rClass == "GtkMenuItem")
2718 OUString sLabel(OStringToOUString(convertMnemonicMarkup(extractLabel(rProps)), RTL_TEXTENCODING_UTF8));
2719 pParent->InsertItem(nNewId, sLabel, MenuItemBits::TEXT, rID);
2721 else if (rClass == "GtkSeparatorMenuItem")
2723 pParent->InsertSeparator(rID);
2726 SAL_WARN_IF(nOldCount == pParent->GetItemCount(), "vcl.layout", "probably need to implement " << rClass.getStr());
2728 if (nOldCount != pParent->GetItemCount())
2730 pParent->SetHelpId(nNewId, m_sHelpRoot + rID);
2732 for (stringmap::iterator aI = rProps.begin(), aEnd = rProps.end(); aI != aEnd; ++aI)
2734 const OString &rKey = aI->first;
2735 const OString &rValue = aI->second;
2737 if (rKey == "tooltip-markup")
2738 pParent->SetTipHelpText(nNewId, OStringToOUString(rValue, RTL_TEXTENCODING_UTF8));
2739 else if (rKey == "tooltip-text")
2740 pParent->SetTipHelpText(nNewId, OStringToOUString(rValue, RTL_TEXTENCODING_UTF8));
2741 else if (rKey == "visible")
2742 pParent->ShowItem(nNewId, toBool(rValue));
2743 else if (rKey == "has-default" && toBool(rValue))
2744 pParent->SetSelectedEntry(nNewId);
2745 else
2746 SAL_INFO("vcl.layout", "unhandled property: " << rKey.getStr());
2749 for (stringmap::iterator aI = rAccels.begin(), aEnd = rAccels.end(); aI != aEnd; ++aI)
2751 const OString &rSignal = aI->first;
2752 const OString &rValue = aI->second;
2754 if (rSignal == "activate")
2755 pParent->SetAccelKey(nNewId, makeKeyCode(rValue));
2756 else
2757 SAL_INFO("vcl.layout", "unhandled accelerator for: " << rSignal.getStr());
2761 rProps.clear();
2764 /// Insert items to a ComboBox or a ListBox.
2765 /// They have no common ancestor that would have 'InsertEntry()', so use a template.
2766 template<typename T> bool insertItems(vcl::Window *pWindow, VclBuilder::stringmap &rMap, const std::vector<OString> &rItems)
2768 T *pContainer = dynamic_cast<T*>(pWindow);
2769 if (!pContainer)
2770 return false;
2772 sal_uInt16 nActiveId = extractActive(rMap);
2773 for (std::vector<OString>::const_iterator aI = rItems.begin(), aEnd = rItems.end(); aI != aEnd; ++aI)
2774 pContainer->InsertEntry(OStringToOUString(*aI, RTL_TEXTENCODING_UTF8));
2775 if (nActiveId < rItems.size())
2776 pContainer->SelectEntryPos(nActiveId);
2778 return true;
2781 VclPtr<vcl::Window> VclBuilder::handleObject(vcl::Window *pParent, xmlreader::XmlReader &reader)
2783 OString sClass;
2784 OString sID;
2785 OString sCustomProperty;
2787 xmlreader::Span name;
2788 int nsId;
2790 while (reader.nextAttribute(&nsId, &name))
2792 if (name.equals("class"))
2794 name = reader.getAttributeValue(false);
2795 sClass = OString(name.begin, name.length);
2797 else if (name.equals("id"))
2799 name = reader.getAttributeValue(false);
2800 sID = OString(name.begin, name.length);
2801 sal_Int32 nDelim = sID.indexOf(':');
2802 if (nDelim != -1)
2804 sCustomProperty = sID.copy(nDelim+1);
2805 sID = sID.copy(0, nDelim);
2810 if (sClass == "GtkListStore")
2812 handleListStore(reader, sID);
2813 return nullptr;
2815 else if (sClass == "GtkMenu")
2817 handleMenu(reader, sID);
2818 return nullptr;
2820 else if (sClass == "GtkSizeGroup")
2822 handleSizeGroup(reader, sID);
2823 return nullptr;
2825 else if (sClass == "AtkObject")
2827 handleAtkObject(reader, sID, pParent);
2828 return nullptr;
2831 int nLevel = 1;
2833 stringmap aProperties, aPangoAttributes, aAtkAttributes;
2834 std::vector<OString> aItems;
2836 if (!sCustomProperty.isEmpty())
2837 aProperties[OString("customproperty")] = sCustomProperty;
2839 VclPtr<vcl::Window> pCurrentChild;
2840 while(true)
2842 xmlreader::XmlReader::Result res = reader.nextItem(
2843 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2845 if (res == xmlreader::XmlReader::Result::Done)
2846 break;
2848 if (res == xmlreader::XmlReader::Result::Begin)
2850 if (name.equals("child"))
2852 if (!pCurrentChild)
2854 pCurrentChild = insertObject(pParent, sClass, sID,
2855 aProperties, aPangoAttributes, aAtkAttributes);
2857 handleChild(pCurrentChild, reader);
2859 else if (name.equals("items"))
2860 aItems = handleItems(reader, sID);
2861 else if (name.equals("style"))
2863 int nPriority = 0;
2864 std::vector<vcl::EnumContext::Context> aContext = handleStyle(reader, nPriority);
2865 if (nPriority != 0)
2866 dynamic_cast<vcl::IPrioritable*>(pCurrentChild.get())->SetPriority(nPriority);
2867 if (aContext.size() != 0)
2868 dynamic_cast<vcl::IContext*>(pCurrentChild.get())->SetContext(aContext);
2870 else
2872 ++nLevel;
2873 if (name.equals("property"))
2874 collectProperty(reader, sID, aProperties);
2875 else if (name.equals("attribute"))
2876 collectPangoAttribute(reader, aPangoAttributes);
2877 else if (name.equals("relation"))
2878 collectAtkAttribute(reader, aAtkAttributes);
2879 else if (name.equals("action-widget"))
2880 handleActionWidget(reader);
2884 if (res == xmlreader::XmlReader::Result::End)
2886 --nLevel;
2889 if (!nLevel)
2890 break;
2893 if (sClass == "GtkAdjustment")
2895 m_pParserState->m_aAdjustments[sID] = aProperties;
2896 return nullptr;
2898 else if (sClass == "GtkTextBuffer")
2900 m_pParserState->m_aTextBuffers[sID] = aProperties;
2901 return nullptr;
2904 if (!pCurrentChild)
2906 pCurrentChild = insertObject(pParent, sClass, sID, aProperties,
2907 aPangoAttributes, aAtkAttributes);
2910 if (!aItems.empty())
2912 // try to fill-in the items
2913 if (!insertItems<ComboBox>(pCurrentChild, aProperties, aItems))
2914 insertItems<ListBox>(pCurrentChild, aProperties, aItems);
2917 return pCurrentChild;
2920 void VclBuilder::handlePacking(vcl::Window *pCurrent, vcl::Window *pParent, xmlreader::XmlReader &reader)
2922 xmlreader::Span name;
2923 int nsId;
2925 int nLevel = 1;
2927 while(true)
2929 xmlreader::XmlReader::Result res = reader.nextItem(
2930 xmlreader::XmlReader::Text::NONE, &name, &nsId);
2932 if (res == xmlreader::XmlReader::Result::Done)
2933 break;
2935 if (res == xmlreader::XmlReader::Result::Begin)
2937 ++nLevel;
2938 if (name.equals("property"))
2939 applyPackingProperty(pCurrent, pParent, reader);
2942 if (res == xmlreader::XmlReader::Result::End)
2944 --nLevel;
2947 if (!nLevel)
2948 break;
2952 void VclBuilder::applyPackingProperty(vcl::Window *pCurrent,
2953 vcl::Window *pParent,
2954 xmlreader::XmlReader &reader)
2956 if (!pCurrent)
2957 return;
2959 //ToolBoxItems are not true widgets just elements
2960 //of the ToolBox itself
2961 ToolBox *pToolBoxParent = nullptr;
2962 if (pCurrent == pParent)
2963 pToolBoxParent = dynamic_cast<ToolBox*>(pParent);
2965 xmlreader::Span name;
2966 int nsId;
2968 if (pCurrent->GetType() == WINDOW_SCROLLWINDOW)
2970 auto aFind = m_pParserState->m_aRedundantParentWidgets.find(VclPtr<vcl::Window>(pCurrent));
2971 if (aFind != m_pParserState->m_aRedundantParentWidgets.end())
2973 pCurrent = aFind->second;
2974 assert(pCurrent);
2978 while (reader.nextAttribute(&nsId, &name))
2980 if (name.equals("name"))
2982 name = reader.getAttributeValue(false);
2983 OString sKey(name.begin, name.length);
2984 sKey = sKey.replace('_', '-');
2985 reader.nextItem(
2986 xmlreader::XmlReader::Text::Raw, &name, &nsId);
2987 OString sValue(name.begin, name.length);
2989 if (sKey == "expand" || sKey == "resize")
2991 bool bTrue = (!sValue.isEmpty() && (sValue[0] == 't' || sValue[0] == 'T' || sValue[0] == '1'));
2992 if (pToolBoxParent)
2993 pToolBoxParent->SetItemExpand(m_pParserState->m_nLastToolbarId, bTrue);
2994 else
2995 pCurrent->set_expand(bTrue);
2996 continue;
2999 if (pToolBoxParent)
3000 continue;
3002 if (sKey == "fill")
3004 bool bTrue = (!sValue.isEmpty() && (sValue[0] == 't' || sValue[0] == 'T' || sValue[0] == '1'));
3005 pCurrent->set_fill(bTrue);
3007 else if (sKey == "pack-type")
3009 VclPackType ePackType = (!sValue.isEmpty() && (sValue[0] == 'e' || sValue[0] == 'E')) ? VclPackType::End : VclPackType::Start;
3010 pCurrent->set_pack_type(ePackType);
3012 else if (sKey == "left-attach")
3014 pCurrent->set_grid_left_attach(sValue.toInt32());
3016 else if (sKey == "top-attach")
3018 pCurrent->set_grid_top_attach(sValue.toInt32());
3020 else if (sKey == "width")
3022 pCurrent->set_grid_width(sValue.toInt32());
3024 else if (sKey == "height")
3026 pCurrent->set_grid_height(sValue.toInt32());
3028 else if (sKey == "padding")
3030 pCurrent->set_padding(sValue.toInt32());
3032 else if (sKey == "position")
3034 set_window_packing_position(pCurrent, sValue.toInt32());
3036 else if (sKey == "secondary")
3038 pCurrent->set_secondary(toBool(sValue));
3040 else if (sKey == "non-homogeneous")
3042 pCurrent->set_non_homogeneous(toBool(sValue));
3044 else if (sKey == "homogeneous")
3046 pCurrent->set_non_homogeneous(!toBool(sValue));
3048 else
3050 SAL_WARN("vcl.layout", "unknown packing: " << sKey.getStr());
3056 std::vector<vcl::EnumContext::Context> VclBuilder::handleStyle(xmlreader::XmlReader &reader, int &nPriority)
3058 std::vector<vcl::EnumContext::Context> aContext;
3060 xmlreader::Span name;
3061 int nsId;
3063 int nLevel = 1;
3065 while(true)
3067 xmlreader::XmlReader::Result res = reader.nextItem(
3068 xmlreader::XmlReader::Text::NONE, &name, &nsId);
3070 if (res == xmlreader::XmlReader::Result::Done)
3071 break;
3073 if (res == xmlreader::XmlReader::Result::Begin)
3075 ++nLevel;
3076 if (name.equals("class"))
3078 OString classStyle = getStyleClass(reader);
3080 if (classStyle.startsWith("context-"))
3082 OString sContext = classStyle.copy(classStyle.indexOf('-') + 1);
3083 OUString sContext2 = OUString(sContext.getStr(), sContext.getLength(), RTL_TEXTENCODING_UTF8);
3084 aContext.push_back(vcl::EnumContext::GetContextEnum(sContext2));
3086 else if (classStyle.startsWith("priority-"))
3088 OString aPriority = classStyle.copy(classStyle.indexOf('-') + 1);
3089 OUString aPriority2 = OUString(aPriority.getStr(), aPriority.getLength(), RTL_TEXTENCODING_UTF8);
3090 nPriority = aPriority2.toInt32();
3092 else
3094 SAL_WARN("vcl.layout", "unknown class: " << classStyle.getStr());
3099 if (res == xmlreader::XmlReader::Result::End)
3101 --nLevel;
3104 if (!nLevel)
3105 break;
3108 return aContext;
3111 OString VclBuilder::getStyleClass(xmlreader::XmlReader &reader)
3113 xmlreader::Span name;
3114 int nsId;
3115 OString aRet;
3117 while (reader.nextAttribute(&nsId, &name))
3119 if (name.equals("name"))
3121 name = reader.getAttributeValue(false);
3122 aRet = OString (name.begin, name.length);
3126 return aRet;
3129 OString VclBuilder::getTranslation(const OString &rID, const OString &rProperty) const
3131 Translations::const_iterator aWidgetFind = m_pParserState->m_aTranslations.find(rID);
3132 if (aWidgetFind != m_pParserState->m_aTranslations.end())
3134 const WidgetTranslations &rWidgetTranslations = aWidgetFind->second;
3135 WidgetTranslations::const_iterator aPropertyFind = rWidgetTranslations.find(rProperty);
3136 if (aPropertyFind != rWidgetTranslations.end())
3137 return aPropertyFind->second;
3139 return OString();
3142 void VclBuilder::collectProperty(xmlreader::XmlReader &reader, const OString &rID, stringmap &rMap)
3144 xmlreader::Span name;
3145 int nsId;
3147 OString sProperty;
3148 OString sValue;
3150 bool bTranslated = false;
3152 while (reader.nextAttribute(&nsId, &name))
3154 if (name.equals("name"))
3156 name = reader.getAttributeValue(false);
3157 sProperty = OString(name.begin, name.length);
3159 else if (name.equals("translatable") && reader.getAttributeValue(false).equals("yes"))
3161 sValue = getTranslation(rID, sProperty);
3162 bTranslated = !sValue.isEmpty();
3167 reader.nextItem(xmlreader::XmlReader::Text::Raw, &name, &nsId);
3168 if (!bTranslated)
3169 sValue = OString(name.begin, name.length);
3171 if (!sProperty.isEmpty())
3173 sProperty = sProperty.replace('_', '-');
3174 if (m_pStringReplace)
3176 OUString sTmp = (*m_pStringReplace)(OStringToOUString(sValue, RTL_TEXTENCODING_UTF8));
3177 rMap[sProperty] = OUStringToOString(sTmp, RTL_TEXTENCODING_UTF8);
3179 else
3181 rMap[sProperty] = sValue;
3186 void VclBuilder::handleActionWidget(xmlreader::XmlReader &reader)
3188 xmlreader::Span name;
3189 int nsId;
3191 OString sResponse;
3193 while (reader.nextAttribute(&nsId, &name))
3195 if (name.equals("response"))
3197 name = reader.getAttributeValue(false);
3198 sResponse = OString(name.begin, name.length);
3202 reader.nextItem(xmlreader::XmlReader::Text::Raw, &name, &nsId);
3203 OString sID = OString(name.begin, name.length);
3204 sal_Int32 nDelim = sID.indexOf(':');
3205 if (nDelim != -1)
3206 sID = sID.copy(0, nDelim);
3207 set_response(sID, sResponse.toInt32());
3210 void VclBuilder::collectAccelerator(xmlreader::XmlReader &reader, stringmap &rMap)
3212 xmlreader::Span name;
3213 int nsId;
3215 OString sProperty;
3216 OString sValue;
3218 while (reader.nextAttribute(&nsId, &name))
3220 if (name.equals("key"))
3222 name = reader.getAttributeValue(false);
3223 sValue = OString(name.begin, name.length);
3225 else if (name.equals("signal"))
3227 name = reader.getAttributeValue(false);
3228 sProperty = OString(name.begin, name.length);
3233 if (!sProperty.isEmpty() && !sValue.isEmpty())
3235 rMap[sProperty] = sValue;
3239 vcl::Window *VclBuilder::get_widget_root()
3241 return m_aChildren.empty() ? nullptr : m_aChildren[0].m_pWindow.get();
3244 vcl::Window *VclBuilder::get_by_name(const OString& sID)
3246 for (std::vector<WinAndId>::iterator aI = m_aChildren.begin(),
3247 aEnd = m_aChildren.end(); aI != aEnd; ++aI)
3249 if (aI->m_sID.equals(sID))
3250 return aI->m_pWindow;
3253 return nullptr;
3256 PopupMenu *VclBuilder::get_menu(const OString& sID)
3258 for (std::vector<MenuAndId>::iterator aI = m_aMenus.begin(),
3259 aEnd = m_aMenus.end(); aI != aEnd; ++aI)
3261 if (aI->m_sID.equals(sID))
3262 return aI->m_pMenu;
3265 return nullptr;
3268 short VclBuilder::get_response(const vcl::Window *pWindow) const
3270 for (std::vector<WinAndId>::const_iterator aI = m_aChildren.begin(),
3271 aEnd = m_aChildren.end(); aI != aEnd; ++aI)
3273 if (aI->m_pWindow == pWindow)
3275 return aI->m_nResponseId;
3279 //how did we not find sID ?
3280 assert(false);
3281 return RET_CANCEL;
3284 void VclBuilder::set_response(const OString& sID, short nResponse)
3286 for (std::vector<WinAndId>::iterator aI = m_aChildren.begin(),
3287 aEnd = m_aChildren.end(); aI != aEnd; ++aI)
3289 if (aI->m_sID.equals(sID))
3291 aI->m_nResponseId = nResponse;
3292 return;
3296 //how did we not find sID ?
3297 assert(false);
3300 void VclBuilder::delete_by_name(const OString& sID)
3302 for (std::vector<WinAndId>::iterator aI = m_aChildren.begin(),
3303 aEnd = m_aChildren.end(); aI != aEnd; ++aI)
3305 if (aI->m_sID.equals(sID))
3307 aI->m_pWindow.disposeAndClear();
3308 m_aChildren.erase(aI);
3309 break;
3314 void VclBuilder::delete_by_window(vcl::Window *pWindow)
3316 drop_ownership(pWindow);
3317 pWindow->disposeOnce();
3320 void VclBuilder::drop_ownership(const vcl::Window *pWindow)
3322 for (std::vector<WinAndId>::iterator aI = m_aChildren.begin(),
3323 aEnd = m_aChildren.end(); aI != aEnd; ++aI)
3325 if (aI->m_pWindow == pWindow)
3327 m_aChildren.erase(aI);
3328 break;
3333 OString VclBuilder::get_by_window(const vcl::Window *pWindow) const
3335 for (std::vector<WinAndId>::const_iterator aI = m_aChildren.begin(),
3336 aEnd = m_aChildren.end(); aI != aEnd; ++aI)
3338 if (aI->m_pWindow == pWindow)
3339 return aI->m_sID;
3342 return OString();
3345 VclBuilder::PackingData VclBuilder::get_window_packing_data(const vcl::Window *pWindow) const
3347 //We've stored the return of new Control, some of these get
3348 //border windows placed around them which are what you get
3349 //from GetChild, so scoot up a level if necessary to get the
3350 //window whose position value we have
3351 const vcl::Window *pPropHolder = pWindow->mpWindowImpl->mpClientWindow ?
3352 pWindow->mpWindowImpl->mpClientWindow : pWindow;
3354 for (std::vector<WinAndId>::const_iterator aI = m_aChildren.begin(),
3355 aEnd = m_aChildren.end(); aI != aEnd; ++aI)
3357 if (aI->m_pWindow == pPropHolder)
3358 return aI->m_aPackingData;
3361 return PackingData();
3364 void VclBuilder::set_window_packing_position(const vcl::Window *pWindow, sal_Int32 nPosition)
3366 for (std::vector<WinAndId>::iterator aI = m_aChildren.begin(),
3367 aEnd = m_aChildren.end(); aI != aEnd; ++aI)
3369 if (aI->m_pWindow == pWindow)
3370 aI->m_aPackingData.m_nPosition = nPosition;
3374 const VclBuilder::ListStore *VclBuilder::get_model_by_name(const OString& sID) const
3376 std::map<OString, ListStore>::const_iterator aI = m_pParserState->m_aModels.find(sID);
3377 if (aI != m_pParserState->m_aModels.end())
3378 return &(aI->second);
3379 return nullptr;
3382 const VclBuilder::TextBuffer *VclBuilder::get_buffer_by_name(const OString& sID) const
3384 std::map<OString, TextBuffer>::const_iterator aI = m_pParserState->m_aTextBuffers.find(sID);
3385 if (aI != m_pParserState->m_aTextBuffers.end())
3386 return &(aI->second);
3387 return nullptr;
3390 const VclBuilder::Adjustment *VclBuilder::get_adjustment_by_name(const OString& sID) const
3392 std::map<OString, Adjustment>::const_iterator aI = m_pParserState->m_aAdjustments.find(sID);
3393 if (aI != m_pParserState->m_aAdjustments.end())
3394 return &(aI->second);
3395 return nullptr;
3398 void VclBuilder::mungeModel(ListBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId)
3400 for (std::vector<ListStore::row>::const_iterator aI = rStore.m_aEntries.begin(), aEnd = rStore.m_aEntries.end();
3401 aI != aEnd; ++aI)
3403 const ListStore::row &rRow = *aI;
3404 sal_uInt16 nEntry = rTarget.InsertEntry(OStringToOUString(rRow[0], RTL_TEXTENCODING_UTF8));
3405 if (rRow.size() > 1)
3407 sal_IntPtr nValue = rRow[1].toInt32();
3408 rTarget.SetEntryData(nEntry, reinterpret_cast<void*>(nValue));
3411 if (nActiveId < rStore.m_aEntries.size())
3412 rTarget.SelectEntryPos(nActiveId);
3415 void VclBuilder::mungeAdjustment(NumericFormatter &rTarget, const Adjustment &rAdjustment)
3417 int nMul = rtl_math_pow10Exp(1, rTarget.GetDecimalDigits());
3419 for (stringmap::const_iterator aI = rAdjustment.begin(), aEnd = rAdjustment.end(); aI != aEnd; ++aI)
3421 const OString &rKey = aI->first;
3422 const OString &rValue = aI->second;
3424 if (rKey == "upper")
3426 sal_Int64 nUpper = rValue.toDouble() * nMul;
3427 rTarget.SetMax(nUpper);
3428 rTarget.SetLast(nUpper);
3430 else if (rKey == "lower")
3432 sal_Int64 nLower = rValue.toDouble() * nMul;
3433 rTarget.SetMin(nLower);
3434 rTarget.SetFirst(nLower);
3436 else if (rKey == "value")
3438 sal_Int64 nValue = rValue.toDouble() * nMul;
3439 rTarget.SetValue(nValue);
3441 else if (rKey == "step-increment")
3443 sal_Int64 nSpinSize = rValue.toDouble() * nMul;
3444 rTarget.SetSpinSize(nSpinSize);
3446 else
3448 SAL_INFO("vcl.layout", "unhandled property :" << rKey.getStr());
3453 void VclBuilder::mungeAdjustment(TimeField &rTarget, const Adjustment &rAdjustment)
3455 for (stringmap::const_iterator aI = rAdjustment.begin(), aEnd = rAdjustment.end(); aI != aEnd; ++aI)
3457 const OString &rKey = aI->first;
3458 const OString &rValue = aI->second;
3460 if (rKey == "upper")
3462 tools::Time aUpper(rValue.toInt32());
3463 rTarget.SetMax(aUpper);
3464 rTarget.SetLast(aUpper);
3466 else if (rKey == "lower")
3468 tools::Time aLower(rValue.toInt32());
3469 rTarget.SetMin(aLower);
3470 rTarget.SetFirst(aLower);
3472 else if (rKey == "value")
3474 tools::Time aValue(rValue.toInt32());
3475 rTarget.SetTime(aValue);
3477 else
3479 SAL_INFO("vcl.layout", "unhandled property :" << rKey.getStr());
3484 void VclBuilder::mungeAdjustment(DateField &rTarget, const Adjustment &rAdjustment)
3486 for (stringmap::const_iterator aI = rAdjustment.begin(), aEnd = rAdjustment.end(); aI != aEnd; ++aI)
3488 const OString &rKey = aI->first;
3489 const OString &rValue = aI->second;
3491 if (rKey == "upper")
3493 Date aUpper(rValue.toInt32());
3494 rTarget.SetMax(aUpper);
3495 rTarget.SetLast(aUpper);
3497 else if (rKey == "lower")
3499 Date aLower(rValue.toInt32());
3500 rTarget.SetMin(aLower);
3501 rTarget.SetFirst(aLower);
3503 else if (rKey == "value")
3505 Date aValue(rValue.toInt32());
3506 rTarget.SetDate(aValue);
3508 else
3510 SAL_INFO("vcl.layout", "unhandled property :" << rKey.getStr());
3515 void VclBuilder::mungeAdjustment(ScrollBar &rTarget, const Adjustment &rAdjustment)
3517 for (stringmap::const_iterator aI = rAdjustment.begin(), aEnd = rAdjustment.end(); aI != aEnd; ++aI)
3519 const OString &rKey = aI->first;
3520 const OString &rValue = aI->second;
3522 if (rKey == "upper")
3523 rTarget.SetRangeMax(rValue.toInt32());
3524 else if (rKey == "lower")
3525 rTarget.SetRangeMin(rValue.toInt32());
3526 else if (rKey == "value")
3527 rTarget.SetThumbPos(rValue.toInt32());
3528 else if (rKey == "step-increment")
3529 rTarget.SetLineSize(rValue.toInt32());
3530 else if (rKey == "page-increment")
3531 rTarget.SetPageSize(rValue.toInt32());
3532 else
3534 SAL_INFO("vcl.layout", "unhandled property :" << rKey.getStr());
3539 void VclBuilder::mungeAdjustment(Slider& rTarget, const Adjustment& rAdjustment)
3541 for (stringmap::const_iterator aI = rAdjustment.begin(), aEnd = rAdjustment.end(); aI != aEnd; ++aI)
3543 const OString &rKey = aI->first;
3544 const OString &rValue = aI->second;
3546 if (rKey == "upper")
3547 rTarget.SetRangeMax(rValue.toInt32());
3548 else if (rKey == "lower")
3549 rTarget.SetRangeMin(rValue.toInt32());
3550 else if (rKey == "value")
3551 rTarget.SetThumbPos(rValue.toInt32());
3552 else if (rKey == "step-increment")
3553 rTarget.SetLineSize(rValue.toInt32());
3554 else if (rKey == "page-increment")
3555 rTarget.SetPageSize(rValue.toInt32());
3556 else
3558 SAL_INFO("vcl.layout", "unhandled property :" << rKey.getStr());
3563 void VclBuilder::mungeTextBuffer(VclMultiLineEdit &rTarget, const TextBuffer &rTextBuffer)
3565 for (stringmap::const_iterator aI = rTextBuffer.begin(), aEnd = rTextBuffer.end(); aI != aEnd; ++aI)
3567 const OString &rKey = aI->first;
3568 const OString &rValue = aI->second;
3570 if (rKey == "text")
3571 rTarget.SetText(OStringToOUString(rValue, RTL_TEXTENCODING_UTF8));
3572 else
3574 SAL_INFO("vcl.layout", "unhandled property :" << rKey.getStr());
3579 VclBuilder::ParserState::ParserState()
3580 : m_nLastToolbarId(0)
3583 VclBuilder::MenuAndId::MenuAndId(const OString &rId, PopupMenu *pMenu)
3584 : m_sID(rId)
3585 , m_pMenu(pMenu)
3588 VclBuilder::MenuAndId::~MenuAndId() {}
3590 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */