Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include <osl/module.hxx>
11 : #include <sal/log.hxx>
12 : #include <unotools/configmgr.hxx>
13 : #include <vcl/builder.hxx>
14 : #include <vcl/button.hxx>
15 : #include <vcl/dialog.hxx>
16 : #include <vcl/edit.hxx>
17 : #include <vcl/field.hxx>
18 : #include <vcl/fixed.hxx>
19 : #include <vcl/fixedhyper.hxx>
20 : #include <vcl/layout.hxx>
21 : #include <vcl/lstbox.hxx>
22 : #include <vcl/menubtn.hxx>
23 : #include <vcl/mnemonic.hxx>
24 : #include <vcl/prgsbar.hxx>
25 : #include <vcl/scrbar.hxx>
26 : #include <vcl/svapp.hxx>
27 : #include <vcl/tabctrl.hxx>
28 : #include <vcl/tabpage.hxx>
29 : #include <vcl/vclmedit.hxx>
30 : #include <svdata.hxx>
31 : #include <svids.hrc>
32 : #include <window.h>
33 :
34 : #ifdef DISABLE_DYNLOADING
35 : #include <dlfcn.h> // For RTLD_DEFAULT
36 : #endif
37 :
38 : namespace
39 : {
40 0 : sal_uInt16 mapStockToImageResource(OString sType)
41 : {
42 0 : sal_uInt16 nRet = 0;
43 0 : if (sType == "gtk-index")
44 0 : nRet = SV_RESID_BITMAP_INDEX;
45 0 : else if (sType == "gtk-refresh")
46 0 : nRet = SV_RESID_BITMAP_REFRESH;
47 0 : return nRet;
48 : }
49 :
50 0 : SymbolType mapStockToSymbol(OString sType)
51 : {
52 0 : SymbolType eRet = SYMBOL_NOSYMBOL;
53 0 : if (sType == "gtk-media-next")
54 0 : eRet = SYMBOL_NEXT;
55 0 : else if (sType == "gtk-media-previous")
56 0 : eRet = SYMBOL_PREV;
57 0 : else if (sType == "gtk-goto-first")
58 0 : eRet = SYMBOL_FIRST;
59 0 : else if (sType == "gtk-goto-last")
60 0 : eRet = SYMBOL_LAST;
61 0 : else if (sType == "gtk-go-back")
62 0 : eRet = SYMBOL_ARROW_LEFT;
63 0 : else if (sType == "gtk-go-forward")
64 0 : eRet = SYMBOL_ARROW_RIGHT;
65 0 : else if (sType == "gtk-go-up")
66 0 : eRet = SYMBOL_ARROW_UP;
67 0 : else if (sType == "gtk-go-down")
68 0 : eRet = SYMBOL_ARROW_DOWN;
69 0 : else if (sType == "gtk-missing-image")
70 0 : eRet = SYMBOL_IMAGE;
71 0 : else if (sType == "gtk-help")
72 0 : eRet = SYMBOL_HELP;
73 0 : else if (sType == "gtk-close")
74 0 : eRet = SYMBOL_CLOSE;
75 0 : else if (mapStockToImageResource(sType))
76 0 : eRet = SYMBOL_IMAGE;
77 0 : return eRet;
78 : }
79 : }
80 :
81 0 : void VclBuilder::loadTranslations(const com::sun::star::lang::Locale &rLocale, const OUString& rUri)
82 : {
83 0 : for (int i = rLocale.Country.isEmpty() ? 1 : 0; i < 2; ++i)
84 : {
85 0 : OUStringBuffer aTransBuf;
86 0 : sal_Int32 nLastSlash = rUri.lastIndexOf('/');
87 0 : if (nLastSlash != -1)
88 0 : aTransBuf.append(rUri.copy(0, nLastSlash));
89 : else
90 : {
91 0 : aTransBuf.append('.');
92 0 : nLastSlash = 0;
93 : }
94 0 : aTransBuf.append("/res/").append(rLocale.Language);
95 0 : switch (i)
96 : {
97 : case 0:
98 0 : aTransBuf.append('-').append(rLocale.Country);
99 0 : break;
100 : default:
101 0 : break;
102 : }
103 0 : sal_Int32 nEndName = rUri.lastIndexOf('.');
104 0 : if (nEndName == -1)
105 0 : nEndName = rUri.getLength();
106 0 : aTransBuf.append(rUri.copy(nLastSlash, nEndName-nLastSlash));
107 :
108 0 : OUString sTransUri = aTransBuf.makeStringAndClear();
109 : try
110 : {
111 0 : xmlreader::XmlReader reader(sTransUri);
112 0 : handleTranslations(reader);
113 : }
114 0 : catch (const ::com::sun::star::uno::Exception &)
115 : {
116 : }
117 0 : }
118 0 : }
119 :
120 : #if defined SAL_LOG_WARN
121 : namespace
122 : {
123 : bool isButtonType(WindowType nType)
124 : {
125 : return nType == WINDOW_PUSHBUTTON ||
126 : nType == WINDOW_OKBUTTON ||
127 : nType == WINDOW_CANCELBUTTON ||
128 : nType == WINDOW_HELPBUTTON ||
129 : nType == WINDOW_IMAGEBUTTON ||
130 : nType == WINDOW_MENUBUTTON ||
131 : nType == WINDOW_MOREBUTTON ||
132 : nType == WINDOW_SPINBUTTON;
133 : }
134 : }
135 : #endif
136 :
137 0 : VclBuilder::VclBuilder(Window *pParent, OUString sUIDir, OUString sUIFile, OString sID)
138 : : m_sID(sID)
139 : , m_sHelpRoot(OUStringToOString(sUIFile, RTL_TEXTENCODING_UTF8))
140 : , m_sProductName(OUStringToOString(utl::ConfigManager::getProductName(), RTL_TEXTENCODING_UTF8))
141 : , m_pParent(pParent)
142 : , m_bToplevelParentFound(false)
143 0 : , m_pParserState(new ParserState)
144 : {
145 0 : m_bToplevelHasDeferredInit = (pParent && pParent->IsDialog()) ? ((Dialog*)pParent)->isDeferredInit() : false;
146 :
147 0 : sal_Int32 nIdx = m_sHelpRoot.lastIndexOf('.');
148 0 : if (nIdx != -1)
149 0 : m_sHelpRoot = m_sHelpRoot.copy(0, nIdx);
150 0 : m_sHelpRoot = m_sHelpRoot + OString('/');
151 :
152 0 : OUString sUri = sUIDir + sUIFile;
153 :
154 0 : com::sun::star::lang::Locale aLocale = Application::GetSettings().GetUILanguageTag().getLocale();
155 0 : bool bEN_US = aLocale.Language == "en" && aLocale.Country == "US" && aLocale.Variant.isEmpty();
156 0 : if (!bEN_US)
157 0 : loadTranslations(aLocale, sUri);
158 :
159 0 : xmlreader::XmlReader reader(sUri);
160 :
161 0 : handleChild(pParent, reader);
162 :
163 : //Set radiobutton groups when everything has been imported
164 0 : for (std::vector<RadioButtonGroupMap>::iterator aI = m_pParserState->m_aGroupMaps.begin(),
165 0 : aEnd = m_pParserState->m_aGroupMaps.end(); aI != aEnd; ++aI)
166 : {
167 0 : RadioButton *pOne = get<RadioButton>(aI->m_sID);
168 0 : RadioButton *pOther = get<RadioButton>(aI->m_sValue);
169 : SAL_WARN_IF(!pOne || !pOther, "vcl", "missing member of radiobutton group");
170 0 : if (pOne && pOther)
171 0 : pOne->group(*pOther);
172 : }
173 :
174 : //Set ComboBox models when everything has been imported
175 0 : for (std::vector<ComboBoxModelMap>::iterator aI = m_pParserState->m_aModelMaps.begin(),
176 0 : aEnd = m_pParserState->m_aModelMaps.end(); aI != aEnd; ++aI)
177 : {
178 0 : ListBox *pTarget = get<ListBox>(aI->m_sID);
179 0 : const ListStore *pStore = get_model_by_name(aI->m_sValue);
180 : SAL_WARN_IF(!pTarget || !pStore, "vcl", "missing elements of combobox/liststore");
181 0 : if (pTarget && pStore)
182 0 : mungeModel(*pTarget, *pStore, aI->m_nActiveId);
183 : }
184 :
185 : //Set TextView buffers when everything has been imported
186 0 : for (std::vector<TextBufferMap>::iterator aI = m_pParserState->m_aTextBufferMaps.begin(),
187 0 : aEnd = m_pParserState->m_aTextBufferMaps.end(); aI != aEnd; ++aI)
188 : {
189 0 : VclMultiLineEdit *pTarget = get<VclMultiLineEdit>(aI->m_sID);
190 0 : const TextBuffer *pBuffer = get_buffer_by_name(aI->m_sValue);
191 : SAL_WARN_IF(!pTarget || !pBuffer, "vcl", "missing elements of textview/textbuffer");
192 0 : if (pTarget && pBuffer)
193 0 : mungeTextBuffer(*pTarget, *pBuffer);
194 : }
195 :
196 : //Set SpinButton adjustments when everything has been imported
197 0 : for (std::vector<WidgetAdjustmentMap>::iterator aI = m_pParserState->m_aSpinAdjustmentMaps.begin(),
198 0 : aEnd = m_pParserState->m_aSpinAdjustmentMaps.end(); aI != aEnd; ++aI)
199 : {
200 0 : NumericFormatter *pTarget = dynamic_cast<NumericFormatter*>(get<Window>(aI->m_sID));
201 0 : const Adjustment *pAdjustment = get_adjustment_by_name(aI->m_sValue);
202 : SAL_WARN_IF(!pTarget || !pAdjustment, "vcl", "missing elements of spinbutton/adjustment");
203 0 : if (pTarget && pAdjustment)
204 0 : mungeSpinAdjustment(*pTarget, *pAdjustment);
205 : }
206 :
207 : //Set ScrollBar adjustments when everything has been imported
208 0 : for (std::vector<WidgetAdjustmentMap>::iterator aI = m_pParserState->m_aScrollAdjustmentMaps.begin(),
209 0 : aEnd = m_pParserState->m_aScrollAdjustmentMaps.end(); aI != aEnd; ++aI)
210 : {
211 0 : ScrollBar *pTarget = get<ScrollBar>(aI->m_sID);
212 0 : const Adjustment *pAdjustment = get_adjustment_by_name(aI->m_sValue);
213 : SAL_WARN_IF(!pTarget || !pAdjustment, "vcl", "missing elements of scrollbar/adjustment");
214 0 : if (pTarget && pAdjustment)
215 0 : mungeScrollAdjustment(*pTarget, *pAdjustment);
216 : }
217 :
218 : //Set button images when everything has been imported
219 0 : std::set<OString> aImagesToBeRemoved;
220 0 : for (std::vector<ButtonImageWidgetMap>::iterator aI = m_pParserState->m_aButtonImageWidgetMaps.begin(),
221 0 : aEnd = m_pParserState->m_aButtonImageWidgetMaps.end(); aI != aEnd; ++aI)
222 : {
223 0 : PushButton *pTarget = get<PushButton>(aI->m_sID);
224 0 : FixedImage *pImage = get<FixedImage>(aI->m_sValue);
225 : SAL_WARN_IF(!pTarget || !pImage,
226 : "vcl", "missing elements of button/image/stock");
227 0 : if (!pTarget || !pImage)
228 0 : continue;
229 0 : aImagesToBeRemoved.insert(aI->m_sValue);
230 :
231 0 : VclBuilder::StockMap::iterator aFind = m_pParserState->m_aStockMap.find(aI->m_sValue);
232 0 : if (aFind == m_pParserState->m_aStockMap.end())
233 0 : pTarget->SetModeImage(pImage->GetImage());
234 : else
235 : {
236 0 : const stockinfo &rImageInfo = aFind->second;
237 0 : SymbolType eType = mapStockToSymbol(rImageInfo.m_sStock);
238 : SAL_WARN_IF(eType == SYMBOL_NOSYMBOL, "vcl", "missing stock image element for button");
239 0 : if (eType == SYMBOL_NOSYMBOL)
240 0 : continue;
241 0 : pTarget->SetSymbol(eType);
242 0 : if (eType == SYMBOL_IMAGE)
243 0 : pTarget->SetModeImage(Bitmap(VclResId(mapStockToImageResource(rImageInfo.m_sStock))));
244 0 : switch (rImageInfo.m_nSize)
245 : {
246 : case 1:
247 0 : pTarget->SetSmallSymbol();
248 0 : break;
249 : case 4:
250 0 : break;
251 : default:
252 : SAL_WARN("vcl.layout", "unsupported image size " << rImageInfo.m_nSize);
253 0 : break;
254 : }
255 : }
256 : }
257 :
258 : //There may be duplicate use of an Image, so we used a set to collect and
259 : //now we can remove them from the tree after their final munge
260 0 : for (std::set<OString>::iterator aI = aImagesToBeRemoved.begin(),
261 0 : aEnd = aImagesToBeRemoved.end(); aI != aEnd; ++aI)
262 : {
263 0 : delete_by_name(*aI);
264 : }
265 :
266 : //Set button menus when everything has been imported
267 0 : for (std::vector<ButtonMenuMap>::iterator aI = m_pParserState->m_aButtonMenuMaps.begin(),
268 0 : aEnd = m_pParserState->m_aButtonMenuMaps.end(); aI != aEnd; ++aI)
269 : {
270 0 : MenuButton *pTarget = get<MenuButton>(aI->m_sID);
271 0 : PopupMenu *pMenu = get_menu_by_name(aI->m_sValue);
272 : SAL_WARN_IF(!pTarget || !pMenu,
273 : "vcl", "missing elements of button/menu");
274 0 : if (!pTarget || !pMenu)
275 0 : continue;
276 0 : pTarget->SetPopupMenu(pMenu);
277 : }
278 :
279 : //Remove ScrollWindow parent widgets whose children in vcl implement scrolling
280 : //internally.
281 0 : for (std::map<Window*, Window*>::iterator aI = m_pParserState->m_aRedundantParentWidgets.begin(),
282 0 : aEnd = m_pParserState->m_aRedundantParentWidgets.end(); aI != aEnd; ++aI)
283 : {
284 0 : delete_by_window(aI->first);
285 : }
286 :
287 : //drop maps, etc. that we don't need again
288 0 : delete m_pParserState;
289 :
290 : SAL_WARN_IF(!m_sID.isEmpty() && (!m_bToplevelParentFound && !get_by_name(m_sID)), "vcl.layout",
291 : "Requested top level widget \"" << m_sID.getStr() <<
292 0 : "\" not found in " << sUIFile);
293 :
294 : #if defined SAL_LOG_WARN
295 : if (m_bToplevelParentFound && m_pParent->IsDialog())
296 : {
297 : int nButtons = 0;
298 : bool bHasDefButton = false;
299 : for (std::vector<WinAndId>::iterator aI = m_aChildren.begin(),
300 : aEnd = m_aChildren.end(); aI != aEnd; ++aI)
301 : {
302 : if (isButtonType(aI->m_pWindow->GetType()))
303 : {
304 : ++nButtons;
305 : if (aI->m_pWindow->GetStyle() & WB_DEFBUTTON)
306 : {
307 : bHasDefButton = true;
308 : break;
309 : }
310 : }
311 : }
312 : SAL_WARN_IF(nButtons && !bHasDefButton, "vcl.layout", "No default button defined");
313 : }
314 : #endif
315 0 : }
316 :
317 0 : VclBuilder::~VclBuilder()
318 : {
319 0 : for (std::vector<WinAndId>::reverse_iterator aI = m_aChildren.rbegin(),
320 0 : aEnd = m_aChildren.rend(); aI != aEnd; ++aI)
321 : {
322 0 : delete aI->m_pWindow;
323 : }
324 :
325 0 : for (std::vector<MenuAndId>::reverse_iterator aI = m_aMenus.rbegin(),
326 0 : aEnd = m_aMenus.rend(); aI != aEnd; ++aI)
327 : {
328 0 : delete aI->m_pMenu;
329 : }
330 0 : }
331 :
332 0 : void VclBuilder::handleTranslations(xmlreader::XmlReader &reader)
333 : {
334 0 : xmlreader::Span name;
335 : int nsId;
336 0 : OString sType;
337 :
338 0 : OString sID, sProperty;
339 :
340 0 : while(1)
341 : {
342 : xmlreader::XmlReader::Result res = reader.nextItem(
343 0 : xmlreader::XmlReader::TEXT_RAW, &name, &nsId);
344 :
345 0 : if (res == xmlreader::XmlReader::RESULT_BEGIN)
346 : {
347 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("e")))
348 : {
349 0 : while (reader.nextAttribute(&nsId, &name))
350 : {
351 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("g")))
352 : {
353 0 : name = reader.getAttributeValue(false);
354 0 : sID = OString(name.begin, name.length);
355 0 : sal_Int32 nDelim = sID.indexOf(':');
356 0 : if (nDelim != -1)
357 0 : sID = sID.copy(nDelim);
358 : }
359 0 : else if (name.equals(RTL_CONSTASCII_STRINGPARAM("i")))
360 : {
361 0 : name = reader.getAttributeValue(false);
362 0 : sProperty = OString(name.begin, name.length);
363 : }
364 : }
365 : }
366 : }
367 :
368 0 : if (res == xmlreader::XmlReader::RESULT_TEXT && !sID.isEmpty())
369 : {
370 0 : OString sTranslation(name.begin, name.length);
371 0 : m_pParserState->m_aTranslations[sID][sProperty] = sTranslation;
372 : }
373 :
374 0 : if (res == xmlreader::XmlReader::RESULT_END)
375 0 : sID = OString();
376 :
377 0 : if (res == xmlreader::XmlReader::RESULT_DONE)
378 0 : break;
379 0 : }
380 0 : }
381 :
382 : namespace
383 : {
384 0 : OString extractCustomProperty(VclBuilder::stringmap &rMap)
385 : {
386 0 : OString sCustomProperty;
387 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("customproperty"));
388 0 : if (aFind != rMap.end())
389 : {
390 0 : sCustomProperty = aFind->second;
391 0 : rMap.erase(aFind);
392 : }
393 0 : return sCustomProperty;
394 : }
395 :
396 0 : bool extractResizable(VclBuilder::stringmap &rMap)
397 : {
398 0 : bool bResizable = true;
399 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("resizable"));
400 0 : if (aFind != rMap.end())
401 : {
402 0 : bResizable = toBool(aFind->second);
403 0 : rMap.erase(aFind);
404 : }
405 0 : return bResizable;
406 : }
407 :
408 0 : bool extractEntry(VclBuilder::stringmap &rMap)
409 : {
410 0 : bool bHasEntry = false;
411 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("has-entry"));
412 0 : if (aFind != rMap.end())
413 : {
414 0 : bHasEntry = toBool(aFind->second);
415 0 : rMap.erase(aFind);
416 : }
417 0 : return bHasEntry;
418 : }
419 :
420 0 : bool extractOrientation(VclBuilder::stringmap &rMap)
421 : {
422 0 : bool bVertical = false;
423 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("orientation"));
424 0 : if (aFind != rMap.end())
425 : {
426 0 : bVertical = aFind->second.equalsIgnoreAsciiCase("vertical");
427 0 : rMap.erase(aFind);
428 : }
429 0 : return bVertical;
430 : }
431 :
432 0 : bool extractInconsistent(VclBuilder::stringmap &rMap)
433 : {
434 0 : bool bInconsistent = false;
435 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("inconsistent"));
436 0 : if (aFind != rMap.end())
437 : {
438 0 : bInconsistent = toBool(aFind->second);
439 0 : rMap.erase(aFind);
440 : }
441 0 : return bInconsistent;
442 : }
443 :
444 0 : OUString getStockText(const OString &rType)
445 : {
446 0 : if (rType == "gtk-ok")
447 0 : return (VclResId(SV_BUTTONTEXT_OK).toString());
448 0 : else if (rType == "gtk-cancel")
449 0 : return (VclResId(SV_BUTTONTEXT_CANCEL).toString());
450 0 : else if (rType == "gtk-help")
451 0 : return (VclResId(SV_BUTTONTEXT_HELP).toString());
452 0 : else if (rType == "gtk-close")
453 0 : return (VclResId(SV_BUTTONTEXT_CLOSE).toString());
454 0 : else if (rType == "gtk-revert-to-saved")
455 0 : return (VclResId(SV_BUTTONTEXT_RESET).toString());
456 0 : else if (rType == "gtk-add")
457 0 : return (VclResId(SV_BUTTONTEXT_ADD).toString());
458 0 : else if (rType == "gtk-delete")
459 0 : return (VclResId(SV_BUTTONTEXT_DELETE).toString());
460 0 : else if (rType == "gtk-remove")
461 0 : return (VclResId(SV_BUTTONTEXT_REMOVE).toString());
462 0 : else if (rType == "gtk-new")
463 0 : return (VclResId(SV_BUTTONTEXT_NEW).toString());
464 0 : else if (rType == "gtk-edit")
465 0 : return (VclResId(SV_BUTTONTEXT_EDIT).toString());
466 : SAL_WARN("vcl.layout", "unknown stock type: " << rType.getStr());
467 0 : return OUString();
468 : }
469 :
470 0 : bool extractStock(VclBuilder::stringmap &rMap)
471 : {
472 0 : bool bIsStock = false;
473 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("use-stock"));
474 0 : if (aFind != rMap.end())
475 : {
476 0 : bIsStock = toBool(aFind->second);
477 0 : rMap.erase(aFind);
478 : }
479 0 : return bIsStock;
480 : }
481 :
482 0 : OString extractLabel(VclBuilder::stringmap &rMap)
483 : {
484 0 : OString sType;
485 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("label"));
486 0 : if (aFind != rMap.end())
487 : {
488 0 : sType = aFind->second;
489 0 : rMap.erase(aFind);
490 : }
491 0 : return sType;
492 : }
493 :
494 0 : Window * extractStockAndBuildPushButton(Window *pParent, VclBuilder::stringmap &rMap)
495 : {
496 0 : WinBits nBits = WB_CENTER|WB_VCENTER|WB_3DLOOK;
497 :
498 0 : bool bIsStock = extractStock(rMap);
499 :
500 0 : Window *pWindow = NULL;
501 :
502 0 : if (bIsStock)
503 : {
504 0 : OString sType = extractLabel(rMap);
505 0 : if (sType == "gtk-ok")
506 0 : pWindow = new OKButton(pParent, nBits);
507 0 : else if (sType == "gtk-cancel")
508 0 : pWindow = new CancelButton(pParent, nBits);
509 0 : else if (sType == "gtk-help")
510 0 : pWindow = new HelpButton(pParent, nBits);
511 0 : else if (sType == "gtk-media-next")
512 : {
513 0 : PushButton *pBtn = new PushButton(pParent, nBits);
514 0 : pBtn->SetSymbol(SYMBOL_NEXT);
515 0 : pWindow = pBtn;
516 : }
517 0 : else if (sType == "gtk-media-previous")
518 : {
519 0 : PushButton *pBtn = new PushButton(pParent, nBits);
520 0 : pBtn->SetSymbol(SYMBOL_PREV);
521 0 : pWindow = pBtn;
522 : }
523 : else
524 : {
525 0 : pWindow = new PushButton(pParent, nBits);
526 0 : pWindow->SetText(getStockText(sType));
527 0 : }
528 : }
529 :
530 0 : if (!pWindow)
531 0 : pWindow = new PushButton(pParent, nBits);
532 0 : return pWindow;
533 : }
534 :
535 0 : Window * extractStockAndBuildMenuButton(Window *pParent, VclBuilder::stringmap &rMap)
536 : {
537 0 : WinBits nBits = WB_CENTER|WB_VCENTER|WB_3DLOOK;
538 :
539 0 : Window *pWindow = new MenuButton(pParent, nBits);
540 :
541 0 : if (extractStock(rMap))
542 : {
543 0 : pWindow->SetText(getStockText(extractLabel(rMap)));
544 : }
545 :
546 0 : return pWindow;
547 : }
548 :
549 0 : FieldUnit detectMetricUnit(OString sUnit)
550 : {
551 0 : FieldUnit eUnit = FUNIT_NONE;
552 :
553 0 : if (sUnit == "mm")
554 0 : eUnit = FUNIT_MM;
555 0 : else if (sUnit == "cm")
556 0 : eUnit = FUNIT_CM;
557 0 : else if (sUnit == "m")
558 0 : eUnit = FUNIT_M;
559 0 : else if (sUnit == "km")
560 0 : eUnit = FUNIT_KM;
561 0 : else if ((sUnit == "twips") || (sUnit == "twip"))
562 0 : eUnit = FUNIT_TWIP;
563 0 : else if (sUnit == "pt")
564 0 : eUnit = FUNIT_POINT;
565 0 : else if (sUnit == "pc")
566 0 : eUnit = FUNIT_PICA;
567 0 : else if (sUnit == "\"" || (sUnit == "in") || (sUnit == "inch"))
568 0 : eUnit = FUNIT_INCH;
569 0 : else if ((sUnit == "'") || (sUnit == "ft") || (sUnit == "foot") || (sUnit == "feet"))
570 0 : eUnit = FUNIT_FOOT;
571 0 : else if (sUnit == "mile" || (sUnit == "miles"))
572 0 : eUnit = FUNIT_MILE;
573 0 : else if (sUnit == "ch")
574 0 : eUnit = FUNIT_CHAR;
575 0 : else if (sUnit == "line")
576 0 : eUnit = FUNIT_LINE;
577 0 : else if (sUnit == "%")
578 0 : eUnit = FUNIT_PERCENT;
579 :
580 0 : return eUnit;
581 : }
582 :
583 0 : void ensureDefaultWidthChars(VclBuilder::stringmap &rMap)
584 : {
585 0 : OString sWidthChars("width-chars");
586 0 : VclBuilder::stringmap::iterator aFind = rMap.find(sWidthChars);
587 0 : if (aFind == rMap.end())
588 0 : rMap[sWidthChars] = "25";
589 0 : }
590 : }
591 :
592 0 : bool VclBuilder::extractGroup(const OString &id, stringmap &rMap)
593 : {
594 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("group"));
595 0 : if (aFind != rMap.end())
596 : {
597 0 : m_pParserState->m_aGroupMaps.push_back(RadioButtonGroupMap(id, aFind->second));
598 0 : rMap.erase(aFind);
599 0 : return true;
600 : }
601 0 : return false;
602 : }
603 :
604 0 : bool VclBuilder::extractSpinAdjustment(const OString &id, stringmap &rMap)
605 : {
606 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("adjustment"));
607 0 : if (aFind != rMap.end())
608 : {
609 0 : m_pParserState->m_aSpinAdjustmentMaps.push_back(WidgetAdjustmentMap(id, aFind->second));
610 0 : rMap.erase(aFind);
611 0 : return true;
612 : }
613 0 : return false;
614 : }
615 :
616 0 : bool VclBuilder::extractScrollAdjustment(const OString &id, stringmap &rMap)
617 : {
618 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("adjustment"));
619 0 : if (aFind != rMap.end())
620 : {
621 0 : m_pParserState->m_aScrollAdjustmentMaps.push_back(WidgetAdjustmentMap(id, aFind->second));
622 0 : rMap.erase(aFind);
623 0 : return true;
624 : }
625 0 : return false;
626 : }
627 :
628 : namespace
629 : {
630 0 : sal_Int32 extractActive(VclBuilder::stringmap &rMap)
631 : {
632 0 : sal_Int32 nActiveId = 0;
633 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("active"));
634 0 : if (aFind != rMap.end())
635 : {
636 0 : nActiveId = aFind->second.toInt32();
637 0 : rMap.erase(aFind);
638 : }
639 0 : return nActiveId;
640 : }
641 :
642 0 : bool extractSelectable(VclBuilder::stringmap &rMap)
643 : {
644 0 : bool bSelectable = false;
645 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("selectable"));
646 0 : if (aFind != rMap.end())
647 : {
648 0 : bSelectable = toBool(aFind->second);
649 0 : rMap.erase(aFind);
650 : }
651 0 : return bSelectable;
652 : }
653 :
654 : }
655 :
656 0 : bool VclBuilder::extractModel(const OString &id, stringmap &rMap)
657 : {
658 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("model"));
659 0 : if (aFind != rMap.end())
660 : {
661 0 : m_pParserState->m_aModelMaps.push_back(ComboBoxModelMap(id, aFind->second,
662 0 : extractActive(rMap)));
663 0 : rMap.erase(aFind);
664 0 : return true;
665 : }
666 0 : return false;
667 : }
668 :
669 0 : bool VclBuilder::extractBuffer(const OString &id, stringmap &rMap)
670 : {
671 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("buffer"));
672 0 : if (aFind != rMap.end())
673 : {
674 0 : m_pParserState->m_aTextBufferMaps.push_back(TextBufferMap(id, aFind->second));
675 0 : rMap.erase(aFind);
676 0 : return true;
677 : }
678 0 : return false;
679 : }
680 :
681 0 : bool VclBuilder::extractStock(const OString &id, stringmap &rMap)
682 : {
683 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("stock"));
684 0 : if (aFind != rMap.end())
685 : {
686 0 : stockinfo aInfo;
687 0 : aInfo.m_sStock = aFind->second;
688 0 : rMap.erase(aFind);
689 0 : aFind = rMap.find(OString("icon-size"));
690 0 : if (aFind != rMap.end())
691 : {
692 0 : aInfo.m_nSize = aFind->second.toInt32();
693 0 : rMap.erase(aFind);
694 : }
695 0 : m_pParserState->m_aStockMap[id] = aInfo;
696 0 : return true;
697 : }
698 0 : return false;
699 : }
700 :
701 0 : bool VclBuilder::extractImage(const OString &id, stringmap &rMap)
702 : {
703 0 : VclBuilder::stringmap::iterator aFind = rMap.find(OString("image"));
704 0 : if (aFind != rMap.end())
705 : {
706 0 : m_pParserState->m_aButtonImageWidgetMaps.push_back(ButtonImageWidgetMap(id, aFind->second));
707 0 : rMap.erase(aFind);
708 0 : return true;
709 : }
710 0 : return false;
711 : }
712 :
713 : #ifndef DISABLE_DYNLOADING
714 0 : extern "C" { static void SAL_CALL thisModule() {} }
715 : #endif
716 :
717 0 : Window *VclBuilder::makeObject(Window *pParent, const OString &name, const OString &id,
718 : stringmap &rMap, const std::vector<OString> &rItems)
719 : {
720 0 : bool bIsPlaceHolder = name.isEmpty();
721 0 : bool bVertical = false;
722 :
723 0 : if (pParent && pParent->GetType() == WINDOW_TABCONTROL)
724 : {
725 : //We have to add a page
726 :
727 : //make default pageid == position
728 0 : TabControl *pTabControl = static_cast<TabControl*>(pParent);
729 0 : sal_uInt16 nNewPageCount = pTabControl->GetPageCount()+1;
730 0 : sal_uInt16 nNewPageId = nNewPageCount;
731 0 : pTabControl->InsertPage(nNewPageId, OUString());
732 0 : pTabControl->SetCurPageId(nNewPageId);
733 :
734 0 : if (!bIsPlaceHolder)
735 : {
736 0 : TabPage* pPage = new TabPage(pTabControl);
737 0 : pPage->Show();
738 :
739 : //Make up a name for it
740 : OString sTabPageId = get_by_window(pParent) +
741 0 : OString("-page") +
742 0 : OString::valueOf(static_cast<sal_Int32>(nNewPageCount));
743 0 : m_aChildren.push_back(WinAndId(sTabPageId, pPage, false));
744 0 : pPage->SetHelpId(m_sHelpRoot + sTabPageId);
745 :
746 : //And give the page one container as a child to make it a layout enabled
747 : //tab page
748 0 : VclBin* pContainer = new VclBin(pPage);
749 0 : pContainer->Show();
750 0 : m_aChildren.push_back(WinAndId(OString(), pContainer, false));
751 0 : pContainer->SetHelpId(m_sHelpRoot + sTabPageId + OString("-bin"));
752 0 : pParent = pContainer;
753 :
754 0 : pTabControl->SetTabPage(nNewPageId, pPage);
755 : }
756 : }
757 :
758 0 : if (bIsPlaceHolder || name == "GtkTreeSelection")
759 0 : return NULL;
760 :
761 0 : Window *pWindow = NULL;
762 0 : if (name == "GtkDialog")
763 : {
764 0 : WinBits nBits = WB_MOVEABLE|WB_3DLOOK|WB_CLOSEABLE;
765 0 : if (extractResizable(rMap))
766 0 : nBits |= WB_SIZEABLE;
767 0 : pWindow = new Dialog(pParent, nBits);
768 : }
769 0 : else if (name == "GtkBox")
770 : {
771 0 : bVertical = extractOrientation(rMap);
772 0 : if (bVertical)
773 0 : pWindow = new VclVBox(pParent);
774 : else
775 0 : pWindow = new VclHBox(pParent);
776 : }
777 0 : else if (name == "GtkHBox")
778 0 : pWindow = new VclHBox(pParent);
779 0 : else if (name == "GtkVBox")
780 0 : pWindow = new VclVBox(pParent);
781 0 : else if (name == "GtkButtonBox")
782 : {
783 0 : bVertical = extractOrientation(rMap);
784 0 : if (bVertical)
785 0 : pWindow = new VclVButtonBox(pParent);
786 : else
787 0 : pWindow = new VclHButtonBox(pParent);
788 : }
789 0 : else if (name == "GtkHButtonBox")
790 0 : pWindow = new VclHButtonBox(pParent);
791 0 : else if (name == "GtkVButtonBox")
792 0 : pWindow = new VclVButtonBox(pParent);
793 0 : else if (name == "GtkGrid")
794 0 : pWindow = new VclGrid(pParent);
795 0 : else if (name == "GtkFrame")
796 0 : pWindow = new VclFrame(pParent);
797 0 : else if (name == "GtkExpander")
798 0 : pWindow = new VclExpander(pParent);
799 0 : else if (name == "GtkAlignment")
800 0 : pWindow = new VclAlignment(pParent);
801 0 : else if (name == "GtkButton")
802 : {
803 0 : extractImage(id, rMap);
804 0 : OString sMenu = extractCustomProperty(rMap);
805 0 : if (sMenu.isEmpty())
806 0 : pWindow = extractStockAndBuildPushButton(pParent, rMap);
807 : else
808 : {
809 0 : pWindow = extractStockAndBuildMenuButton(pParent, rMap);
810 0 : m_pParserState->m_aButtonMenuMaps.push_back(ButtonMenuMap(id, sMenu));
811 0 : }
812 : }
813 0 : else if (name == "GtkRadioButton")
814 : {
815 0 : extractGroup(id, rMap);
816 0 : pWindow = new RadioButton(pParent, WB_CENTER|WB_VCENTER|WB_3DLOOK);
817 : }
818 0 : else if (name == "GtkCheckButton")
819 : {
820 : //maybe always import as TriStateBox and enable/disable tristate
821 0 : bool bIsTriState = extractInconsistent(rMap);
822 : CheckBox *pCheckBox = bIsTriState ?
823 0 : new TriStateBox(pParent, WB_CENTER|WB_VCENTER|WB_3DLOOK) :
824 0 : new CheckBox(pParent, WB_CENTER|WB_VCENTER|WB_3DLOOK);
825 0 : if (bIsTriState)
826 0 : pCheckBox->SetState(STATE_DONTKNOW);
827 0 : pWindow = pCheckBox;
828 : }
829 0 : else if (name == "GtkSpinButton")
830 : {
831 0 : extractSpinAdjustment(id, rMap);
832 0 : OString sPattern = extractCustomProperty(rMap);
833 0 : OString sUnit = sPattern;
834 :
835 0 : for (sal_Int32 i = 0; i < sPattern.getLength(); ++i)
836 : {
837 0 : if (sPattern[i] != '.' && sPattern[i] != ',' && sPattern[i] != '0')
838 : {
839 0 : sUnit = sPattern.copy(i);
840 0 : break;
841 : }
842 : }
843 :
844 0 : FieldUnit eUnit = detectMetricUnit(sUnit);
845 :
846 0 : WinBits nBits = WB_RIGHT|WB_BORDER|WB_3DLOOK;
847 0 : if (!id.endsWith("-nospin"))
848 0 : nBits |= WB_SPIN;
849 :
850 0 : if (sPattern.isEmpty())
851 : {
852 : SAL_INFO("vcl.layout", "making numeric field for " << name.getStr() << " " << sUnit.getStr());
853 0 : pWindow = new NumericField(pParent, nBits);
854 : }
855 : else
856 : {
857 : SAL_INFO("vcl.layout", "making metric field for " << name.getStr() << " " << sUnit.getStr());
858 0 : MetricField *pField = new MetricField(pParent, nBits);
859 0 : pField->SetUnit(eUnit);
860 0 : pWindow = pField;
861 0 : }
862 : }
863 0 : else if (name == "GtkLinkButton")
864 0 : pWindow = new FixedHyperlink(pParent, WB_CENTER|WB_VCENTER|WB_3DLOOK|WB_NOLABEL);
865 0 : else if ((name == "GtkComboBox") || (name == "GtkComboBoxText"))
866 : {
867 0 : extractModel(id, rMap);
868 0 : if (extractEntry(rMap))
869 : {
870 0 : ComboBox* pComboBox = new ComboBox(pParent, WB_LEFT|WB_DROPDOWN|WB_VCENTER|WB_3DLOOK);
871 0 : pComboBox->EnableAutoSize(true);
872 0 : if (!rItems.empty())
873 : {
874 0 : sal_uInt16 nActiveId = extractActive(rMap);
875 0 : for (std::vector<OString>::const_iterator aI = rItems.begin(), aEnd = rItems.end(); aI != aEnd; ++aI)
876 0 : pComboBox->InsertEntry(OStringToOUString(*aI, RTL_TEXTENCODING_UTF8));
877 0 : if (nActiveId < rItems.size())
878 0 : pComboBox->SelectEntryPos(nActiveId);
879 : }
880 0 : pWindow = pComboBox;
881 : }
882 : else
883 : {
884 0 : ListBox *pListBox = new ListBox(pParent, WB_LEFT|WB_DROPDOWN|WB_VCENTER|WB_3DLOOK);
885 0 : pListBox->EnableAutoSize(true);
886 0 : if (!rItems.empty())
887 : {
888 0 : sal_uInt16 nActiveId = extractActive(rMap);
889 0 : for (std::vector<OString>::const_iterator aI = rItems.begin(), aEnd = rItems.end(); aI != aEnd; ++aI)
890 0 : pListBox->InsertEntry(OStringToOUString(*aI, RTL_TEXTENCODING_UTF8));
891 0 : if (nActiveId < rItems.size())
892 0 : pListBox->SelectEntryPos(nActiveId);
893 : }
894 0 : pWindow = pListBox;
895 : }
896 : }
897 0 : else if (name == "GtkTreeView")
898 : {
899 : //To-Do
900 : //a) move svtools SvTreeViewBox into vcl
901 : //b) make that the default target for GtkTreeView
902 : //c) remove the non-drop down mode of ListBox and convert
903 : // everything over to SvTreeViewBox
904 : //d) remove the users of makeSvTreeViewBox
905 0 : extractModel(id, rMap);
906 0 : pWindow = new ListBox(pParent, WB_LEFT|WB_VCENTER|WB_3DLOOK);
907 : }
908 0 : else if (name == "GtkLabel")
909 : {
910 0 : if (extractSelectable(rMap))
911 0 : pWindow = new SelectableFixedText(pParent, WB_CENTER|WB_VCENTER|WB_3DLOOK);
912 : else
913 0 : pWindow = new FixedText(pParent, WB_CENTER|WB_VCENTER|WB_3DLOOK);
914 : }
915 0 : else if (name == "GtkImage")
916 : {
917 0 : extractStock(id, rMap);
918 0 : pWindow = new FixedImage(pParent, WB_CENTER|WB_VCENTER|WB_3DLOOK);
919 : }
920 0 : else if (name == "GtkSeparator")
921 : {
922 0 : bVertical = extractOrientation(rMap);
923 0 : if (bVertical)
924 0 : pWindow = new FixedLine(pParent, WB_VERT);
925 : else
926 0 : pWindow = new FixedLine(pParent, WB_HORZ);
927 : }
928 0 : else if (name == "GtkScrollbar")
929 : {
930 0 : extractScrollAdjustment(id, rMap);
931 0 : bVertical = extractOrientation(rMap);
932 0 : if (bVertical)
933 0 : pWindow = new ScrollBar(pParent, WB_VERT);
934 : else
935 0 : pWindow = new ScrollBar(pParent, WB_HORZ);
936 : }
937 0 : else if (name == "GtkProgressBar")
938 : {
939 0 : extractScrollAdjustment(id, rMap);
940 0 : bVertical = extractOrientation(rMap);
941 0 : if (bVertical)
942 0 : pWindow = new ProgressBar(pParent, WB_VERT);
943 : else
944 0 : pWindow = new ProgressBar(pParent, WB_HORZ);
945 : }
946 0 : else if (name == "GtkScrolledWindow")
947 : {
948 0 : pWindow = new VclScrolledWindow(pParent);
949 : }
950 0 : else if (name == "GtkEntry")
951 : {
952 0 : pWindow = new Edit(pParent, WB_LEFT|WB_VCENTER|WB_BORDER|WB_3DLOOK);
953 0 : ensureDefaultWidthChars(rMap);
954 : }
955 0 : else if (name == "GtkNotebook")
956 0 : pWindow = new TabControl(pParent, WB_STDTABCONTROL|WB_3DLOOK);
957 0 : else if (name == "GtkDrawingArea")
958 0 : pWindow = new Window(pParent);
959 0 : else if (name == "GtkTextView")
960 : {
961 0 : extractBuffer(id, rMap);
962 :
963 0 : WinBits nWinStyle = WB_LEFT | WB_BORDER;
964 : //VclMultiLineEdit manage their own scrolling,
965 : //so if it appears as a child of a scrolling window
966 : //shoehorn that scrolling settings to this
967 : //widget and remove the parent
968 0 : Window *pScrollParent = NULL;
969 0 : if (pParent && pParent->GetType() == WINDOW_SCROLLWINDOW)
970 : {
971 0 : WinBits nScrollBits = pParent->GetStyle();
972 0 : nScrollBits &= (WB_AUTOHSCROLL|WB_HSCROLL|WB_AUTOVSCROLL|WB_VSCROLL);
973 0 : nWinStyle |= nScrollBits;
974 :
975 0 : pScrollParent = pParent;
976 0 : pParent = pParent->GetParent();
977 : }
978 :
979 0 : pWindow = new VclMultiLineEdit(pParent, nWinStyle);
980 :
981 0 : if (pScrollParent)
982 : {
983 0 : sal_Int32 nWidthReq = pScrollParent->get_width_request();
984 0 : rMap[OString("width-request")] = OString::valueOf(nWidthReq);
985 0 : sal_Int32 nHeightReq = pScrollParent->get_height_request();
986 0 : rMap[OString("height-request")] = OString::valueOf(nHeightReq);
987 :
988 0 : m_pParserState->m_aRedundantParentWidgets[pScrollParent] = pWindow;
989 : }
990 : }
991 : else
992 : {
993 0 : sal_Int32 nDelim = name.indexOf(':');
994 0 : if (nDelim != -1)
995 : {
996 : #ifndef DISABLE_DYNLOADING
997 0 : OUStringBuffer sModule;
998 : #ifdef SAL_DLLPREFIX
999 0 : sModule.append(SAL_DLLPREFIX);
1000 : #endif
1001 0 : sModule.append(OStringToOUString(name.copy(0, nDelim), RTL_TEXTENCODING_UTF8));
1002 : #ifdef SAL_DLLEXTENSION
1003 0 : sModule.append(SAL_DLLEXTENSION);
1004 : #endif
1005 : #endif
1006 0 : OUString sFunction(OStringToOUString(OString("make") + name.copy(nDelim+1), RTL_TEXTENCODING_UTF8));
1007 : #ifndef DISABLE_DYNLOADING
1008 0 : osl::Module aModule;
1009 0 : aModule.loadRelative(&thisModule, sModule.makeStringAndClear());
1010 0 : customMakeWidget pFunction = (customMakeWidget)aModule.getFunctionSymbol(sFunction);
1011 : #else
1012 : customMakeWidget pFunction = (customMakeWidget)osl_getFunctionSymbol((oslModule) RTLD_DEFAULT, sFunction.pData);
1013 : #endif
1014 0 : if (pFunction)
1015 0 : pWindow = (*pFunction)(pParent, rMap);
1016 : }
1017 : }
1018 : SAL_WARN_IF(!pWindow, "vcl.layout", "probably need to implement " << name.getStr() << " or add a make" << name.getStr() << " function");
1019 0 : if (pWindow)
1020 : {
1021 0 : pWindow->SetHelpId(m_sHelpRoot + id);
1022 : SAL_INFO("vcl.layout", "for " << name.getStr() <<
1023 : ", created " << pWindow << " child of " <<
1024 : pParent << "(" << pWindow->mpWindowImpl->mpParent << "/" <<
1025 : pWindow->mpWindowImpl->mpRealParent << "/" <<
1026 : pWindow->mpWindowImpl->mpBorderWindow << ") with helpid " <<
1027 : pWindow->GetHelpId().getStr());
1028 0 : m_aChildren.push_back(WinAndId(id, pWindow, bVertical));
1029 : }
1030 0 : return pWindow;
1031 : }
1032 :
1033 : namespace
1034 : {
1035 : //return true for window types which exist in vcl but are not themselves
1036 : //represented in the .ui format, i.e. only their children exist.
1037 0 : bool isConsideredGtkPseudo(Window *pWindow)
1038 : {
1039 0 : return pWindow->GetType() == WINDOW_TABPAGE;
1040 : }
1041 : }
1042 :
1043 0 : Window *VclBuilder::insertObject(Window *pParent, const OString &rClass,
1044 : const OString &rID, stringmap &rProps, stringmap &rPango, std::vector<OString> &rItems)
1045 : {
1046 0 : Window *pCurrentChild = NULL;
1047 :
1048 0 : if (m_pParent && !isConsideredGtkPseudo(m_pParent) && !m_sID.isEmpty() && rID.equals(m_sID))
1049 : {
1050 0 : pCurrentChild = m_pParent;
1051 : //toplevels default to resizable
1052 0 : if (pCurrentChild->IsDialog())
1053 : {
1054 0 : Dialog *pDialog = (Dialog*)pCurrentChild;
1055 0 : pDialog->doDeferredInit(extractResizable(rProps));
1056 0 : m_bToplevelHasDeferredInit = false;
1057 : }
1058 0 : if (pCurrentChild->GetHelpId().isEmpty())
1059 : {
1060 0 : pCurrentChild->SetHelpId(m_sHelpRoot + m_sID);
1061 : SAL_INFO("vcl.layout", "for toplevel dialog " << this << " " <<
1062 : rID.getStr() << ", set helpid " <<
1063 : pCurrentChild->GetHelpId().getStr());
1064 : }
1065 0 : m_bToplevelParentFound = true;
1066 : }
1067 : else
1068 : {
1069 : //if we're being inserting under a toplevel dialog whose init is
1070 : //deferred due to waiting to encounter it in this .ui, and it hasn't
1071 : //been seen yet, then make unattached widgets parent-less toplevels
1072 0 : if (pParent == m_pParent && m_bToplevelHasDeferredInit)
1073 0 : pParent = NULL;
1074 0 : pCurrentChild = makeObject(pParent, rClass, rID, rProps, rItems);
1075 : }
1076 :
1077 0 : if (pCurrentChild)
1078 : {
1079 0 : for (stringmap::iterator aI = rProps.begin(), aEnd = rProps.end(); aI != aEnd; ++aI)
1080 : {
1081 0 : const OString &rKey = aI->first;
1082 0 : const OString &rValue = aI->second;
1083 0 : pCurrentChild->set_property(rKey, rValue);
1084 : }
1085 :
1086 0 : for (stringmap::iterator aI = rPango.begin(), aEnd = rPango.end(); aI != aEnd; ++aI)
1087 : {
1088 0 : const OString &rKey = aI->first;
1089 0 : const OString &rValue = aI->second;
1090 0 : pCurrentChild->set_font_attribute(rKey, rValue);
1091 : }
1092 : }
1093 :
1094 0 : rProps.clear();
1095 0 : rPango.clear();
1096 0 : rItems.clear();
1097 :
1098 0 : if (!pCurrentChild)
1099 0 : pCurrentChild = m_aChildren.empty() ? pParent : m_aChildren.back().m_pWindow;
1100 0 : return pCurrentChild;
1101 : }
1102 :
1103 0 : void VclBuilder::reorderWithinParent(Window &rWindow, sal_uInt16 nNewPosition)
1104 : {
1105 0 : if (rWindow.mpWindowImpl->mpParent != rWindow.mpWindowImpl->mpRealParent)
1106 : {
1107 : assert(rWindow.mpWindowImpl->mpBorderWindow ==
1108 : rWindow.mpWindowImpl->mpParent);
1109 : assert(rWindow.mpWindowImpl->mpBorderWindow->mpWindowImpl->mpParent ==
1110 : rWindow.mpWindowImpl->mpRealParent);
1111 0 : reorderWithinParent(*rWindow.mpWindowImpl->mpBorderWindow, nNewPosition);
1112 0 : return;
1113 : }
1114 0 : rWindow.reorderWithinParent(nNewPosition);
1115 : }
1116 :
1117 0 : void VclBuilder::handleTabChild(Window *pParent, xmlreader::XmlReader &reader)
1118 : {
1119 0 : OString sID;
1120 :
1121 0 : int nLevel = 1;
1122 0 : stringmap aProperties;
1123 0 : while(1)
1124 : {
1125 0 : xmlreader::Span name;
1126 : int nsId;
1127 :
1128 : xmlreader::XmlReader::Result res = reader.nextItem(
1129 0 : xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
1130 :
1131 0 : if (res == xmlreader::XmlReader::RESULT_BEGIN)
1132 : {
1133 0 : ++nLevel;
1134 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("object")))
1135 : {
1136 0 : while (reader.nextAttribute(&nsId, &name))
1137 : {
1138 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("id")))
1139 : {
1140 0 : name = reader.getAttributeValue(false);
1141 0 : sID = OString(name.begin, name.length);
1142 0 : sal_Int32 nDelim = sID.indexOf(':');
1143 0 : if (nDelim != -1)
1144 : {
1145 0 : OString sPattern = sID.copy(nDelim+1);
1146 0 : aProperties[OString("customproperty")] = sPattern;
1147 0 : sID = sID.copy(0, nDelim);
1148 : }
1149 : }
1150 : }
1151 : }
1152 0 : else if (name.equals(RTL_CONSTASCII_STRINGPARAM("property")))
1153 0 : collectProperty(reader, sID, aProperties);
1154 : }
1155 :
1156 0 : if (res == xmlreader::XmlReader::RESULT_END)
1157 0 : --nLevel;
1158 :
1159 0 : if (!nLevel)
1160 : break;
1161 :
1162 0 : if (res == xmlreader::XmlReader::RESULT_DONE)
1163 : break;
1164 : }
1165 :
1166 0 : TabControl *pTabControl = static_cast<TabControl*>(pParent);
1167 0 : VclBuilder::stringmap::iterator aFind = aProperties.find(OString("label"));
1168 0 : if (aFind != aProperties.end())
1169 : {
1170 0 : sal_uInt16 nPageId = pTabControl->GetCurPageId();
1171 : pTabControl->SetPageText(nPageId,
1172 0 : OStringToOUString(aFind->second, RTL_TEXTENCODING_UTF8));
1173 0 : pTabControl->SetPageName(nPageId, sID);
1174 : }
1175 : else
1176 0 : pTabControl->RemovePage(pTabControl->GetCurPageId());
1177 0 : }
1178 :
1179 : //so that tabbing between controls goes in a visually sensible sequence
1180 : //we sort these into a best-tab-order sequence
1181 0 : bool VclBuilder::sortIntoBestTabTraversalOrder::operator()(const Window *pA, const Window *pB) const
1182 : {
1183 : //sort child order within parent list by grid position
1184 0 : sal_Int32 nTopA = pA->get_grid_top_attach();
1185 0 : sal_Int32 nTopB = pB->get_grid_top_attach();
1186 0 : if (nTopA < nTopB)
1187 0 : return true;
1188 0 : if (nTopA > nTopB)
1189 0 : return false;
1190 0 : sal_Int32 nLeftA = pA->get_grid_left_attach();
1191 0 : sal_Int32 nLeftB = pB->get_grid_left_attach();
1192 0 : if (nLeftA < nLeftB)
1193 0 : return true;
1194 0 : if (nLeftA > nLeftB)
1195 0 : return false;
1196 : //sort into two groups of pack start and pack end
1197 0 : VclPackType ePackA = pA->get_pack_type();
1198 0 : VclPackType ePackB = pB->get_pack_type();
1199 0 : if (ePackA < ePackB)
1200 0 : return true;
1201 0 : if (ePackA > ePackB)
1202 0 : return false;
1203 0 : bool bVerticalContainer = m_pBuilder->get_window_packing_data(pA->GetParent()).m_bVerticalOrient;
1204 0 : bool bPackA = pA->get_secondary();
1205 0 : bool bPackB = pB->get_secondary();
1206 0 : if (!bVerticalContainer)
1207 : {
1208 : //for horizontal boxes group secondaries before primaries
1209 0 : if (bPackA > bPackB)
1210 0 : return true;
1211 0 : if (bPackA < bPackB)
1212 0 : return false;
1213 : }
1214 : else
1215 : {
1216 : //for vertical boxes group secondaries after primaries
1217 0 : if (bPackA < bPackB)
1218 0 : return true;
1219 0 : if (bPackA > bPackB)
1220 0 : return false;
1221 : }
1222 : //honour relative box positions with pack group
1223 0 : return m_pBuilder->get_window_packing_data(pA).m_nPosition < m_pBuilder->get_window_packing_data(pB).m_nPosition;
1224 : }
1225 :
1226 0 : void VclBuilder::handleChild(Window *pParent, xmlreader::XmlReader &reader)
1227 : {
1228 0 : Window *pCurrentChild = NULL;
1229 0 : bool bIsInternalChild = false;
1230 :
1231 0 : xmlreader::Span name;
1232 : int nsId;
1233 0 : OString sType;
1234 :
1235 0 : while (reader.nextAttribute(&nsId, &name))
1236 : {
1237 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("type")))
1238 : {
1239 0 : name = reader.getAttributeValue(false);
1240 0 : sType = OString(name.begin, name.length);
1241 : }
1242 0 : else if (name.equals(RTL_CONSTASCII_STRINGPARAM("internal-child")))
1243 : {
1244 0 : bIsInternalChild = true;
1245 : }
1246 : }
1247 :
1248 0 : if (sType == "tab")
1249 : {
1250 0 : handleTabChild(pParent, reader);
1251 0 : return;
1252 : }
1253 :
1254 0 : int nLevel = 1;
1255 0 : while(1)
1256 : {
1257 : xmlreader::XmlReader::Result res = reader.nextItem(
1258 0 : xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
1259 :
1260 0 : if (res == xmlreader::XmlReader::RESULT_BEGIN)
1261 : {
1262 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("object")) || name.equals(RTL_CONSTASCII_STRINGPARAM("placeholder")))
1263 : {
1264 0 : pCurrentChild = handleObject(pParent, reader);
1265 :
1266 0 : bool bObjectInserted = pCurrentChild && pParent != pCurrentChild;
1267 :
1268 0 : if (bObjectInserted)
1269 : {
1270 : //Internal-children default in glade to not having their visible bits set
1271 : //even though they are visible (generally anyway)
1272 0 : if (bIsInternalChild)
1273 0 : pCurrentChild->Show();
1274 :
1275 : //Select the first page if its a notebook
1276 0 : if (pCurrentChild->GetType() == WINDOW_TABCONTROL)
1277 : {
1278 0 : TabControl *pTabControl = static_cast<TabControl*>(pCurrentChild);
1279 0 : pTabControl->SetCurPageId(pTabControl->GetPageId(0));
1280 :
1281 : //To-Do add reorder capability to the TabControl
1282 : }
1283 : else
1284 : {
1285 : //To-Do make reorder a virtual in Window, move this foo
1286 : //there and see above
1287 0 : std::vector<Window*> aChilds;
1288 0 : for (Window* pChild = pCurrentChild->GetWindow(WINDOW_FIRSTCHILD); pChild;
1289 0 : pChild = pChild->GetWindow(WINDOW_NEXT))
1290 : {
1291 0 : aChilds.push_back(pChild);
1292 : }
1293 :
1294 : //sort child order within parent so that tabbing
1295 : //between controls goes in a visually sensible sequence
1296 0 : std::stable_sort(aChilds.begin(), aChilds.end(), sortIntoBestTabTraversalOrder(this));
1297 0 : for (size_t i = 0; i < aChilds.size(); ++i)
1298 0 : reorderWithinParent(*aChilds[i], i);
1299 : }
1300 : }
1301 : }
1302 0 : else if (name.equals(RTL_CONSTASCII_STRINGPARAM("packing")))
1303 : {
1304 0 : handlePacking(pCurrentChild, reader);
1305 : }
1306 : else
1307 0 : ++nLevel;
1308 : }
1309 :
1310 0 : if (res == xmlreader::XmlReader::RESULT_END)
1311 0 : --nLevel;
1312 :
1313 0 : if (!nLevel)
1314 0 : break;
1315 :
1316 0 : if (res == xmlreader::XmlReader::RESULT_DONE)
1317 0 : break;
1318 0 : }
1319 : }
1320 :
1321 0 : void VclBuilder::collectPangoAttribute(xmlreader::XmlReader &reader, stringmap &rMap)
1322 : {
1323 0 : xmlreader::Span span;
1324 : int nsId;
1325 :
1326 0 : OString sProperty;
1327 0 : OString sValue;
1328 :
1329 0 : while (reader.nextAttribute(&nsId, &span))
1330 : {
1331 0 : if (span.equals(RTL_CONSTASCII_STRINGPARAM("name")))
1332 : {
1333 0 : span = reader.getAttributeValue(false);
1334 0 : sProperty = OString(span.begin, span.length);
1335 : }
1336 0 : else if (span.equals(RTL_CONSTASCII_STRINGPARAM("value")))
1337 : {
1338 0 : span = reader.getAttributeValue(false);
1339 0 : sValue = OString(span.begin, span.length);
1340 : }
1341 : }
1342 :
1343 0 : if (!sProperty.isEmpty())
1344 0 : rMap[sProperty] = sValue;
1345 0 : }
1346 :
1347 0 : void VclBuilder::handleAdjustment(const OString &rID, stringmap &rProperties)
1348 : {
1349 0 : m_pParserState->m_aAdjustments[rID] = rProperties;
1350 0 : }
1351 :
1352 0 : void VclBuilder::handleTextBuffer(const OString &rID, stringmap &rProperties)
1353 : {
1354 0 : m_pParserState->m_aTextBuffers[rID] = rProperties;
1355 0 : }
1356 :
1357 0 : void VclBuilder::handleRow(xmlreader::XmlReader &reader, const OString &rID, sal_Int32 nRowIndex)
1358 : {
1359 0 : int nLevel = 1;
1360 :
1361 0 : ListStore::row aRow;
1362 :
1363 0 : while(1)
1364 : {
1365 0 : xmlreader::Span name;
1366 : int nsId;
1367 :
1368 : xmlreader::XmlReader::Result res = reader.nextItem(
1369 0 : xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
1370 :
1371 0 : if (res == xmlreader::XmlReader::RESULT_DONE)
1372 : break;
1373 :
1374 0 : if (res == xmlreader::XmlReader::RESULT_BEGIN)
1375 : {
1376 0 : ++nLevel;
1377 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("col")))
1378 : {
1379 0 : bool bTranslated = false;
1380 0 : OString sProperty, sValue;
1381 0 : sal_uInt32 nId = 0;
1382 :
1383 0 : while (reader.nextAttribute(&nsId, &name))
1384 : {
1385 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("id")))
1386 : {
1387 0 : name = reader.getAttributeValue(false);
1388 0 : nId = OString(name.begin, name.length).toInt32();
1389 : }
1390 0 : else if (nId == 0 && name.equals(RTL_CONSTASCII_STRINGPARAM("translatable")) && reader.getAttributeValue(false).equals(RTL_CONSTASCII_STRINGPARAM("yes")))
1391 : {
1392 0 : sValue = getTranslation(rID, OString::valueOf(nRowIndex));
1393 0 : bTranslated = !sValue.isEmpty();
1394 : }
1395 : }
1396 :
1397 : reader.nextItem(
1398 0 : xmlreader::XmlReader::TEXT_RAW, &name, &nsId);
1399 :
1400 0 : if (!bTranslated)
1401 0 : sValue = OString(name.begin, name.length);
1402 :
1403 0 : if (aRow.size() < nId+1)
1404 0 : aRow.resize(nId+1);
1405 0 : aRow[nId] = sValue;
1406 : }
1407 : }
1408 :
1409 0 : if (res == xmlreader::XmlReader::RESULT_END)
1410 : {
1411 0 : --nLevel;
1412 : }
1413 :
1414 0 : if (!nLevel)
1415 : break;
1416 : }
1417 :
1418 0 : m_pParserState->m_aModels[rID].m_aEntries.push_back(aRow);
1419 0 : }
1420 :
1421 0 : void VclBuilder::handleListStore(xmlreader::XmlReader &reader, const OString &rID)
1422 : {
1423 0 : int nLevel = 1;
1424 0 : sal_Int32 nRowIndex = 0;
1425 :
1426 0 : while(1)
1427 : {
1428 0 : xmlreader::Span name;
1429 : int nsId;
1430 :
1431 : xmlreader::XmlReader::Result res = reader.nextItem(
1432 0 : xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
1433 :
1434 0 : if (res == xmlreader::XmlReader::RESULT_DONE)
1435 : break;
1436 :
1437 0 : if (res == xmlreader::XmlReader::RESULT_BEGIN)
1438 : {
1439 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("row")))
1440 0 : handleRow(reader, rID, nRowIndex++);
1441 : else
1442 0 : ++nLevel;
1443 : }
1444 :
1445 0 : if (res == xmlreader::XmlReader::RESULT_END)
1446 : {
1447 0 : --nLevel;
1448 : }
1449 :
1450 0 : if (!nLevel)
1451 : break;
1452 : }
1453 0 : }
1454 :
1455 0 : std::vector<OString> VclBuilder::handleItems(xmlreader::XmlReader &reader, const OString &rID)
1456 : {
1457 0 : int nLevel = 1;
1458 :
1459 0 : std::vector<OString> aItems;
1460 0 : sal_Int32 nItemIndex = 0;
1461 :
1462 0 : while(1)
1463 : {
1464 0 : xmlreader::Span name;
1465 : int nsId;
1466 :
1467 : xmlreader::XmlReader::Result res = reader.nextItem(
1468 0 : xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
1469 :
1470 0 : if (res == xmlreader::XmlReader::RESULT_DONE)
1471 : break;
1472 :
1473 0 : if (res == xmlreader::XmlReader::RESULT_BEGIN)
1474 : {
1475 0 : ++nLevel;
1476 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("item")))
1477 : {
1478 0 : bool bTranslated = false;
1479 0 : OString sValue;
1480 :
1481 0 : while (reader.nextAttribute(&nsId, &name))
1482 : {
1483 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("translatable")) && reader.getAttributeValue(false).equals(RTL_CONSTASCII_STRINGPARAM("yes")))
1484 : {
1485 0 : sValue = getTranslation(rID, OString::valueOf(nItemIndex));
1486 0 : bTranslated = !sValue.isEmpty();
1487 : }
1488 : }
1489 :
1490 : reader.nextItem(
1491 0 : xmlreader::XmlReader::TEXT_RAW, &name, &nsId);
1492 :
1493 0 : if (!bTranslated)
1494 0 : sValue = OString(name.begin, name.length);
1495 :
1496 0 : aItems.push_back(sValue);
1497 0 : ++nItemIndex;
1498 : }
1499 : }
1500 :
1501 0 : if (res == xmlreader::XmlReader::RESULT_END)
1502 : {
1503 0 : --nLevel;
1504 : }
1505 :
1506 0 : if (!nLevel)
1507 : break;
1508 : }
1509 :
1510 0 : return aItems;
1511 : }
1512 :
1513 0 : void VclBuilder::handleMenu(xmlreader::XmlReader &reader, const OString &rID)
1514 : {
1515 0 : PopupMenu *pCurrentMenu = new PopupMenu;
1516 :
1517 0 : int nLevel = 1;
1518 :
1519 0 : stringmap aProperties;
1520 :
1521 0 : while(1)
1522 : {
1523 0 : xmlreader::Span name;
1524 : int nsId;
1525 :
1526 : xmlreader::XmlReader::Result res = reader.nextItem(
1527 0 : xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
1528 :
1529 0 : if (res == xmlreader::XmlReader::RESULT_DONE)
1530 : break;
1531 :
1532 0 : if (res == xmlreader::XmlReader::RESULT_BEGIN)
1533 : {
1534 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("child")))
1535 : {
1536 0 : handleMenuChild(pCurrentMenu, reader);
1537 : }
1538 : else
1539 : {
1540 0 : ++nLevel;
1541 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("property")))
1542 0 : collectProperty(reader, rID, aProperties);
1543 : }
1544 : }
1545 :
1546 0 : if (res == xmlreader::XmlReader::RESULT_END)
1547 : {
1548 0 : --nLevel;
1549 : }
1550 :
1551 0 : if (!nLevel)
1552 : break;
1553 : }
1554 :
1555 0 : m_aMenus.push_back(MenuAndId(rID, pCurrentMenu));
1556 0 : }
1557 :
1558 0 : void VclBuilder::handleMenuChild(PopupMenu *pParent, xmlreader::XmlReader &reader)
1559 : {
1560 0 : xmlreader::Span name;
1561 : int nsId;
1562 0 : OString sType;
1563 :
1564 0 : int nLevel = 1;
1565 0 : while(1)
1566 : {
1567 : xmlreader::XmlReader::Result res = reader.nextItem(
1568 0 : xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
1569 :
1570 0 : if (res == xmlreader::XmlReader::RESULT_BEGIN)
1571 : {
1572 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("object")) || name.equals(RTL_CONSTASCII_STRINGPARAM("placeholder")))
1573 : {
1574 0 : handleMenuObject(pParent, reader);
1575 : }
1576 : else
1577 0 : ++nLevel;
1578 : }
1579 :
1580 0 : if (res == xmlreader::XmlReader::RESULT_END)
1581 0 : --nLevel;
1582 :
1583 0 : if (!nLevel)
1584 0 : break;
1585 :
1586 0 : if (res == xmlreader::XmlReader::RESULT_DONE)
1587 0 : break;
1588 0 : }
1589 0 : }
1590 :
1591 0 : void VclBuilder::handleMenuObject(PopupMenu *pParent, xmlreader::XmlReader &reader)
1592 : {
1593 0 : OString sClass;
1594 0 : OString sID;
1595 0 : OString sCustomProperty;
1596 :
1597 0 : xmlreader::Span name;
1598 : int nsId;
1599 :
1600 0 : while (reader.nextAttribute(&nsId, &name))
1601 : {
1602 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("class")))
1603 : {
1604 0 : name = reader.getAttributeValue(false);
1605 0 : sClass = OString(name.begin, name.length);
1606 : }
1607 0 : else if (name.equals(RTL_CONSTASCII_STRINGPARAM("id")))
1608 : {
1609 0 : name = reader.getAttributeValue(false);
1610 0 : sID = OString(name.begin, name.length);
1611 0 : sal_Int32 nDelim = sID.indexOf(':');
1612 0 : if (nDelim != -1)
1613 : {
1614 0 : sCustomProperty = sID.copy(nDelim+1);
1615 0 : sID = sID.copy(0, nDelim);
1616 : }
1617 : }
1618 : }
1619 :
1620 0 : int nLevel = 1;
1621 :
1622 0 : stringmap aProperties, aAccelerators;
1623 :
1624 0 : if (!sCustomProperty.isEmpty())
1625 0 : aProperties[OString("customproperty")] = sCustomProperty;
1626 :
1627 0 : while(1)
1628 : {
1629 : xmlreader::XmlReader::Result res = reader.nextItem(
1630 0 : xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
1631 :
1632 0 : if (res == xmlreader::XmlReader::RESULT_DONE)
1633 0 : break;
1634 :
1635 0 : if (res == xmlreader::XmlReader::RESULT_BEGIN)
1636 : {
1637 0 : ++nLevel;
1638 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("property")))
1639 0 : collectProperty(reader, sID, aProperties);
1640 0 : else if (name.equals(RTL_CONSTASCII_STRINGPARAM("accelerator")))
1641 0 : collectAccelerator(reader, aAccelerators);
1642 : }
1643 :
1644 0 : if (res == xmlreader::XmlReader::RESULT_END)
1645 : {
1646 0 : --nLevel;
1647 : }
1648 :
1649 0 : if (!nLevel)
1650 0 : break;
1651 : }
1652 :
1653 0 : insertMenuObject(pParent, sClass, sID, aProperties, aAccelerators);
1654 0 : }
1655 :
1656 0 : OString VclBuilder::convertMnemonicMarkup(const OString &rIn)
1657 : {
1658 0 : OStringBuffer aRet(rIn);
1659 0 : for (sal_Int32 nI = 0; nI < aRet.getLength(); ++nI)
1660 : {
1661 0 : if (aRet[nI] == '_')
1662 : {
1663 0 : if (aRet[nI+1] != '_')
1664 0 : aRet[nI] = MNEMONIC_CHAR;
1665 : else
1666 0 : aRet.remove(nI, 1);
1667 0 : ++nI;
1668 : }
1669 : }
1670 0 : return aRet.makeStringAndClear();
1671 : }
1672 :
1673 : namespace
1674 : {
1675 0 : KeyCode makeKeyCode(const OString &rKey)
1676 : {
1677 0 : if (rKey == "Insert")
1678 0 : return KeyCode(KEY_INSERT);
1679 0 : else if (rKey == "Delete")
1680 0 : return KeyCode(KEY_DELETE);
1681 :
1682 : assert (rKey.getLength() == 1);
1683 0 : sal_Char cChar = rKey.toChar();
1684 :
1685 0 : if (cChar >= 'a' && cChar <= 'z')
1686 0 : return KeyCode(KEY_A + (cChar - 'a'));
1687 0 : else if (cChar >= 'A' && cChar <= 'Z')
1688 0 : return KeyCode(KEY_A + (cChar - 'A'));
1689 0 : else if (cChar >= '0' && cChar <= '9')
1690 0 : return KeyCode(KEY_0 + (cChar - 'A'));
1691 :
1692 0 : return KeyCode(cChar);
1693 : }
1694 : }
1695 :
1696 0 : void VclBuilder::insertMenuObject(PopupMenu *pParent, const OString &rClass, const OString &rID,
1697 : stringmap &rProps, stringmap &rAccels)
1698 : {
1699 0 : sal_uInt16 nOldCount = pParent->GetItemCount();
1700 0 : sal_uInt16 nNewId = nOldCount + 1;
1701 :
1702 0 : if (rClass == "GtkMenuItem")
1703 : {
1704 0 : OUString sLabel(OStringToOUString(convertMnemonicMarkup(extractLabel(rProps)), RTL_TEXTENCODING_UTF8));
1705 0 : pParent->InsertItem(nNewId, sLabel, MIB_TEXT);
1706 : }
1707 0 : else if (rClass == "GtkSeparatorMenuItem")
1708 : {
1709 0 : pParent->InsertSeparator();
1710 : }
1711 :
1712 : SAL_WARN_IF(nOldCount == pParent->GetItemCount(), "vcl.layout", "probably need to implement " << rClass.getStr());
1713 :
1714 0 : if (nOldCount != pParent->GetItemCount())
1715 : {
1716 0 : pParent->SetHelpId(nNewId, m_sHelpRoot + rID);
1717 :
1718 0 : for (stringmap::iterator aI = rProps.begin(), aEnd = rProps.end(); aI != aEnd; ++aI)
1719 : {
1720 0 : const OString &rKey = aI->first;
1721 0 : const OString &rValue = aI->second;
1722 :
1723 0 : if (rKey == "tooltip-markup")
1724 0 : pParent->SetTipHelpText(nNewId, OStringToOUString(rValue, RTL_TEXTENCODING_UTF8));
1725 0 : else if (rKey == "tooltip-text")
1726 0 : pParent->SetTipHelpText(nNewId, OStringToOUString(rValue, RTL_TEXTENCODING_UTF8));
1727 0 : else if (rKey == "visible")
1728 0 : pParent->ShowItem(nNewId, toBool(rValue));
1729 0 : else if (rKey == "has-default" && toBool(rValue))
1730 0 : pParent->SetSelectedEntry(nNewId);
1731 : else
1732 : SAL_INFO("vcl.layout", "unhandled property: " << rKey.getStr());
1733 : }
1734 :
1735 0 : for (stringmap::iterator aI = rAccels.begin(), aEnd = rAccels.end(); aI != aEnd; ++aI)
1736 : {
1737 0 : const OString &rSignal = aI->first;
1738 0 : const OString &rValue = aI->second;
1739 :
1740 0 : if (rSignal == "activate")
1741 0 : pParent->SetAccelKey(nNewId, makeKeyCode(rValue));
1742 : else
1743 : SAL_INFO("vcl.layout", "unhandled accelerator for: " << rSignal.getStr());
1744 : }
1745 : }
1746 :
1747 0 : rProps.clear();
1748 0 : }
1749 :
1750 0 : Window* VclBuilder::handleObject(Window *pParent, xmlreader::XmlReader &reader)
1751 : {
1752 0 : OString sClass;
1753 0 : OString sID;
1754 0 : OString sCustomProperty;
1755 :
1756 0 : xmlreader::Span name;
1757 : int nsId;
1758 :
1759 0 : while (reader.nextAttribute(&nsId, &name))
1760 : {
1761 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("class")))
1762 : {
1763 0 : name = reader.getAttributeValue(false);
1764 0 : sClass = OString(name.begin, name.length);
1765 : }
1766 0 : else if (name.equals(RTL_CONSTASCII_STRINGPARAM("id")))
1767 : {
1768 0 : name = reader.getAttributeValue(false);
1769 0 : sID = OString(name.begin, name.length);
1770 0 : sal_Int32 nDelim = sID.indexOf(':');
1771 0 : if (nDelim != -1)
1772 : {
1773 0 : sCustomProperty = sID.copy(nDelim+1);
1774 0 : sID = sID.copy(0, nDelim);
1775 : }
1776 : }
1777 : }
1778 :
1779 0 : if (sClass == "GtkListStore")
1780 : {
1781 0 : handleListStore(reader, sID);
1782 0 : return NULL;
1783 : }
1784 0 : else if (sClass == "GtkMenu")
1785 : {
1786 0 : handleMenu(reader, sID);
1787 0 : return NULL;
1788 : }
1789 :
1790 0 : int nLevel = 1;
1791 :
1792 0 : stringmap aProperties, aPangoAttributes;
1793 0 : std::vector<OString> aItems;
1794 :
1795 0 : if (!sCustomProperty.isEmpty())
1796 0 : aProperties[OString("customproperty")] = sCustomProperty;
1797 :
1798 0 : Window *pCurrentChild = NULL;
1799 0 : while(1)
1800 : {
1801 : xmlreader::XmlReader::Result res = reader.nextItem(
1802 0 : xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
1803 :
1804 0 : if (res == xmlreader::XmlReader::RESULT_DONE)
1805 0 : break;
1806 :
1807 0 : if (res == xmlreader::XmlReader::RESULT_BEGIN)
1808 : {
1809 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("child")))
1810 : {
1811 0 : if (!pCurrentChild)
1812 : {
1813 : pCurrentChild = insertObject(pParent, sClass, sID,
1814 0 : aProperties, aPangoAttributes, aItems);
1815 : }
1816 0 : handleChild(pCurrentChild, reader);
1817 : }
1818 0 : else if (name.equals(RTL_CONSTASCII_STRINGPARAM("items")))
1819 0 : aItems = handleItems(reader, sID);
1820 : else
1821 : {
1822 0 : ++nLevel;
1823 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("property")))
1824 0 : collectProperty(reader, sID, aProperties);
1825 0 : else if (name.equals(RTL_CONSTASCII_STRINGPARAM("attribute")))
1826 0 : collectPangoAttribute(reader, aPangoAttributes);
1827 : }
1828 : }
1829 :
1830 0 : if (res == xmlreader::XmlReader::RESULT_END)
1831 : {
1832 0 : --nLevel;
1833 : }
1834 :
1835 0 : if (!nLevel)
1836 0 : break;
1837 : }
1838 :
1839 0 : if (sClass == "GtkAdjustment")
1840 : {
1841 0 : handleAdjustment(sID, aProperties);
1842 0 : return NULL;
1843 : }
1844 0 : else if (sClass == "GtkTextBuffer")
1845 : {
1846 0 : handleTextBuffer(sID, aProperties);
1847 0 : return NULL;
1848 : }
1849 :
1850 0 : if (!pCurrentChild)
1851 0 : pCurrentChild = insertObject(pParent, sClass, sID, aProperties, aPangoAttributes, aItems);
1852 :
1853 0 : return pCurrentChild;
1854 : }
1855 :
1856 0 : void VclBuilder::handlePacking(Window *pCurrent, xmlreader::XmlReader &reader)
1857 : {
1858 0 : xmlreader::Span name;
1859 : int nsId;
1860 :
1861 0 : int nLevel = 1;
1862 :
1863 0 : while(1)
1864 : {
1865 : xmlreader::XmlReader::Result res = reader.nextItem(
1866 0 : xmlreader::XmlReader::TEXT_NONE, &name, &nsId);
1867 :
1868 0 : if (res == xmlreader::XmlReader::RESULT_DONE)
1869 0 : break;
1870 :
1871 0 : if (res == xmlreader::XmlReader::RESULT_BEGIN)
1872 : {
1873 0 : ++nLevel;
1874 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("property")))
1875 0 : applyPackingProperty(pCurrent, reader);
1876 : }
1877 :
1878 0 : if (res == xmlreader::XmlReader::RESULT_END)
1879 : {
1880 0 : --nLevel;
1881 : }
1882 :
1883 0 : if (!nLevel)
1884 0 : break;
1885 : }
1886 0 : }
1887 :
1888 0 : void VclBuilder::applyPackingProperty(Window *pCurrent,
1889 : xmlreader::XmlReader &reader)
1890 : {
1891 0 : if (!pCurrent)
1892 0 : return;
1893 :
1894 0 : xmlreader::Span name;
1895 : int nsId;
1896 :
1897 0 : if (pCurrent->GetType() == WINDOW_SCROLLWINDOW)
1898 : {
1899 0 : pCurrent = m_pParserState->m_aRedundantParentWidgets[pCurrent];
1900 : assert(pCurrent);
1901 : }
1902 :
1903 0 : while (reader.nextAttribute(&nsId, &name))
1904 : {
1905 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
1906 : {
1907 0 : name = reader.getAttributeValue(false);
1908 0 : OString sKey(name.begin, name.length);
1909 0 : sKey = sKey.replace('_', '-');
1910 : reader.nextItem(
1911 0 : xmlreader::XmlReader::TEXT_RAW, &name, &nsId);
1912 0 : OString sValue(name.begin, name.length);
1913 :
1914 0 : if (sKey == "expand")
1915 : {
1916 0 : bool bTrue = (sValue[0] == 't' || sValue[0] == 'T' || sValue[0] == '1');
1917 0 : pCurrent->set_expand(bTrue);
1918 : }
1919 0 : else if (sKey == "fill")
1920 : {
1921 0 : bool bTrue = (sValue[0] == 't' || sValue[0] == 'T' || sValue[0] == '1');
1922 0 : pCurrent->set_fill(bTrue);
1923 : }
1924 0 : else if (sKey == "pack-type")
1925 : {
1926 0 : VclPackType ePackType = (sValue[0] == 'e' || sValue[0] == 'E') ? VCL_PACK_END : VCL_PACK_START;
1927 0 : pCurrent->set_pack_type(ePackType);
1928 : }
1929 0 : else if (sKey == "left-attach")
1930 : {
1931 0 : pCurrent->set_grid_left_attach(sValue.toInt32());
1932 : }
1933 0 : else if (sKey == "top-attach")
1934 : {
1935 0 : pCurrent->set_grid_top_attach(sValue.toInt32());
1936 : }
1937 0 : else if (sKey == "width")
1938 : {
1939 0 : pCurrent->set_grid_width(sValue.toInt32());
1940 : }
1941 0 : else if (sKey == "height")
1942 : {
1943 0 : pCurrent->set_grid_height(sValue.toInt32());
1944 : }
1945 0 : else if (sKey == "padding")
1946 : {
1947 0 : pCurrent->set_padding(sValue.toInt32());
1948 : }
1949 0 : else if (sKey == "position")
1950 : {
1951 0 : set_window_packing_position(pCurrent, sValue.toInt32());
1952 : }
1953 0 : else if (sKey == "secondary")
1954 : {
1955 0 : pCurrent->set_secondary(toBool(sValue));
1956 : }
1957 : else
1958 : {
1959 : SAL_WARN("vcl.layout", "unknown packing: " << sKey.getStr());
1960 0 : }
1961 : }
1962 : }
1963 : }
1964 :
1965 0 : OString VclBuilder::getTranslation(const OString &rID, const OString &rProperty) const
1966 : {
1967 0 : Translations::const_iterator aWidgetFind = m_pParserState->m_aTranslations.find(rID);
1968 0 : if (aWidgetFind != m_pParserState->m_aTranslations.end())
1969 : {
1970 0 : const WidgetTranslations &rWidgetTranslations = aWidgetFind->second;
1971 0 : WidgetTranslations::const_iterator aPropertyFind = rWidgetTranslations.find(rProperty);
1972 0 : if (aPropertyFind != rWidgetTranslations.end())
1973 0 : return aPropertyFind->second;
1974 : }
1975 0 : return OString();
1976 : }
1977 :
1978 0 : void VclBuilder::collectProperty(xmlreader::XmlReader &reader, const OString &rID, stringmap &rMap)
1979 : {
1980 0 : xmlreader::Span name;
1981 : int nsId;
1982 :
1983 0 : OString sProperty;
1984 0 : OString sValue;
1985 :
1986 0 : bool bTranslated = false;
1987 :
1988 0 : while (reader.nextAttribute(&nsId, &name))
1989 : {
1990 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("name")))
1991 : {
1992 0 : name = reader.getAttributeValue(false);
1993 0 : sProperty = OString(name.begin, name.length);
1994 : }
1995 0 : else if (name.equals(RTL_CONSTASCII_STRINGPARAM("translatable")) && reader.getAttributeValue(false).equals(RTL_CONSTASCII_STRINGPARAM("yes")))
1996 : {
1997 0 : sValue = getTranslation(rID, sProperty);
1998 0 : bTranslated = !sValue.isEmpty();
1999 : }
2000 :
2001 : }
2002 :
2003 0 : reader.nextItem(xmlreader::XmlReader::TEXT_RAW, &name, &nsId);
2004 0 : if (!bTranslated)
2005 0 : sValue = OString(name.begin, name.length);
2006 :
2007 0 : if (!sProperty.isEmpty())
2008 : {
2009 0 : sProperty = sProperty.replace('_', '-');
2010 0 : rMap[sProperty] = sValue.replaceAll("%PRODUCTNAME", m_sProductName);
2011 0 : }
2012 0 : }
2013 :
2014 0 : void VclBuilder::collectAccelerator(xmlreader::XmlReader &reader, stringmap &rMap)
2015 : {
2016 0 : xmlreader::Span name;
2017 : int nsId;
2018 :
2019 0 : OString sProperty;
2020 0 : OString sValue;
2021 :
2022 0 : while (reader.nextAttribute(&nsId, &name))
2023 : {
2024 0 : if (name.equals(RTL_CONSTASCII_STRINGPARAM("key")))
2025 : {
2026 0 : name = reader.getAttributeValue(false);
2027 0 : sValue = OString(name.begin, name.length);
2028 : }
2029 0 : else if (name.equals(RTL_CONSTASCII_STRINGPARAM("signal")))
2030 : {
2031 0 : name = reader.getAttributeValue(false);
2032 0 : sProperty = OString(name.begin, name.length);
2033 : }
2034 :
2035 : }
2036 :
2037 0 : if (!sProperty.isEmpty() && !sValue.isEmpty())
2038 : {
2039 0 : rMap[sProperty] = sValue;
2040 0 : }
2041 0 : }
2042 :
2043 0 : Window *VclBuilder::get_widget_root()
2044 : {
2045 0 : return m_aChildren.empty() ? NULL : m_aChildren[0].m_pWindow;
2046 : }
2047 :
2048 0 : Window *VclBuilder::get_by_name(OString sID)
2049 : {
2050 0 : for (std::vector<WinAndId>::iterator aI = m_aChildren.begin(),
2051 0 : aEnd = m_aChildren.end(); aI != aEnd; ++aI)
2052 : {
2053 0 : if (aI->m_sID.equals(sID))
2054 0 : return aI->m_pWindow;
2055 : }
2056 :
2057 0 : return NULL;
2058 : }
2059 :
2060 0 : PopupMenu *VclBuilder::get_menu_by_name(OString sID)
2061 : {
2062 0 : for (std::vector<MenuAndId>::iterator aI = m_aMenus.begin(),
2063 0 : aEnd = m_aMenus.end(); aI != aEnd; ++aI)
2064 : {
2065 0 : if (aI->m_sID.equals(sID))
2066 0 : return aI->m_pMenu;
2067 : }
2068 :
2069 0 : return NULL;
2070 : }
2071 :
2072 0 : void VclBuilder::delete_by_name(OString sID)
2073 : {
2074 0 : for (std::vector<WinAndId>::iterator aI = m_aChildren.begin(),
2075 0 : aEnd = m_aChildren.end(); aI != aEnd; ++aI)
2076 : {
2077 0 : if (aI->m_sID.equals(sID))
2078 : {
2079 0 : delete aI->m_pWindow;
2080 0 : m_aChildren.erase(aI);
2081 0 : break;
2082 : }
2083 : }
2084 0 : }
2085 :
2086 0 : void VclBuilder::delete_by_window(const Window *pWindow)
2087 : {
2088 0 : for (std::vector<WinAndId>::iterator aI = m_aChildren.begin(),
2089 0 : aEnd = m_aChildren.end(); aI != aEnd; ++aI)
2090 : {
2091 0 : if (aI->m_pWindow == pWindow)
2092 : {
2093 0 : delete aI->m_pWindow;
2094 0 : m_aChildren.erase(aI);
2095 0 : break;
2096 : }
2097 : }
2098 0 : }
2099 :
2100 0 : OString VclBuilder::get_by_window(const Window *pWindow) const
2101 : {
2102 0 : for (std::vector<WinAndId>::const_iterator aI = m_aChildren.begin(),
2103 0 : aEnd = m_aChildren.end(); aI != aEnd; ++aI)
2104 : {
2105 0 : if (aI->m_pWindow == pWindow)
2106 0 : return aI->m_sID;
2107 : }
2108 :
2109 0 : return OString();
2110 : }
2111 :
2112 0 : VclBuilder::PackingData VclBuilder::get_window_packing_data(const Window *pWindow) const
2113 : {
2114 : //We've stored the return of new Control, some of these get
2115 : //border windows placed around them which are what you get
2116 : //from GetChild, so scoot up a level if necessary to get the
2117 : //window whose position value we have
2118 : const Window *pPropHolder = pWindow->mpWindowImpl->mpClientWindow ?
2119 0 : pWindow->mpWindowImpl->mpClientWindow : pWindow;
2120 :
2121 0 : for (std::vector<WinAndId>::const_iterator aI = m_aChildren.begin(),
2122 0 : aEnd = m_aChildren.end(); aI != aEnd; ++aI)
2123 : {
2124 0 : if (aI->m_pWindow == pPropHolder)
2125 0 : return aI->m_aPackingData;
2126 : }
2127 :
2128 0 : return PackingData();
2129 : }
2130 :
2131 0 : void VclBuilder::set_window_packing_position(const Window *pWindow, sal_Int32 nPosition)
2132 : {
2133 0 : for (std::vector<WinAndId>::iterator aI = m_aChildren.begin(),
2134 0 : aEnd = m_aChildren.end(); aI != aEnd; ++aI)
2135 : {
2136 0 : if (aI->m_pWindow == pWindow)
2137 0 : aI->m_aPackingData.m_nPosition = nPosition;
2138 : }
2139 0 : }
2140 :
2141 0 : const VclBuilder::ListStore *VclBuilder::get_model_by_name(OString sID) const
2142 : {
2143 0 : std::map<OString, ListStore>::const_iterator aI = m_pParserState->m_aModels.find(sID);
2144 0 : if (aI != m_pParserState->m_aModels.end())
2145 0 : return &(aI->second);
2146 0 : return NULL;
2147 : }
2148 :
2149 0 : const VclBuilder::TextBuffer *VclBuilder::get_buffer_by_name(OString sID) const
2150 : {
2151 0 : std::map<OString, TextBuffer>::const_iterator aI = m_pParserState->m_aTextBuffers.find(sID);
2152 0 : if (aI != m_pParserState->m_aTextBuffers.end())
2153 0 : return &(aI->second);
2154 0 : return NULL;
2155 : }
2156 :
2157 0 : const VclBuilder::Adjustment *VclBuilder::get_adjustment_by_name(OString sID) const
2158 : {
2159 0 : std::map<OString, Adjustment>::const_iterator aI = m_pParserState->m_aAdjustments.find(sID);
2160 0 : if (aI != m_pParserState->m_aAdjustments.end())
2161 0 : return &(aI->second);
2162 0 : return NULL;
2163 : }
2164 :
2165 0 : void VclBuilder::mungeModel(ListBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId)
2166 : {
2167 0 : for (std::vector<ListStore::row>::const_iterator aI = rStore.m_aEntries.begin(), aEnd = rStore.m_aEntries.end();
2168 : aI != aEnd; ++aI)
2169 : {
2170 0 : const ListStore::row &rRow = *aI;
2171 0 : sal_uInt16 nEntry = rTarget.InsertEntry(OStringToOUString(rRow[0], RTL_TEXTENCODING_UTF8));
2172 0 : if (rRow.size() > 1)
2173 : {
2174 0 : sal_IntPtr nValue = rRow[1].toInt32();
2175 0 : rTarget.SetEntryData(nEntry, (void*)nValue);
2176 : }
2177 : }
2178 0 : if (nActiveId < rStore.m_aEntries.size())
2179 0 : rTarget.SelectEntryPos(nActiveId);
2180 0 : }
2181 :
2182 0 : void VclBuilder::mungeSpinAdjustment(NumericFormatter &rTarget, const Adjustment &rAdjustment)
2183 : {
2184 0 : int nMul = rtl_math_pow10Exp(1, rTarget.GetDecimalDigits());
2185 :
2186 0 : for (stringmap::const_iterator aI = rAdjustment.begin(), aEnd = rAdjustment.end(); aI != aEnd; ++aI)
2187 : {
2188 0 : const OString &rKey = aI->first;
2189 0 : const OString &rValue = aI->second;
2190 :
2191 0 : if (rKey == "upper")
2192 : {
2193 0 : sal_Int64 nUpper = rValue.toDouble() * nMul;
2194 0 : rTarget.SetMax(nUpper);
2195 0 : rTarget.SetLast(nUpper);
2196 : }
2197 0 : else if (rKey == "lower")
2198 : {
2199 0 : sal_Int64 nLower = rValue.toDouble() * nMul;
2200 0 : rTarget.SetMin(nLower);
2201 0 : rTarget.SetFirst(nLower);
2202 : }
2203 0 : else if (rKey == "value")
2204 : {
2205 0 : sal_Int64 nValue = rValue.toDouble() * nMul;
2206 0 : rTarget.SetValue(nValue);
2207 : }
2208 0 : else if (rKey == "step-increment")
2209 : {
2210 0 : sal_Int64 nSpinSize = rValue.toDouble() * nMul;
2211 0 : rTarget.SetSpinSize(nSpinSize);
2212 : }
2213 : else
2214 : {
2215 : SAL_INFO("vcl.layout", "unhandled property :" << rKey.getStr());
2216 : }
2217 : }
2218 0 : }
2219 :
2220 0 : void VclBuilder::mungeScrollAdjustment(ScrollBar &rTarget, const Adjustment &rAdjustment)
2221 : {
2222 0 : for (stringmap::const_iterator aI = rAdjustment.begin(), aEnd = rAdjustment.end(); aI != aEnd; ++aI)
2223 : {
2224 0 : const OString &rKey = aI->first;
2225 0 : const OString &rValue = aI->second;
2226 :
2227 0 : if (rKey == "upper")
2228 0 : rTarget.SetRangeMax(rValue.toInt32());
2229 0 : else if (rKey == "lower")
2230 0 : rTarget.SetRangeMin(rValue.toInt32());
2231 0 : else if (rKey == "value")
2232 0 : rTarget.SetThumbPos(rValue.toInt32());
2233 0 : else if (rKey == "step-increment")
2234 0 : rTarget.SetLineSize(rValue.toInt32());
2235 0 : else if (rKey == "page-increment")
2236 0 : rTarget.SetPageSize(rValue.toInt32());
2237 : else
2238 : {
2239 : SAL_INFO("vcl.layout", "unhandled property :" << rKey.getStr());
2240 : }
2241 : }
2242 0 : }
2243 :
2244 0 : void VclBuilder::mungeTextBuffer(VclMultiLineEdit &rTarget, const TextBuffer &rTextBuffer)
2245 : {
2246 0 : for (stringmap::const_iterator aI = rTextBuffer.begin(), aEnd = rTextBuffer.end(); aI != aEnd; ++aI)
2247 : {
2248 0 : const OString &rKey = aI->first;
2249 0 : const OString &rValue = aI->second;
2250 :
2251 0 : if (rKey == "text")
2252 0 : rTarget.SetText(OStringToOUString(rValue, RTL_TEXTENCODING_UTF8));
2253 : else
2254 : {
2255 : SAL_INFO("vcl.layout", "unhandled property :" << rKey.getStr());
2256 : }
2257 : }
2258 108 : }
2259 :
2260 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|