Browse code

* Fixes for gcc and clang (while they can compile the code, the DLLs made aren't functional, but oh well).

* [2SF] Used more up-to-date asmjit, despite the ugly looking code.

Naram Qashat authored on 2014/09/17 19:51:45
Showing 1 changed files
1 1
deleted file mode 100644
... ...
@@ -1,677 +0,0 @@
1
-/*
2
- * Windows Dynamic Dialog Builder framework
3
- * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
- * Last modification on 2013-04-23
5
- */
6
-
7
-#ifndef DIALOG_BUILDER_H
8
-#define DIALOG_BUILDER_H
9
-
10
-#include <string>
11
-#include <memory>
12
-#include <vector>
13
-#include <algorithm>
14
-#include <stdexcept>
15
-#include <cstdint>
16
-#include "windowsh_wrapper.h"
17
-#include "UtfConverter.h"
18
-
19
-template<typename T> struct Point
20
-{
21
-	T x, y;
22
-
23
-	Point() : x(), y() { }
24
-	Point(T X, T Y) : x(X), y(Y) { }
25
-};
26
-
27
-template<typename T> struct Size
28
-{
29
-	T width, height;
30
-
31
-	Size() : width(), height() { }
32
-	Size(T Width, T Height) : width(Width), height(Height) { }
33
-};
34
-
35
-template<typename T> struct Rect
36
-{
37
-	Point<T> position;
38
-	Size<T> size;
39
-
40
-	Rect() : position(), size() { }
41
-	Rect(const Point<T> &Position, const Size<T> &Sz) : position(Position), size(Sz) { }
42
-	Rect(T X, T Y, T Width, T Height) : position(X, Y), size(Width, Height) { }
43
-};
44
-
45
-class RelativePosition
46
-{
47
-public:
48
-	Point<short> relativePosition;
49
-	enum BaseType
50
-	{
51
-		TO_PARENT,
52
-		TO_SIBLING
53
-	} type;
54
-	enum PositionType
55
-	{
56
-		FROM_TOP,
57
-		FROM_BOTTOM,
58
-		FROM_LEFT,
59
-		FROM_RIGHT,
60
-		FROM_TOPLEFT,
61
-		FROM_BOTTOMLEFT,
62
-		FROM_TOPRIGHT,
63
-		FROM_BOTTOMRIGHT
64
-	} positionType;
65
-
66
-	RelativePosition(const Point<short> &RelPosition, BaseType Type, PositionType PosType) : relativePosition(RelPosition), type(Type), positionType(PosType) { }
67
-	virtual ~RelativePosition() { }
68
-	virtual RelativePosition *Clone() const = 0;
69
-	Point<short> CalculatePosition(const Rect<short> &child, const Rect<short> &other);
70
-};
71
-
72
-class RelativePositionToParent : public RelativePosition
73
-{
74
-public:
75
-	RelativePositionToParent(const Point<short> &RelPosition, PositionType PosType) : RelativePosition(RelPosition, TO_PARENT, PosType) { }
76
-	RelativePositionToParent *Clone() const { return new RelativePositionToParent(this->relativePosition, this->positionType); }
77
-};
78
-
79
-class RelativePositionToSibling : public RelativePosition
80
-{
81
-public:
82
-	short siblingsBack;
83
-
84
-	RelativePositionToSibling(const Point<short> &RelPosition, PositionType PosType, short SiblingsBack = 1) : RelativePosition(RelPosition, TO_SIBLING, PosType), siblingsBack(SiblingsBack) { }
85
-	RelativePositionToSibling *Clone() const { return new RelativePositionToSibling(this->relativePosition, this->positionType, this->siblingsBack); }
86
-};
87
-
88
-enum DialogControlType
89
-{
90
-	NO_CONTROL,
91
-	GROUP_CONTROL,
92
-	EDITBOX_CONTROL,
93
-	LABEL_CONTROL,
94
-	CHECKBOX_CONTROL,
95
-	BUTTON_CONTROL,
96
-	LISTBOX_CONTROL,
97
-	COMBOBOX_CONTROL
98
-};
99
-
100
-class DialogTemplate;
101
-
102
-class DialogBuilder
103
-{
104
-protected:
105
-	friend class DialogTemplate;
106
-	std::wstring title, fontName;
107
-	uint32_t style, exstyle;
108
-	uint16_t fontSizeInPts;
109
-	Size<short> size;
110
-	bool resetControls;
111
-public:
112
-	DialogBuilder() : title(L""), fontName(L""), style(0), exstyle(0), fontSizeInPts(0), size(), resetControls(false) { }
113
-	DialogBuilder &WithTitle(const std::wstring &Title) { this->title = Title; return *this; }
114
-	DialogBuilder &WithFont(const std::wstring &FontName, uint16_t FontSizeInPts) { this->fontName = FontName; this->fontSizeInPts = FontSizeInPts; return *this; }
115
-	DialogBuilder &WithSize(short Width, short Height) { this->size.width = Width; this->size.height = Height; return *this; }
116
-	DialogBuilder &WithSize(const Size<short> &Sz) { this->size = Sz; return *this; }
117
-	DialogBuilder &ResetControls(bool Reset = true) { this->resetControls = Reset; return *this; }
118
-	DialogBuilder &IsOverlapped() { this->style &= ~(WS_OVERLAPPED | WS_POPUP | WS_CHILD); this->style |= WS_OVERLAPPED; return *this; }
119
-	DialogBuilder &IsPopup() { this->style &= ~(WS_OVERLAPPED | WS_POPUP | WS_CHILD); this->style |= WS_POPUP; return *this; }
120
-	DialogBuilder &IsChild() { this->style &= ~(WS_OVERLAPPED | WS_POPUP | WS_CHILD); this->style |= WS_CHILD; return *this; }
121
-	DialogBuilder &WithBorder(bool Border = true) { if (Border) this->style |= WS_BORDER; else this->style &= ~WS_BORDER; return *this; }
122
-	DialogBuilder &WithDialogFrame(bool DialogFrame = true) { if (DialogFrame) this->style |= WS_DLGFRAME; else this->style &= ~WS_DLGFRAME; return *this; }
123
-	DialogBuilder &WithVerticalScrollbar(bool VerticalScrollbar = true) { if (VerticalScrollbar) this->style |= WS_VSCROLL; else this->style &= ~WS_VSCROLL; return *this; }
124
-	DialogBuilder &WithHorizontalScrollbar(bool HorizontalScrollbar = true) { if (HorizontalScrollbar) this->style |= WS_HSCROLL; else this->style &= ~WS_HSCROLL; return *this; }
125
-	DialogBuilder &WithSystemMenu(bool SystemMenu = true) { if (SystemMenu) this->style |= WS_SYSMENU; else this->style &= ~WS_SYSMENU; return *this; }
126
-	DialogBuilder &WithSizingBorder(bool SizingBorder = true) { if (SizingBorder) this->style |= WS_THICKFRAME; else this->style &= ~WS_THICKFRAME; return *this; }
127
-	DialogBuilder &WithMinimizeBox(bool MinimizeBox = true) { if (MinimizeBox) this->style |= WS_MINIMIZEBOX; else this->style &= ~WS_MINIMIZEBOX; return *this; }
128
-	DialogBuilder &WithMaximizeBox(bool MaximizeBox = true) { if (MaximizeBox) this->style |= WS_MAXIMIZEBOX; else this->style &= ~WS_MAXIMIZEBOX; return *this; }
129
-	DialogBuilder &WithDialogModalFrame(bool DialogModalFrame = true) { if (DialogModalFrame) this->exstyle |= WS_EX_DLGMODALFRAME; else this->exstyle &= ~WS_EX_DLGMODALFRAME; return *this; }
130
-#if WINVER >= 0x0400
131
-	DialogBuilder &WithRaisedEdge(bool RaisedEdge = true) { if (RaisedEdge) this->exstyle |= WS_EX_WINDOWEDGE; else this->exstyle &= ~WS_EX_WINDOWEDGE; return *this; }
132
-	DialogBuilder &WithSunkenEdge(bool SunkenEdge = true) { if (SunkenEdge) this->exstyle |= WS_EX_CLIENTEDGE; else this->exstyle &= ~WS_EX_CLIENTEDGE; return *this; }
133
-	DialogBuilder &WithContextHelp(bool ContextHelp = true) { if (ContextHelp) this->exstyle |= WS_EX_CONTEXTHELP; else this->exstyle &= ~WS_EX_CONTEXTHELP; return *this; }
134
-	DialogBuilder &IsControlWindow(bool ControlWindow = true) { if (ControlWindow) this->style |= DS_CONTROL; else this->style &= ~DS_CONTROL; return *this; }
135
-	DialogBuilder &IsCentered(bool Centered = true) { if (Centered) this->style |= DS_CENTER; else this->style &= ~DS_CENTER; return *this; }
136
-#endif
137
-};
138
-
139
-template<class T> class DialogControlBuilder
140
-{
141
-protected:
142
-	friend class DialogTemplate;
143
-	DialogControlType controlType;
144
-	uint32_t style, exstyle;
145
-	Rect<short> rect;
146
-	short id;
147
-	int index;
148
-	std::unique_ptr<RelativePosition> relativePosition;
149
-
150
-	T &me() { return dynamic_cast<T &>(*this); }
151
-public:
152
-	DialogControlBuilder(DialogControlType Type = NO_CONTROL) : controlType(Type), style(0), exstyle(0), rect(), id(-1), index(-1), relativePosition() { }
153
-	virtual ~DialogControlBuilder() { }
154
-	T &WithPosition(short X, short Y) { this->rect.position.x = X; this->rect.position.y = Y; return this->me(); }
155
-	T &WithPosition(const Point<short> &Position) { this->rect.position = Position; return this->me(); }
156
-	T &WithRelativePositionToParent(RelativePosition::PositionType PosType, const Point<short> &RelativePosition)
157
-	{
158
-		this->relativePosition.reset(new RelativePositionToParent(RelativePosition, PosType));
159
-		return this->me();
160
-	}
161
-	T &WithRelativePositionToSibling(RelativePosition::PositionType PosType, const Point<short> &RelativePosition, short SiblingsBack = 1)
162
-	{
163
-		this->relativePosition.reset(new RelativePositionToSibling(RelativePosition, PosType, SiblingsBack));
164
-		return this->me();
165
-	}
166
-	T &WithSize(short Width, short Height) { this->rect.size.width = Width; this->rect.size.height = Height; return this->me(); }
167
-	T &WithSize(const Size<short> &Sz) { this->rect.size = Sz; return this->me(); }
168
-	T &WithID(short ID) { this->id = ID; return this->me(); }
169
-	T &AtIndex(int Index) { this->index = Index; return this->me(); }
170
-	T &IsDisabled(bool Disabled = true) { if (Disabled) this->style |= WS_DISABLED; else this->style &= ~WS_DISABLED; return this->me(); }
171
-	T &WithBorder(bool ThinBorder = true) { if (ThinBorder) this->style |= WS_BORDER; else this->style &= ~WS_BORDER; return this->me(); }
172
-	T &WithVerticalScrollbar(bool VerticalScrollbar = true) { if (VerticalScrollbar) this->style |= WS_VSCROLL; else this->style &= ~WS_VSCROLL; return this->me(); }
173
-	T &WithHorizontalScrollbar(bool HorizontalScrollbar = true) { if (HorizontalScrollbar) this->style |= WS_HSCROLL; else this->style &= ~WS_HSCROLL; return this->me(); }
174
-	T &WithTabStop(bool TabStop = true) { if (TabStop) this->style |= WS_TABSTOP; else this->style &= ~WS_TABSTOP; return this->me(); }
175
-#if WINVER >= 0x0400
176
-	T &WithRaisedEdge(bool RaisedEdge = true) { if (RaisedEdge) this->exstyle |= WS_EX_WINDOWEDGE; else this->exstyle &= ~WS_EX_WINDOWEDGE; return this->me(); }
177
-	T &WithSunkenEdge(bool SunkenEdge = true) { if (SunkenEdge) this->exstyle |= WS_EX_CLIENTEDGE; else this->exstyle &= ~WS_EX_CLIENTEDGE; return this->me(); }
178
-#endif
179
-};
180
-
181
-class DialogGroupBuilder : public DialogControlBuilder<DialogGroupBuilder>
182
-{
183
-protected:
184
-	friend class DialogTemplate;
185
-	std::wstring groupName;
186
-public:
187
-	DialogGroupBuilder(const std::wstring &newGroupName) : DialogControlBuilder(GROUP_CONTROL), groupName(newGroupName) { }
188
-};
189
-
190
-template<class T> class DialogInGroupBuilder : public DialogControlBuilder<T>
191
-{
192
-protected:
193
-	friend class DialogTemplate;
194
-	std::wstring groupName;
195
-public:
196
-	DialogInGroupBuilder(DialogControlType Type) : DialogControlBuilder<T>(Type), groupName(L"") { }
197
-	T &InGroup(const std::wstring &GroupName) { this->groupName = GroupName; return this->me(); }
198
-};
199
-
200
-class DialogEditBoxBuilder : public DialogInGroupBuilder<DialogEditBoxBuilder>
201
-{
202
-protected:
203
-	friend class DialogTemplate;
204
-public:
205
-	DialogEditBoxBuilder() : DialogInGroupBuilder(EDITBOX_CONTROL) { }
206
-	DialogEditBoxBuilder &IsLeftJustified() { this->style &= ~(ES_LEFT | ES_CENTER | ES_RIGHT); this->style |= ES_LEFT; return this->me(); }
207
-	DialogEditBoxBuilder &IsCenterJustified() { this->style &= ~(ES_LEFT | ES_CENTER | ES_RIGHT); this->style |= ES_CENTER; return this->me(); }
208
-	DialogEditBoxBuilder &IsRightJustified() { this->style &= ~(ES_LEFT | ES_CENTER | ES_RIGHT); this->style |= ES_RIGHT; return this->me(); }
209
-	DialogEditBoxBuilder &IsMultiline(bool Multiline = true) { if (Multiline) this->style |= ES_MULTILINE; else this->style &= ~ES_MULTILINE; return this->me(); }
210
-	DialogEditBoxBuilder &WithAllUppercase(bool AllUppercase = true) { if (AllUppercase) this->style |= ES_UPPERCASE; else this->style &= ~ES_UPPERCASE; return this->me(); }
211
-	DialogEditBoxBuilder &WithAllLowercase(bool AllLowercase = true) { if (AllLowercase) this->style |= ES_LOWERCASE; else this->style &= ~ES_LOWERCASE; return this->me(); }
212
-	DialogEditBoxBuilder &IsPasswordInput(bool PasswordInput = true) { if (PasswordInput) this->style |= ES_PASSWORD; else this->style &= ~ES_PASSWORD; return this->me(); }
213
-	DialogEditBoxBuilder &WithAutoVScroll(bool AutoVScroll = true) { if (AutoVScroll) this->style |= ES_AUTOVSCROLL; else this->style &= ~ES_AUTOVSCROLL; return this->me(); }
214
-	DialogEditBoxBuilder &WithAutoHScroll(bool AutoHScroll = true) { if (AutoHScroll) this->style |= ES_AUTOHSCROLL; else this->style &= ~ES_AUTOHSCROLL; return this->me(); }
215
-	DialogEditBoxBuilder &WithDontHideSelection(bool DontHideSelection = true) { if (DontHideSelection) this->style |= ES_NOHIDESEL; else this->style &= ~ES_NOHIDESEL; return this->me(); }
216
-	DialogEditBoxBuilder &IsReadOnly(bool ReadOnly = true) { if (ReadOnly) this->style |= ES_READONLY; else this->style &= ~ES_READONLY; return this->me(); }
217
-	DialogEditBoxBuilder &WithWantReturn(bool WantReturn = true) { if (WantReturn) this->style |= ES_WANTRETURN; else this->style &= ~ES_WANTRETURN; return this->me(); }
218
-};
219
-
220
-template<class T> class DialogControlWithLabelBuilder : public DialogInGroupBuilder<T>
221
-{
222
-protected:
223
-	friend class DialogTemplate;
224
-	std::wstring label;
225
-public:
226
-	DialogControlWithLabelBuilder(DialogControlType Type, const std::wstring &Label) : DialogInGroupBuilder<T>(Type), label(Label) { }
227
-};
228
-
229
-class DialogLabelBuilder : public DialogControlWithLabelBuilder<DialogLabelBuilder>
230
-{
231
-protected:
232
-	friend class DialogTemplate;
233
-public:
234
-	DialogLabelBuilder(const std::wstring &Label) : DialogControlWithLabelBuilder(LABEL_CONTROL, Label) { }
235
-	DialogLabelBuilder &IsLeftJustified(bool WithWordWrap = false)
236
-	{
237
-		this->style &= ~(SS_LEFT | SS_CENTER | SS_RIGHT | SS_LEFTNOWORDWRAP);
238
-		if (WithWordWrap)
239
-			this->style |= SS_LEFTNOWORDWRAP;
240
-		else
241
-			this->style |= SS_LEFT;
242
-		return this->me();
243
-	}
244
-	DialogLabelBuilder &IsCenterJustified() { this->style &= ~(SS_LEFT | SS_CENTER | SS_RIGHT | SS_LEFTNOWORDWRAP); this->style |= SS_CENTER; return this->me(); }
245
-	DialogLabelBuilder &IsRightJustified() { this->style &= ~(SS_LEFT | SS_CENTER | SS_RIGHT | SS_LEFTNOWORDWRAP); this->style |= SS_RIGHT; return this->me(); }
246
-	DialogLabelBuilder &WithAmpsNotTranslated(bool AmpsNotTranslated = true) { if (AmpsNotTranslated) this->style |= SS_NOPREFIX; else this->style &= ~SS_NOPREFIX; return this->me(); }
247
-#if WINVER >= 0x0400
248
-	DialogLabelBuilder &WithNotify(bool Notify = true) { if (Notify) this->style |= SS_NOTIFY; else this->style &= ~SS_NOTIFY; return this->me(); }
249
-#endif
250
-};
251
-
252
-template<class T> class DialogButtonBaseBuilder : public DialogControlWithLabelBuilder<T>
253
-{
254
-protected:
255
-	friend class DialogTemplate;
256
-public:
257
-	DialogButtonBaseBuilder(DialogControlType Type, const std::wstring &Label) : DialogControlWithLabelBuilder<T>(Type, Label) { }
258
-#if WINVER >= 0x0400
259
-	T &IsLeftJustified(bool LeftJustified = true)
260
-	{
261
-		if (LeftJustified)
262
-		{
263
-			this->style |= BS_LEFT;
264
-			this->style &= ~BS_RIGHT;
265
-		}
266
-		else
267
-			this->style &= ~BS_LEFT;
268
-		return this->me();
269
-	}
270
-	T &IsRightJustified(bool RightJustified = true)
271
-	{
272
-		if (RightJustified)
273
-		{
274
-			this->style |= BS_RIGHT;
275
-			this->style &= ~BS_LEFT;
276
-		}
277
-		else
278
-			this->style &= ~BS_RIGHT;
279
-		return this->me();
280
-	}
281
-	T &IsCenterJustified(bool CenterJustified = true) { if (CenterJustified) this->style |= BS_CENTER; else this->style &= ~BS_CENTER; return this->me(); }
282
-	T &WithVerticalTop(bool VerticalTop = true)
283
-	{
284
-		if (VerticalTop)
285
-		{
286
-			this->style |= BS_TOP;
287
-			this->style &= ~BS_BOTTOM;
288
-		}
289
-		else
290
-			this->style &= ~BS_TOP;
291
-		return this->me();
292
-	}
293
-	T &WithVerticalBottom(bool VerticalBottom = true)
294
-	{
295
-		if (VerticalBottom)
296
-		{
297
-			this->style |= BS_BOTTOM;
298
-			this->style &= ~BS_TOP;
299
-		}
300
-		else
301
-			this->style &= ~BS_BOTTOM;
302
-		return this->me();
303
-	}
304
-	T &WithVerticalCenter(bool VerticalCenter = true) { if (VerticalCenter) this->style |= BS_VCENTER; else this->style &= ~BS_VCENTER; return this->me(); }
305
-	T &IsMultiline(bool Multiline = true) { if (Multiline) this->style |= BS_MULTILINE; else this->style &= ~BS_MULTILINE; return this->me(); }
306
-	T &WithNotify(bool Notify = true) { if (Notify) this->style |= BS_NOTIFY; else this->style &= ~BS_NOTIFY; return this->me(); }
307
-	T &IsFlat(bool Flat = true) { if (Flat) this->style |= BS_FLAT; else this->style &= ~BS_FLAT; return this->me(); }
308
-#endif
309
-};
310
-
311
-class DialogButtonBuilder : public DialogButtonBaseBuilder<DialogButtonBuilder>
312
-{
313
-protected:
314
-	friend class DialogTemplate;
315
-public:
316
-	DialogButtonBuilder(const std::wstring &Label) : DialogButtonBaseBuilder(BUTTON_CONTROL, Label) { }
317
-	DialogButtonBuilder &IsDefault(bool Default = true) { if (Default) this->style |= BS_DEFPUSHBUTTON; else this->style &= ~BS_DEFPUSHBUTTON; return this->me(); }
318
-};
319
-
320
-class DialogCheckBoxBuilder : public DialogButtonBaseBuilder<DialogCheckBoxBuilder>
321
-{
322
-protected:
323
-	friend class DialogTemplate;
324
-public:
325
-	DialogCheckBoxBuilder(const std::wstring &Label) : DialogButtonBaseBuilder(CHECKBOX_CONTROL, Label) { this->style |= BS_AUTOCHECKBOX; }
326
-	DialogCheckBoxBuilder &WithTextOnLeft(bool TextOnLeft = true) { if (TextOnLeft) this->style |= BS_LEFTTEXT; else this->style &= ~BS_LEFTTEXT; return this->me(); }
327
-	DialogCheckBoxBuilder &LikePushButton(bool PushButton = true) { if (PushButton) this->style |= BS_PUSHLIKE; else this->style &= ~BS_PUSHLIKE; return this->me(); }
328
-};
329
-
330
-class DialogListBoxBuilder : public DialogInGroupBuilder<DialogListBoxBuilder>
331
-{
332
-protected:
333
-	friend class DialogTemplate;
334
-public:
335
-	DialogListBoxBuilder() : DialogInGroupBuilder(LISTBOX_CONTROL) { }
336
-	DialogListBoxBuilder &WithNotify(bool Notify = true) { if (Notify) this->style |= LBS_NOTIFY; else this->style &= ~LBS_NOTIFY; return this->me(); }
337
-	DialogListBoxBuilder &WithSort(bool Sort = true) { if (Sort) this->style |= LBS_SORT; else this->style &= ~LBS_SORT; return this->me(); }
338
-	DialogListBoxBuilder &WithMultipleSelect(bool MultipleSelect = true) { if (MultipleSelect) this->style |= LBS_MULTIPLESEL; else this->style &= ~LBS_MULTIPLESEL; return this->me(); }
339
-	DialogListBoxBuilder &WithExactHeight(bool ExactHeight = true) { if (ExactHeight) this->style |= LBS_NOINTEGRALHEIGHT; else this->style &= ~LBS_NOINTEGRALHEIGHT; return this->me(); }
340
-	DialogListBoxBuilder &WithMultipleColumns(bool MultipleColumns = true) { if (MultipleColumns) this->style |= LBS_MULTICOLUMN; else this->style &= ~LBS_MULTICOLUMN; return this->me(); }
341
-	DialogListBoxBuilder &WithExtendedSelect(bool ExtendedSelect = true) { if (ExtendedSelect) this->style |= LBS_EXTENDEDSEL; else this->style &= ~LBS_EXTENDEDSEL; return this->me(); }
342
-	DialogListBoxBuilder &WithDisabledNoScroll(bool DisabledNoScroll = true) { if (DisabledNoScroll) this->style |= LBS_DISABLENOSCROLL; else this->style &= ~LBS_DISABLENOSCROLL; return this->me(); }
343
-#if WINVER >= 0x0400
344
-	DialogListBoxBuilder &WithNoSelect(bool NoSelect = true) { if (NoSelect) this->style |= LBS_NOSEL; else this->style &= ~LBS_NOSEL; return this->me(); }
345
-#endif
346
-};
347
-
348
-class DialogComboBoxBuilder : public DialogInGroupBuilder<DialogComboBoxBuilder>
349
-{
350
-protected:
351
-	friend class DialogTemplate;
352
-public:
353
-	DialogComboBoxBuilder() : DialogInGroupBuilder(COMBOBOX_CONTROL) { }
354
-	DialogComboBoxBuilder &IsSimple() { this->style &= ~(CBS_SIMPLE | CBS_DROPDOWN | CBS_DROPDOWNLIST); this->style |= CBS_SIMPLE; return this->me(); }
355
-	DialogComboBoxBuilder &IsDropDown() { this->style &= ~(CBS_SIMPLE | CBS_DROPDOWN | CBS_DROPDOWNLIST); this->style |= CBS_DROPDOWN; return this->me(); }
356
-	DialogComboBoxBuilder &IsDropDownList() { this->style &= ~(CBS_SIMPLE | CBS_DROPDOWN | CBS_DROPDOWNLIST); this->style |= CBS_DROPDOWNLIST; return this->me(); }
357
-	DialogComboBoxBuilder &WithAutoHScroll(bool AutoHScroll = true) { if (AutoHScroll) this->style |= CBS_AUTOHSCROLL; else this->style &= ~CBS_AUTOHSCROLL; return this->me(); }
358
-	DialogComboBoxBuilder &WithSort(bool Sort = true) { if (Sort) this->style |= CBS_SORT; else this->style &= ~CBS_SORT; return this->me(); }
359
-	DialogComboBoxBuilder &WithExactHeight(bool ExactHeight = true) { if (ExactHeight) this->style |= CBS_NOINTEGRALHEIGHT; else this->style &= ~CBS_NOINTEGRALHEIGHT; return this->me(); }
360
-	DialogComboBoxBuilder &WithDisabledNoScroll(bool DisabledNoScroll = true) { if (DisabledNoScroll) this->style |= CBS_DISABLENOSCROLL; else this->style &= ~CBS_DISABLENOSCROLL; return this->me(); }
361
-#if WINVER >= 0x0400
362
-	DialogComboBoxBuilder &WithAllLowercase(bool AllLowercase = true) { if (AllLowercase) this->style |= CBS_LOWERCASE; else this->style &= ~CBS_LOWERCASE; return this->me(); }
363
-	DialogComboBoxBuilder &WithAllUppercase(bool AllUppercase = true) { if (AllUppercase) this->style |= CBS_UPPERCASE; else this->style &= ~CBS_UPPERCASE; return this->me(); }
364
-#endif
365
-};
366
-
367
-class DialogTemplate
368
-{
369
-	class DialogControl;
370
-
371
-	typedef std::vector<std::unique_ptr<DialogControl>> Controls;
372
-
373
-	class DialogControl
374
-	{
375
-	protected:
376
-		DialogControlType controlType;
377
-		uint32_t style, exstyle;
378
-		Rect<short> rect;
379
-		short id;
380
-		std::unique_ptr<RelativePosition> relativePosition;
381
-
382
-		friend class DialogTemplate;
383
-		DialogControl() : controlType(NO_CONTROL), style(0), exstyle(0), rect(), id(-1), relativePosition() { }
384
-		DialogControl(const DialogControl &control) : controlType(control.controlType), style(control.style), exstyle(control.exstyle), rect(control.rect), id(control.id),
385
-			relativePosition(control.relativePosition ? control.relativePosition->Clone() : nullptr) { }
386
-		DialogControl &operator=(const DialogControl &control)
387
-		{
388
-			this->controlType = control.controlType;
389
-			this->style = control.style;
390
-			this->exstyle = control.exstyle;
391
-			this->rect = control.rect;
392
-			this->id = control.id;
393
-			if (control.relativePosition)
394
-				this->relativePosition.reset(control.relativePosition->Clone());
395
-			else
396
-				this->relativePosition.reset();
397
-
398
-			return *this;
399
-		}
400
-	public:
401
-		virtual ~DialogControl() { }
402
-		template<typename Control, typename Builder> static std::unique_ptr<Control> CreateControl(const DialogControlBuilder<Builder> &builder)
403
-		{
404
-			auto control = std::unique_ptr<Control>(new Control());
405
-
406
-			control->controlType = builder.controlType;
407
-			control->style = builder.style;
408
-			control->exstyle = builder.exstyle;
409
-			control->rect = builder.rect;
410
-			control->id = builder.id;
411
-			if (builder.relativePosition)
412
-				control->relativePosition.reset(builder.relativePosition->Clone());
413
-
414
-			return control;
415
-		}
416
-		virtual uint16_t GetControlCount() const { return 1; }
417
-		virtual short GetControlHeight() const { return this->rect.size.height; }
418
-		virtual std::vector<uint8_t> GenerateControlTemplate() const = 0;
419
-		virtual DialogControl *Clone() const = 0;
420
-	};
421
-
422
-	class DialogGroup : public DialogControl
423
-	{
424
-	protected:
425
-		DialogTemplate::Controls controls;
426
-		std::wstring groupName;
427
-
428
-		friend class DialogTemplate;
429
-		friend class DialogControl;
430
-		DialogGroup() : DialogControl(), controls(), groupName(L"") { }
431
-		DialogGroup(const DialogGroup &control) : DialogControl(control), controls(), groupName(control.groupName)
432
-		{
433
-			std::for_each(control.controls.begin(), control.controls.end(), [&](const std::unique_ptr<DialogControl> &control) { this->controls.push_back(std::unique_ptr<DialogControl>(control->Clone())); });
434
-		}
435
-		DialogGroup &operator=(const DialogGroup &control)
436
-		{
437
-			DialogControl::operator=(control);
438
-
439
-			this->controls.clear();
440
-			std::for_each(control.controls.begin(), control.controls.end(), [&](const std::unique_ptr<DialogControl> &control) { this->controls.push_back(std::unique_ptr<DialogControl>(control->Clone())); });
441
-
442
-			this->groupName = control.groupName;
443
-
444
-			return *this;
445
-		}
446
-	public:
447
-		static std::unique_ptr<DialogGroup> CreateControl(const DialogControlBuilder<DialogGroupBuilder> &builder)
448
-		{
449
-			auto control = DialogControl::CreateControl<DialogGroup>(builder);
450
-
451
-			control->groupName = dynamic_cast<const DialogGroupBuilder &>(builder).groupName;
452
-
453
-			return control;
454
-		}
455
-		void CalculatePositions(bool doRightAndBottom = false);
456
-		void CalculateSize();
457
-		uint16_t GetControlCount() const;
458
-		std::vector<uint8_t> GenerateControlTemplate() const;
459
-		DialogGroup *Clone() const { return new DialogGroup(*this); }
460
-	};
461
-
462
-	class DialogControlWithoutLabel : public DialogControl
463
-	{
464
-	protected:
465
-		uint16_t type;
466
-
467
-		friend class DialogTemplate;
468
-		friend class DialogControl;
469
-		DialogControlWithoutLabel() : DialogControl(), type(0) { }
470
-		DialogControlWithoutLabel(const DialogControlWithoutLabel &control) : DialogControl(control), type(control.type) { }
471
-		DialogControlWithoutLabel &operator=(const DialogControlWithoutLabel &control)
472
-		{
473
-			DialogControl::operator=(control);
474
-
475
-			this->type = control.type;
476
-
477
-			return *this;
478
-		}
479
-	public:
480
-		template<typename Control, typename Builder> static std::unique_ptr<Control> CreateControl(const DialogControlBuilder<Builder> &builder, uint16_t Type)
481
-		{
482
-			auto control = DialogControl::CreateControl<Control>(builder);
483
-
484
-			control->type = Type;
485
-
486
-			return control;
487
-		}
488
-		virtual std::vector<uint8_t> GenerateControlTemplate() const;
489
-		virtual DialogControlWithoutLabel *Clone() const { return new DialogControlWithoutLabel(*this); }
490
-	};
491
-
492
-	class DialogControlWithLabel : public DialogControl
493
-	{
494
-	protected:
495
-		uint16_t type;
496
-		std::wstring label;
497
-
498
-		friend class DialogTemplate;
499
-		friend class DialogControl;
500
-		DialogControlWithLabel() : DialogControl(), type(0), label(L"") { }
501
-		DialogControlWithLabel(const DialogControlWithLabel &control) : DialogControl(control), type(control.type), label(control.label) { }
502
-		DialogControlWithLabel &operator=(const DialogControlWithLabel &control)
503
-		{
504
-			DialogControl::operator=(control);
505
-
506
-			this->type = control.type;
507
-			this->label = control.label;
508
-
509
-			return *this;
510
-		}
511
-	public:
512
-		template<typename Control, typename Builder> static std::unique_ptr<Control> CreateControl(const DialogControlBuilder<Builder> &builder, uint16_t Type)
513
-		{
514
-			auto control = DialogControl::CreateControl<Control>(builder);
515
-
516
-			control->type = Type;
517
-			control->label = dynamic_cast<const DialogControlWithLabelBuilder<Builder> &>(builder).label;
518
-
519
-			return control;
520
-		}
521
-		virtual std::vector<uint8_t> GenerateControlTemplate() const;
522
-		virtual DialogControlWithLabel *Clone() const { return new DialogControlWithLabel(*this); }
523
-	};
524
-
525
-	class DialogEditBox : public DialogControlWithoutLabel
526
-	{
527
-	protected:
528
-		friend class DialogTemplate;
529
-		friend class DialogControl;
530
-		DialogEditBox() : DialogControlWithoutLabel() { }
531
-	public:
532
-		static std::unique_ptr<DialogEditBox> CreateControl(const DialogControlBuilder<DialogEditBoxBuilder> &builder)
533
-		{
534
-			return DialogControlWithoutLabel::CreateControl<DialogEditBox>(builder, 0x0081);
535
-		}
536
-	};
537
-
538
-	class DialogLabel : public DialogControlWithLabel
539
-	{
540
-	protected:
541
-		friend class DialogTemplate;
542
-		friend class DialogControl;
543
-		DialogLabel() : DialogControlWithLabel() { }
544
-	public:
545
-		static std::unique_ptr<DialogLabel> CreateControl(const DialogControlBuilder<DialogLabelBuilder> &builder)
546
-		{
547
-			return DialogControlWithLabel::CreateControl<DialogLabel>(builder, 0x0082);
548
-		}
549
-	};
550
-
551
-	class DialogButton : public DialogControlWithLabel
552
-	{
553
-	protected:
554
-		friend class DialogTemplate;
555
-		friend class DialogControl;
556
-		DialogButton() : DialogControlWithLabel() { }
557
-	public:
558
-		template<typename Builder> static std::unique_ptr<DialogButton> CreateControl(const DialogControlBuilder<Builder> &builder)
559
-		{
560
-			return DialogControlWithLabel::CreateControl<DialogButton>(builder, 0x0080);
561
-		}
562
-	};
563
-
564
-	class DialogListBox : public DialogControlWithoutLabel
565
-	{
566
-	protected:
567
-		friend class DialogTemplate;
568
-		friend class DialogControl;
569
-		DialogListBox() : DialogControlWithoutLabel() { }
570
-	public:
571
-		static std::unique_ptr<DialogListBox> CreateControl(const DialogControlBuilder<DialogListBoxBuilder> &builder)
572
-		{
573
-			return DialogControlWithoutLabel::CreateControl<DialogListBox>(builder, 0x0083);
574
-		}
575
-	};
576
-
577
-	class DialogComboBox : public DialogControlWithoutLabel
578
-	{
579
-	protected:
580
-		friend class DialogTemplate;
581
-		friend class DialogControl;
582
-		DialogComboBox() : DialogControlWithoutLabel() { }
583
-	public:
584
-		static std::unique_ptr<DialogComboBox> CreateControl(const DialogControlBuilder<DialogComboBoxBuilder> &builder)
585
-		{
586
-			return DialogControlWithoutLabel::CreateControl<DialogComboBox>(builder, 0x0085);
587
-		}
588
-		short GetControlHeight() const { return (this->style & CBS_SIMPLE && !(this->style & CBS_DROPDOWNLIST)) ? this->rect.size.height : 14; }
589
-	};
590
-
591
-	std::wstring title;
592
-	uint32_t style, exstyle;
593
-	std::wstring fontName;
594
-	uint16_t fontSizeInPts;
595
-	Size<short> size;
596
-	DialogTemplate::Controls controls;
597
-	std::vector<uint8_t> templateData;
598
-
599
-	template<typename Builder> void AddControlToGroup(std::unique_ptr<DialogControl> &&control, const DialogControlBuilder<Builder> &builder)
600
-	{
601
-		const auto &groupBuilder = dynamic_cast<const DialogInGroupBuilder<Builder> &>(builder);
602
-		if (groupBuilder.groupName.empty())
603
-		{
604
-			if (builder.index == -1)
605
-				this->controls.push_back(std::move(control));
606
-			else
607
-				this->controls.insert(this->controls.begin() + builder.index, std::move(control));
608
-		}
609
-		else
610
-		{
611
-			for (auto curr = this->controls.begin(), end = this->controls.end(); curr != end; ++curr)
612
-			{
613
-				if ((*curr)->controlType != GROUP_CONTROL)
614
-					continue;
615
-				DialogGroup *group = dynamic_cast<DialogGroup *>(curr->get());
616
-				if (group->groupName == groupBuilder.groupName)
617
-				{
618
-					if (builder.index == -1)
619
-						group->controls.push_back(std::move(control));
620
-					else
621
-						group->controls.insert(group->controls.begin() + builder.index, std::move(control));
622
-					return;
623
-				}
624
-			}
625
-			throw std::runtime_error("Group " + UtfConverter::ToUtf8(groupBuilder.groupName) + " was not found.");
626
-		}
627
-	}
628
-	uint16_t GetTotalControlCount() const;
629
-	bool CalculateControlPosition(short index, bool doRightAndBottom = false);
630
-	void CalculateSize();
631
-public:
632
-	DialogTemplate() : title(L""), style(0), exstyle(0), fontName(L""), fontSizeInPts(0), size(), controls(), templateData() { }
633
-	DialogTemplate(const DialogBuilder &builder) : title(builder.title), style(builder.style), exstyle(builder.exstyle), fontName(builder.fontName), fontSizeInPts(builder.fontSizeInPts),
634
-		size(builder.size), controls(), templateData() { }
635
-	DialogTemplate(const DialogTemplate &dlg) : title(dlg.title), style(dlg.style), exstyle(dlg.style), fontName(dlg.fontName), fontSizeInPts(dlg.fontSizeInPts), size(dlg.size),
636
-		controls(), templateData()
637
-	{
638
-		std::for_each(dlg.controls.begin(), dlg.controls.end(), [&](const std::unique_ptr<DialogControl> &control) { this->controls.push_back(std::unique_ptr<DialogControl>(control->Clone())); });
639
-	}
640
-	DialogTemplate &operator=(const DialogBuilder &builder)
641
-	{
642
-		this->title = builder.title;
643
-		this->style = builder.style;
644
-		this->exstyle = builder.exstyle;
645
-		this->fontName = builder.fontName;
646
-		this->fontSizeInPts = builder.fontSizeInPts;
647
-		this->size = builder.size;
648
-		if (builder.resetControls)
649
-			this->controls.clear();
650
-
651
-		return *this;
652
-	}
653
-	DialogTemplate &operator=(const DialogTemplate &dlg)
654
-	{
655
-		this->title = dlg.title;
656
-		this->style = dlg.style;
657
-		this->exstyle = dlg.exstyle;
658
-		this->fontName = dlg.fontName;
659
-		this->fontSizeInPts = dlg.fontSizeInPts;
660
-		this->size = dlg.size;
661
-		this->controls.clear();
662
-		std::for_each(dlg.controls.begin(), dlg.controls.end(), [&](const std::unique_ptr<DialogControl> &control) { this->controls.push_back(std::unique_ptr<DialogControl>(control->Clone())); });
663
-
664
-		return *this;
665
-	}
666
-	void AddGroupControl(const DialogControlBuilder<DialogGroupBuilder> &builder);
667
-	void AddEditBoxControl(const DialogControlBuilder<DialogEditBoxBuilder> &builder);
668
-	void AddLabelControl(const DialogControlBuilder<DialogLabelBuilder> &builder);
669
-	void AddCheckBoxControl(const DialogControlBuilder<DialogCheckBoxBuilder> &builder);
670
-	void AddButtonControl(const DialogControlBuilder<DialogButtonBuilder> &builder);
671
-	void AddListBoxControl(const DialogControlBuilder<DialogListBoxBuilder> &builder);
672
-	void AddComboBoxControl(const DialogControlBuilder<DialogComboBoxBuilder> &builder);
673
-	void AutoSize();
674
-	const DLGTEMPLATE *GenerateTemplate();
675
-};
676
-
677
-#endif
Browse code

Added Lanczos interpolation to the NCSF plugin, and cleaned up a bit of the other code, as well as removing pstdint.h since it's no longer needed.

Naram Qashat authored on 2013/04/23 20:29:21
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,677 @@
1
+/*
2
+ * Windows Dynamic Dialog Builder framework
3
+ * By Naram Qashat (CyberBotX) [cyberbotx@cyberbotx.com]
4
+ * Last modification on 2013-04-23
5
+ */
6
+
7
+#ifndef DIALOG_BUILDER_H
8
+#define DIALOG_BUILDER_H
9
+
10
+#include <string>
11
+#include <memory>
12
+#include <vector>
13
+#include <algorithm>
14
+#include <stdexcept>
15
+#include <cstdint>
16
+#include "windowsh_wrapper.h"
17
+#include "UtfConverter.h"
18
+
19
+template<typename T> struct Point
20
+{
21
+	T x, y;
22
+
23
+	Point() : x(), y() { }
24
+	Point(T X, T Y) : x(X), y(Y) { }
25
+};
26
+
27
+template<typename T> struct Size
28
+{
29
+	T width, height;
30
+
31
+	Size() : width(), height() { }
32
+	Size(T Width, T Height) : width(Width), height(Height) { }
33
+};
34
+
35
+template<typename T> struct Rect
36
+{
37
+	Point<T> position;
38
+	Size<T> size;
39
+
40
+	Rect() : position(), size() { }
41
+	Rect(const Point<T> &Position, const Size<T> &Sz) : position(Position), size(Sz) { }
42
+	Rect(T X, T Y, T Width, T Height) : position(X, Y), size(Width, Height) { }
43
+};
44
+
45
+class RelativePosition
46
+{
47
+public:
48
+	Point<short> relativePosition;
49
+	enum BaseType
50
+	{
51
+		TO_PARENT,
52
+		TO_SIBLING
53
+	} type;
54
+	enum PositionType
55
+	{
56
+		FROM_TOP,
57
+		FROM_BOTTOM,
58
+		FROM_LEFT,
59
+		FROM_RIGHT,
60
+		FROM_TOPLEFT,
61
+		FROM_BOTTOMLEFT,
62
+		FROM_TOPRIGHT,
63
+		FROM_BOTTOMRIGHT
64
+	} positionType;
65
+
66
+	RelativePosition(const Point<short> &RelPosition, BaseType Type, PositionType PosType) : relativePosition(RelPosition), type(Type), positionType(PosType) { }
67
+	virtual ~RelativePosition() { }
68
+	virtual RelativePosition *Clone() const = 0;
69
+	Point<short> CalculatePosition(const Rect<short> &child, const Rect<short> &other);
70
+};
71
+
72
+class RelativePositionToParent : public RelativePosition
73
+{
74
+public:
75
+	RelativePositionToParent(const Point<short> &RelPosition, PositionType PosType) : RelativePosition(RelPosition, TO_PARENT, PosType) { }
76
+	RelativePositionToParent *Clone() const { return new RelativePositionToParent(this->relativePosition, this->positionType); }
77
+};
78
+
79
+class RelativePositionToSibling : public RelativePosition
80
+{
81
+public:
82
+	short siblingsBack;
83
+
84
+	RelativePositionToSibling(const Point<short> &RelPosition, PositionType PosType, short SiblingsBack = 1) : RelativePosition(RelPosition, TO_SIBLING, PosType), siblingsBack(SiblingsBack) { }
85
+	RelativePositionToSibling *Clone() const { return new RelativePositionToSibling(this->relativePosition, this->positionType, this->siblingsBack); }
86
+};
87
+
88
+enum DialogControlType
89
+{
90
+	NO_CONTROL,
91
+	GROUP_CONTROL,
92
+	EDITBOX_CONTROL,
93
+	LABEL_CONTROL,
94
+	CHECKBOX_CONTROL,
95
+	BUTTON_CONTROL,
96
+	LISTBOX_CONTROL,
97
+	COMBOBOX_CONTROL
98
+};
99
+
100
+class DialogTemplate;
101
+
102
+class DialogBuilder
103
+{
104
+protected:
105
+	friend class DialogTemplate;
106
+	std::wstring title, fontName;
107
+	uint32_t style, exstyle;
108
+	uint16_t fontSizeInPts;
109
+	Size<short> size;
110
+	bool resetControls;
111
+public:
112
+	DialogBuilder() : title(L""), fontName(L""), style(0), exstyle(0), fontSizeInPts(0), size(), resetControls(false) { }
113
+	DialogBuilder &WithTitle(const std::wstring &Title) { this->title = Title; return *this; }
114
+	DialogBuilder &WithFont(const std::wstring &FontName, uint16_t FontSizeInPts) { this->fontName = FontName; this->fontSizeInPts = FontSizeInPts; return *this; }
115
+	DialogBuilder &WithSize(short Width, short Height) { this->size.width = Width; this->size.height = Height; return *this; }
116
+	DialogBuilder &WithSize(const Size<short> &Sz) { this->size = Sz; return *this; }
117
+	DialogBuilder &ResetControls(bool Reset = true) { this->resetControls = Reset; return *this; }
118
+	DialogBuilder &IsOverlapped() { this->style &= ~(WS_OVERLAPPED | WS_POPUP | WS_CHILD); this->style |= WS_OVERLAPPED; return *this; }
119
+	DialogBuilder &IsPopup() { this->style &= ~(WS_OVERLAPPED | WS_POPUP | WS_CHILD); this->style |= WS_POPUP; return *this; }
120
+	DialogBuilder &IsChild() { this->style &= ~(WS_OVERLAPPED | WS_POPUP | WS_CHILD); this->style |= WS_CHILD; return *this; }
121
+	DialogBuilder &WithBorder(bool Border = true) { if (Border) this->style |= WS_BORDER; else this->style &= ~WS_BORDER; return *this; }
122
+	DialogBuilder &WithDialogFrame(bool DialogFrame = true) { if (DialogFrame) this->style |= WS_DLGFRAME; else this->style &= ~WS_DLGFRAME; return *this; }
123
+	DialogBuilder &WithVerticalScrollbar(bool VerticalScrollbar = true) { if (VerticalScrollbar) this->style |= WS_VSCROLL; else this->style &= ~WS_VSCROLL; return *this; }
124
+	DialogBuilder &WithHorizontalScrollbar(bool HorizontalScrollbar = true) { if (HorizontalScrollbar) this->style |= WS_HSCROLL; else this->style &= ~WS_HSCROLL; return *this; }
125
+	DialogBuilder &WithSystemMenu(bool SystemMenu = true) { if (SystemMenu) this->style |= WS_SYSMENU; else this->style &= ~WS_SYSMENU; return *this; }
126
+	DialogBuilder &WithSizingBorder(bool SizingBorder = true) { if (SizingBorder) this->style |= WS_THICKFRAME; else this->style &= ~WS_THICKFRAME; return *this; }
127
+	DialogBuilder &WithMinimizeBox(bool MinimizeBox = true) { if (MinimizeBox) this->style |= WS_MINIMIZEBOX; else this->style &= ~WS_MINIMIZEBOX; return *this; }
128
+	DialogBuilder &WithMaximizeBox(bool MaximizeBox = true) { if (MaximizeBox) this->style |= WS_MAXIMIZEBOX; else this->style &= ~WS_MAXIMIZEBOX; return *this; }
129
+	DialogBuilder &WithDialogModalFrame(bool DialogModalFrame = true) { if (DialogModalFrame) this->exstyle |= WS_EX_DLGMODALFRAME; else this->exstyle &= ~WS_EX_DLGMODALFRAME; return *this; }
130
+#if WINVER >= 0x0400
131
+	DialogBuilder &WithRaisedEdge(bool RaisedEdge = true) { if (RaisedEdge) this->exstyle |= WS_EX_WINDOWEDGE; else this->exstyle &= ~WS_EX_WINDOWEDGE; return *this; }
132
+	DialogBuilder &WithSunkenEdge(bool SunkenEdge = true) { if (SunkenEdge) this->exstyle |= WS_EX_CLIENTEDGE; else this->exstyle &= ~WS_EX_CLIENTEDGE; return *this; }
133
+	DialogBuilder &WithContextHelp(bool ContextHelp = true) { if (ContextHelp) this->exstyle |= WS_EX_CONTEXTHELP; else this->exstyle &= ~WS_EX_CONTEXTHELP; return *this; }
134
+	DialogBuilder &IsControlWindow(bool ControlWindow = true) { if (ControlWindow) this->style |= DS_CONTROL; else this->style &= ~DS_CONTROL; return *this; }
135
+	DialogBuilder &IsCentered(bool Centered = true) { if (Centered) this->style |= DS_CENTER; else this->style &= ~DS_CENTER; return *this; }
136
+#endif
137
+};
138
+
139
+template<class T> class DialogControlBuilder
140
+{
141
+protected:
142
+	friend class DialogTemplate;
143
+	DialogControlType controlType;
144
+	uint32_t style, exstyle;
145
+	Rect<short> rect;
146
+	short id;
147
+	int index;
148
+	std::unique_ptr<RelativePosition> relativePosition;
149
+
150
+	T &me() { return dynamic_cast<T &>(*this); }
151
+public:
152
+	DialogControlBuilder(DialogControlType Type = NO_CONTROL) : controlType(Type), style(0), exstyle(0), rect(), id(-1), index(-1), relativePosition() { }
153
+	virtual ~DialogControlBuilder() { }
154
+	T &WithPosition(short X, short Y) { this->rect.position.x = X; this->rect.position.y = Y; return this->me(); }
155
+	T &WithPosition(const Point<short> &Position) { this->rect.position = Position; return this->me(); }
156
+	T &WithRelativePositionToParent(RelativePosition::PositionType PosType, const Point<short> &RelativePosition)
157
+	{
158
+		this->relativePosition.reset(new RelativePositionToParent(RelativePosition, PosType));
159
+		return this->me();
160
+	}
161
+	T &WithRelativePositionToSibling(RelativePosition::PositionType PosType, const Point<short> &RelativePosition, short SiblingsBack = 1)
162
+	{
163
+		this->relativePosition.reset(new RelativePositionToSibling(RelativePosition, PosType, SiblingsBack));
164
+		return this->me();
165
+	}
166
+	T &WithSize(short Width, short Height) { this->rect.size.width = Width; this->rect.size.height = Height; return this->me(); }
167
+	T &WithSize(const Size<short> &Sz) { this->rect.size = Sz; return this->me(); }
168
+	T &WithID(short ID) { this->id = ID; return this->me(); }
169
+	T &AtIndex(int Index) { this->index = Index; return this->me(); }
170
+	T &IsDisabled(bool Disabled = true) { if (Disabled) this->style |= WS_DISABLED; else this->style &= ~WS_DISABLED; return this->me(); }
171
+	T &WithBorder(bool ThinBorder = true) { if (ThinBorder) this->style |= WS_BORDER; else this->style &= ~WS_BORDER; return this->me(); }
172
+	T &WithVerticalScrollbar(bool VerticalScrollbar = true) { if (VerticalScrollbar) this->style |= WS_VSCROLL; else this->style &= ~WS_VSCROLL; return this->me(); }
173
+	T &WithHorizontalScrollbar(bool HorizontalScrollbar = true) { if (HorizontalScrollbar) this->style |= WS_HSCROLL; else this->style &= ~WS_HSCROLL; return this->me(); }
174
+	T &WithTabStop(bool TabStop = true) { if (TabStop) this->style |= WS_TABSTOP; else this->style &= ~WS_TABSTOP; return this->me(); }
175
+#if WINVER >= 0x0400
176
+	T &WithRaisedEdge(bool RaisedEdge = true) { if (RaisedEdge) this->exstyle |= WS_EX_WINDOWEDGE; else this->exstyle &= ~WS_EX_WINDOWEDGE; return this->me(); }
177
+	T &WithSunkenEdge(bool SunkenEdge = true) { if (SunkenEdge) this->exstyle |= WS_EX_CLIENTEDGE; else this->exstyle &= ~WS_EX_CLIENTEDGE; return this->me(); }
178
+#endif
179
+};
180
+
181
+class DialogGroupBuilder : public DialogControlBuilder<DialogGroupBuilder>
182
+{
183
+protected:
184
+	friend class DialogTemplate;
185
+	std::wstring groupName;
186
+public:
187
+	DialogGroupBuilder(const std::wstring &newGroupName) : DialogControlBuilder(GROUP_CONTROL), groupName(newGroupName) { }
188
+};
189
+
190
+template<class T> class DialogInGroupBuilder : public DialogControlBuilder<T>
191
+{
192
+protected:
193
+	friend class DialogTemplate;
194
+	std::wstring groupName;
195
+public:
196
+	DialogInGroupBuilder(DialogControlType Type) : DialogControlBuilder<T>(Type), groupName(L"") { }
197
+	T &InGroup(const std::wstring &GroupName) { this->groupName = GroupName; return this->me(); }
198
+};
199
+
200
+class DialogEditBoxBuilder : public DialogInGroupBuilder<DialogEditBoxBuilder>
201
+{
202
+protected:
203
+	friend class DialogTemplate;
204
+public:
205
+	DialogEditBoxBuilder() : DialogInGroupBuilder(EDITBOX_CONTROL) { }
206
+	DialogEditBoxBuilder &IsLeftJustified() { this->style &= ~(ES_LEFT | ES_CENTER | ES_RIGHT); this->style |= ES_LEFT; return this->me(); }
207
+	DialogEditBoxBuilder &IsCenterJustified() { this->style &= ~(ES_LEFT | ES_CENTER | ES_RIGHT); this->style |= ES_CENTER; return this->me(); }
208
+	DialogEditBoxBuilder &IsRightJustified() { this->style &= ~(ES_LEFT | ES_CENTER | ES_RIGHT); this->style |= ES_RIGHT; return this->me(); }
209
+	DialogEditBoxBuilder &IsMultiline(bool Multiline = true) { if (Multiline) this->style |= ES_MULTILINE; else this->style &= ~ES_MULTILINE; return this->me(); }
210
+	DialogEditBoxBuilder &WithAllUppercase(bool AllUppercase = true) { if (AllUppercase) this->style |= ES_UPPERCASE; else this->style &= ~ES_UPPERCASE; return this->me(); }
211
+	DialogEditBoxBuilder &WithAllLowercase(bool AllLowercase = true) { if (AllLowercase) this->style |= ES_LOWERCASE; else this->style &= ~ES_LOWERCASE; return this->me(); }
212
+	DialogEditBoxBuilder &IsPasswordInput(bool PasswordInput = true) { if (PasswordInput) this->style |= ES_PASSWORD; else this->style &= ~ES_PASSWORD; return this->me(); }
213
+	DialogEditBoxBuilder &WithAutoVScroll(bool AutoVScroll = true) { if (AutoVScroll) this->style |= ES_AUTOVSCROLL; else this->style &= ~ES_AUTOVSCROLL; return this->me(); }
214
+	DialogEditBoxBuilder &WithAutoHScroll(bool AutoHScroll = true) { if (AutoHScroll) this->style |= ES_AUTOHSCROLL; else this->style &= ~ES_AUTOHSCROLL; return this->me(); }
215
+	DialogEditBoxBuilder &WithDontHideSelection(bool DontHideSelection = true) { if (DontHideSelection) this->style |= ES_NOHIDESEL; else this->style &= ~ES_NOHIDESEL; return this->me(); }
216
+	DialogEditBoxBuilder &IsReadOnly(bool ReadOnly = true) { if (ReadOnly) this->style |= ES_READONLY; else this->style &= ~ES_READONLY; return this->me(); }
217
+	DialogEditBoxBuilder &WithWantReturn(bool WantReturn = true) { if (WantReturn) this->style |= ES_WANTRETURN; else this->style &= ~ES_WANTRETURN; return this->me(); }
218
+};
219
+
220
+template<class T> class DialogControlWithLabelBuilder : public DialogInGroupBuilder<T>
221
+{
222
+protected:
223
+	friend class DialogTemplate;
224
+	std::wstring label;
225
+public:
226
+	DialogControlWithLabelBuilder(DialogControlType Type, const std::wstring &Label) : DialogInGroupBuilder<T>(Type), label(Label) { }
227
+};
228
+
229
+class DialogLabelBuilder : public DialogControlWithLabelBuilder<DialogLabelBuilder>
230
+{
231
+protected:
232
+	friend class DialogTemplate;
233
+public:
234
+	DialogLabelBuilder(const std::wstring &Label) : DialogControlWithLabelBuilder(LABEL_CONTROL, Label) { }
235
+	DialogLabelBuilder &IsLeftJustified(bool WithWordWrap = false)
236
+	{
237
+		this->style &= ~(SS_LEFT | SS_CENTER | SS_RIGHT | SS_LEFTNOWORDWRAP);
238
+		if (WithWordWrap)
239
+			this->style |= SS_LEFTNOWORDWRAP;
240
+		else
241
+			this->style |= SS_LEFT;
242
+		return this->me();
243
+	}
244
+	DialogLabelBuilder &IsCenterJustified() { this->style &= ~(SS_LEFT | SS_CENTER | SS_RIGHT | SS_LEFTNOWORDWRAP); this->style |= SS_CENTER; return this->me(); }
245
+	DialogLabelBuilder &IsRightJustified() { this->style &= ~(SS_LEFT | SS_CENTER | SS_RIGHT | SS_LEFTNOWORDWRAP); this->style |= SS_RIGHT; return this->me(); }
246
+	DialogLabelBuilder &WithAmpsNotTranslated(bool AmpsNotTranslated = true) { if (AmpsNotTranslated) this->style |= SS_NOPREFIX; else this->style &= ~SS_NOPREFIX; return this->me(); }
247
+#if WINVER >= 0x0400
248
+	DialogLabelBuilder &WithNotify(bool Notify = true) { if (Notify) this->style |= SS_NOTIFY; else this->style &= ~SS_NOTIFY; return this->me(); }
249
+#endif
250
+};
251
+
252
+template<class T> class DialogButtonBaseBuilder : public DialogControlWithLabelBuilder<T>
253
+{
254
+protected:
255
+	friend class DialogTemplate;
256
+public:
257
+	DialogButtonBaseBuilder(DialogControlType Type, const std::wstring &Label) : DialogControlWithLabelBuilder<T>(Type, Label) { }
258
+#if WINVER >= 0x0400
259
+	T &IsLeftJustified(bool LeftJustified = true)
260
+	{
261
+		if (LeftJustified)
262
+		{
263
+			this->style |= BS_LEFT;
264
+			this->style &= ~BS_RIGHT;
265
+		}
266
+		else
267
+			this->style &= ~BS_LEFT;
268
+		return this->me();
269
+	}
270
+	T &IsRightJustified(bool RightJustified = true)
271
+	{
272
+		if (RightJustified)
273
+		{
274
+			this->style |= BS_RIGHT;
275
+			this->style &= ~BS_LEFT;
276
+		}
277
+		else
278
+			this->style &= ~BS_RIGHT;
279
+		return this->me();
280
+	}
281
+	T &IsCenterJustified(bool CenterJustified = true) { if (CenterJustified) this->style |= BS_CENTER; else this->style &= ~BS_CENTER; return this->me(); }
282
+	T &WithVerticalTop(bool VerticalTop = true)
283
+	{
284
+		if (VerticalTop)
285
+		{
286
+			this->style |= BS_TOP;
287
+			this->style &= ~BS_BOTTOM;
288
+		}
289
+		else
290
+			this->style &= ~BS_TOP;
291
+		return this->me();
292
+	}
293
+	T &WithVerticalBottom(bool VerticalBottom = true)
294
+	{
295
+		if (VerticalBottom)
296
+		{
297
+			this->style |= BS_BOTTOM;
298
+			this->style &= ~BS_TOP;
299
+		}
300
+		else
301
+			this->style &= ~BS_BOTTOM;
302
+		return this->me();
303
+	}
304
+	T &WithVerticalCenter(bool VerticalCenter = true) { if (VerticalCenter) this->style |= BS_VCENTER; else this->style &= ~BS_VCENTER; return this->me(); }
305
+	T &IsMultiline(bool Multiline = true) { if (Multiline) this->style |= BS_MULTILINE; else this->style &= ~BS_MULTILINE; return this->me(); }
306
+	T &WithNotify(bool Notify = true) { if (Notify) this->style |= BS_NOTIFY; else this->style &= ~BS_NOTIFY; return this->me(); }
307
+	T &IsFlat(bool Flat = true) { if (Flat) this->style |= BS_FLAT; else this->style &= ~BS_FLAT; return this->me(); }
308
+#endif
309
+};
310
+
311
+class DialogButtonBuilder : public DialogButtonBaseBuilder<DialogButtonBuilder>
312
+{
313
+protected:
314
+	friend class DialogTemplate;
315
+public:
316
+	DialogButtonBuilder(const std::wstring &Label) : DialogButtonBaseBuilder(BUTTON_CONTROL, Label) { }
317
+	DialogButtonBuilder &IsDefault(bool Default = true) { if (Default) this->style |= BS_DEFPUSHBUTTON; else this->style &= ~BS_DEFPUSHBUTTON; return this->me(); }
318
+};
319
+
320
+class DialogCheckBoxBuilder : public DialogButtonBaseBuilder<DialogCheckBoxBuilder>
321
+{
322
+protected:
323
+	friend class DialogTemplate;
324
+public:
325
+	DialogCheckBoxBuilder(const std::wstring &Label) : DialogButtonBaseBuilder(CHECKBOX_CONTROL, Label) { this->style |= BS_AUTOCHECKBOX; }
326
+	DialogCheckBoxBuilder &WithTextOnLeft(bool TextOnLeft = true) { if (TextOnLeft) this->style |= BS_LEFTTEXT; else this->style &= ~BS_LEFTTEXT; return this->me(); }
327
+	DialogCheckBoxBuilder &LikePushButton(bool PushButton = true) { if (PushButton) this->style |= BS_PUSHLIKE; else this->style &= ~BS_PUSHLIKE; return this->me(); }
328
+};
329
+
330
+class DialogListBoxBuilder : public DialogInGroupBuilder<DialogListBoxBuilder>
331
+{
332
+protected:
333
+	friend class DialogTemplate;
334
+public:
335
+	DialogListBoxBuilder() : DialogInGroupBuilder(LISTBOX_CONTROL) { }
336
+	DialogListBoxBuilder &WithNotify(bool Notify = true) { if (Notify) this->style |= LBS_NOTIFY; else this->style &= ~LBS_NOTIFY; return this->me(); }
337
+	DialogListBoxBuilder &WithSort(bool Sort = true) { if (Sort) this->style |= LBS_SORT; else this->style &= ~LBS_SORT; return this->me(); }
338
+	DialogListBoxBuilder &WithMultipleSelect(bool MultipleSelect = true) { if (MultipleSelect) this->style |= LBS_MULTIPLESEL; else this->style &= ~LBS_MULTIPLESEL; return this->me(); }
339
+	DialogListBoxBuilder &WithExactHeight(bool ExactHeight = true) { if (ExactHeight) this->style |= LBS_NOINTEGRALHEIGHT; else this->style &= ~LBS_NOINTEGRALHEIGHT; return this->me(); }
340
+	DialogListBoxBuilder &WithMultipleColumns(bool MultipleColumns = true) { if (MultipleColumns) this->style |= LBS_MULTICOLUMN; else this->style &= ~LBS_MULTICOLUMN; return this->me(); }
341
+	DialogListBoxBuilder &WithExtendedSelect(bool ExtendedSelect = true) { if (ExtendedSelect) this->style |= LBS_EXTENDEDSEL; else this->style &= ~LBS_EXTENDEDSEL; return this->me(); }
342
+	DialogListBoxBuilder &WithDisabledNoScroll(bool DisabledNoScroll = true) { if (DisabledNoScroll) this->style |= LBS_DISABLENOSCROLL; else this->style &= ~LBS_DISABLENOSCROLL; return this->me(); }
343
+#if WINVER >= 0x0400
344
+	DialogListBoxBuilder &WithNoSelect(bool NoSelect = true) { if (NoSelect) this->style |= LBS_NOSEL; else this->style &= ~LBS_NOSEL; return this->me(); }
345
+#endif
346
+};
347
+
348
+class DialogComboBoxBuilder : public DialogInGroupBuilder<DialogComboBoxBuilder>
349
+{
350
+protected:
351
+	friend class DialogTemplate;
352
+public:
353
+	DialogComboBoxBuilder() : DialogInGroupBuilder(COMBOBOX_CONTROL) { }
354
+	DialogComboBoxBuilder &IsSimple() { this->style &= ~(CBS_SIMPLE | CBS_DROPDOWN | CBS_DROPDOWNLIST); this->style |= CBS_SIMPLE; return this->me(); }
355
+	DialogComboBoxBuilder &IsDropDown() { this->style &= ~(CBS_SIMPLE | CBS_DROPDOWN | CBS_DROPDOWNLIST); this->style |= CBS_DROPDOWN; return this->me(); }
356
+	DialogComboBoxBuilder &IsDropDownList() { this->style &= ~(CBS_SIMPLE | CBS_DROPDOWN | CBS_DROPDOWNLIST); this->style |= CBS_DROPDOWNLIST; return this->me(); }
357
+	DialogComboBoxBuilder &WithAutoHScroll(bool AutoHScroll = true) { if (AutoHScroll) this->style |= CBS_AUTOHSCROLL; else this->style &= ~CBS_AUTOHSCROLL; return this->me(); }
358
+	DialogComboBoxBuilder &WithSort(bool Sort = true) { if (Sort) this->style |= CBS_SORT; else this->style &= ~CBS_SORT; return this->me(); }
359
+	DialogComboBoxBuilder &WithExactHeight(bool ExactHeight = true) { if (ExactHeight) this->style |= CBS_NOINTEGRALHEIGHT; else this->style &= ~CBS_NOINTEGRALHEIGHT; return this->me(); }
360
+	DialogComboBoxBuilder &WithDisabledNoScroll(bool DisabledNoScroll = true) { if (DisabledNoScroll) this->style |= CBS_DISABLENOSCROLL; else this->style &= ~CBS_DISABLENOSCROLL; return this->me(); }
361
+#if WINVER >= 0x0400
362
+	DialogComboBoxBuilder &WithAllLowercase(bool AllLowercase = true) { if (AllLowercase) this->style |= CBS_LOWERCASE; else this->style &= ~CBS_LOWERCASE; return this->me(); }
363
+	DialogComboBoxBuilder &WithAllUppercase(bool AllUppercase = true) { if (AllUppercase) this->style |= CBS_UPPERCASE; else this->style &= ~CBS_UPPERCASE; return this->me(); }
364
+#endif
365
+};
366
+
367
+class DialogTemplate
368
+{
369
+	class DialogControl;
370
+
371
+	typedef std::vector<std::unique_ptr<DialogControl>> Controls;
372
+
373
+	class DialogControl
374
+	{
375
+	protected:
376
+		DialogControlType controlType;
377
+		uint32_t style, exstyle;
378
+		Rect<short> rect;
379
+		short id;
380
+		std::unique_ptr<RelativePosition> relativePosition;
381
+
382
+		friend class DialogTemplate;
383
+		DialogControl() : controlType(NO_CONTROL), style(0), exstyle(0), rect(), id(-1), relativePosition() { }
384
+		DialogControl(const DialogControl &control) : controlType(control.controlType), style(control.style), exstyle(control.exstyle), rect(control.rect), id(control.id),
385
+			relativePosition(control.relativePosition ? control.relativePosition->Clone() : nullptr) { }
386
+		DialogControl &operator=(const DialogControl &control)
387
+		{
388
+			this->controlType = control.controlType;
389
+			this->style = control.style;
390
+			this->exstyle = control.exstyle;
391
+			this->rect = control.rect;
392
+			this->id = control.id;
393
+			if (control.relativePosition)
394
+				this->relativePosition.reset(control.relativePosition->Clone());
395
+			else
396
+				this->relativePosition.reset();
397
+
398
+			return *this;
399
+		}
400
+	public:
401
+		virtual ~DialogControl() { }
402
+		template<typename Control, typename Builder> static std::unique_ptr<Control> CreateControl(const DialogControlBuilder<Builder> &builder)
403
+		{
404
+			auto control = std::unique_ptr<Control>(new Control());
405
+
406
+			control->controlType = builder.controlType;
407
+			control->style = builder.style;
408
+			control->exstyle = builder.exstyle;
409
+			control->rect = builder.rect;
410
+			control->id = builder.id;
411
+			if (builder.relativePosition)
412
+				control->relativePosition.reset(builder.relativePosition->Clone());
413
+
414
+			return control;
415
+		}
416
+		virtual uint16_t GetControlCount() const { return 1; }
417
+		virtual short GetControlHeight() const { return this->rect.size.height; }
418
+		virtual std::vector<uint8_t> GenerateControlTemplate() const = 0;
419
+		virtual DialogControl *Clone() const = 0;
420
+	};
421
+
422
+	class DialogGroup : public DialogControl
423
+	{
424
+	protected:
425
+		DialogTemplate::Controls controls;
426
+		std::wstring groupName;
427
+
428
+		friend class DialogTemplate;
429
+		friend class DialogControl;
430
+		DialogGroup() : DialogControl(), controls(), groupName(L"") { }
431
+		DialogGroup(const DialogGroup &control) : DialogControl(control), controls(), groupName(control.groupName)
432
+		{
433
+			std::for_each(control.controls.begin(), control.controls.end(), [&](const std::unique_ptr<DialogControl> &control) { this->controls.push_back(std::unique_ptr<DialogControl>(control->Clone())); });
434
+		}
435
+		DialogGroup &operator=(const DialogGroup &control)
436
+		{
437
+			DialogControl::operator=(control);
438
+
439
+			this->controls.clear();
440
+			std::for_each(control.controls.begin(), control.controls.end(), [&](const std::unique_ptr<DialogControl> &control) { this->controls.push_back(std::unique_ptr<DialogControl>(control->Clone())); });
441
+
442
+			this->groupName = control.groupName;
443
+
444
+			return *this;
445
+		}
446
+	public:
447
+		static std::unique_ptr<DialogGroup> CreateControl(const DialogControlBuilder<DialogGroupBuilder> &builder)
448
+		{
449
+			auto control = DialogControl::CreateControl<DialogGroup>(builder);
450
+
451
+			control->groupName = dynamic_cast<const DialogGroupBuilder &>(builder).groupName;
452
+
453
+			return control;
454
+		}
455
+		void CalculatePositions(bool doRightAndBottom = false);
456
+		void CalculateSize();
457
+		uint16_t GetControlCount() const;
458
+		std::vector<uint8_t> GenerateControlTemplate() const;
459
+		DialogGroup *Clone() const { return new DialogGroup(*this); }
460
+	};
461
+
462
+	class DialogControlWithoutLabel : public DialogControl
463
+	{
464
+	protected:
465
+		uint16_t type;
466
+
467
+		friend class DialogTemplate;
468
+		friend class DialogControl;
469
+		DialogControlWithoutLabel() : DialogControl(), type(0) { }
470
+		DialogControlWithoutLabel(const DialogControlWithoutLabel &control) : DialogControl(control), type(control.type) { }
471
+		DialogControlWithoutLabel &operator=(const DialogControlWithoutLabel &control)
472
+		{
473
+			DialogControl::operator=(control);
474
+
475
+			this->type = control.type;
476
+
477
+			return *this;
478
+		}
479
+	public:
480
+		template<typename Control, typename Builder> static std::unique_ptr<Control> CreateControl(const DialogControlBuilder<Builder> &builder, uint16_t Type)
481
+		{
482
+			auto control = DialogControl::CreateControl<Control>(builder);
483
+
484
+			control->type = Type;
485
+
486
+			return control;
487
+		}
488
+		virtual std::vector<uint8_t> GenerateControlTemplate() const;
489
+		virtual DialogControlWithoutLabel *Clone() const { return new DialogControlWithoutLabel(*this); }
490
+	};
491
+
492
+	class DialogControlWithLabel : public DialogControl
493
+	{
494
+	protected:
495
+		uint16_t type;
496
+		std::wstring label;
497
+
498
+		friend class DialogTemplate;
499
+		friend class DialogControl;
500
+		DialogControlWithLabel() : DialogControl(), type(0), label(L"") { }
501
+		DialogControlWithLabel(const DialogControlWithLabel &control) : DialogControl(control), type(control.type), label(control.label) { }
502
+		DialogControlWithLabel &operator=(const DialogControlWithLabel &control)
503
+		{
504
+			DialogControl::operator=(control);
505
+
506
+			this->type = control.type;
507
+			this->label = control.label;
508
+
509
+			return *this;
510
+		}
511
+	public:
512
+		template<typename Control, typename Builder> static std::unique_ptr<Control> CreateControl(const DialogControlBuilder<Builder> &builder, uint16_t Type)
513
+		{
514
+			auto control = DialogControl::CreateControl<Control>(builder);
515
+
516
+			control->type = Type;
517
+			control->label = dynamic_cast<const DialogControlWithLabelBuilder<Builder> &>(builder).label;
518
+
519
+			return control;
520
+		}
521
+		virtual std::vector<uint8_t> GenerateControlTemplate() const;
522
+		virtual DialogControlWithLabel *Clone() const { return new DialogControlWithLabel(*this); }
523
+	};
524
+
525
+	class DialogEditBox : public DialogControlWithoutLabel
526
+	{
527
+	protected:
528
+		friend class DialogTemplate;
529
+		friend class DialogControl;
530
+		DialogEditBox() : DialogControlWithoutLabel() { }
531
+	public:
532
+		static std::unique_ptr<DialogEditBox> CreateControl(const DialogControlBuilder<DialogEditBoxBuilder> &builder)
533
+		{
534
+			return DialogControlWithoutLabel::CreateControl<DialogEditBox>(builder, 0x0081);
535
+		}
536
+	};
537
+
538
+	class DialogLabel : public DialogControlWithLabel
539
+	{
540
+	protected:
541
+		friend class DialogTemplate;
542
+		friend class DialogControl;
543
+		DialogLabel() : DialogControlWithLabel() { }
544
+	public:
545
+		static std::unique_ptr<DialogLabel> CreateControl(const DialogControlBuilder<DialogLabelBuilder> &builder)
546
+		{
547
+			return DialogControlWithLabel::CreateControl<DialogLabel>(builder, 0x0082);
548
+		}
549
+	};
550
+
551
+	class DialogButton : public DialogControlWithLabel
552
+	{
553
+	protected:
554
+		friend class DialogTemplate;
555
+		friend class DialogControl;
556
+		DialogButton() : DialogControlWithLabel() { }
557
+	public:
558
+		template<typename Builder> static std::unique_ptr<DialogButton> CreateControl(const DialogControlBuilder<Builder> &builder)
559
+		{
560
+			return DialogControlWithLabel::CreateControl<DialogButton>(builder, 0x0080);
561
+		}
562
+	};
563
+
564
+	class DialogListBox : public DialogControlWithoutLabel
565
+	{
566
+	protected:
567
+		friend class DialogTemplate;
568
+		friend class DialogControl;
569
+		DialogListBox() : DialogControlWithoutLabel() { }
570
+	public:
571
+		static std::unique_ptr<DialogListBox> CreateControl(const DialogControlBuilder<DialogListBoxBuilder> &builder)
572
+		{
573
+			return DialogControlWithoutLabel::CreateControl<DialogListBox>(builder, 0x0083);
574
+		}
575
+	};
576
+
577
+	class DialogComboBox : public DialogControlWithoutLabel
578
+	{
579
+	protected:
580
+		friend class DialogTemplate;
581
+		friend class DialogControl;
582
+		DialogComboBox() : DialogControlWithoutLabel() { }
583
+	public:
584
+		static std::unique_ptr<DialogComboBox> CreateControl(const DialogControlBuilder<DialogComboBoxBuilder> &builder)
585
+		{
586
+			return DialogControlWithoutLabel::CreateControl<DialogComboBox>(builder, 0x0085);
587
+		}
588
+		short GetControlHeight() const { return (this->style & CBS_SIMPLE && !(this->style & CBS_DROPDOWNLIST)) ? this->rect.size.height : 14; }
589
+	};
590
+
591
+	std::wstring title;
592
+	uint32_t style, exstyle;
593
+	std::wstring fontName;
594
+	uint16_t fontSizeInPts;
595
+	Size<short> size;
596
+	DialogTemplate::Controls controls;
597
+	std::vector<uint8_t> templateData;
598
+
599
+	template<typename Builder> void AddControlToGroup(std::unique_ptr<DialogControl> &&control, const DialogControlBuilder<Builder> &builder)
600
+	{
601
+		const auto &groupBuilder = dynamic_cast<const DialogInGroupBuilder<Builder> &>(builder);
602
+		if (groupBuilder.groupName.empty())
603
+		{
604
+			if (builder.index == -1)
605
+				this->controls.push_back(std::move(control));
606
+			else
607
+				this->controls.insert(this->controls.begin() + builder.index, std::move(control));
608
+		}
609
+		else
610
+		{
611
+			for (auto curr = this->controls.begin(), end = this->controls.end(); curr != end; ++curr)
612
+			{
613
+				if ((*curr)->controlType != GROUP_CONTROL)
614
+					continue;
615
+				DialogGroup *group = dynamic_cast<DialogGroup *>(curr->get());
616
+				if (group->groupName == groupBuilder.groupName)
617
+				{
618
+					if (builder.index == -1)
619
+						group->controls.push_back(std::move(control));
620
+					else
621
+						group->controls.insert(group->controls.begin() + builder.index, std::move(control));
622
+					return;
623
+				}
624
+			}
625
+			throw std::runtime_error("Group " + UtfConverter::ToUtf8(groupBuilder.groupName) + " was not found.");
626
+		}
627
+	}
628
+	uint16_t GetTotalControlCount() const;
629
+	bool CalculateControlPosition(short index, bool doRightAndBottom = false);
630
+	void CalculateSize();
631
+public:
632
+	DialogTemplate() : title(L""), style(0), exstyle(0), fontName(L""), fontSizeInPts(0), size(), controls(), templateData() { }
633
+	DialogTemplate(const DialogBuilder &builder) : title(builder.title), style(builder.style), exstyle(builder.exstyle), fontName(builder.fontName), fontSizeInPts(builder.fontSizeInPts),
634
+		size(builder.size), controls(), templateData() { }
635
+	DialogTemplate(const DialogTemplate &dlg) : title(dlg.title), style(dlg.style), exstyle(dlg.style), fontName(dlg.fontName), fontSizeInPts(dlg.fontSizeInPts), size(dlg.size),
636
+		controls(), templateData()
637
+	{
638
+		std::for_each(dlg.controls.begin(), dlg.controls.end(), [&](const std::unique_ptr<DialogControl> &control) { this->controls.push_back(std::unique_ptr<DialogControl>(control->Clone())); });
639
+	}
640
+	DialogTemplate &operator=(const DialogBuilder &builder)
641
+	{
642
+		this->title = builder.title;
643
+		this->style = builder.style;
644
+		this->exstyle = builder.exstyle;
645
+		this->fontName = builder.fontName;
646
+		this->fontSizeInPts = builder.fontSizeInPts;
647
+		this->size = builder.size;
648
+		if (builder.resetControls)
649
+			this->controls.clear();
650
+
651
+		return *this;
652
+	}
653
+	DialogTemplate &operator=(const DialogTemplate &dlg)
654
+	{
655
+		this->title = dlg.title;
656
+		this->style = dlg.style;
657
+		this->exstyle = dlg.exstyle;
658
+		this->fontName = dlg.fontName;
659
+		this->fontSizeInPts = dlg.fontSizeInPts;
660
+		this->size = dlg.size;
661
+		this->controls.clear();
662
+		std::for_each(dlg.controls.begin(), dlg.controls.end(), [&](const std::unique_ptr<DialogControl> &control) { this->controls.push_back(std::unique_ptr<DialogControl>(control->Clone())); });
663
+
664
+		return *this;
665
+	}
666
+	void AddGroupControl(const DialogControlBuilder<DialogGroupBuilder> &builder);
667
+	void AddEditBoxControl(const DialogControlBuilder<DialogEditBoxBuilder> &builder);
668
+	void AddLabelControl(const DialogControlBuilder<DialogLabelBuilder> &builder);
669
+	void AddCheckBoxControl(const DialogControlBuilder<DialogCheckBoxBuilder> &builder);
670
+	void AddButtonControl(const DialogControlBuilder<DialogButtonBuilder> &builder);
671
+	void AddListBoxControl(const DialogControlBuilder<DialogListBoxBuilder> &builder);
672
+	void AddComboBoxControl(const DialogControlBuilder<DialogComboBoxBuilder> &builder);
673
+	void AutoSize();
674
+	const DLGTEMPLATE *GenerateTemplate();
675
+};
676
+
677
+#endif