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