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