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 : #ifndef INCLUDED_VCL_BUILDER_HXX
11 : #define INCLUDED_VCL_BUILDER_HXX
12 :
13 : #include <typeinfo>
14 : #include <osl/module.hxx>
15 : #include <sal/log.hxx>
16 : #include <tools/resmgr.hxx>
17 : #include <tools/fldunit.hxx>
18 : #include <vcl/dllapi.h>
19 : #include <vcl/window.hxx>
20 : #include <vcl/vclptr.hxx>
21 : #include <map>
22 : #include <set>
23 : #include <stack>
24 : #include <vector>
25 : #ifdef check
26 : # //some problem with MacOSX and a check define
27 : # undef check
28 : #endif
29 : #include <boost/ptr_container/ptr_map.hpp>
30 :
31 : #include <com/sun/star/frame/XFrame.hpp>
32 : #include <com/sun/star/uno/XComponentContext.hpp>
33 :
34 : class ListBox;
35 : class NumericFormatter;
36 : class PopupMenu;
37 : class ScrollBar;
38 : class Slider;
39 : class DateField;
40 : class TimeField;
41 : class VclExpander;
42 : class VclMultiLineEdit;
43 : namespace xmlreader { class XmlReader; }
44 :
45 : class VCL_DLLPUBLIC VclBuilder
46 : {
47 : public:
48 : typedef std::map<OString, OString> stringmap;
49 : /// These functions create a new widget with parent @pParent and return it in @rRet
50 : typedef void (*customMakeWidget)(VclPtr<vcl::Window> &rRet, VclPtr<vcl::Window> &pParent, stringmap &rVec);
51 :
52 : public:
53 : VclBuilder(
54 : vcl::Window *pParent,
55 : const OUString& sUIRootDir,
56 : const OUString& sUIFile,
57 : const OString& sID = OString(),
58 : const css::uno::Reference<css::frame::XFrame> &rFrame = css::uno::Reference<css::frame::XFrame>());
59 : ~VclBuilder();
60 :
61 : ///releases references and disposes all children.
62 : void disposeBuilder();
63 :
64 : //sID must exist and be of type T
65 : template <typename T> T* get(VclPtr<T>& ret, const OString& sID);
66 :
67 : //sID may not exist, but must be of type T if it does
68 : template <typename T /*= vcl::Window if we had c++11*/> T* get(const OString& sID);
69 :
70 : vcl::Window* get_widget_root();
71 :
72 : PopupMenu* get_menu(PopupMenu*& ret, const OString& sID);
73 :
74 : //sID may not exist
75 : PopupMenu* get_menu(const OString& sID);
76 :
77 : //given an sID return the response value for that widget
78 : short get_response(const vcl::Window *pWindow) const;
79 :
80 : OString get_by_window(const vcl::Window *pWindow) const;
81 : void delete_by_window(vcl::Window *pWindow);
82 :
83 : //release ownership of pWindow, i.e. don't delete it
84 : void drop_ownership(const vcl::Window *pWindow);
85 :
86 : //apply the properties of rProps to pWindow
87 : static void set_properties(vcl::Window *pWindow, const stringmap &rProps);
88 :
89 : //Convert _ gtk markup to ~ vcl markup
90 : static OString convertMnemonicMarkup(const OString &rIn);
91 :
92 : static OString extractCustomProperty(stringmap &rMap);
93 : static FieldUnit detectUnit(OString const&);
94 :
95 : static bool extractDropdown(stringmap &rMap);
96 :
97 : //add a default value of 25 width-chars to a map if width-chars not set
98 : static void ensureDefaultWidthChars(VclBuilder::stringmap &rMap);
99 :
100 : //see m_aDeferredProperties, you need this for toplevel dialogs
101 : //which build themselves from their ctor. The properties on
102 : //the top level are stored in m_aDeferredProperties and need
103 : //to be applied post ctor
104 : void setDeferredProperties();
105 :
106 : //Helpers to retrofit all the existing code to the builder
107 : static void reorderWithinParent(std::vector< vcl::Window*>& rChilds, bool bIsButtonBox);
108 : static void reorderWithinParent(vcl::Window &rWindow, sal_uInt16 nNewPosition);
109 :
110 : /// Get label of the command (like of .uno:Save) from the description service
111 : static OUString getCommandLabel(const OUString& rCommand, const css::uno::Reference<css::uno::XComponentContext>& rContext, const OUString& rModuleId);
112 :
113 : /// Get image of the command (like of .uno:Save) from the description service
114 : static Image getCommandImage(
115 : const OUString& rCommand,
116 : bool bLarge,
117 : const css::uno::Reference<css::uno::XComponentContext>& rContext,
118 : const css::uno::Reference<css::frame::XFrame>& rFrame,
119 : const OUString& rModuleId );
120 :
121 0 : css::uno::Reference<css::frame::XFrame> getFrame() { return m_xFrame; }
122 :
123 : private:
124 : VclBuilder(const VclBuilder&) SAL_DELETED_FUNCTION;
125 : VclBuilder& operator=(const VclBuilder&) SAL_DELETED_FUNCTION;
126 :
127 : typedef boost::ptr_map<OUString, osl::Module> ModuleMap;
128 :
129 : //We store these until the builder is deleted, that way we can use the
130 : //ui-previewer on custom widgets and guarantee the modules they are from
131 : //exist for the duration of the dialog
132 : ModuleMap m_aModuleMap;
133 :
134 : //If the toplevel window has any properties which need to be set on it,
135 : //but the toplevel is the owner of the builder, then its ctor
136 : //has not been completed during the building, so properties for it
137 : //are collected here and need to be set afterwards, e.g. during
138 : //Show or Execute
139 : stringmap m_aDeferredProperties;
140 :
141 : struct PackingData
142 : {
143 : bool m_bVerticalOrient;
144 : sal_Int32 m_nPosition;
145 25204 : PackingData(bool bVerticalOrient = false, sal_Int32 nPosition = -1)
146 : : m_bVerticalOrient(bVerticalOrient)
147 25204 : , m_nPosition(nPosition)
148 : {
149 25204 : }
150 : };
151 :
152 133056 : struct WinAndId
153 : {
154 : OString m_sID;
155 : VclPtr<vcl::Window> m_pWindow;
156 : short m_nResponseId;
157 : PackingData m_aPackingData;
158 24546 : WinAndId(const OString &rId, vcl::Window *pWindow, bool bVertical)
159 : : m_sID(rId)
160 : , m_pWindow(pWindow)
161 : , m_nResponseId(RET_CANCEL)
162 24546 : , m_aPackingData(bVertical)
163 : {
164 24546 : }
165 : };
166 : std::vector<WinAndId> m_aChildren;
167 :
168 3 : struct MenuAndId
169 : {
170 : OString m_sID;
171 : PopupMenu *m_pMenu;
172 1 : MenuAndId(const OString &rId, PopupMenu *pMenu)
173 : : m_sID(rId)
174 1 : , m_pMenu(pMenu)
175 : {
176 1 : }
177 : };
178 : std::vector<MenuAndId> m_aMenus;
179 :
180 4414 : struct StringPair
181 : {
182 : OString m_sID;
183 : OString m_sValue;
184 1140 : StringPair(const OString &rId, const OString &rValue)
185 : : m_sID(rId)
186 1140 : , m_sValue(rValue)
187 : {
188 1140 : }
189 : };
190 :
191 : typedef StringPair RadioButtonGroupMap;
192 :
193 57 : struct ButtonImageWidgetMap
194 : {
195 : OString m_sID;
196 : OString m_sValue;
197 : bool m_bRadio;
198 9 : ButtonImageWidgetMap(const OString &rId, const OString &rValue, bool bRadio)
199 : : m_sID(rId)
200 : , m_sValue(rValue)
201 9 : , m_bRadio(bRadio)
202 : {
203 9 : }
204 : };
205 :
206 : typedef StringPair TextBufferMap;
207 : typedef StringPair WidgetAdjustmentMap;
208 : typedef StringPair ButtonMenuMap;
209 : typedef StringPair MnemonicWidgetMap;
210 :
211 0 : struct ComboBoxModelMap
212 : {
213 : OString m_sID;
214 : OString m_sValue;
215 : sal_Int32 m_nActiveId;
216 0 : ComboBoxModelMap(const OString &rId, const OString &rValue, sal_Int32 nActiveId)
217 : : m_sID(rId)
218 : , m_sValue(rValue)
219 0 : , m_nActiveId(nActiveId)
220 : {
221 0 : }
222 : };
223 :
224 0 : struct ListStore
225 : {
226 : typedef std::vector<OString> row;
227 : std::vector<row> m_aEntries;
228 : };
229 :
230 : const ListStore* get_model_by_name(const OString& sID) const;
231 : static void mungeModel(ListBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId);
232 :
233 : typedef stringmap TextBuffer;
234 : const TextBuffer*
235 : get_buffer_by_name(const OString& sID) const;
236 :
237 : static void mungeTextBuffer(VclMultiLineEdit &rTarget, const TextBuffer &rTextBuffer);
238 :
239 : typedef stringmap Adjustment;
240 : const Adjustment* get_adjustment_by_name(const OString& sID) const;
241 :
242 : static void mungeAdjustment(NumericFormatter &rTarget, const Adjustment &rAdjustment);
243 : static void mungeAdjustment(DateField &rTarget, const Adjustment &rAdjustment);
244 : static void mungeAdjustment(TimeField &rTarget, const Adjustment &rAdjustment);
245 : static void mungeAdjustment(ScrollBar &rTarget, const Adjustment &rAdjustment);
246 : static void mungeAdjustment(Slider &rTarget, const Adjustment &rAdjustment);
247 :
248 : typedef std::map<OString, OString> WidgetTranslations;
249 : typedef std::map<OString, WidgetTranslations> Translations;
250 :
251 0 : struct stockinfo
252 : {
253 : OString m_sStock;
254 : int m_nSize;
255 0 : stockinfo() : m_nSize(4) {}
256 : };
257 :
258 : typedef std::map<OString, stockinfo> StockMap;
259 :
260 1017 : struct SizeGroup
261 : {
262 : OString m_sID;
263 : std::vector<OString> m_aWidgets;
264 : stringmap m_aProperties;
265 339 : SizeGroup(const OString &rId)
266 339 : : m_sID(rId)
267 : {
268 339 : }
269 : };
270 :
271 : typedef std::map< VclPtr<vcl::Window>, stringmap> AtkMap;
272 :
273 1638 : struct ParserState
274 : {
275 : std::vector<RadioButtonGroupMap> m_aGroupMaps;
276 :
277 : std::vector<ComboBoxModelMap> m_aModelMaps;
278 : std::map<OString, ListStore> m_aModels;
279 :
280 : std::vector<TextBufferMap> m_aTextBufferMaps;
281 : std::map<OString, TextBuffer> m_aTextBuffers;
282 :
283 : std::vector<WidgetAdjustmentMap> m_aNumericFormatterAdjustmentMaps;
284 : std::vector<WidgetAdjustmentMap> m_aTimeFormatterAdjustmentMaps;
285 : std::vector<WidgetAdjustmentMap> m_aDateFormatterAdjustmentMaps;
286 : std::vector<WidgetAdjustmentMap> m_aScrollAdjustmentMaps;
287 : std::vector<WidgetAdjustmentMap> m_aSliderAdjustmentMaps;
288 :
289 : std::map<OString, Adjustment> m_aAdjustments;
290 :
291 : std::vector<ButtonImageWidgetMap> m_aButtonImageWidgetMaps;
292 : StockMap m_aStockMap;
293 :
294 : std::vector<ButtonMenuMap> m_aButtonMenuMaps;
295 :
296 : Translations m_aTranslations;
297 :
298 : std::map< VclPtr<vcl::Window>, VclPtr<vcl::Window> > m_aRedundantParentWidgets;
299 :
300 : std::vector<SizeGroup> m_aSizeGroups;
301 :
302 : AtkMap m_aAtkInfo;
303 :
304 : std::vector<MnemonicWidgetMap> m_aMnemonicWidgetMaps;
305 :
306 : std::vector< VclPtr<VclExpander> > m_aExpanderWidgets;
307 :
308 : sal_uInt16 m_nLastToolbarId;
309 :
310 : ParserState();
311 : };
312 :
313 : void loadTranslations(const LanguageTag &rLanguageTag, const OUString &rUri);
314 : OString getTranslation(const OString &rId, const OString &rProperty) const;
315 :
316 : OString m_sID;
317 : OString m_sHelpRoot;
318 : ResHookProc m_pStringReplace;
319 : VclPtr<vcl::Window> m_pParent;
320 : bool m_bToplevelHasDeferredInit;
321 : bool m_bToplevelHasDeferredProperties;
322 : bool m_bToplevelParentFound;
323 : ParserState *m_pParserState;
324 :
325 : vcl::Window *get_by_name(const OString& sID);
326 : void delete_by_name(const OString& sID);
327 :
328 : class sortIntoBestTabTraversalOrder
329 : : public std::binary_function<const vcl::Window*, const vcl::Window*, bool>
330 : {
331 : public:
332 24548 : sortIntoBestTabTraversalOrder(VclBuilder *pBuilder)
333 24548 : : m_pBuilder(pBuilder) {}
334 :
335 : bool operator()(const vcl::Window *pA, const vcl::Window *pB) const;
336 :
337 : private:
338 : VclBuilder *m_pBuilder;
339 : };
340 :
341 : /// XFrame to be able to extract labels and other properties of the UNO commands (like of .uno:Bold).
342 : css::uno::Reference<css::frame::XFrame> m_xFrame;
343 :
344 : private:
345 : VclPtr<vcl::Window> insertObject(vcl::Window *pParent,
346 : const OString &rClass, const OString &rID,
347 : stringmap &rProps, stringmap &rPangoAttributes,
348 : stringmap &rAtkProps);
349 :
350 : VclPtr<vcl::Window> makeObject(vcl::Window *pParent,
351 : const OString &rClass, const OString &rID,
352 : stringmap &rVec);
353 :
354 : void connectNumericFormatterAdjustment(const OString &id, const OString &rAdjustment);
355 : void connectTimeFormatterAdjustment(const OString &id, const OString &rAdjustment);
356 : void connectDateFormatterAdjustment(const OString &id, const OString &rAdjustment);
357 :
358 : bool extractGroup(const OString &id, stringmap &rVec);
359 : bool extractModel(const OString &id, stringmap &rVec);
360 : bool extractBuffer(const OString &id, stringmap &rVec);
361 : static bool extractAdjustmentToMap(const OString &id, stringmap &rVec, std::vector<WidgetAdjustmentMap>& rAdjustmentMap);
362 : bool extractButtonImage(const OString &id, stringmap &rMap, bool bRadio);
363 : bool extractStock(const OString &id, stringmap &rMap);
364 : void extractMnemonicWidget(const OString &id, stringmap &rMap);
365 :
366 : void handleTranslations(xmlreader::XmlReader &reader);
367 :
368 : void handleChild(vcl::Window *pParent, xmlreader::XmlReader &reader);
369 : VclPtr<vcl::Window> handleObject(vcl::Window *pParent, xmlreader::XmlReader &reader);
370 : void handlePacking(vcl::Window *pCurrent, vcl::Window *pParent, xmlreader::XmlReader &reader);
371 : void applyPackingProperty(vcl::Window *pCurrent, vcl::Window *pParent, xmlreader::XmlReader &reader);
372 : void collectProperty(xmlreader::XmlReader &reader, const OString &rID, stringmap &rVec);
373 : static void collectPangoAttribute(xmlreader::XmlReader &reader, stringmap &rMap);
374 : static void collectAtkAttribute(xmlreader::XmlReader &reader, stringmap &rMap);
375 : static void collectAccelerator(xmlreader::XmlReader &reader, stringmap &rMap);
376 :
377 : void insertMenuObject(
378 : PopupMenu *pParent,
379 : const OString &rClass,
380 : const OString &rID,
381 : stringmap &rProps,
382 : stringmap &rAccels);
383 :
384 : void handleMenuChild(PopupMenu *pParent, xmlreader::XmlReader &reader);
385 : void handleMenuObject(PopupMenu *pParent, xmlreader::XmlReader &reader);
386 :
387 : void handleListStore(xmlreader::XmlReader &reader, const OString &rID);
388 : void handleRow(xmlreader::XmlReader &reader, const OString &rID, sal_Int32 nRowIndex);
389 : void handleAdjustment(const OString &rID, stringmap &rProperties);
390 : void handleTextBuffer(const OString &rID, stringmap &rProperties);
391 : void handleTabChild(vcl::Window *pParent, xmlreader::XmlReader &reader);
392 : void handleMenu(xmlreader::XmlReader &reader, const OString &rID);
393 : std::vector<OString> handleItems(xmlreader::XmlReader &reader, const OString &rID);
394 :
395 : void handleSizeGroup(xmlreader::XmlReader &reader, const OString &rID);
396 :
397 : void handleAtkObject(xmlreader::XmlReader &reader, const OString &rID, vcl::Window *pWindow);
398 :
399 : void handleActionWidget(xmlreader::XmlReader &reader);
400 :
401 : PackingData get_window_packing_data(const vcl::Window *pWindow) const;
402 : void set_window_packing_position(const vcl::Window *pWindow, sal_Int32 nPosition);
403 :
404 : static vcl::Window* prepareWidgetOwnScrolling(vcl::Window *pParent, WinBits &rWinStyle);
405 : void cleanupWidgetOwnScrolling(vcl::Window *pScrollParent, vcl::Window *pWindow, stringmap &rMap);
406 :
407 : void set_response(const OString& sID, short nResponse);
408 : };
409 :
410 : template <typename T>
411 10000 : inline T* VclBuilder::get(VclPtr<T>& ret, const OString& sID)
412 : {
413 10000 : vcl::Window *w = get_by_name(sID);
414 : SAL_WARN_IF(!w, "vcl.layout", "widget \"" << sID.getStr() << "\" not found in .ui");
415 : SAL_WARN_IF(!dynamic_cast<T*>(w),
416 : "vcl.layout", ".ui widget \"" << sID.getStr() << "\" needs to correspond to vcl type " << typeid(T).name());
417 : assert(w);
418 : assert(dynamic_cast<T*>(w));
419 10000 : ret = static_cast<T*>(w);
420 10000 : return ret.get();
421 : }
422 :
423 : //sID may not exist, but must be of type T if it does
424 : template <typename T /*= vcl::Window if we had c++11*/>
425 4349 : inline T* VclBuilder::get(const OString& sID)
426 : {
427 4349 : vcl::Window *w = get_by_name(sID);
428 : SAL_WARN_IF(w && !dynamic_cast<T*>(w),
429 : "vcl.layout", ".ui widget \"" << sID.getStr() << "\" needs to correspond to vcl type " << typeid(T).name());
430 : assert(!w || dynamic_cast<T*>(w));
431 4349 : return static_cast<T*>(w);
432 : }
433 :
434 : inline PopupMenu* VclBuilder::get_menu(PopupMenu*& ret, const OString& sID)
435 : {
436 : ret = get_menu(sID);
437 : SAL_WARN_IF(!ret, "vcl.layout", "menu \"" << sID.getStr() << "\" not found in .ui");
438 : assert(ret);
439 : return ret;
440 : }
441 :
442 : //helper baseclass to ease retro fitting dialogs/tabpages that load a resource
443 : //to load a .ui file instead
444 : //
445 : //vcl requires the Window Children of a Parent Window to be destroyed before
446 : //the Parent Window. VclBuilderContainer owns the VclBuilder which owns the
447 : //Children Window. So the VclBuilderContainer dtor must be called before
448 : //the Parent Window dtor.
449 : //
450 : //i.e. class Dialog : public SystemWindow, public VclBuilderContainer
451 : //not class Dialog : public VclBuilderContainer, public SystemWindow
452 : //
453 : //With the new 'dispose' framework, it is necessary to force the builder
454 : //dispose before the Window dispose; so a Dialog::dispose() method would
455 : //finish: disposeBuilder(); SystemWindow::dispose() to capture this ordering.
456 :
457 : class VCL_DLLPUBLIC VclBuilderContainer
458 : {
459 : public:
460 : VclBuilderContainer();
461 : virtual ~VclBuilderContainer();
462 : void disposeBuilder();
463 :
464 : static OUString getUIRootDir();
465 0 : bool hasBuilder() const { return m_pUIBuilder != NULL; }
466 :
467 0 : css::uno::Reference<css::frame::XFrame> getFrame() { return m_pUIBuilder->getFrame(); }
468 :
469 10000 : template <typename T> T* get(VclPtr<T>& ret, const OString& sID)
470 : {
471 10000 : return m_pUIBuilder->get<T>(ret, sID);
472 : }
473 19 : template <typename T /*= vcl::Window if we had c++11*/> T* get(const OString & sID)
474 : {
475 19 : return m_pUIBuilder->get<T>(sID);
476 : }
477 : PopupMenu* get_menu(PopupMenu*& ret, const OString & sID)
478 : {
479 : return m_pUIBuilder->get_menu(ret, sID);
480 : }
481 0 : PopupMenu* get_menu(const OString & sID)
482 : {
483 0 : return m_pUIBuilder->get_menu(sID);
484 : }
485 39734 : void setDeferredProperties()
486 : {
487 39734 : if (!m_pUIBuilder)
488 79398 : return;
489 70 : m_pUIBuilder->setDeferredProperties();
490 : }
491 :
492 : protected:
493 : VclBuilder *m_pUIBuilder;
494 : };
495 :
496 : /*
497 : * @return true if rValue is "True", "true", "1", etc.
498 : */
499 : bool VCL_DLLPUBLIC toBool(const OString &rValue);
500 :
501 : #endif
502 :
503 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|