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 <sal/log.hxx>
15 #include <unotools/resmgr.hxx>
16 #include <tools/fldunit.hxx>
17 #include <vcl/dllapi.h>
18 #include <vcl/window.hxx>
19 #include <vcl/vclptr.hxx>
20 #include <vcl/toolbox.hxx>
21 #include <tools/wintypes.hxx>
22 #include <vcl/EnumContext.hxx>
23
24 #include <memory>
25 #include <map>
26 #include <string_view>
27 #include <vector>
28 #ifdef check
29 # //some problem with MacOSX and a check define
30 # undef check
31 #endif
32
33 class Button;
34 class ComboBox;
35 class FormattedField;
36 class ListBox;
37 class Menu;
38 class MessageDialog;
39 class NumericFormatter;
40 class PopupMenu;
41 class SalInstanceBuilder;
42 class ScreenshotTest;
43 class ScrollBar;
44 class SvTabListBox;
45 class Slider;
46 class DateField;
47 class TimeField;
48 class VclExpander;
49 class VclMultiLineEdit;
50 struct NotebookBarAddonsItem;
51 namespace xmlreader { class XmlReader; }
52 namespace com::sun::star::frame { class XFrame; }
53
54 struct ComboBoxTextItem
55 {
56 OUString m_sItem;
57 OString m_sId;
ComboBoxTextItemComboBoxTextItem58 ComboBoxTextItem(const OUString& rItem, const OString& rId)
59 : m_sItem(rItem)
60 , m_sId(rId)
61 {
62 }
63 };
64
65 /// Creates a hierarchy of vcl::Windows (widgets) from a .ui file for dialogs, sidebar, etc.
66 class VCL_DLLPUBLIC VclBuilder
67 {
68 public:
69 typedef std::map<OString, OUString> stringmap;
70 typedef std::map<OString, std::pair<OString, OString>> accelmap;
71 /// These functions create a new widget with parent pParent and return it in rRet
72 typedef void (*customMakeWidget)(VclPtr<vcl::Window> &rRet, const VclPtr<vcl::Window> &pParent, stringmap &rVec);
73
74 public:
75 VclBuilder(vcl::Window* pParent, const OUString& sUIRootDir, const OUString& sUIFile,
76 const OString& sID = OString(),
77 const css::uno::Reference<css::frame::XFrame>& rFrame
78 = css::uno::Reference<css::frame::XFrame>(),
79 bool bLegacy = true,
80 const NotebookBarAddonsItem* pNotebookBarAddonsItem = nullptr);
81 ~VclBuilder();
82 ///releases references and disposes all children.
83 void disposeBuilder();
84 //sID must exist and be of type T
85 template <typename T> T* get(VclPtr<T>& ret, const OString& sID);
86
87 //sID may not exist, but must be of type T if it does
88 template <typename T = vcl::Window> T* get(const OString& sID);
89
90 vcl::Window* get_widget_root();
91
92 //sID may not exist
93 PopupMenu* get_menu(std::string_view sID);
94
95 //release ownership of pWindow, i.e. don't delete it
96 void drop_ownership(const vcl::Window *pWindow);
97
98 //see m_aDeferredProperties, you need this for toplevel dialogs
99 //which build themselves from their ctor. The properties on
100 //the top level are stored in m_aDeferredProperties and need
101 //to be applied post ctor
102 void setDeferredProperties();
103
104 /// return UI-File name (without '.ui')
getUIFile() const105 const OString& getUIFile() const
106 {
107 return m_sHelpRoot;
108 }
109
110 static SymbolType mapStockToSymbol(std::u16string_view icon_name);
111
112 private:
113 VclBuilder(const VclBuilder&) = delete;
114 VclBuilder& operator=(const VclBuilder&) = delete;
115
116 // owner for ListBox/ComboBox UserData
117 std::vector<std::unique_ptr<OUString>> m_aUserData;
118
119 //If the toplevel window has any properties which need to be set on it,
120 //but the toplevel is the owner of the builder, then its ctor
121 //has not been completed during the building, so properties for it
122 //are collected here and need to be set afterwards, e.g. during
123 //Show or Execute
124 stringmap m_aDeferredProperties;
125
126 std::unique_ptr<NotebookBarAddonsItem> m_pNotebookBarAddonsItem;
127
128 struct PackingData
129 {
130 bool m_bVerticalOrient;
131 sal_Int32 m_nPosition;
PackingDataVclBuilder::PackingData132 PackingData(bool bVerticalOrient = false)
133 : m_bVerticalOrient(bVerticalOrient)
134 , m_nPosition(-1)
135 {
136 }
137 };
138
139 struct WinAndId
140 {
141 OString m_sID;
142 VclPtr<vcl::Window> m_pWindow;
143 PackingData m_aPackingData;
WinAndIdVclBuilder::WinAndId144 WinAndId(const OString &rId, vcl::Window *pWindow, bool bVertical)
145 : m_sID(rId)
146 , m_pWindow(pWindow)
147 , m_aPackingData(bVertical)
148 {
149 }
150 };
151 std::vector<WinAndId> m_aChildren;
152
153 struct MenuAndId
154 {
155 OString m_sID;
156 VclPtr<Menu> m_pMenu;
157 MenuAndId(const OString &rId, Menu *pMenu);
158 };
159 std::vector<MenuAndId> m_aMenus;
160
161 struct StringPair
162 {
163 OString m_sID;
164 OString m_sValue;
StringPairVclBuilder::StringPair165 StringPair(const OString &rId, const OString &rValue)
166 : m_sID(rId)
167 , m_sValue(rValue)
168 {
169 }
170 };
171
172 struct UStringPair
173 {
174 OString m_sID;
175 OUString m_sValue;
UStringPairVclBuilder::UStringPair176 UStringPair(const OString &rId, const OUString &rValue)
177 : m_sID(rId)
178 , m_sValue(rValue)
179 {
180 }
181 };
182
183 typedef StringPair RadioButtonGroupMap;
184
185 struct ButtonImageWidgetMap
186 {
187 OString m_sID;
188 OUString m_sValue;
189 bool m_bRadio;
ButtonImageWidgetMapVclBuilder::ButtonImageWidgetMap190 ButtonImageWidgetMap(const OString &rId, const OUString &rValue, bool bRadio)
191 : m_sID(rId)
192 , m_sValue(rValue)
193 , m_bRadio(bRadio)
194 {
195 }
196 };
197
198 typedef UStringPair TextBufferMap;
199 typedef UStringPair WidgetAdjustmentMap;
200 typedef UStringPair ButtonMenuMap;
201 typedef UStringPair MnemonicWidgetMap;
202
203 struct ComboBoxModelMap
204 {
205 OString m_sID;
206 OUString m_sValue;
207 sal_Int32 m_nActiveId;
ComboBoxModelMapVclBuilder::ComboBoxModelMap208 ComboBoxModelMap(const OString &rId, const OUString &rValue, sal_Int32 nActiveId)
209 : m_sID(rId)
210 , m_sValue(rValue)
211 , m_nActiveId(nActiveId)
212 {
213 }
214 };
215
216 struct ListStore
217 {
218 typedef std::vector<OUString> row;
219 std::vector<row> m_aEntries;
220 };
221
222 const ListStore* get_model_by_name(const OString& sID) const;
223 void mungeModel(ListBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId);
224 void mungeModel(ComboBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId);
225 void mungeModel(SvTabListBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId);
226
227 typedef stringmap TextBuffer;
228 const TextBuffer* get_buffer_by_name(const OString& sID) const;
229
230 static void mungeTextBuffer(VclMultiLineEdit &rTarget, const TextBuffer &rTextBuffer);
231
232 typedef stringmap Adjustment;
233 const Adjustment* get_adjustment_by_name(const OString& sID) const;
234
235 static void mungeAdjustment(NumericFormatter &rTarget, const Adjustment &rAdjustment);
236 static void mungeAdjustment(FormattedField &rTarget, const Adjustment &rAdjustment);
237 static void mungeAdjustment(ScrollBar &rTarget, const Adjustment &rAdjustment);
238 static void mungeAdjustment(Slider &rTarget, const Adjustment &rAdjustment);
239
240 typedef std::map<OString, int> ImageSizeMap;
241
242 struct SizeGroup
243 {
244 std::vector<OString> m_aWidgets;
245 stringmap m_aProperties;
SizeGroupVclBuilder::SizeGroup246 SizeGroup() {}
247 };
248
249
250 struct ParserState
251 {
252 std::locale m_aResLocale;
253
254 std::vector<RadioButtonGroupMap> m_aGroupMaps;
255
256 std::vector<ComboBoxModelMap> m_aModelMaps;
257 std::map<OString, ListStore> m_aModels;
258
259 std::vector<TextBufferMap> m_aTextBufferMaps;
260 std::map<OString, TextBuffer> m_aTextBuffers;
261
262 std::vector<WidgetAdjustmentMap> m_aNumericFormatterAdjustmentMaps;
263 std::vector<WidgetAdjustmentMap> m_aFormattedFormatterAdjustmentMaps;
264 std::vector<WidgetAdjustmentMap> m_aScrollAdjustmentMaps;
265 std::vector<WidgetAdjustmentMap> m_aSliderAdjustmentMaps;
266
267 std::map<OString, Adjustment> m_aAdjustments;
268
269 std::vector<ButtonImageWidgetMap> m_aButtonImageWidgetMaps;
270 ImageSizeMap m_aImageSizeMap;
271
272 std::vector<ButtonMenuMap> m_aButtonMenuMaps;
273
274 std::map<VclPtr<vcl::Window>, VclPtr<vcl::Window>> m_aRedundantParentWidgets;
275
276 std::vector<SizeGroup> m_aSizeGroups;
277
278 std::map<VclPtr<vcl::Window>, stringmap> m_aAtkInfo;
279
280 std::vector<MnemonicWidgetMap> m_aMnemonicWidgetMaps;
281
282 std::vector< VclPtr<VclExpander> > m_aExpanderWidgets;
283
284 std::vector< VclPtr<MessageDialog> > m_aMessageDialogs;
285
286 ToolBoxItemId m_nLastToolbarId;
287
288 sal_uInt16 m_nLastMenuItemId;
289
290 ParserState();
291 };
292
293 OString m_sID;
294 OString m_sHelpRoot;
295 ResHookProc m_pStringReplace;
296 VclPtr<vcl::Window> m_pParent;
297 bool m_bToplevelHasDeferredInit;
298 bool m_bToplevelHasDeferredProperties;
299 bool m_bToplevelParentFound;
300 bool m_bLegacy;
301 std::unique_ptr<ParserState> m_pParserState;
302
303 vcl::Window *get_by_name(std::string_view sID);
304 void delete_by_name(const OString& sID);
305
306 class sortIntoBestTabTraversalOrder
307 {
308 public:
sortIntoBestTabTraversalOrder(VclBuilder * pBuilder)309 sortIntoBestTabTraversalOrder(VclBuilder *pBuilder)
310 : m_pBuilder(pBuilder) {}
311
312 bool operator()(const vcl::Window *pA, const vcl::Window *pB) const;
313
314 private:
315 VclBuilder *m_pBuilder;
316 };
317
318 /// XFrame to be able to extract labels and other properties of the UNO commands (like of .uno:Bold).
319 css::uno::Reference<css::frame::XFrame> m_xFrame;
320
321 private:
322 VclPtr<vcl::Window> insertObject(vcl::Window *pParent,
323 const OString &rClass, const OString &rID,
324 stringmap &rProps, stringmap &rPangoAttributes,
325 stringmap &rAtkProps);
326
327 VclPtr<vcl::Window> makeObject(vcl::Window *pParent,
328 const OString &rClass, const OString &rID,
329 stringmap &rVec);
330
331 void connectNumericFormatterAdjustment(const OString &id, const OUString &rAdjustment);
332 void connectFormattedFormatterAdjustment(const OString &id, const OUString &rAdjustment);
333
334 static int getImageSize(const stringmap &rMap);
335
336 void extractGroup(const OString &id, stringmap &rVec);
337 void extractModel(const OString &id, stringmap &rVec);
338 void extractBuffer(const OString &id, stringmap &rVec);
339 static bool extractAdjustmentToMap(const OString &id, stringmap &rVec, std::vector<WidgetAdjustmentMap>& rAdjustmentMap);
340 void extractButtonImage(const OString &id, stringmap &rMap, bool bRadio);
341 void extractMnemonicWidget(const OString &id, stringmap &rMap);
342
343 // either pParent or pAtkProps must be set, pParent for a child of a widget, pAtkProps for
344 // collecting the atk info for a GtkMenuItem
345 void handleChild(vcl::Window *pParent, stringmap *pAtkProps, xmlreader::XmlReader &reader);
346 VclPtr<vcl::Window> handleObject(vcl::Window *pParent, stringmap *pAtkProps, xmlreader::XmlReader &reader);
347 void handlePacking(vcl::Window *pCurrent, vcl::Window *pParent, xmlreader::XmlReader &reader);
348 static std::vector<vcl::EnumContext::Context> handleStyle(xmlreader::XmlReader &reader, int &nPriority);
349 static OString getStyleClass(xmlreader::XmlReader &reader);
350 void applyPackingProperty(vcl::Window *pCurrent, vcl::Window *pParent, xmlreader::XmlReader &reader);
351 void collectProperty(xmlreader::XmlReader &reader, stringmap &rVec) const;
352 static void collectPangoAttribute(xmlreader::XmlReader &reader, stringmap &rMap);
353 static void collectAtkRelationAttribute(xmlreader::XmlReader &reader, stringmap &rMap);
354 static void collectAtkRoleAttribute(xmlreader::XmlReader &reader, stringmap &rMap);
355 static void collectAccelerator(xmlreader::XmlReader &reader, accelmap &rMap);
356
357 void insertMenuObject(
358 Menu *pParent,
359 PopupMenu *pSubMenu,
360 const OString &rClass,
361 const OString &rID,
362 stringmap &rProps,
363 stringmap &rAtkProps,
364 accelmap &rAccels);
365
366 void handleMenuChild(Menu *pParent, xmlreader::XmlReader &reader);
367 void handleMenuObject(Menu *pParent, xmlreader::XmlReader &reader);
368
369 void handleListStore(xmlreader::XmlReader &reader, const OString &rID, std::string_view rClass);
370 void handleRow(xmlreader::XmlReader &reader, const OString &rID);
371 void handleTabChild(vcl::Window *pParent, xmlreader::XmlReader &reader);
372 VclPtr<Menu> handleMenu(xmlreader::XmlReader &reader, const OString &rID, bool bMenuBar);
373 std::vector<ComboBoxTextItem> handleItems(xmlreader::XmlReader &reader) const;
374
375 void handleSizeGroup(xmlreader::XmlReader &reader);
376
377 stringmap handleAtkObject(xmlreader::XmlReader &reader);
378
379 static void applyAtkProperties(vcl::Window *pWindow, const stringmap& rProperties);
380
381 void handleActionWidget(xmlreader::XmlReader &reader);
382
383 PackingData get_window_packing_data(const vcl::Window *pWindow) const;
384 void set_window_packing_position(const vcl::Window *pWindow, sal_Int32 nPosition);
385
386 static vcl::Window* prepareWidgetOwnScrolling(vcl::Window *pParent, WinBits &rWinStyle);
387 void cleanupWidgetOwnScrolling(vcl::Window *pScrollParent, vcl::Window *pWindow, stringmap &rMap);
388
389 void set_response(std::string_view sID, short nResponse);
390
391 OString get_by_window(const vcl::Window *pWindow) const;
392 void delete_by_window(vcl::Window *pWindow);
393 };
394
395 namespace BuilderUtils
396 {
397 //apply the properties of rProps to pWindow
398 VCL_DLLPUBLIC void set_properties(vcl::Window *pWindow, const VclBuilder::stringmap &rProps);
399
400 //Convert _ gtk markup to ~ vcl markup
401 VCL_DLLPUBLIC OUString convertMnemonicMarkup(const OUString &rIn);
402
403 VCL_DLLPUBLIC OUString extractCustomProperty(VclBuilder::stringmap &rMap);
404
405 VCL_DLLPUBLIC bool extractDropdown(VclBuilder::stringmap &rMap);
406
407 //add a default value of 25 width-chars to a map if width-chars not set
408 VCL_DLLPUBLIC void ensureDefaultWidthChars(VclBuilder::stringmap &rMap);
409
410 //Helpers to retrofit all the existing code to the builder
411 VCL_DLLPUBLIC void reorderWithinParent(std::vector< vcl::Window*>& rChilds, bool bIsButtonBox);
412 VCL_DLLPUBLIC void reorderWithinParent(vcl::Window &rWindow, sal_uInt16 nNewPosition);
413
414 //Convert an accessibility role name to accessibility role number
415 VCL_DLLPUBLIC sal_Int16 getRoleFromName(const OString& roleName);
416 }
417
418 template <typename T>
get(VclPtr<T> & ret,const OString & sID)419 inline T* VclBuilder::get(VclPtr<T>& ret, const OString& sID)
420 {
421 vcl::Window *w = get_by_name(sID);
422 SAL_WARN_IF(!w, "vcl.layout", "widget \"" << sID << "\" not found in .ui");
423 SAL_WARN_IF(!dynamic_cast<T*>(w),
424 "vcl.layout", ".ui widget \"" << sID << "\" needs to correspond to vcl type " << typeid(T).name());
425 assert(w);
426 assert(dynamic_cast<T*>(w));
427 ret = static_cast<T*>(w);
428 return ret.get();
429 }
430
431 //sID may not exist, but must be of type T if it does
432 template <typename T>
get(const OString & sID)433 inline T* VclBuilder::get(const OString& sID)
434 {
435 vcl::Window *w = get_by_name(sID);
436 SAL_WARN_IF(w && !dynamic_cast<T*>(w),
437 "vcl.layout", ".ui widget \"" << sID << "\" needs to correspond to vcl type " << typeid(T).name());
438 assert(!w || dynamic_cast<T*>(w));
439 return static_cast<T*>(w);
440 }
441
442 /*
443 * @return true if rValue is "True", "true", "1", etc.
444 */
445 VCL_DLLPUBLIC bool toBool(std::u16string_view rValue);
446
447 #endif
448
449 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
450