android: Reuse launcher icon in activities
[LibreOffice.git] / vcl / source / gdi / WidgetDefinitionReader.cxx
blobb635c5e3f9b0c6b12b176d2eb44c4b9481f3b1be
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 */
11 #include <utility>
12 #include <widgetdraw/WidgetDefinitionReader.hxx>
14 #include <sal/config.h>
15 #include <osl/file.hxx>
16 #include <tools/stream.hxx>
17 #include <o3tl/string_view.hxx>
18 #include <unordered_map>
20 namespace vcl
22 namespace
24 bool lcl_fileExists(OUString const& sFilename)
26 osl::File aFile(sFilename);
27 osl::FileBase::RC eRC = aFile.open(osl_File_OpenFlag_Read);
28 return osl::FileBase::E_None == eRC;
31 int lcl_gethex(char aChar)
33 if (aChar >= '0' && aChar <= '9')
34 return aChar - '0';
35 else if (aChar >= 'a' && aChar <= 'f')
36 return aChar - 'a' + 10;
37 else if (aChar >= 'A' && aChar <= 'F')
38 return aChar - 'A' + 10;
39 else
40 return 0;
43 bool readColor(OString const& rString, Color& rColor)
45 if (rString.getLength() != 7)
46 return false;
48 const char aChar(rString[0]);
50 if (aChar != '#')
51 return false;
53 rColor.SetRed((lcl_gethex(rString[1]) << 4) | lcl_gethex(rString[2]));
54 rColor.SetGreen((lcl_gethex(rString[3]) << 4) | lcl_gethex(rString[4]));
55 rColor.SetBlue((lcl_gethex(rString[5]) << 4) | lcl_gethex(rString[6]));
57 return true;
60 bool readSetting(OString const& rInputString, OString& rOutputString)
62 if (!rInputString.isEmpty())
63 rOutputString = rInputString;
64 return true;
67 OString getValueOrAny(OString const& rInputString)
69 if (rInputString.isEmpty())
70 return "any";
71 return rInputString;
74 ControlPart xmlStringToControlPart(std::string_view sPart)
76 if (o3tl::equalsIgnoreAsciiCase(sPart, "NONE"))
77 return ControlPart::NONE;
78 else if (o3tl::equalsIgnoreAsciiCase(sPart, "Entire"))
79 return ControlPart::Entire;
80 else if (o3tl::equalsIgnoreAsciiCase(sPart, "ListboxWindow"))
81 return ControlPart::ListboxWindow;
82 else if (o3tl::equalsIgnoreAsciiCase(sPart, "Button"))
83 return ControlPart::Button;
84 else if (o3tl::equalsIgnoreAsciiCase(sPart, "ButtonUp"))
85 return ControlPart::ButtonUp;
86 else if (o3tl::equalsIgnoreAsciiCase(sPart, "ButtonDown"))
87 return ControlPart::ButtonDown;
88 else if (o3tl::equalsIgnoreAsciiCase(sPart, "ButtonLeft"))
89 return ControlPart::ButtonLeft;
90 else if (o3tl::equalsIgnoreAsciiCase(sPart, "ButtonRight"))
91 return ControlPart::ButtonRight;
92 else if (o3tl::equalsIgnoreAsciiCase(sPart, "AllButtons"))
93 return ControlPart::AllButtons;
94 else if (o3tl::equalsIgnoreAsciiCase(sPart, "SeparatorHorz"))
95 return ControlPart::SeparatorHorz;
96 else if (o3tl::equalsIgnoreAsciiCase(sPart, "SeparatorVert"))
97 return ControlPart::SeparatorVert;
98 else if (o3tl::equalsIgnoreAsciiCase(sPart, "TrackHorzLeft"))
99 return ControlPart::TrackHorzLeft;
100 else if (o3tl::equalsIgnoreAsciiCase(sPart, "TrackVertUpper"))
101 return ControlPart::TrackVertUpper;
102 else if (o3tl::equalsIgnoreAsciiCase(sPart, "TrackHorzRight"))
103 return ControlPart::TrackHorzRight;
104 else if (o3tl::equalsIgnoreAsciiCase(sPart, "TrackVertLower"))
105 return ControlPart::TrackVertLower;
106 else if (o3tl::equalsIgnoreAsciiCase(sPart, "TrackHorzArea"))
107 return ControlPart::TrackHorzArea;
108 else if (o3tl::equalsIgnoreAsciiCase(sPart, "TrackVertArea"))
109 return ControlPart::TrackVertArea;
110 else if (o3tl::equalsIgnoreAsciiCase(sPart, "Arrow"))
111 return ControlPart::Arrow;
112 else if (o3tl::equalsIgnoreAsciiCase(sPart, "ThumbHorz"))
113 return ControlPart::ThumbHorz;
114 else if (o3tl::equalsIgnoreAsciiCase(sPart, "ThumbVert"))
115 return ControlPart::ThumbVert;
116 else if (o3tl::equalsIgnoreAsciiCase(sPart, "MenuItem"))
117 return ControlPart::MenuItem;
118 else if (o3tl::equalsIgnoreAsciiCase(sPart, "MenuItemCheckMark"))
119 return ControlPart::MenuItemCheckMark;
120 else if (o3tl::equalsIgnoreAsciiCase(sPart, "MenuItemRadioMark"))
121 return ControlPart::MenuItemRadioMark;
122 else if (o3tl::equalsIgnoreAsciiCase(sPart, "Separator"))
123 return ControlPart::Separator;
124 else if (o3tl::equalsIgnoreAsciiCase(sPart, "SubmenuArrow"))
125 return ControlPart::SubmenuArrow;
126 else if (o3tl::equalsIgnoreAsciiCase(sPart, "SubEdit"))
127 return ControlPart::SubEdit;
128 else if (o3tl::equalsIgnoreAsciiCase(sPart, "DrawBackgroundHorz"))
129 return ControlPart::DrawBackgroundHorz;
130 else if (o3tl::equalsIgnoreAsciiCase(sPart, "DrawBackgroundVert"))
131 return ControlPart::DrawBackgroundVert;
132 else if (o3tl::equalsIgnoreAsciiCase(sPart, "TabsDrawRtl"))
133 return ControlPart::TabsDrawRtl;
134 else if (o3tl::equalsIgnoreAsciiCase(sPart, "HasBackgroundTexture"))
135 return ControlPart::HasBackgroundTexture;
136 else if (o3tl::equalsIgnoreAsciiCase(sPart, "HasThreeButtons"))
137 return ControlPart::HasThreeButtons;
138 else if (o3tl::equalsIgnoreAsciiCase(sPart, "BackgroundWindow"))
139 return ControlPart::BackgroundWindow;
140 else if (o3tl::equalsIgnoreAsciiCase(sPart, "BackgroundDialog"))
141 return ControlPart::BackgroundDialog;
142 else if (o3tl::equalsIgnoreAsciiCase(sPart, "Border"))
143 return ControlPart::Border;
144 else if (o3tl::equalsIgnoreAsciiCase(sPart, "Focus"))
145 return ControlPart::Focus;
146 return ControlPart::NONE;
149 bool getControlTypeForXmlString(OString const& rString, ControlType& reType)
151 static std::unordered_map<OString, ControlType> aPartMap = {
152 { "pushbutton", ControlType::Pushbutton },
153 { "radiobutton", ControlType::Radiobutton },
154 { "checkbox", ControlType::Checkbox },
155 { "combobox", ControlType::Combobox },
156 { "editbox", ControlType::Editbox },
157 { "listbox", ControlType::Listbox },
158 { "scrollbar", ControlType::Scrollbar },
159 { "spinbox", ControlType::Spinbox },
160 { "slider", ControlType::Slider },
161 { "fixedline", ControlType::Fixedline },
162 { "progress", ControlType::Progress },
163 { "tabitem", ControlType::TabItem },
164 { "tabheader", ControlType::TabHeader },
165 { "tabpane", ControlType::TabPane },
166 { "tabbody", ControlType::TabBody },
167 { "frame", ControlType::Frame },
168 { "windowbackground", ControlType::WindowBackground },
169 { "toolbar", ControlType::Toolbar },
170 { "listnode", ControlType::ListNode },
171 { "listnet", ControlType::ListNet },
172 { "listheader", ControlType::ListHeader },
173 { "menubar", ControlType::Menubar },
174 { "menupopup", ControlType::MenuPopup },
175 { "tooltip", ControlType::Tooltip },
178 auto const& rIterator = aPartMap.find(rString);
179 if (rIterator != aPartMap.end())
181 reType = rIterator->second;
182 return true;
184 return false;
187 } // end anonymous namespace
189 WidgetDefinitionReader::WidgetDefinitionReader(OUString aDefinitionFile, OUString aResourcePath)
190 : m_rDefinitionFile(std::move(aDefinitionFile))
191 , m_rResourcePath(std::move(aResourcePath))
195 void WidgetDefinitionReader::readDrawingDefinition(
196 tools::XmlWalker& rWalker, const std::shared_ptr<WidgetDefinitionState>& rpState)
198 rWalker.children();
199 while (rWalker.isValid())
201 if (rWalker.name() == "rect")
203 Color aStrokeColor;
204 readColor(rWalker.attribute("stroke"), aStrokeColor);
205 Color aFillColor;
206 readColor(rWalker.attribute("fill"), aFillColor);
207 OString sStrokeWidth = rWalker.attribute("stroke-width");
208 sal_Int32 nStrokeWidth = -1;
209 if (!sStrokeWidth.isEmpty())
210 nStrokeWidth = sStrokeWidth.toInt32();
212 sal_Int32 nRx = -1;
213 OString sRx = rWalker.attribute("rx");
214 if (!sRx.isEmpty())
215 nRx = sRx.toInt32();
217 sal_Int32 nRy = -1;
218 OString sRy = rWalker.attribute("ry");
219 if (!sRy.isEmpty())
220 nRy = sRy.toInt32();
222 OString sX1 = rWalker.attribute("x1");
223 float fX1 = sX1.isEmpty() ? 0.0 : sX1.toFloat();
225 OString sY1 = rWalker.attribute("y1");
226 float fY1 = sY1.isEmpty() ? 0.0 : sY1.toFloat();
228 OString sX2 = rWalker.attribute("x2");
229 float fX2 = sX2.isEmpty() ? 1.0 : sX2.toFloat();
231 OString sY2 = rWalker.attribute("y2");
232 float fY2 = sY2.isEmpty() ? 1.0 : sY2.toFloat();
234 rpState->addDrawRectangle(aStrokeColor, nStrokeWidth, aFillColor, fX1, fY1, fX2, fY2,
235 nRx, nRy);
237 else if (rWalker.name() == "line")
239 Color aStrokeColor;
240 readColor(rWalker.attribute("stroke"), aStrokeColor);
242 OString sStrokeWidth = rWalker.attribute("stroke-width");
243 sal_Int32 nStrokeWidth = -1;
244 if (!sStrokeWidth.isEmpty())
245 nStrokeWidth = sStrokeWidth.toInt32();
247 OString sX1 = rWalker.attribute("x1");
248 float fX1 = sX1.isEmpty() ? -1.0 : sX1.toFloat();
250 OString sY1 = rWalker.attribute("y1");
251 float fY1 = sY1.isEmpty() ? -1.0 : sY1.toFloat();
253 OString sX2 = rWalker.attribute("x2");
254 float fX2 = sX2.isEmpty() ? -1.0 : sX2.toFloat();
256 OString sY2 = rWalker.attribute("y2");
257 float fY2 = sY2.isEmpty() ? -1.0 : sY2.toFloat();
259 rpState->addDrawLine(aStrokeColor, nStrokeWidth, fX1, fY1, fX2, fY2);
261 else if (rWalker.name() == "image")
263 OString sSource = rWalker.attribute("source");
264 rpState->addDrawImage(m_rResourcePath
265 + OStringToOUString(sSource, RTL_TEXTENCODING_UTF8));
267 else if (rWalker.name() == "external")
269 OString sSource = rWalker.attribute("source");
270 rpState->addDrawExternal(m_rResourcePath
271 + OStringToOUString(sSource, RTL_TEXTENCODING_UTF8));
273 rWalker.next();
275 rWalker.parent();
278 void WidgetDefinitionReader::readDefinition(tools::XmlWalker& rWalker,
279 WidgetDefinition& rWidgetDefinition, ControlType eType)
281 rWalker.children();
282 while (rWalker.isValid())
284 if (rWalker.name() == "part")
286 OString sPart = rWalker.attribute("value");
287 ControlPart ePart = xmlStringToControlPart(sPart);
289 std::shared_ptr<WidgetDefinitionPart> pPart = std::make_shared<WidgetDefinitionPart>();
291 OString sWidth = rWalker.attribute("width");
292 if (!sWidth.isEmpty())
294 sal_Int32 nWidth = sWidth.isEmpty() ? 0 : sWidth.toInt32();
295 pPart->mnWidth = nWidth;
298 OString sHeight = rWalker.attribute("height");
299 if (!sHeight.isEmpty())
301 sal_Int32 nHeight = sHeight.isEmpty() ? 0 : sHeight.toInt32();
302 pPart->mnHeight = nHeight;
305 OString sMarginHeight = rWalker.attribute("margin-height");
306 if (!sMarginHeight.isEmpty())
308 sal_Int32 nMarginHeight = sMarginHeight.isEmpty() ? 0 : sMarginHeight.toInt32();
309 pPart->mnMarginHeight = nMarginHeight;
312 OString sMarginWidth = rWalker.attribute("margin-width");
313 if (!sMarginWidth.isEmpty())
315 sal_Int32 nMarginWidth = sMarginWidth.isEmpty() ? 0 : sMarginWidth.toInt32();
316 pPart->mnMarginWidth = nMarginWidth;
319 OString sOrientation = rWalker.attribute("orientation");
320 if (!sOrientation.isEmpty())
322 pPart->msOrientation = sOrientation;
325 rWidgetDefinition.maDefinitions.emplace(ControlTypeAndPart(eType, ePart), pPart);
326 readPart(rWalker, pPart);
328 rWalker.next();
330 rWalker.parent();
333 void WidgetDefinitionReader::readPart(tools::XmlWalker& rWalker,
334 std::shared_ptr<WidgetDefinitionPart> rpPart)
336 rWalker.children();
337 while (rWalker.isValid())
339 if (rWalker.name() == "state")
341 OString sEnabled = getValueOrAny(rWalker.attribute("enabled"));
342 OString sFocused = getValueOrAny(rWalker.attribute("focused"));
343 OString sPressed = getValueOrAny(rWalker.attribute("pressed"));
344 OString sRollover = getValueOrAny(rWalker.attribute("rollover"));
345 OString sDefault = getValueOrAny(rWalker.attribute("default"));
346 OString sSelected = getValueOrAny(rWalker.attribute("selected"));
347 OString sButtonValue = getValueOrAny(rWalker.attribute("button-value"));
348 OString sExtra = getValueOrAny(rWalker.attribute("extra"));
350 std::shared_ptr<WidgetDefinitionState> pState = std::make_shared<WidgetDefinitionState>(
351 sEnabled, sFocused, sPressed, sRollover, sDefault, sSelected, sButtonValue, sExtra);
353 rpPart->maStates.push_back(pState);
354 readDrawingDefinition(rWalker, pState);
356 rWalker.next();
358 rWalker.parent();
361 bool WidgetDefinitionReader::read(WidgetDefinition& rWidgetDefinition)
363 if (!lcl_fileExists(m_rDefinitionFile))
364 return false;
366 auto pStyle = std::make_shared<WidgetDefinitionStyle>();
368 std::unordered_map<OString, Color*> aStyleColorMap = {
369 { "faceColor", &pStyle->maFaceColor },
370 { "checkedColor", &pStyle->maCheckedColor },
371 { "lightColor", &pStyle->maLightColor },
372 { "lightBorderColor", &pStyle->maLightBorderColor },
373 { "shadowColor", &pStyle->maShadowColor },
374 { "darkShadowColor", &pStyle->maDarkShadowColor },
375 { "buttonTextColor", &pStyle->maButtonTextColor },
376 { "defaultActionButtonTextColor", &pStyle->maDefaultActionButtonTextColor },
377 { "actionButtonTextColor", &pStyle->maActionButtonTextColor },
378 { "actionButtonRolloverTextColor", &pStyle->maActionButtonRolloverTextColor },
379 { "buttonRolloverTextColor", &pStyle->maButtonRolloverTextColor },
380 { "radioCheckTextColor", &pStyle->maRadioCheckTextColor },
381 { "groupTextColor", &pStyle->maGroupTextColor },
382 { "labelTextColor", &pStyle->maLabelTextColor },
383 { "windowColor", &pStyle->maWindowColor },
384 { "windowTextColor", &pStyle->maWindowTextColor },
385 { "dialogColor", &pStyle->maDialogColor },
386 { "dialogTextColor", &pStyle->maDialogTextColor },
387 { "workspaceColor", &pStyle->maWorkspaceColor },
388 { "monoColor", &pStyle->maMonoColor },
389 { "fieldColor", &pStyle->maFieldColor },
390 { "fieldTextColor", &pStyle->maFieldTextColor },
391 { "fieldRolloverTextColor", &pStyle->maFieldRolloverTextColor },
392 { "activeColor", &pStyle->maActiveColor },
393 { "activeTextColor", &pStyle->maActiveTextColor },
394 { "activeBorderColor", &pStyle->maActiveBorderColor },
395 { "deactiveColor", &pStyle->maDeactiveColor },
396 { "deactiveTextColor", &pStyle->maDeactiveTextColor },
397 { "deactiveBorderColor", &pStyle->maDeactiveBorderColor },
398 { "menuColor", &pStyle->maMenuColor },
399 { "menuBarColor", &pStyle->maMenuBarColor },
400 { "menuBarRolloverColor", &pStyle->maMenuBarRolloverColor },
401 { "menuBorderColor", &pStyle->maMenuBorderColor },
402 { "menuTextColor", &pStyle->maMenuTextColor },
403 { "menuBarTextColor", &pStyle->maMenuBarTextColor },
404 { "menuBarRolloverTextColor", &pStyle->maMenuBarRolloverTextColor },
405 { "menuBarHighlightTextColor", &pStyle->maMenuBarHighlightTextColor },
406 { "menuHighlightColor", &pStyle->maMenuHighlightColor },
407 { "menuHighlightTextColor", &pStyle->maMenuHighlightTextColor },
408 { "highlightColor", &pStyle->maHighlightColor },
409 { "highlightTextColor", &pStyle->maHighlightTextColor },
410 { "activeTabColor", &pStyle->maActiveTabColor },
411 { "inactiveTabColor", &pStyle->maInactiveTabColor },
412 { "tabTextColor", &pStyle->maTabTextColor },
413 { "tabRolloverTextColor", &pStyle->maTabRolloverTextColor },
414 { "tabHighlightTextColor", &pStyle->maTabHighlightTextColor },
415 { "disableColor", &pStyle->maDisableColor },
416 { "helpColor", &pStyle->maHelpColor },
417 { "helpTextColor", &pStyle->maHelpTextColor },
418 { "linkColor", &pStyle->maLinkColor },
419 { "visitedLinkColor", &pStyle->maVisitedLinkColor },
420 { "toolTextColor", &pStyle->maToolTextColor },
423 rWidgetDefinition.mpStyle = pStyle;
425 auto pSettings = std::make_shared<WidgetDefinitionSettings>();
427 std::unordered_map<OString, OString*> aSettingMap = {
428 { "noActiveTabTextRaise", &pSettings->msNoActiveTabTextRaise },
429 { "centeredTabs", &pSettings->msCenteredTabs },
430 { "listBoxEntryMargin", &pSettings->msListBoxEntryMargin },
431 { "defaultFontSize", &pSettings->msDefaultFontSize },
432 { "titleHeight", &pSettings->msTitleHeight },
433 { "floatTitleHeight", &pSettings->msFloatTitleHeight },
434 { "listBoxPreviewDefaultLogicWidth", &pSettings->msListBoxPreviewDefaultLogicWidth },
435 { "listBoxPreviewDefaultLogicHeight", &pSettings->msListBoxPreviewDefaultLogicHeight },
438 rWidgetDefinition.mpSettings = pSettings;
440 SvFileStream aFileStream(m_rDefinitionFile, StreamMode::READ);
442 tools::XmlWalker aWalker;
443 if (!aWalker.open(&aFileStream))
444 return false;
446 if (aWalker.name() != "widgets")
447 return false;
449 aWalker.children();
450 while (aWalker.isValid())
452 ControlType eType;
453 if (aWalker.name() == "style")
455 aWalker.children();
456 while (aWalker.isValid())
458 auto pair = aStyleColorMap.find(aWalker.name());
459 if (pair != aStyleColorMap.end())
461 readColor(aWalker.attribute("value"), *pair->second);
463 aWalker.next();
465 aWalker.parent();
467 if (aWalker.name() == "settings")
469 aWalker.children();
470 while (aWalker.isValid())
472 auto pair = aSettingMap.find(aWalker.name());
473 if (pair != aSettingMap.end())
475 readSetting(aWalker.attribute("value"), *pair->second);
477 aWalker.next();
479 aWalker.parent();
481 else if (getControlTypeForXmlString(aWalker.name(), eType))
483 readDefinition(aWalker, rWidgetDefinition, eType);
485 aWalker.next();
487 aWalker.parent();
489 return true;
492 } // end vcl namespace
494 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */