1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "gui/ThemeEval.h"
24
25 #include "graphics/scaler.h"
26
27 #include "common/system.h"
28 #include "common/tokenizer.h"
29
30 namespace GUI {
31
~ThemeEval()32 ThemeEval::~ThemeEval() {
33 reset();
34 }
35
buildBuiltinVars()36 void ThemeEval::buildBuiltinVars() {
37 _builtin["kThumbnailWidth"] = kThumbnailWidth;
38 _builtin["kThumbnailHeight"] = kThumbnailHeight1;
39 _builtin["kThumbnailHeight2"] = kThumbnailHeight2;
40 }
41
reset()42 void ThemeEval::reset() {
43 _vars.clear();
44 _curDialog.clear();
45 _curLayout.clear();
46
47 for (LayoutsMap::iterator i = _layouts.begin(); i != _layouts.end(); ++i)
48 delete i->_value;
49
50 _layouts.clear();
51 }
52
getWidgetData(const Common::String & widget,int16 & x,int16 & y,int16 & w,int16 & h)53 bool ThemeEval::getWidgetData(const Common::String &widget, int16 &x, int16 &y, int16 &w, int16 &h) {
54 bool useRTL;
55
56 return getWidgetData(widget, x, y, w, h, useRTL);
57 }
58
getWidgetData(const Common::String & widget,int16 & x,int16 & y,int16 & w,int16 & h,bool & useRTL)59 bool ThemeEval::getWidgetData(const Common::String &widget, int16 &x, int16 &y, int16 &w, int16 &h, bool &useRTL) {
60 Common::StringTokenizer tokenizer(widget, ".");
61
62 if (widget.hasPrefix("Dialog."))
63 tokenizer.nextToken();
64
65 Common::String dialogName = "Dialog." + tokenizer.nextToken();
66 Common::String widgetName = tokenizer.nextToken();
67
68 if (!_layouts.contains(dialogName))
69 return false;
70
71 return _layouts[dialogName]->getWidgetData(widgetName, x, y, w, h, useRTL);
72 }
73
getWidgetTextHAlign(const Common::String & widget)74 Graphics::TextAlign ThemeEval::getWidgetTextHAlign(const Common::String &widget) {
75 Common::StringTokenizer tokenizer(widget, ".");
76
77 if (widget.hasPrefix("Dialog."))
78 tokenizer.nextToken();
79
80 Common::String dialogName = "Dialog." + tokenizer.nextToken();
81 Common::String widgetName = tokenizer.nextToken();
82
83 if (!_layouts.contains(dialogName))
84 return Graphics::kTextAlignInvalid;
85
86 return _layouts[dialogName]->getWidgetTextHAlign(widgetName);
87 }
88
addWidget(const Common::String & name,const Common::String & type,int w,int h,Graphics::TextAlign align,bool useRTL)89 ThemeEval &ThemeEval::addWidget(const Common::String &name, const Common::String &type, int w, int h, Graphics::TextAlign align, bool useRTL) {
90 int typeW = -1;
91 int typeH = -1;
92 Graphics::TextAlign typeAlign = Graphics::kTextAlignInvalid;
93
94 if (!type.empty()) {
95 typeW = getVar("Globals." + type + ".Width", -1);
96 typeH = getVar("Globals." + type + ".Height", -1);
97 typeAlign = (Graphics::TextAlign)getVar("Globals." + type + ".Align", Graphics::kTextAlignInvalid);
98 }
99
100 ThemeLayoutWidget *widget;
101 if (type == "TabWidget")
102 widget = new ThemeLayoutTabWidget(_curLayout.top(), name,
103 typeW == -1 ? w : typeW,
104 typeH == -1 ? h : typeH,
105 typeAlign == Graphics::kTextAlignInvalid ? align : typeAlign,
106 getVar("Globals.TabWidget.Tab.Height", 0));
107 else
108 widget = new ThemeLayoutWidget(_curLayout.top(), name,
109 typeW == -1 ? w : typeW,
110 typeH == -1 ? h : typeH,
111 typeAlign == Graphics::kTextAlignInvalid ? align : typeAlign,
112 useRTL);
113
114 _curLayout.top()->addChild(widget);
115
116 return *this;
117 }
118
addDialog(const Common::String & name,const Common::String & overlays,int16 width,int16 height,int inset)119 ThemeEval &ThemeEval::addDialog(const Common::String &name, const Common::String &overlays, int16 width, int16 height, int inset) {
120 Common::String var = "Dialog." + name;
121
122 ThemeLayout *layout = new ThemeLayoutMain(name, overlays, width, height, inset);
123
124 if (_layouts.contains(var))
125 delete _layouts[var];
126
127 _layouts[var] = layout;
128
129 layout->setPadding(
130 getVar("Globals.Padding.Left", 0),
131 getVar("Globals.Padding.Right", 0),
132 getVar("Globals.Padding.Top", 0),
133 getVar("Globals.Padding.Bottom", 0)
134 );
135
136 _curLayout.push(layout);
137 _curDialog = name;
138
139 return *this;
140 }
141
addLayout(ThemeLayout::LayoutType type,int spacing,ThemeLayout::ItemAlign itemAlign)142 ThemeEval &ThemeEval::addLayout(ThemeLayout::LayoutType type, int spacing, ThemeLayout::ItemAlign itemAlign) {
143 ThemeLayout *layout = nullptr;
144
145 if (spacing == -1)
146 spacing = getVar("Globals.Layout.Spacing");
147
148 layout = new ThemeLayoutStacked(_curLayout.top(), type, spacing, itemAlign);
149
150 assert(layout);
151
152 layout->setPadding(
153 getVar("Globals.Padding.Left", 0),
154 getVar("Globals.Padding.Right", 0),
155 getVar("Globals.Padding.Top", 0),
156 getVar("Globals.Padding.Bottom", 0)
157 );
158
159 _curLayout.top()->addChild(layout);
160 _curLayout.push(layout);
161
162 return *this;
163 }
164
addSpace(int size)165 ThemeEval &ThemeEval::addSpace(int size) {
166 ThemeLayout *space = new ThemeLayoutSpacing(_curLayout.top(), size);
167 _curLayout.top()->addChild(space);
168
169 return *this;
170 }
171
172 #define SCALEVALUE(val) (val > 0 ? val * _scaleFactor : val)
173
addPadding(int16 l,int16 r,int16 t,int16 b)174 ThemeEval &ThemeEval::addPadding(int16 l, int16 r, int16 t, int16 b) {
175 _curLayout.top()->setPadding(SCALEVALUE(l), SCALEVALUE(r), SCALEVALUE(t), SCALEVALUE(b));
176
177 return *this;
178 }
179
hasDialog(const Common::String & name)180 bool ThemeEval::hasDialog(const Common::String &name) {
181 Common::StringTokenizer tokenizer(name, ".");
182
183 if (name.hasPrefix("Dialog."))
184 tokenizer.nextToken();
185
186 Common::String dialogName = "Dialog." + tokenizer.nextToken();
187 return _layouts.contains(dialogName);
188 }
189
reflowDialogLayout(const Common::String & name,Widget * widgetChain)190 void ThemeEval::reflowDialogLayout(const Common::String &name, Widget *widgetChain) {
191 if (!_layouts.contains("Dialog." + name)) {
192 warning("No layout found for dialog '%s'", name.c_str());
193 return;
194 }
195
196 _layouts["Dialog." + name]->reflowLayout(widgetChain);
197 }
198
addImportedLayout(const Common::String & name)199 ThemeEval &ThemeEval::addImportedLayout(const Common::String &name) {
200 ThemeLayout *importedLayout = _layouts[name];
201 assert(importedLayout);
202
203 _curLayout.top()->importLayout(importedLayout);
204
205 return *this;
206 }
207
208 } // End of namespace GUI
209