1 // Written in the D programming language.
2
3 /**
4 This app is a demo for most of DlangUI library features.
5
6 Synopsis:
7
8 ----
9 dub run dlangui:example1
10 ----
11
12 Copyright: Vadim Lopatin, 2014
13 License: Boost License 1.0
14 Authors: Vadim Lopatin, coolreader.org@gmail.com
15 */
16 module main;
17
18 import dlangui;
19 import dlangui.dialogs.dialog;
20 import dlangui.dialogs.filedlg;
21 import dlangui.dialogs.msgbox;
22 import std.stdio;
23 import std.conv;
24 import std.utf;
25 import std.algorithm;
26 import std.path;
27
28
29 mixin APP_ENTRY_POINT;
30
31 class TimerTest : HorizontalLayout {
32 ulong timerId;
33 TextWidget _counter;
34 int _value;
35 Button _start;
36 Button _stop;
37 override bool onTimer(ulong id) {
38 _value++;
39 _counter.text = to!dstring(_value);
40 return true;
41 }
42 this() {
43 addChild(new TextWidget(null, "Timer test."d));
44 _counter = new TextWidget(null, "0"d);
45 _counter.fontSize(32);
46 _start = new Button(null, "Start timer"d);
47 _stop = new Button(null, "Stop timer"d);
48 _stop.enabled = false;
49 _start.click = delegate(Widget src) {
50 _start.enabled = false;
51 _stop.enabled = true;
52 timerId = setTimer(1000);
53 return true;
54 };
55 _stop.click = delegate(Widget src) {
56 _start.enabled = true;
57 _stop.enabled = false;
58 cancelTimer(timerId);
59 return true;
60 };
61 addChild(_start);
62 addChild(_stop);
63 addChild(_counter);
64 }
65 }
66
67 static if (BACKEND_GUI) {
68 class AnimatedDrawable : Drawable {
69 DrawableRef background;
70 this() {
71 background = drawableCache.get("tx_fabric.tiled");
72 }
73 void drawAnimatedRect(DrawBuf buf, uint p, Rect rc, int speedx, int speedy, int sz) {
74 int x = (p * speedx % rc.width);
75 int y = (p * speedy % rc.height);
76 if (x < 0)
77 x += rc.width;
78 if (y < 0)
79 y += rc.height;
80 uint a = 64 + ((p / 2) & 0x7F);
81 uint r = 128 + ((p / 7) & 0x7F);
82 uint g = 128 + ((p / 5) & 0x7F);
83 uint b = 128 + ((p / 3) & 0x7F);
84 uint color = (a << 24) | (r << 16) | (g << 8) | b;
85 buf.fillRect(Rect(rc.left + x, rc.top + y, rc.left + x + sz, rc.top + y + sz), color);
86 }
87 void drawAnimatedIcon(DrawBuf buf, uint p, Rect rc, int speedx, int speedy, string resourceId) {
88 int x = (p * speedx % rc.width);
89 int y = (p * speedy % rc.height);
90 if (x < 0)
91 x += rc.width;
92 if (y < 0)
93 y += rc.height;
94 DrawBufRef image = drawableCache.getImage(resourceId);
95 buf.drawImage(x, y, image.get);
96 }
97 override void drawTo(DrawBuf buf, Rect rc, uint state = 0, int tilex0 = 0, int tiley0 = 0) {
98 background.drawTo(buf, rc, state, cast(int)(animationProgress / 695430), cast(int)(animationProgress / 1500000));
99 drawAnimatedRect(buf, cast(uint)(animationProgress / 295430), rc, 2, 3, 100);
100 drawAnimatedRect(buf, cast(uint)(animationProgress / 312400) + 100, rc, 3, 2, 130);
101 drawAnimatedIcon(buf, cast(uint)(animationProgress / 212400) + 200, rc, -2, 1, "dlangui-logo1");
102 drawAnimatedRect(buf, cast(uint)(animationProgress / 512400) + 300, rc, 2, -2, 200);
103 drawAnimatedRect(buf, cast(uint)(animationProgress / 214230) + 800, rc, 1, 2, 390);
104 drawAnimatedIcon(buf, cast(uint)(animationProgress / 123320) + 900, rc, 1, 2, "cr3_logo");
105 drawAnimatedRect(buf, cast(uint)(animationProgress / 100000) + 100, rc, -1, -1, 120);
106 }
107 @property override int width() {
108 return 1;
109 }
110 @property override int height() {
111 return 1;
112 }
113 ulong animationProgress;
114 void animate(long interval) {
115 animationProgress += interval;
116 }
117
118 }
119 }
120
121 class TextEditorWidget : VerticalLayout {
122 EditBox _edit;
123 this(string ID) {
124 super(ID);
125 _edit = new EditBox("editor");
126 _edit.layoutWidth = FILL_PARENT;
127 _edit.layoutHeight = FILL_PARENT;
128 addChild(_edit);
129 }
130 }
131
132 static if (BACKEND_GUI) {
133 class SampleAnimationWidget : VerticalLayout {
134 AnimatedDrawable drawable;
135 DrawableRef drawableRef;
136 this(string ID) {
137 super(ID);
138 drawable = new AnimatedDrawable();
139 drawableRef = drawable;
140 padding = Rect(20, 20, 20, 20);
141 addChild(new TextWidget(null, "This is TextWidget on top of animated background"d));
142 addChild(new EditLine(null, "This is EditLine on top of animated background"d));
143 addChild(new Button(null, "This is Button on top of animated background"d));
144 addChild(new VSpacer());
145 }
146
147 /// background drawable
148 @property override DrawableRef backgroundDrawable() const {
149 return (cast(SampleAnimationWidget)this).drawableRef;
150 }
151
152 /// returns true is widget is being animated - need to call animate() and redraw
153 @property override bool animating() { return true; }
154 /// animates window; interval is time left from previous draw, in hnsecs (1/10000000 of second)
155 override void animate(long interval) {
156 drawable.animate(interval);
157 invalidate();
158 }
159 }
160 }
161
162 Widget createEditorSettingsControl(EditWidgetBase editor) {
163 HorizontalLayout res = new HorizontalLayout("editor_options");
164 res.addChild((new CheckBox("wantTabs", "wantTabs"d)).checked(editor.wantTabs).addOnCheckChangeListener(delegate(Widget, bool checked) { editor.wantTabs = checked; return true;}));
165 res.addChild((new CheckBox("useSpacesForTabs", "useSpacesForTabs"d)).checked(editor.useSpacesForTabs).addOnCheckChangeListener(delegate(Widget, bool checked) { editor.useSpacesForTabs = checked; return true;}));
166 res.addChild((new CheckBox("readOnly", "readOnly"d)).checked(editor.readOnly).addOnCheckChangeListener(delegate(Widget, bool checked) { editor.readOnly = checked; return true;}));
167 res.addChild((new CheckBox("showLineNumbers", "showLineNumbers"d)).checked(editor.showLineNumbers).addOnCheckChangeListener(delegate(Widget, bool checked) { editor.showLineNumbers = checked; return true;}));
168 res.addChild((new CheckBox("fixedFont", "fixedFont"d)).checked(editor.fontFamily == FontFamily.MonoSpace).addOnCheckChangeListener(delegate(Widget, bool checked) {
169 if (checked)
170 editor.fontFamily(FontFamily.MonoSpace).fontFace("Courier New");
171 else
172 editor.fontFamily(FontFamily.SansSerif).fontFace("Arial");
173 return true;
174 }));
175 res.addChild((new CheckBox("tabSize", "Tab size 8"d)).checked(editor.tabSize == 8).addOnCheckChangeListener(delegate(Widget, bool checked) {
176 if (checked)
177 editor.tabSize(8);
178 else
179 editor.tabSize(4);
180 return true;
181 }));
182 return res;
183 }
184
185 enum : int {
186 ACTION_FILE_OPEN = 5500,
187 ACTION_FILE_SAVE,
188 ACTION_FILE_CLOSE,
189 ACTION_FILE_EXIT,
190 }
191
192 debug(SDLSettings) {
193 import dlangui.core.settings;
194 void testSDL(string fn) {
195 Log.d("Loading SDL from ", fn);
196 Setting s = new Setting();
197 if (s.load(fn)) {
198 Log.d("JSON:\n", s.toJSON(true));
199 } else {
200 Log.e("failed to read SDL from ", fn);
201 }
202 }
203 void testSDLSettings() {
204 testSDL(`C:\Users\vlopatin\AppData\Roaming\.dlangide\settings.json`);
205 testSDL("dub.json");
206 testSDL("test1.sdl");
207 }
208 }
209
210 /// entry point for dlangui based application
211 extern (C) int UIAppMain(string[] args) {
212
213 debug(SDLSettings) {
214 testSDLSettings();
215 }
216
217 // always use trace, even for release builds
218 //Log.setLogLevel(LogLevel.Trace);
219 //Log.setFileLogger(new std.stdio.File("ui.log", "w"));
220
221 // resource directory search paths
222 // not required if only embedded resources are used
223 //string[] resourceDirs = [
224 // appendPath(exePath, "../../../res/"), // for Visual D and DUB builds
225 // appendPath(exePath, "../../../res/mdpi/"), // for Visual D and DUB builds
226 // appendPath(exePath, "../../../../res/"),// for Mono-D builds
227 // appendPath(exePath, "../../../../res/mdpi/"),// for Mono-D builds
228 // appendPath(exePath, "res/"), // when res dir is located at the same directory as executable
229 // appendPath(exePath, "../res/"), // when res dir is located at project directory
230 // appendPath(exePath, "../../res/"), // when res dir is located at the same directory as executable
231 // appendPath(exePath, "res/mdpi/"), // when res dir is located at the same directory as executable
232 // appendPath(exePath, "../res/mdpi/"), // when res dir is located at project directory
233 // appendPath(exePath, "../../res/mdpi/") // when res dir is located at the same directory as executable
234 //];
235 // setup resource directories - will use only existing directories
236 //Platform.instance.resourceDirs = resourceDirs;
237
238 // embed resources listed in views/resources.list into executable
239 embeddedResourceList.addResources(embedResourcesFromList!("resources.list")());
240
241 //version (USE_OPENGL) {
242 // // you can turn on subpixel font rendering (ClearType) here
243 //FontManager.subpixelRenderingMode = SubpixelRenderingMode.None; //
244 //} else {
245 // you can turn on subpixel font rendering (ClearType) here
246 FontManager.subpixelRenderingMode = SubpixelRenderingMode.BGR; //SubpixelRenderingMode.None; //
247 //}
248
249 // select translation file - for english language
250 Platform.instance.uiLanguage = "en";
251 // load theme from file "theme_default.xml"
252 Platform.instance.uiTheme = "theme_default";
253 //Platform.instance.uiTheme = "theme_dark";
254
255 // you can override default hinting mode here (Normal, AutoHint, Disabled)
256 FontManager.hintingMode = HintingMode.Normal;
257 // you can override antialiasing setting here (0 means antialiasing always on, some big value = always off)
258 // fonts with size less than specified value will not be antialiased
259 FontManager.minAnitialiasedFontSize = 0; // 0 means always antialiased
260 //version (USE_OPENGL) {
261 // // you can turn on subpixel font rendering (ClearType) here
262 FontManager.subpixelRenderingMode = SubpixelRenderingMode.None; //
263 //} else {
264 // you can turn on subpixel font rendering (ClearType) here
265 //FontManager.subpixelRenderingMode = SubpixelRenderingMode.BGR; //SubpixelRenderingMode.None; //
266 //}
267
268 // create window
269 //Window window = Platform.instance.createWindow("DlangUI Example 1", null, WindowFlag.Resizable, 800, 700);
270 // Expand window size if content is bigger than 800, 700 (change to above version if you want scrollbars and 800, 700 size)
271 Window window = Platform.instance.createWindow("DlangUI Example 1", null, WindowFlag.Resizable | WindowFlag.ExpandSize, 800, 700);
272 // here you can see window or content resize mode
273 //Window window = Platform.instance.createWindow("DlangUI Example 1", null, WindowFlag.Resizable, 400, 400);
274 //window.windowOrContentResizeMode = WindowOrContentResizeMode.resizeWindow;
275 //window.windowOrContentResizeMode = WindowOrContentResizeMode.scrollWindow;
276 //window.windowOrContentResizeMode = WindowOrContentResizeMode.shrinkWidgets;
277 static if (true) {
278 VerticalLayout contentLayout = new VerticalLayout();
279
280 TabWidget tabs = new TabWidget("TABS");
281 tabs.tabClose = delegate(string tabId) {
282 tabs.removeTab(tabId);
283 };
284
285 //=========================================================================
286 // create main menu
287
288 MenuItem mainMenuItems = new MenuItem();
289 MenuItem fileItem = new MenuItem(new Action(1, "MENU_FILE"c));
290 fileItem.add(new Action(ACTION_FILE_OPEN, "MENU_FILE_OPEN"c, "document-open", KeyCode.KEY_O, KeyFlag.Control));
291 fileItem.add(new Action(ACTION_FILE_SAVE, "MENU_FILE_SAVE"c, "document-save", KeyCode.KEY_S, KeyFlag.Control));
292 MenuItem openRecentItem = new MenuItem(new Action(13, "MENU_FILE_OPEN_RECENT", "document-open-recent"));
293 openRecentItem.add(new Action(100, "&1: File 1"d));
294 openRecentItem.add(new Action(101, "&2: File 2"d));
295 openRecentItem.add(new Action(102, "&3: File 3"d));
296 openRecentItem.add(new Action(103, "&4: File 4"d));
297 openRecentItem.add(new Action(104, "&5: File 5"d));
298 fileItem.add(openRecentItem);
299 fileItem.add(new Action(ACTION_FILE_EXIT, "MENU_FILE_EXIT"c, "document-close"c, KeyCode.KEY_X, KeyFlag.Alt));
300
301 MenuItem editItem = new MenuItem(new Action(2, "MENU_EDIT"));
302 editItem.add(new Action(EditorActions.Copy, "MENU_EDIT_COPY"c, "edit-copy", KeyCode.KEY_C, KeyFlag.Control));
303 editItem.add(new Action(EditorActions.Paste, "MENU_EDIT_PASTE"c, "edit-paste", KeyCode.KEY_V, KeyFlag.Control));
304 editItem.add(new Action(EditorActions.Cut, "MENU_EDIT_CUT"c, "edit-cut", KeyCode.KEY_X, KeyFlag.Control));
305 editItem.add(new Action(EditorActions.Undo, "MENU_EDIT_UNDO"c, "edit-undo", KeyCode.KEY_Z, KeyFlag.Control));
306 editItem.add(new Action(EditorActions.Redo, "MENU_EDIT_REDO"c, "edit-redo", KeyCode.KEY_Y, KeyFlag.Control));
307 editItem.add(new Action(EditorActions.Indent, "MENU_EDIT_INDENT"c, "edit-indent", KeyCode.TAB, 0));
308 editItem.add(new Action(EditorActions.Unindent, "MENU_EDIT_UNINDENT"c, "edit-unindent", KeyCode.TAB, KeyFlag.Control));
309 editItem.add(new Action(20, "MENU_EDIT_PREFERENCES"));
310
311 MenuItem editPopupItem = new MenuItem(null);
312 editPopupItem.add(new Action(EditorActions.Copy, "MENU_EDIT_COPY"c, "edit-copy", KeyCode.KEY_C, KeyFlag.Control));
313 editPopupItem.add(new Action(EditorActions.Paste, "MENU_EDIT_PASTE"c, "edit-paste", KeyCode.KEY_V, KeyFlag.Control));
314 editPopupItem.add(new Action(EditorActions.Cut, "MENU_EDIT_CUT"c, "edit-cut", KeyCode.KEY_X, KeyFlag.Control));
315 editPopupItem.add(new Action(EditorActions.Undo, "MENU_EDIT_UNDO"c, "edit-undo", KeyCode.KEY_Z, KeyFlag.Control));
316 editPopupItem.add(new Action(EditorActions.Redo, "MENU_EDIT_REDO"c, "edit-redo", KeyCode.KEY_Y, KeyFlag.Control));
317 editPopupItem.add(new Action(EditorActions.Indent, "MENU_EDIT_INDENT"c, "edit-indent", KeyCode.TAB, 0));
318 editPopupItem.add(new Action(EditorActions.Unindent, "MENU_EDIT_UNINDENT"c, "edit-unindent", KeyCode.TAB, KeyFlag.Control));
319
320 MenuItem viewItem = new MenuItem(new Action(60, "MENU_VIEW"));
321 MenuItem langItem = new MenuItem(new Action(61, "MENU_VIEW_LANGUAGE"));
322 auto onLangChange = delegate (MenuItem item) {
323 if (!item.checked)
324 return false;
325 if (item.id == 611) {
326 // set interface language to english
327 platform.instance.uiLanguage = "en";
328 } else if (item.id == 612) {
329 // set interface language to russian
330 platform.instance.uiLanguage = "ru";
331 }
332 return true;
333 };
334 MenuItem enLang = (new MenuItem(new Action(611, "MENU_VIEW_LANGUAGE_EN"))).type(MenuItemType.Radio).checked(true);
335 MenuItem ruLang = (new MenuItem(new Action(612, "MENU_VIEW_LANGUAGE_RU"))).type(MenuItemType.Radio);
336 enLang.menuItemClick = onLangChange;
337 ruLang.menuItemClick = onLangChange;
338 langItem.add(enLang);
339 langItem.add(ruLang);
340 viewItem.add(langItem);
341 MenuItem themeItem = new MenuItem(new Action(62, "MENU_VIEW_THEME"));
342 MenuItem theme1 = (new MenuItem(new Action(621, "MENU_VIEW_THEME_DEFAULT"))).type(MenuItemType.Radio).checked(true);
343 MenuItem theme2 = (new MenuItem(new Action(622, "MENU_VIEW_THEME_DARK"))).type(MenuItemType.Radio);
344 MenuItem theme3 = (new MenuItem(new Action(623, "MENU_VIEW_THEME_CUSTOM1"))).type(MenuItemType.Radio);
345 auto onThemeChange = delegate (MenuItem item) {
346 if (!item.checked)
347 return false;
348 if (item.id == 621) {
349 platform.instance.uiTheme = "theme_default";
350 } else if (item.id == 622) {
351 platform.instance.uiTheme = "theme_dark";
352 } else if (item.id == 623) {
353 platform.instance.uiTheme = "theme_custom1";
354 }
355 return true;
356 };
357 theme1.menuItemClick = onThemeChange;
358 theme2.menuItemClick = onThemeChange;
359 theme3.menuItemClick = onThemeChange;
360 themeItem.add(theme1);
361 themeItem.add(theme2);
362 themeItem.add(theme3);
363 viewItem.add(themeItem);
364
365 MenuItem windowItem = new MenuItem(new Action(3, "MENU_WINDOW"c));
366 windowItem.add(new Action(30, "MENU_WINDOW_PREFERENCES"));
367 windowItem.add(new Action(31, UIString.fromId("MENU_WINDOW_MINIMIZE")));
368 windowItem.add(new Action(32, UIString.fromId("MENU_WINDOW_MAXIMIZE")));
369 windowItem.add(new Action(33, UIString.fromId("MENU_WINDOW_RESTORE")));
370 MenuItem helpItem = new MenuItem(new Action(4, "MENU_HELP"c));
371 helpItem.add(new Action(40, "MENU_HELP_VIEW_HELP"));
372 MenuItem aboutItem = new MenuItem(new Action(41, "MENU_HELP_ABOUT"));
373 helpItem.add(aboutItem);
374 mainMenuItems.add(fileItem);
375 mainMenuItems.add(editItem);
376 mainMenuItems.add(viewItem);
377 mainMenuItems.add(windowItem);
378 mainMenuItems.add(helpItem);
379 MainMenu mainMenu = new MainMenu(mainMenuItems);
380 contentLayout.addChild(mainMenu);
381 // to let main menu handle keyboard shortcuts
382 contentLayout.keyToAction = delegate(Widget source, uint keyCode, uint flags) {
383 return mainMenu.findKeyAction(keyCode, flags);
384 };
385 contentLayout.onAction = delegate(Widget source, const Action a) {
386 if (a.id == ACTION_FILE_EXIT) {
387 window.close();
388 return true;
389 } else if (a.id == 31) {
390 window.minimizeWindow();
391 return true;
392 } else if (a.id == 32) {
393 window.maximizeWindow();
394 return true;
395 } else if (a.id == 33) {
396 window.restoreWindow();
397 return true;
398 } else if (a.id == 41) {
399 window.showMessageBox(UIString.fromRaw("About"d), UIString.fromRaw("DLangUI demo app\n(C) Vadim Lopatin, 2014\nhttp://github.com/buggins/dlangui"d));
400 return true;
401 } else if (a.id == ACTION_FILE_OPEN) {
402 UIString caption;
403 caption = "Open Text File"d;
404 FileDialog dlg = new FileDialog(caption, window, null);
405 dlg.allowMultipleFiles = true;
406 dlg.addFilter(FileFilterEntry(UIString("FILTER_ALL_FILES", "All files (*)"d), "*"));
407 dlg.addFilter(FileFilterEntry(UIString("FILTER_TEXT_FILES", "Text files (*.txt)"d), "*.txt"));
408 dlg.addFilter(FileFilterEntry(UIString("FILTER_SOURCE_FILES", "Source files"d), "*.d;*.dd;*.c;*.cc;*.cpp;*.h;*.hpp"));
409 dlg.addFilter(FileFilterEntry(UIString("FILTER_EXECUTABLE_FILES", "Executable files"d), "*", true));
410 //dlg.filterIndex = 2;
411 dlg.dialogResult = delegate(Dialog dlg, const Action result) {
412 if (result.id == ACTION_OPEN.id) {
413 string[] filenames = (cast(FileDialog)dlg).filenames;
414 foreach (filename; filenames) {
415 if (filename.endsWith(".d") || filename.endsWith(".txt") || filename.endsWith(".cpp") || filename.endsWith(".h") || filename.endsWith(".c")
416 || filename.endsWith(".json") || filename.endsWith(".dd") || filename.endsWith(".ddoc") || filename.endsWith(".xml") || filename.endsWith(".html")
417 || filename.endsWith(".html") || filename.endsWith(".css") || filename.endsWith(".log") || filename.endsWith(".hpp")) {
418 // open source file in tab
419 int index = tabs.tabIndex(filename);
420 if (index >= 0) {
421 // file is already opened in tab
422 tabs.selectTab(index, true);
423 } else {
424 SourceEdit editor = new SourceEdit(filename);
425 if (editor.load(filename)) {
426 tabs.addTab(editor, toUTF32(baseName(filename)), null, true);
427 tabs.selectTab(filename);
428 } else {
429 destroy(editor);
430 window.showMessageBox(UIString.fromRaw("File open error"d), UIString.fromRaw("Cannot open file "d ~ toUTF32(filename)));
431 }
432 }
433 } else {
434 Log.d("FileDialog.onDialogResult: ", result, " param=", result.stringParam);
435 window.showMessageBox(UIString.fromRaw("FileOpen result"d), UIString.fromRaw("Filename: "d ~ toUTF32(filename)));
436 }
437 }
438 }
439
440 };
441 dlg.show();
442 return true;
443 }
444 //else
445 //return contentLayout.dispatchAction(a);
446 return false;
447 };
448 mainMenu.menuItemClick = delegate(MenuItem item) {
449 Log.d("mainMenu.onMenuItemListener", item.label);
450 const Action a = item.action;
451 if (a) {
452 return contentLayout.dispatchAction(a);
453 }
454 return false;
455 };
456
457 // ========= create tabs ===================
458
459 tabs.tabChanged = delegate(string newTabId, string oldTabId) {
460 window.windowCaption = tabs.tab(newTabId).text.value ~ " - dlangui example 1"d;
461 };
462 tabs.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
463
464 // most of controls example
465 {
466 LinearLayout controls = new VerticalLayout("controls");
467 controls.layoutHeight(FILL_PARENT);
468 controls.padding = Rect(12.pointsToPixels,12.pointsToPixels,12.pointsToPixels,12.pointsToPixels);
469
470 HorizontalLayout line1 = new HorizontalLayout();
471 controls.addChild(line1);
472
473 GroupBox gb = new GroupBox("checkboxes", "CheckBox"d);
474 gb.addChild(new CheckBox("cb1", "CheckBox 1"d));
475 gb.addChild(new CheckBox("cb2", "CheckBox 2"d).checked(true));
476 gb.addChild(new CheckBox("cb3", "CheckBox disabled"d).enabled(false));
477 gb.addChild(new CheckBox("cb4", "CheckBox disabled"d).checked(true).enabled(false));
478 line1.addChild(gb);
479
480 GroupBox gb2 = new GroupBox("radiobuttons", "RadioButton"d);
481 gb2.addChild(new RadioButton("rb1", "RadioButton 1"d).checked(true));
482 gb2.addChild(new RadioButton("rb2", "RadioButton 2"d));
483 gb2.addChild(new RadioButton("rb3", "RadioButton disabled"d).enabled(false));
484 line1.addChild(gb2);
485
486 VerticalLayout col1 = new VerticalLayout();
487 GroupBox gb3 = new GroupBox("textbuttons", "Button"d, Orientation.Horizontal);
488 gb3.addChild(new Button("tb1", "Button"d));
489 gb3.addChild(new Button("tb2", "Button disabled"d).enabled(false));
490 col1.addChild(gb3);
491 GroupBox gb4 = new GroupBox("imagetextbuttons", "ImageTextButton"d, Orientation.Horizontal);
492 gb4.addChild(new ImageTextButton("itb1", "document-open", "Enabled"d));
493 gb4.addChild(new ImageTextButton("itb2", "document-save", "Disabled"d).enabled(false));
494 col1.addChild(gb4);
495 GroupBox gbtext = new GroupBox("text", "TextWidget"d, Orientation.Horizontal);
496 gbtext.addChild(new TextWidget("t1", "Red text"d).fontSize(12.pointsToPixels).textColor(0xFF0000));
497 gbtext.addChild(new TextWidget("t2", "Italic text"d).fontSize(12.pointsToPixels).fontItalic(true));
498 col1.addChild(gbtext);
499 line1.addChild(col1);
500
501 VerticalLayout col2 = new VerticalLayout();
502 GroupBox gb31 = new GroupBox("switches", "SwitchButton"d, Orientation.Vertical);
503 gb31.addChild(new SwitchButton("sb1"));
504 gb31.addChild(new SwitchButton("sb2").checked(true));
505 gb31.addChild(new SwitchButton("sb3").enabled(false));
506 gb31.addChild(new SwitchButton("sb4").enabled(false).checked(true));
507 col2.addChild(gb31);
508 line1.addChild(col2);
509
510 VerticalLayout col3 = new VerticalLayout();
511 GroupBox gb32 = new GroupBox("switches", "ImageButton"d, Orientation.Vertical);
512 gb32.addChild(new ImageButton("ib1", "edit-copy"));
513 gb32.addChild(new ImageButton("ib3", "edit-paste").enabled(false));
514 col3.addChild(gb32);
515 GroupBox gb33 = new GroupBox("images", "ImageWidget"d, Orientation.Vertical);
516 gb33.addChild(new ImageWidget("cr3_logo", "cr3_logo"));
517 col3.addChild(gb33);
518 line1.addChild(col3);
519
520
521 HorizontalLayout line2 = new HorizontalLayout();
522 controls.addChild(line2);
523
524 GroupBox gb5 = new GroupBox("scrollbar", "horizontal ScrollBar"d);
525 gb5.addChild(new ScrollBar("sb1", Orientation.Horizontal));
526 line2.addChild(gb5);
527 GroupBox gb6 = new GroupBox("slider", "horizontal SliderWidget"d);
528 gb6.addChild(new SliderWidget("sb2", Orientation.Horizontal));
529 line2.addChild(gb6);
530 GroupBox gb7 = new GroupBox("editline1", "EditLine"d);
531 gb7.addChild(new EditLine("ed1", "Some text"d).minWidth(120.pointsToPixels));
532 line2.addChild(gb7);
533 GroupBox gb8 = new GroupBox("editline2", "EditLine disabled"d);
534 gb8.addChild(new EditLine("ed2", "Some text"d).enabled(false).minWidth(120.pointsToPixels));
535 line2.addChild(gb8);
536
537 HorizontalLayout line3 = new HorizontalLayout();
538 line3.layoutWidth(FILL_PARENT);
539 GroupBox gbeditbox = new GroupBox("editbox", "EditBox"d, Orientation.Horizontal);
540 gbeditbox.layoutWidth(FILL_PARENT);
541 EditBox ed1 = new EditBox("ed1", "Some text in EditBox\nOne more line\nYet another text line");
542 ed1.layoutHeight(FILL_PARENT);
543 gbeditbox.addChild(ed1);
544 line3.addChild(gbeditbox);
545 GroupBox gbtabs = new GroupBox(null, "TabWidget"d);
546 gbtabs.layoutWidth(FILL_PARENT);
547 TabWidget tabs1 = new TabWidget("tabs1");
548 tabs1.addTab(new TextWidget("tab1", "TextWidget on tab page\nTextWidgets can be\nMultiline"d).maxLines(3), "Tab 1"d);
549 tabs1.addTab(new ImageWidget("tab2", "dlangui-logo1"), "Tab 2"d);
550 tabs1.tabHost.backgroundColor = 0xE0E0E0;
551 tabs1.tabHost.padding = Rect(10.pointsToPixels, 10.pointsToPixels, 10.pointsToPixels, 10.pointsToPixels);
552 gbtabs.addChild(tabs1);
553 line3.addChild(gbtabs);
554 controls.addChild(line3);
555
556 HorizontalLayout line4 = new HorizontalLayout();
557 line4.layoutWidth(FILL_PARENT);
558 line4.layoutHeight(FILL_PARENT);
559 GroupBox gbgrid = new GroupBox("grid", "StringGridWidget"d, Orientation.Horizontal);
560 StringGridWidget grid = new StringGridWidget("stringgrid");
561 grid.resize(12, 10);
562 gbgrid.layoutWidth(FILL_PARENT);
563 gbgrid.layoutHeight(FILL_PARENT);
564 grid.layoutWidth(FILL_PARENT);
565 grid.layoutHeight(FILL_PARENT);
566 foreach (index, month; ["January"d, "February"d, "March"d, "April"d, "May"d, "June"d, "July"d, "August"d, "September"d, "October"d, "November"d, "December"d])
567 grid.setColTitle(cast(int)index, month);
568 for (int y = 0; y < 10; y++)
569 grid.setRowTitle(y, to!dstring(y+1));
570 //grid.alignment = Align.Right;
571 grid.setColWidth(0, 30.pointsToPixels);
572 grid.autoFit();
573 import std.random;
574 import std.string;
575 for (int x = 0; x < 12; x++) {
576 for (int y = 0; y < 10; y++) {
577 int n = uniform(0, 10000);
578 grid.setCellText(x, y, to!dstring("%.2f".format(n / 100.0)));
579 }
580 }
581 //grid.autoFit();
582 gbgrid.addChild(grid);
583 line4.addChild(gbgrid);
584
585 GroupBox gbtree = new GroupBox("tree", "TreeWidget"d, Orientation.Vertical);
586 auto tree = new TreeWidget("gbtree");
587 //tree.layoutWidth(WRAP_CONTENT).layoutHeight(FILL_PARENT);
588 tree.maxHeight(200.pointsToPixels);
589 TreeItem tree1 = tree.items.newChild("group1", "Group 1"d, "document-open");
590 tree1.newChild("g1_1", "Group 1 item 1"d);
591 tree1.newChild("g1_2", "Group 1 item 2"d);
592 tree1.newChild("g1_3", "Group 1 item 3"d);
593 TreeItem tree2 = tree.items.newChild("group2", "Group 2"d, "document-save");
594 tree2.newChild("g2_1", "Group 2 item 1"d, "edit-copy");
595 tree2.newChild("g2_2", "Group 2 item 2"d, "edit-cut");
596 tree2.newChild("g2_3", "Group 2 item 3"d, "edit-paste");
597 tree2.newChild("g2_4", "Group 2 item 4"d);
598 TreeItem tree3 = tree.items.newChild("group3", "Group 3"d);
599 tree3.newChild("g3_1", "Group 3 item 1"d);
600 tree3.newChild("g3_2", "Group 3 item 2"d);
601 TreeItem tree32 = tree3.newChild("g3_3", "Group 3 item 3"d);
602 tree3.newChild("g3_4", "Group 3 item 4"d);
603 tree32.newChild("group3_2_1", "Group 3 item 2 subitem 1"d);
604 tree32.newChild("group3_2_2", "Group 3 item 2 subitem 2"d);
605 tree32.newChild("group3_2_3", "Group 3 item 2 subitem 3"d);
606 tree32.newChild("group3_2_4", "Group 3 item 2 subitem 4"d);
607 tree32.newChild("group3_2_5", "Group 3 item 2 subitem 5"d);
608 tree3.newChild("g3_5", "Group 3 item 5"d);
609 tree3.newChild("g3_6", "Group 3 item 6"d);
610 gbtree.addChild(tree);
611 tree.items.selectItem(tree1);
612 // test adding new tree items
613 HorizontalLayout newTreeItem = new HorizontalLayout();
614 newTreeItem.layoutWidth = FILL_PARENT;
615 EditLine edNewTreeItem = new EditLine("newTreeItem", "new item"d);
616 edNewTreeItem.layoutWidth = FILL_PARENT;
617 Button btnAddItem = new Button("btnAddTreeItem", "Add"d);
618 Button btnRemoveItem = new Button("btnRemoveTreeItem", "Remove"d);
619 newTreeItem.addChild(edNewTreeItem);
620 newTreeItem.addChild(btnAddItem);
621 newTreeItem.addChild(btnRemoveItem);
622 btnAddItem.click = delegate(Widget source) {
623 import std.random;
624 dstring label = edNewTreeItem.text;
625 string id = "item%d".format(uniform(1000000, 9999999, rndGen));
626 TreeItem item = tree.items.selectedItem;
627 if (item) {
628 Log.d("Creating new tree item ", id, " ", label);
629 TreeItem newItem = new TreeItem(id, label);
630 item.addChild(newItem);
631 }
632 return true;
633 };
634 btnRemoveItem.click = delegate(Widget source) {
635 TreeItem item = tree.items.selectedItem;
636 if (item) {
637 Log.d("Removing tree item ", item.id, " ", item.text);
638 item.parent.removeChild(item);
639 }
640 return true;
641 };
642 gbtree.addChild(newTreeItem);
643 line4.addChild(gbtree);
644
645 controls.addChild(line4);
646
647 tabs.addTab(controls, "Controls"d);
648 }
649
650 LinearLayout layout = new LinearLayout("tab1");
651
652
653 layout.addChild((new TextWidget()).textColor(0x00802000).text("Text widget 0"));
654 layout.addChild((new TextWidget()).textColor(0x40FF4000).text("Text widget"));
655 layout.addChild(new ProgressBarWidget().progress(300).animationInterval(50));
656 layout.addChild(new ProgressBarWidget().progress(-1).animationInterval(50));
657 layout.addChild((new Button("BTN1")).textResource("EXIT")); //.textColor(0x40FF4000)
658 layout.addChild(new TimerTest());
659
660 static if (true) {
661
662
663 LinearLayout hlayout = new HorizontalLayout();
664 hlayout.layoutWidth(FILL_PARENT);
665 //hlayout.addChild((new Button()).text("<<")); //.textColor(0x40FF4000)
666 hlayout.addChild((new TextWidget()).text("Several").alignment(Align.Center));
667 hlayout.addChild((new ImageWidget()).drawableId("btn_radio").padding(Rect(5,5,5,5)).alignment(Align.Center));
668 hlayout.addChild((new TextWidget()).text("items").alignment(Align.Center));
669 hlayout.addChild((new ImageWidget()).drawableId("btn_check").padding(Rect(5,5,5,5)).alignment(Align.Center));
670 hlayout.addChild((new TextWidget()).text("in horizontal layout"));
671 hlayout.addChild((new ImageWidget()).drawableId("exit").padding(Rect(5,5,5,5)).alignment(Align.Center));
672 hlayout.addChild((new EditLine("editline", "Some text to edit"d)).popupMenu(editPopupItem).alignment(Align.Center).layoutWidth(FILL_PARENT));
673 hlayout.addChild((new EditLine("passwd", "Password"d)).passwordChar('*').popupMenu(editPopupItem).alignment(Align.Center).layoutWidth(FILL_PARENT));
674 //hlayout.addChild((new Button()).text(">>")); //.textColor(0x40FF4000)
675 hlayout.backgroundColor = 0x8080C0;
676 layout.addChild(hlayout);
677
678 LinearLayout vlayoutgroup = new HorizontalLayout();
679 LinearLayout vlayout = new VerticalLayout();
680 vlayout.addChild((new TextWidget()).text("VLayout line 1").textColor(0x40FF4000)); //
681 vlayout.addChild((new TextWidget()).text("VLayout line 2").textColor(0x40FF8000));
682 vlayout.addChild((new TextWidget()).text("VLayout line 2").textColor(0x40008000));
683 vlayout.addChild(new RadioButton("rb1", "Radio button 1"d));
684 vlayout.addChild(new RadioButton("rb2", "Radio button 2"d));
685 vlayout.addChild(new RadioButton("rb3", "Radio button 3"d));
686 vlayout.layoutWidth(FILL_PARENT);
687 vlayoutgroup.addChild(vlayout);
688 vlayoutgroup.layoutWidth(FILL_PARENT);
689 ScrollBar vsb = new ScrollBar("vscroll", Orientation.Vertical);
690 vlayoutgroup.addChild(vsb);
691 layout.addChild(vlayoutgroup);
692
693 ScrollBar sb = new ScrollBar("hscroll", Orientation.Horizontal);
694 layout.addChild(sb.layoutHeight(WRAP_CONTENT).layoutWidth(FILL_PARENT));
695
696 layout.addChild((new CheckBox("BTN2", "Some checkbox"d)));
697 layout.addChild((new TextWidget()).textColor(0x40FF4000).text("Text widget"));
698 layout.addChild((new ImageWidget()).drawableId("exit").padding(Rect(5,5,5,5)));
699 layout.addChild((new TextWidget()).textColor(0xFF4000).text("Text widget2").padding(Rect(5,5,5,5)).margins(Rect(5,5,5,5)).backgroundColor(0xA0A0A0));
700 layout.addChild((new RadioButton("BTN3", "Some radio button"d)));
701 layout.addChild((new TextWidget(null, "Text widget3 with very long text"d)).textColor(0x004000));
702 layout.addChild(new VSpacer()); // vertical spacer to fill extra space
703
704
705 Widget w = parseML(q{
706 VerticalLayout {
707 id: vlayout
708 margins: Rect { left: 5; right: 3; top: 2; bottom: 4 }
709 padding: Rect { 5, 4, 3, 2 } // same as Rect { left: 5; top: 4; right: 3; bottom: 2 }
710 TextWidget {
711 /* this widget can be accessed via id myLabel1
712 e.g. w.childById!TextWidget("myLabel1")
713 */
714 id: myLabel1
715 text: "Some text"; padding: 5
716 enabled: false
717 }
718 TextWidget {
719 id: myLabel2
720 text: SOME_TEXT_RESOURCE_ID; margins: 5
721 enabled: true
722 }
723 }
724 });
725 Log.d("id=", w.id, " text=", w.text, " padding=", w.padding, " margins=", w.margins,
726 " lbl1.text=", w.childById!TextWidget("myLabel1").text,
727 " lbl1.enabled=", w.childById!TextWidget("myLabel1").enabled,
728 " lbl2.text=", w.childById!TextWidget("myLabel2").text
729 );
730 destroy(w);
731
732 layout.childById("BTN1").click = delegate (Widget w) {
733 Log.d("onClick ", w.id);
734 //w.backgroundImageId = null;
735 //w.backgroundColor = 0xFF00FF;
736 w.textColor = 0xFF00FF;
737 w.styleId = STYLE_BUTTON_NOMARGINS;
738 return true;
739 };
740 layout.childById("BTN2").click = delegate (Widget w) { Log.d("onClick ", w.id); return true; };
741 layout.childById("BTN3").click = delegate (Widget w) { Log.d("onClick ", w.id); return true; };
742
743 }
744
745 layout.layoutHeight(FILL_PARENT).layoutWidth(FILL_PARENT);
746
747 tabs.addTab(layout, "Misc"d);
748
749 static if (true) {
750 // two long lists
751 // left one is list with widgets as items
752 // right one is list with string list adapter
753 HorizontalLayout longLists = new HorizontalLayout("tab2");
754 longLists.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
755
756 ListWidget list = new ListWidget("list1", Orientation.Vertical);
757 list.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
758
759 StringListAdapter stringList = new StringListAdapter();
760 WidgetListAdapter listAdapter = new WidgetListAdapter();
761 listAdapter.add((new TextWidget()).text("This is a list of widgets"d).styleId("LIST_ITEM"));
762 stringList.add("This is a list of strings from StringListAdapter"d);
763 stringList.add("If you type with your keyboard,"d);
764 stringList.add("then you can find the"d);
765 stringList.add("item in the list"d);
766 stringList.add("neat!"d);
767 for (int i = 1; i < 1000; i++) {
768 dstring label = "List item "d ~ to!dstring(i);
769 listAdapter.add((new TextWidget()).text("Widget list - "d ~ label).styleId("LIST_ITEM"));
770 stringList.add("Simple string - "d ~ label);
771 }
772 list.ownAdapter = listAdapter;
773 listAdapter.resetItemState(0, State.Enabled);
774 listAdapter.resetItemState(5, State.Enabled);
775 listAdapter.resetItemState(7, State.Enabled);
776 listAdapter.resetItemState(12, State.Enabled);
777 assert(list.itemEnabled(5) == false);
778 assert(list.itemEnabled(6) == true);
779 list.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
780 list.selectItem(0);
781
782 longLists.addChild(list);
783
784 ListWidget list2 = new StringListWidget("list2");
785 list2.ownAdapter = stringList;
786 list2.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
787 list2.selectItem(0);
788 longLists.addChild(list2);
789
790 VerticalLayout itemedit = new VerticalLayout();
791 itemedit.addChild(new TextWidget(null, "New item text:"d));
792 EditLine itemtext = new EditLine(null, "Text for new item"d);
793 itemedit.addChild(itemtext);
794 Button btn = new Button(null, "Add item"d);
795 itemedit.addChild(btn);
796 longLists.addChild(itemedit);
797 btn.click = delegate(Widget src)
798 {
799 stringList.add(itemtext.text);
800 listAdapter.add((new TextWidget()).text(itemtext.text).styleId("LIST_ITEM"));
801 return true;
802 };
803 tabs.addTab(longLists, "TAB_LONG_LIST"c);
804 }
805
806 {
807 LinearLayout layout3 = new VerticalLayout("tab3");
808 // 3 types of buttons: Button, ImageButton, ImageTextButton
809 layout3.addChild(new TextWidget(null, "Buttons in HorizontalLayout"d));
810 WidgetGroup buttons1 = new HorizontalLayout();
811 buttons1.addChild(new TextWidget(null, "Button widgets: "d));
812 buttons1.addChild((new Button("btn1", "Button"d)).tooltipText("Tooltip text for button"d));
813 buttons1.addChild((new Button("btn2", "Disabled Button"d)).enabled(false));
814 buttons1.addChild(new TextWidget(null, "ImageButton widgets: "d));
815 buttons1.addChild(new ImageButton("btn3", "text-plain"));
816 buttons1.addChild(new TextWidget(null, "disabled: "d));
817 buttons1.addChild((new ImageButton("btn4", "folder")).enabled(false));
818 layout3.addChild(buttons1);
819
820 WidgetGroup buttons10 = new HorizontalLayout();
821 buttons10.addChild(new TextWidget(null, "ImageTextButton widgets: "d));
822 buttons10.addChild(new ImageTextButton("btn5", "text-plain", "Enabled"d));
823 buttons10.addChild((new ImageTextButton("btn6", "folder", "Disabled"d)).enabled(false));
824 buttons10.addChild(new TextWidget(null, "SwitchButton widgets: "d));
825 buttons10.addChild((new SwitchButton("SW1")).checked(true));
826 buttons10.addChild((new SwitchButton("SW2")).checked(false));
827 buttons10.addChild((new SwitchButton("SW3")).checked(true).enabled(false));
828 buttons10.addChild((new SwitchButton("SW4")).checked(false).enabled(false));
829 layout3.addChild(buttons10);
830
831 WidgetGroup buttons11 = new HorizontalLayout();
832 buttons11.addChild(new TextWidget(null, "Construct buttons by action (Button, ImageButton, ImageTextButton): "d));
833 Action FILE_OPEN_ACTION = new Action(ACTION_FILE_OPEN, "MENU_FILE_OPEN"c, "document-open", KeyCode.KEY_O, KeyFlag.Control);
834 buttons11.addChild(new Button(FILE_OPEN_ACTION));
835 buttons11.addChild(new ImageButton(FILE_OPEN_ACTION));
836 buttons11.addChild(new ImageTextButton(FILE_OPEN_ACTION));
837 layout3.addChild(buttons11);
838
839 WidgetGroup buttons12 = new HorizontalLayout();
840 buttons12.addChild(new TextWidget(null, "The same in disabled state: "d));
841 buttons12.addChild((new Button(FILE_OPEN_ACTION)).enabled(false));
842 buttons12.addChild((new ImageButton(FILE_OPEN_ACTION)).enabled(false));
843 buttons12.addChild((new ImageTextButton(FILE_OPEN_ACTION)).enabled(false));
844 layout3.addChild(buttons12);
845
846 layout3.addChild(new VSpacer());
847 layout3.addChild(new TextWidget(null, "CheckBoxes in HorizontalLayout"d));
848 WidgetGroup buttons2 = new HorizontalLayout();
849 buttons2.addChild(new CheckBox("btn1", "CheckBox 1"d));
850 buttons2.addChild(new CheckBox("btn2", "CheckBox 2"d));
851 //buttons2.addChild(new ResizerWidget());
852 buttons2.addChild(new CheckBox("btn3", "CheckBox 3"d));
853 buttons2.addChild(new CheckBox("btn4", "CheckBox 4"d));
854 layout3.addChild(buttons2);
855
856 layout3.addChild(new VSpacer());
857 layout3.addChild(new TextWidget(null, "RadioButtons in HorizontalLayout"d));
858 WidgetGroup buttons3 = new HorizontalLayout();
859 buttons3.addChild(new RadioButton("btn1", "RadioButton 1"d));
860 buttons3.addChild(new RadioButton("btn2", "RadioButton 2"d));
861 buttons3.addChild(new RadioButton("btn3", "RadioButton 3"d));
862 buttons3.addChild(new RadioButton("btn4", "RadioButton 4"d));
863 layout3.addChild(buttons3);
864
865 layout3.addChild(new VSpacer());
866 layout3.addChild(new TextWidget(null, "ImageButtons HorizontalLayout"d));
867 WidgetGroup buttons4 = new HorizontalLayout();
868 buttons4.addChild(new ImageButton("btn1", "fileclose"));
869 buttons4.addChild(new ImageButton("btn2", "fileopen"));
870 buttons4.addChild(new ImageButton("btn3", "exit"));
871 layout3.addChild(buttons4);
872
873 layout3.addChild(new VSpacer());
874 layout3.addChild(new TextWidget(null, "In vertical layouts:"d));
875 HorizontalLayout hlayout2 = new HorizontalLayout();
876 hlayout2.layoutHeight(FILL_PARENT); //layoutWidth(FILL_PARENT).
877
878 buttons1 = new VerticalLayout();
879 buttons1.addChild(new TextWidget(null, "Buttons"d));
880 buttons1.addChild(new Button("btn1", "Button 1"d));
881 buttons1.addChild(new Button("btn2", "Button 2"d));
882 buttons1.addChild((new Button("btn3", "Button 3 - disabled"d)).enabled(false));
883 buttons1.addChild(new Button("btn4", "Button 4"d));
884 hlayout2.addChild(buttons1);
885 hlayout2.addChild(new HSpacer());
886
887 buttons2 = new VerticalLayout();
888 buttons2.addChild(new TextWidget(null, "CheckBoxes"d));
889 buttons2.addChild(new CheckBox("btn1", "CheckBox 1"d));
890 buttons2.addChild(new CheckBox("btn2", "CheckBox 2"d));
891 buttons2.addChild(new CheckBox("btn3", "CheckBox 3"d));
892 buttons2.addChild(new CheckBox("btn4", "CheckBox 4"d));
893 hlayout2.addChild(buttons2);
894 hlayout2.addChild(new HSpacer());
895
896 buttons3 = new VerticalLayout();
897 buttons3.addChild(new TextWidget(null, "RadioButtons"d));
898 buttons3.addChild(new RadioButton("btn1", "RadioButton 1"d));
899 buttons3.addChild(new RadioButton("btn2", "RadioButton 2"d));
900 //buttons3.addChild(new ResizerWidget());
901 buttons3.addChild(new RadioButton("btn3", "RadioButton 3"d));
902 buttons3.addChild(new RadioButton("btn4", "RadioButton 4"d));
903 hlayout2.addChild(buttons3);
904 hlayout2.addChild(new HSpacer());
905
906 buttons4 = new VerticalLayout();
907 buttons4.addChild(new TextWidget(null, "ImageButtons"d));
908 buttons4.addChild(new ImageButton("btn1", "fileclose"));
909 buttons4.addChild(new ImageButton("btn2", "fileopen"));
910 buttons4.addChild(new ImageButton("btn3", "exit"));
911 hlayout2.addChild(buttons4);
912 hlayout2.addChild(new HSpacer());
913
914 WidgetGroup buttons5 = new VerticalLayout();
915 buttons5.addChild(new TextWidget(null, "ImageTextButtons"d));
916 buttons5.addChild(new ImageTextButton("btn1", "fileclose", "Close"d));
917 buttons5.addChild(new ImageTextButton("btn2", "fileopen", "Open"d));
918 buttons5.addChild(new ImageTextButton("btn3", "exit", "Exit"d));
919 hlayout2.addChild(buttons5);
920
921
922 layout3.addChild(hlayout2);
923
924 layout3.addChild(new VSpacer());
925 layout3.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
926 tabs.addTab(layout3, "TAB_BUTTONS"c);
927 }
928
929 TableLayout table = new TableLayout("TABLE");
930 table.colCount = 2;
931 // headers
932 table.addChild((new TextWidget(null, "Parameter Name"d)).alignment(Align.Right | Align.VCenter));
933 table.addChild((new TextWidget(null, "Edit Box to edit parameter"d)).alignment(Align.Left | Align.VCenter));
934 // row 1
935 table.addChild((new TextWidget(null, "Parameter 1 name"d)).alignment(Align.Right | Align.VCenter));
936 table.addChild((new EditLine("edit1", "Text 1"d)).layoutWidth(FILL_PARENT));
937 // row 2
938 table.addChild((new TextWidget(null, "Parameter 2 name bla bla"d)).alignment(Align.Right | Align.VCenter));
939 table.addChild((new EditLine("edit2", "Some text for parameter 2"d)).layoutWidth(FILL_PARENT));
940 // row 3
941 table.addChild((new TextWidget(null, "Param 3 is disabled"d)).alignment(Align.Right | Align.VCenter).enabled(false));
942 table.addChild((new EditLine("edit3", "Parameter 3 value"d)).layoutWidth(FILL_PARENT).enabled(false));
943 // normal readonly combo box
944 ComboBox combo1 = new ComboBox("combo1", ["item value 1"d, "item value 2"d, "item value 3"d, "item value 4"d, "item value 5"d, "item value 6"d]);
945 table.addChild((new TextWidget(null, "Combo box param"d)).alignment(Align.Right | Align.VCenter));
946 combo1.selectedItemIndex = 3;
947 table.addChild(combo1).layoutWidth(FILL_PARENT);
948 // disabled readonly combo box
949 ComboBox combo2 = new ComboBox("combo2", ["item value 1"d, "item value 2"d, "item value 3"d]);
950 table.addChild((new TextWidget(null, "Disabled combo box"d)).alignment(Align.Right | Align.VCenter));
951 combo2.enabled = false;
952 combo2.selectedItemIndex = 0;
953 table.addChild(combo2).layoutWidth(FILL_PARENT);
954
955 table.margins(Rect(2,2,2,2)).layoutWidth(FILL_PARENT);
956 tabs.addTab(table, "TAB_TABLE_LAYOUT"c);
957
958 //tabs.addTab((new TextWidget()).id("tab5").textColor(0x00802000).text("Tab 5 contents"), "Tab 5"d);
959
960 //==========================================================================
961 // create Editors test tab
962 VerticalLayout editors = new VerticalLayout("editors");
963
964 // EditLine sample
965 editors.addChild(new TextWidget(null, "EditLine: Single line editor"d));
966 EditLine editLine = new EditLine("editline1", "Single line editor sample text");
967 editors.addChild(createEditorSettingsControl(editLine));
968 editors.addChild(editLine);
969 editLine.popupMenu = editPopupItem;
970
971 // EditBox sample
972 editors.addChild(new TextWidget(null, "SourceEdit: multiline editor, for source code editing"d));
973
974 SourceEdit editBox = new SourceEdit("editbox1");
975 editBox.text = q{#!/usr/bin/env rdmd
976 // Computes average line length for standard input.
977 import std.stdio;
978
979 void main()
980 {
981 ulong lines = 0;
982 double sumLength = 0;
983 foreach (line; stdin.byLine())
984 {
985 ++lines;
986 sumLength += line.length;
987 }
988 writeln("Average line length: ",
989 lines ? sumLength / lines : 0);
990 }
991 }};
992 editors.addChild(createEditorSettingsControl(editBox));
993 editors.addChild(editBox);
994 editBox.popupMenu = editPopupItem;
995
996 editors.addChild(new TextWidget(null, "EditBox: additional view for the same content (split view testing)"d));
997 SourceEdit editBox2 = new SourceEdit("editbox2");
998 editBox2.content = editBox.content; // view the same content as first editbox
999 editors.addChild(editBox2);
1000 editors.layoutHeight(FILL_PARENT).layoutWidth(FILL_PARENT);
1001
1002 tabs.addTab(editors, "TAB_EDITORS"c);
1003
1004 //==========================================================================
1005
1006 VerticalLayout gridContent = new VerticalLayout("GRID_CONTENT");
1007 gridContent.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
1008 HorizontalLayout gridSettings = new HorizontalLayout();
1009 StringGridWidget grid = new StringGridWidget("GRID1");
1010
1011 gridSettings.addChild((new CheckBox("fullColumnOnLeft", "fullColumnOnLeft"d)).checked(grid.fullColumnOnLeft).tooltipText("Extends scroll area to show full column at left when scrolled to rightmost column"d).addOnCheckChangeListener(delegate(Widget, bool checked) { grid.fullColumnOnLeft = checked; return true;}));
1012 gridSettings.addChild((new CheckBox("fullRowOnTop", "fullRowOnTop"d)).checked(grid.fullRowOnTop).tooltipText("Extends scroll area to show full row at top when scrolled to end row"d).addOnCheckChangeListener(delegate(Widget, bool checked) { grid.fullRowOnTop = checked; return true;}));
1013 gridContent.addChild(gridSettings);
1014
1015 grid.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
1016 grid.showColHeaders = true;
1017 grid.showRowHeaders = true;
1018 grid.resize(30, 50);
1019 grid.fixedCols = 3;
1020 grid.fixedRows = 2;
1021 //grid.rowSelect = true; // testing full row selection
1022 grid.multiSelect = true;
1023 grid.selectCell(4, 6, false);
1024 // create sample grid content
1025 for (int y = 0; y < grid.rows; y++) {
1026 for (int x = 0; x < grid.cols; x++) {
1027 grid.setCellText(x, y, "cell("d ~ to!dstring(x + 1) ~ ","d ~ to!dstring(y + 1) ~ ")"d);
1028 }
1029 grid.setRowTitle(y, to!dstring(y + 1));
1030 }
1031 for (int x = 0; x < grid.cols; x++) {
1032 int col = x + 1;
1033 dstring res;
1034 int n1 = col / 26;
1035 int n2 = col % 26;
1036 if (n1)
1037 res ~= n1 + 'A';
1038 res ~= n2 + 'A';
1039 grid.setColTitle(x, res);
1040 }
1041 grid.autoFit();
1042 gridContent.addChild(grid);
1043 tabs.addTab(gridContent, "Grid"d);
1044
1045 //==========================================================================
1046 // Scroll view example
1047 ScrollWidget scroll = new ScrollWidget("SCROLL1");
1048 scroll.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
1049 WidgetGroup scrollContent = new VerticalLayout("CONTENT");
1050 scrollContent.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
1051
1052 TableLayout table2 = new TableLayout("TABLE2");
1053 table2.colCount = 2;
1054 // headers
1055 table2.addChild((new TextWidget(null, "Parameter Name"d)).alignment(Align.Right | Align.VCenter));
1056 table2.addChild((new TextWidget(null, "Edit Box to edit parameter"d)).alignment(Align.Left | Align.VCenter));
1057 // row 1
1058 table2.addChild((new TextWidget(null, "Parameter 1 name"d)).alignment(Align.Right | Align.VCenter));
1059 table2.addChild((new EditLine("edit1", "Text 1"d)).layoutWidth(FILL_PARENT));
1060 // row 2
1061 table2.addChild((new TextWidget(null, "Parameter 2 name bla bla"d)).alignment(Align.Right | Align.VCenter));
1062 table2.addChild((new EditLine("edit2", "Some text for parameter 2 blah blah blah"d)).layoutWidth(FILL_PARENT));
1063 // row 3
1064 table2.addChild((new TextWidget(null, "Param 3"d)).alignment(Align.Right | Align.VCenter));
1065 table2.addChild((new EditLine("edit3", "Parameter 3 value"d)).layoutWidth(FILL_PARENT));
1066 // row 4
1067 table2.addChild((new TextWidget(null, "Param 4"d)).alignment(Align.Right | Align.VCenter));
1068 table2.addChild((new EditLine("edit3", "Parameter 4 value shdjksdfh hsjdfas hdjkf hdjsfk ah"d)).layoutWidth(FILL_PARENT));
1069 // row 5
1070 table2.addChild((new TextWidget(null, "Param 5 - edit text here - blah blah blah"d)).alignment(Align.Right | Align.VCenter));
1071 table2.addChild((new EditLine("edit3", "Parameter 5 value"d)).layoutWidth(FILL_PARENT));
1072 // row 6
1073 table2.addChild((new TextWidget(null, "Param 6 - just to fill content widget (DISABLED)"d)).alignment(Align.Right | Align.VCenter).enabled(false));
1074 table2.addChild((new EditLine("edit3", "Parameter 5 value"d)).layoutWidth(FILL_PARENT).enabled(false));
1075 // row 7
1076 table2.addChild((new TextWidget(null, "Param 7 - just to fill content widget (DISABLED)"d)).alignment(Align.Right | Align.VCenter).enabled(false));
1077 table2.addChild((new EditLine("edit3", "Parameter 5 value"d)).layoutWidth(FILL_PARENT).enabled(false));
1078 // row 8
1079 table2.addChild((new TextWidget(null, "Param 8 - just to fill content widget"d)).alignment(Align.Right | Align.VCenter));
1080 table2.addChild((new EditLine("edit3", "Parameter 5 value"d)).layoutWidth(FILL_PARENT));
1081 table2.margins(Rect(10,10,10,10)).layoutWidth(FILL_PARENT);
1082 scrollContent.addChild(table2);
1083
1084 scrollContent.addChild(new TextWidget(null, "Now - some buttons"d));
1085 scrollContent.addChild(new ImageTextButton("btn1", "fileclose", "Close"d));
1086 scrollContent.addChild(new ImageTextButton("btn2", "fileopen", "Open"d));
1087 scrollContent.addChild(new TextWidget(null, "And checkboxes"d));
1088 scrollContent.addChild(new CheckBox("btn1", "CheckBox 1"d));
1089 scrollContent.addChild(new CheckBox("btn2", "CheckBox 2"d));
1090
1091 scroll.contentWidget = scrollContent;
1092 tabs.addTab(scroll, "Scroll"d);
1093 //==========================================================================
1094 // tree view example
1095 TreeWidget tree = new TreeWidget("TREE1");
1096 tree.layoutWidth(WRAP_CONTENT).layoutHeight(FILL_PARENT);
1097 TreeItem tree1 = tree.items.newChild("group1", "Group 1"d, "document-open");
1098 tree1.newChild("g1_1", "Group 1 item 1"d);
1099 tree1.newChild("g1_2", "Group 1 item 2"d);
1100 tree1.newChild("g1_3", "Group 1 item 3"d);
1101 TreeItem tree2 = tree.items.newChild("group2", "Group 2"d, "document-save");
1102 tree2.newChild("g2_1", "Group 2 item 1"d, "edit-copy");
1103 tree2.newChild("g2_2", "Group 2 item 2"d, "edit-cut");
1104 tree2.newChild("g2_3", "Group 2 item 3"d, "edit-paste");
1105 tree2.newChild("g2_4", "Group 2 item 4"d);
1106 TreeItem tree3 = tree.items.newChild("group3", "Group 3"d);
1107 tree3.newChild("g3_1", "Group 3 item 1"d);
1108 tree3.newChild("g3_2", "Group 3 item 2"d);
1109 TreeItem tree32 = tree3.newChild("g3_3", "Group 3 item 3"d);
1110 tree3.newChild("g3_4", "Group 3 item 4"d);
1111 tree32.newChild("group3_2_1", "Group 3 item 2 subitem 1"d);
1112 tree32.newChild("group3_2_2", "Group 3 item 2 subitem 2"d);
1113 tree32.newChild("group3_2_3", "Group 3 item 2 subitem 3"d);
1114 tree32.newChild("group3_2_4", "Group 3 item 2 subitem 4"d);
1115 tree32.newChild("group3_2_5", "Group 3 item 2 subitem 5"d);
1116 tree3.newChild("g3_5", "Group 3 item 5"d);
1117 tree3.newChild("g3_6", "Group 3 item 6"d);
1118
1119 LinearLayout treeLayout = new HorizontalLayout("TREE");
1120 LinearLayout treeControlledPanel = new VerticalLayout();
1121 treeLayout.layoutWidth = FILL_PARENT;
1122 treeControlledPanel.layoutWidth = FILL_PARENT;
1123 treeControlledPanel.layoutHeight = FILL_PARENT;
1124 TextWidget treeItemLabel = new TextWidget("TREE_ITEM_DESC");
1125 treeItemLabel.layoutWidth = FILL_PARENT;
1126 treeItemLabel.layoutHeight = FILL_PARENT;
1127 treeItemLabel.alignment = Align.Center;
1128 treeItemLabel.text = "Sample text"d;
1129 treeControlledPanel.addChild(treeItemLabel);
1130 treeLayout.addChild(tree);
1131 treeLayout.addChild(new ResizerWidget());
1132 treeLayout.addChild(treeControlledPanel);
1133
1134 tree.selectionChange = delegate(TreeItems source, TreeItem selectedItem, bool activated) {
1135 dstring label = "Selected item: "d ~ toUTF32(selectedItem.id) ~ (activated ? " selected + activated"d : " selected"d);
1136 treeItemLabel.text = label;
1137 };
1138
1139 tree.items.selectItem(tree.items.child(0));
1140
1141 tabs.addTab(treeLayout, "Tree"d);
1142 //==========================================================================
1143 // charts example
1144 SimpleBarChart barChart1 = new SimpleBarChart("barChart1","SimpleBarChart Example"d);
1145 barChart1.addBar(12.0, makeRGBA(255,0,0,0), "Red bar"d);
1146 barChart1.addBar(24.0, makeRGBA(0,255,0,0), "Green bar"d);
1147 barChart1.addBar(5.0, makeRGBA(0,0,255,0), "Blue bar"d);
1148 barChart1.addBar(12.0, makeRGBA(230,126,34,0), "Orange bar"d);
1149 //barChart1.layoutWidth = FILL_PARENT;
1150 //barChart1.layoutHeight = FILL_PARENT;
1151
1152 SimpleBarChart barChart2 = new SimpleBarChart("barChart2","SimpleBarChart Example - long descriptions"d);
1153 barChart2.addBar(12.0, makeRGBA(255,0,0,0), "Red bar\n(12.0)"d);
1154 barChart2.addBar(24.0, makeRGBA(0,255,0,0), "Green bar\n(24.0)"d);
1155 barChart2.addBar(5.0, makeRGBA(0,0,255,0), "Blue bar\n(5.0)"d);
1156 barChart2.addBar(12.0, makeRGBA(230,126,34,0), "Orange bar\n(12.0)\nlong long long description added here"d);
1157
1158 SimpleBarChart barChart3 = new SimpleBarChart("barChart3","SimpleBarChart Example with axis ratio 0.3"d);
1159 barChart3.addBar(12.0, makeRGBA(255,0,0,0), "Red bar"d);
1160 barChart3.addBar(24.0, makeRGBA(0,255,0,0), "Green bar"d);
1161 barChart3.addBar(5.0, makeRGBA(0,0,255,0), "Blue bar"d);
1162 barChart3.addBar(12.0, makeRGBA(230,126,34,0), "Orange bar"d);
1163 barChart3.axisRatio = 0.3;
1164
1165 SimpleBarChart barChart4 = new SimpleBarChart("barChart4","SimpleBarChart Example with axis ratio 1.3"d);
1166 barChart4.addBar(12.0, makeRGBA(255,0,0,0), "Red bar"d);
1167 barChart4.addBar(24.0, makeRGBA(0,255,0,0), "Green bar"d);
1168 barChart4.addBar(5.0, makeRGBA(0,0,255,0), "Blue bar"d);
1169 barChart4.addBar(12.0, makeRGBA(230,126,34,0), "Orange bar"d);
1170 barChart4.axisRatio = 1.3;
1171
1172 HorizontalLayout chartsLayout = new HorizontalLayout("CHARTS");
1173 chartsLayout.layoutWidth = FILL_PARENT;
1174 chartsLayout.layoutHeight = FILL_PARENT;
1175
1176 VerticalLayout chartColumn1 = new VerticalLayout();
1177 VerticalLayout chartColumn2 = new VerticalLayout();
1178
1179 chartColumn1.addChild(barChart1);
1180 chartColumn1.addChild(barChart2);
1181 chartsLayout.addChild(chartColumn1);
1182 chartColumn2.addChild(barChart3);
1183 chartColumn2.addChild(barChart4);
1184 chartsLayout.addChild(chartColumn2);
1185 tabs.addTab(chartsLayout, "Charts"d);
1186
1187 static if (BACKEND_GUI) {
1188
1189 tabs.addTab((new SampleAnimationWidget("tab6")).layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT), "TAB_ANIMATION"c);
1190
1191 CanvasWidget canvas = new CanvasWidget("canvas");
1192 canvas.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
1193 canvas.onDrawListener = delegate(CanvasWidget canvas, DrawBuf buf, Rect rc) {
1194 //Log.w("canvas.onDrawListener clipRect=" ~ to!string(buf.clipRect));
1195 buf.fill(0xFFFFFF);
1196 int x = rc.left;
1197 int y = rc.top;
1198 buf.fillRect(Rect(x+20, y+20, x+150, y+200), 0x80FF80);
1199 buf.fillRect(Rect(x+90, y+80, x+250, y+250), 0x80FF80FF);
1200 canvas.font.drawText(buf, x + 40, y + 50, "fillRect()"d, 0xC080C0);
1201 buf.drawFrame(Rect(x + 400, y + 30, x + 550, y + 150), 0x204060, Rect(2,3,4,5), 0x80704020);
1202 canvas.font.drawText(buf, x + 400, y + 5, "drawFrame()"d, 0x208020);
1203 canvas.font.drawText(buf, x + 300, y + 100, "drawPixel()"d, 0x000080);
1204 for (int i = 0; i < 80; i++)
1205 buf.drawPixel(x+300 + i * 4, y+140 + i * 3 % 100, 0xFF0000 + i * 2);
1206 canvas.font.drawText(buf, x + 300, y + 420, "drawLine()"d, 0x800020);
1207 for (int i = 0; i < 40; i+=3)
1208 buf.drawLine(Point(x+200 + i * 4, y+290), Point(x+150 + i * 7, y+420 + i * 2), 0x008000 + i * 5);
1209 // poly line test
1210 //Rect newClipRect = Rect(x + 110, y + 100, x + 350, y + 320);
1211 //buf.fillRect(newClipRect, 0xC08080FF);
1212 //Rect oldClip = buf.clipRect;
1213 //buf.clipRect = newClipRect;
1214 PointF[] poly = [vec2(x+130, y+150), vec2(x+240, y+80), vec2(x+170, y+170), vec2(x+380, y+270), vec2(x+220, y+400), vec2(x+130, y+330)];
1215 buf.polyLineF(poly, 18.0f, 0x80804020, true, 0x80FFFF00);
1216 //buf.fillTriangleF(vec2(x+230, y+50), vec2(x+400, y+250), vec2(x+130, y+200), 0xC0FF0000);
1217 //buf.fillTriangleF(vec2(x+230, y+250), vec2(x+200, y+350), vec2(x+80, y+200), 0xC000FF00);
1218 //buf.fillTriangleF(vec2(x+430, y+250), vec2(x+280, y+150), vec2(x+200, y+300), 0xC00000FF);
1219 //buf.fillTriangleF(vec2(x+80, y+150), vec2(x+280, y+250), vec2(x+80, y+200), 0xC0008080);
1220 //buf.clipRect = oldClip;
1221 canvas.font.drawText(buf, x + 190, y + 260, "polyLineF()"d, 0x603010);
1222 PointF[] poly2 = [vec2(x+430, y+250), vec2(x+540, y+180), vec2(x+470, y+270), vec2(x+580, y+300),
1223 vec2(x+620, y+400), vec2(x+480, y+350), vec2(x+520, y+450), vec2(x+480, y+430)];
1224 buf.fillPolyF(poly2, 0x80203050);
1225 //buf.polyLineF(poly2, 2.0f, 0x80000000, true);
1226 canvas.font.drawText(buf, x + 500, y + 460, "fillPolyF()"d, 0x203050);
1227
1228 buf.drawEllipseF(x+300, y+600, 200, 150, 3, 0x80008000, 0x804040FF);
1229 canvas.font.drawText(buf, x + 300, y + 600, "fillEllipseF()"d, 0x208050);
1230
1231 buf.drawEllipseArcF(x+540, y+600, 150, 180, 45, 130, 3, 0x40008000, 0x804040FF);
1232 canvas.font.drawText(buf, x + 540, y + 580, "drawEllipseArcF()"d, 0x208050);
1233 };
1234 tabs.addTab(canvas, "TAB_CANVAS"c);
1235
1236 static if (ENABLE_OPENGL) {
1237 //
1238 tabs.addTab(new MyOpenglWidget(), "OpenGL"d);
1239 }
1240
1241 {
1242 import dlangui.graphics.iconprovider;
1243 TableLayout icons = new TableLayout("icons");
1244 icons.colCount = 6;
1245 for(StandardIcon icon = StandardIcon.init; icon <= StandardIcon.deviceCameraVideo; ++icon)
1246 {
1247 icons.addChild(new TextWidget(to!string(icon), to!dstring(icon)).fontSize(12.pointsToPixels).alignment(Align.Right | Align.VCenter));
1248 auto imageBufRef = platform.iconProvider().getStandardIcon(icon);
1249 auto imageWidget = new ImageWidget();
1250 if (!imageBufRef.isNull()) {
1251 auto imageDrawable = new ImageDrawable(imageBufRef);
1252 imageWidget.drawable = imageDrawable;
1253 }
1254 icons.addChild(imageWidget).alignment(Align.Left | Align.VCenter);
1255 }
1256 icons.margins(Rect(10,10,10,10)).layoutWidth(FILL_PARENT);
1257 tabs.addTab(icons, "Icons"d);
1258 }
1259 }
1260
1261 //==========================================================================
1262
1263 contentLayout.addChild(tabs);
1264 window.mainWidget = contentLayout;
1265
1266 tabs.selectTab("controls");
1267 } else {
1268 window.mainWidget = (new Button()).text("sample button");
1269 }
1270 static if (BACKEND_GUI) {
1271 window.windowIcon = drawableCache.getImage("dlangui-logo1");
1272 }
1273 window.show();
1274 //window.windowCaption = "New Window Caption";
1275 // run message loop
1276
1277 Log.i("HOME path: ", homePath);
1278 Log.i("APPDATA path: ", appDataPath(".dlangui"));
1279 Log.i("Root paths: ", getRootPaths);
1280
1281 return Platform.instance.enterMessageLoop();
1282 }
1283
1284 static if (ENABLE_OPENGL) {
1285
1286 import derelict.opengl; //3.gl3;
1287 //import derelict.opengl3.gl;
1288
1289 class MyOpenglWidget : VerticalLayout {
1290 this() {
1291 super("OpenGLView");
1292 layoutWidth = FILL_PARENT;
1293 layoutHeight = FILL_PARENT;
1294 alignment = Align.Center;
1295 // add some UI on top of OpenGL drawable
1296 Widget w = parseML(q{
1297 VerticalLayout {
1298 alignment: center
1299 layoutWidth: fill; layoutHeight: fill
1300 // background for window - tiled texture
1301 backgroundImageId: "tx_fabric.tiled"
1302 VerticalLayout {
1303 // child widget - will draw using OpenGL here
1304 id: glView
1305 margins: 20
1306 padding: 20
1307 layoutWidth: fill; layoutHeight: fill
1308
1309 //backgroundColor: "#C0E0E070" // semitransparent yellow background
1310 // red bold text with size = 150% of base style size and font face Arial
1311 TextWidget { text: "Some controls to draw on top of OpenGL scene"; textColor: "red"; fontSize: 150%; fontWeight: 800; fontFace: "Arial" }
1312 // arrange controls as form - table with two columns
1313 TableLayout {
1314 colCount: 2
1315 TextWidget { text: "param 1" }
1316 EditLine { id: edit1; text: "some text" }
1317 TextWidget { text: "param 2" }
1318 EditLine { id: edit2; text: "some text for param2" }
1319 TextWidget { text: "some radio buttons" }
1320 // arrange some radio buttons vertically
1321 VerticalLayout {
1322 RadioButton { id: rb1; text: "Item 1" }
1323 RadioButton { id: rb2; text: "Item 2" }
1324 RadioButton { id: rb3; text: "Item 3" }
1325 }
1326 TextWidget { text: "and checkboxes" }
1327 // arrange some checkboxes horizontally
1328 HorizontalLayout {
1329 CheckBox { id: cb1; text: "checkbox 1" }
1330 CheckBox { id: cb2; text: "checkbox 2" }
1331 }
1332 }
1333 VSpacer { layoutWeight: 10 }
1334 HorizontalLayout {
1335 Button { id: btnOk; text: "Ok" }
1336 Button { id: btnCancel; text: "Cancel" }
1337 }
1338 }
1339 }
1340 });
1341 // setting OpenGL background drawable for one of child widgets
1342 w.childById("glView").backgroundDrawable = DrawableRef(new OpenGLDrawable(&doDraw));
1343 addChild(w);
1344 }
1345
1346 bool _oldApi;
1347
1348 /// this is OpenGLDrawableDelegate implementation
1349 private void doDraw(Rect windowRect, Rect rc) {
1350 if (!openglEnabled) {
1351 Log.v("GlGears: OpenGL is disabled");
1352 return;
1353 }
1354 import dlangui.graphics.glsupport : glSupport;
1355 _oldApi = glSupport.legacyMode;
1356 if (_oldApi) {
1357 drawUsingOldAPI(rc);
1358 } else {
1359 drawUsingNewAPI(rc);
1360 }
1361 }
1362
1363 /// Legacy API example (glBegin/glEnd)
1364 void drawUsingOldAPI(Rect rc) {
1365 /*
1366 static bool _initCalled;
1367 if (!_initCalled) {
1368 Log.d("GlGears: calling init()");
1369 _initCalled = true;
1370 glxgears_init();
1371 }
1372 glxgears_reshape(rc);
1373 glEnable(GL_LIGHTING);
1374 glEnable(GL_LIGHT0);
1375 glEnable(GL_DEPTH_TEST);
1376 glxgears_draw();
1377 glDisable(GL_LIGHTING);
1378 glDisable(GL_LIGHT0);
1379 glDisable(GL_DEPTH_TEST);
1380 */
1381 }
1382
1383 /// New API example (OpenGL3+, shaders)
1384 void drawUsingNewAPI(Rect rc) {
1385 // TODO: put some sample code here
1386 }
1387 /// returns true is widget is being animated - need to call animate() and redraw
1388 @property override bool animating() { return true; }
1389 /// animates window; interval is time left from previous draw, in hnsecs (1/10000000 of second)
1390 override void animate(long interval) {
1391 if (_oldApi) {
1392 // animate legacy API example
1393 // rotate gears
1394 angle += interval * 0.000002f;
1395 } else {
1396 // TODO: animate new API example
1397 }
1398 invalidate();
1399 }
1400 }
1401
1402 static __gshared GLfloat angle = 0.0;
1403
1404 version (GLLegacyAPI) {
1405
1406 // Sample project for old API: GlxGears
1407
1408 import std.math;
1409 static __gshared GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
1410 static __gshared GLint gear1, gear2, gear3;
1411 alias M_PI = std.math.PI;
1412
1413 /*
1414 *
1415 * Draw a gear wheel. You'll probably want to call this function when
1416 * building a display list since we do a lot of trig here.
1417 *
1418 * Input: inner_radius - radius of hole at center
1419 * outer_radius - radius at center of teeth
1420 * width - width of gear
1421 * teeth - number of teeth
1422 * tooth_depth - depth of tooth
1423 */
1424
1425 static void
1426 gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
1427 GLint teeth, GLfloat tooth_depth)
1428 {
1429 GLint i;
1430 GLfloat r0, r1, r2;
1431 GLfloat angle, da;
1432 GLfloat u, v, len;
1433
1434 r0 = inner_radius;
1435 r1 = outer_radius - tooth_depth / 2.0;
1436 r2 = outer_radius + tooth_depth / 2.0;
1437
1438 da = 2.0 * M_PI / teeth / 4.0;
1439
1440 glShadeModel(GL_FLAT);
1441
1442 glNormal3f(0.0, 0.0, 1.0);
1443
1444 /* draw front face */
1445 glBegin(GL_QUAD_STRIP);
1446 for (i = 0; i <= teeth; i++) {
1447 angle = i * 2.0 * M_PI / teeth;
1448 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
1449 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
1450 if (i < teeth) {
1451 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
1452 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
1453 width * 0.5);
1454 }
1455 }
1456 glEnd();
1457
1458 /* draw front sides of teeth */
1459 glBegin(GL_QUADS);
1460 da = 2.0 * M_PI / teeth / 4.0;
1461 for (i = 0; i < teeth; i++) {
1462 angle = i * 2.0 * M_PI / teeth;
1463
1464 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
1465 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
1466 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
1467 width * 0.5);
1468 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
1469 width * 0.5);
1470 }
1471 glEnd();
1472
1473 glNormal3f(0.0, 0.0, -1.0);
1474
1475 /* draw back face */
1476 glBegin(GL_QUAD_STRIP);
1477 for (i = 0; i <= teeth; i++) {
1478 angle = i * 2.0 * M_PI / teeth;
1479 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
1480 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
1481 if (i < teeth) {
1482 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
1483 -width * 0.5);
1484 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
1485 }
1486 }
1487 glEnd();
1488
1489 /* draw back sides of teeth */
1490 glBegin(GL_QUADS);
1491 da = 2.0 * M_PI / teeth / 4.0;
1492 for (i = 0; i < teeth; i++) {
1493 angle = i * 2.0 * M_PI / teeth;
1494
1495 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
1496 -width * 0.5);
1497 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
1498 -width * 0.5);
1499 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
1500 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
1501 }
1502 glEnd();
1503
1504 /* draw outward faces of teeth */
1505 glBegin(GL_QUAD_STRIP);
1506 for (i = 0; i < teeth; i++) {
1507 angle = i * 2.0 * M_PI / teeth;
1508
1509 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
1510 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
1511 u = r2 * cos(angle + da) - r1 * cos(angle);
1512 v = r2 * sin(angle + da) - r1 * sin(angle);
1513 len = sqrt(u * u + v * v);
1514 u /= len;
1515 v /= len;
1516 glNormal3f(v, -u, 0.0);
1517 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
1518 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
1519 glNormal3f(cos(angle), sin(angle), 0.0);
1520 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
1521 width * 0.5);
1522 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da),
1523 -width * 0.5);
1524 u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
1525 v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
1526 glNormal3f(v, -u, 0.0);
1527 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
1528 width * 0.5);
1529 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da),
1530 -width * 0.5);
1531 glNormal3f(cos(angle), sin(angle), 0.0);
1532 }
1533
1534 glVertex3f(r1 * cos(0.0), r1 * sin(0.0), width * 0.5);
1535 glVertex3f(r1 * cos(0.0), r1 * sin(0.0), -width * 0.5);
1536
1537 glEnd();
1538
1539 glShadeModel(GL_SMOOTH);
1540
1541 /* draw inside radius cylinder */
1542 glBegin(GL_QUAD_STRIP);
1543 for (i = 0; i <= teeth; i++) {
1544 angle = i * 2.0 * M_PI / teeth;
1545 glNormal3f(-cos(angle), -sin(angle), 0.0);
1546 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
1547 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
1548 }
1549 glEnd();
1550 }
1551
1552
1553 static void glxgears_draw()
1554 {
1555 glClear(/*GL_COLOR_BUFFER_BIT | */GL_DEPTH_BUFFER_BIT);
1556
1557 glPushMatrix();
1558 glRotatef(view_rotx, 1.0, 0.0, 0.0);
1559 glRotatef(view_roty, 0.0, 1.0, 0.0);
1560 glRotatef(view_rotz, 0.0, 0.0, 1.0);
1561
1562 glPushMatrix();
1563 glTranslatef(-3.0, -2.0, 0.0);
1564 glRotatef(angle, 0.0, 0.0, 1.0);
1565 glCallList(gear1);
1566 glPopMatrix();
1567
1568 glPushMatrix();
1569 glTranslatef(3.1, -2.0, 0.0);
1570 glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
1571 glCallList(gear2);
1572 glPopMatrix();
1573
1574 glPushMatrix();
1575 glTranslatef(-3.1, 4.2, 0.0);
1576 glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
1577 glCallList(gear3);
1578 glPopMatrix();
1579
1580 glPopMatrix();
1581 }
1582
1583
1584 /* new window size or exposure */
1585 static void
1586 glxgears_reshape(Rect rc)
1587 {
1588 GLfloat h = cast(GLfloat) rc.height / cast(GLfloat) rc.width;
1589 glMatrixMode(GL_PROJECTION);
1590 glLoadIdentity();
1591 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0);
1592 glMatrixMode(GL_MODELVIEW);
1593 glLoadIdentity();
1594 glTranslatef(0.0, 0.0, -40.0);
1595 }
1596
1597
1598 static void glxgears_init()
1599 {
1600 static GLfloat[4] pos = [ 5.0, 5.0, 10.0, 0.0 ];
1601 static GLfloat[4] red = [ 0.8, 0.1, 0.0, 1.0 ];
1602 static GLfloat[4] green = [ 0.0, 0.8, 0.2, 1.0 ];
1603 static GLfloat[4] blue = [ 0.2, 0.2, 1.0, 1.0 ];
1604
1605 glLightfv(GL_LIGHT0, GL_POSITION, pos.ptr);
1606 glEnable(GL_CULL_FACE);
1607 glEnable(GL_LIGHTING);
1608 glEnable(GL_LIGHT0);
1609 glEnable(GL_DEPTH_TEST);
1610
1611 /* make the gears */
1612 gear1 = glGenLists(1);
1613 glNewList(gear1, GL_COMPILE);
1614 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red.ptr);
1615 gear(1.0, 4.0, 1.0, 20, 0.7);
1616 glEndList();
1617
1618 gear2 = glGenLists(1);
1619 glNewList(gear2, GL_COMPILE);
1620 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green.ptr);
1621 gear(0.5, 2.0, 2.0, 10, 0.7);
1622 glEndList();
1623
1624 gear3 = glGenLists(1);
1625 glNewList(gear3, GL_COMPILE);
1626 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue.ptr);
1627 gear(1.3, 2.0, 0.5, 10, 0.7);
1628 glEndList();
1629
1630 glEnable(GL_NORMALIZE);
1631 }
1632
1633 }
1634 }