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 bindbc.opengl; 1287 1288 class MyOpenglWidget : VerticalLayout { 1289 this() { 1290 super("OpenGLView"); 1291 layoutWidth = FILL_PARENT; 1292 layoutHeight = FILL_PARENT; 1293 alignment = Align.Center; 1294 // add some UI on top of OpenGL drawable 1295 Widget w = parseML(q{ 1296 VerticalLayout { 1297 alignment: center 1298 layoutWidth: fill; layoutHeight: fill 1299 // background for window - tiled texture 1300 backgroundImageId: "tx_fabric.tiled" 1301 VerticalLayout { 1302 // child widget - will draw using OpenGL here 1303 id: glView 1304 margins: 20 1305 padding: 20 1306 layoutWidth: fill; layoutHeight: fill 1307 1308 //backgroundColor: "#C0E0E070" // semitransparent yellow background 1309 // red bold text with size = 150% of base style size and font face Arial 1310 TextWidget { text: "Some controls to draw on top of OpenGL scene"; textColor: "red"; fontSize: 150%; fontWeight: 800; fontFace: "Arial" } 1311 // arrange controls as form - table with two columns 1312 TableLayout { 1313 colCount: 2 1314 TextWidget { text: "param 1" } 1315 EditLine { id: edit1; text: "some text" } 1316 TextWidget { text: "param 2" } 1317 EditLine { id: edit2; text: "some text for param2" } 1318 TextWidget { text: "some radio buttons" } 1319 // arrange some radio buttons vertically 1320 VerticalLayout { 1321 RadioButton { id: rb1; text: "Item 1" } 1322 RadioButton { id: rb2; text: "Item 2" } 1323 RadioButton { id: rb3; text: "Item 3" } 1324 } 1325 TextWidget { text: "and checkboxes" } 1326 // arrange some checkboxes horizontally 1327 HorizontalLayout { 1328 CheckBox { id: cb1; text: "checkbox 1" } 1329 CheckBox { id: cb2; text: "checkbox 2" } 1330 } 1331 } 1332 VSpacer { layoutWeight: 10 } 1333 HorizontalLayout { 1334 Button { id: btnOk; text: "Ok" } 1335 Button { id: btnCancel; text: "Cancel" } 1336 } 1337 } 1338 } 1339 }); 1340 // setting OpenGL background drawable for one of child widgets 1341 w.childById("glView").backgroundDrawable = DrawableRef(new OpenGLDrawable(&doDraw)); 1342 addChild(w); 1343 } 1344 1345 bool _oldApi; 1346 1347 /// this is OpenGLDrawableDelegate implementation 1348 private void doDraw(Rect windowRect, Rect rc) { 1349 if (!openglEnabled) { 1350 Log.v("GlGears: OpenGL is disabled"); 1351 return; 1352 } 1353 import dlangui.graphics.glsupport : glSupport; 1354 _oldApi = glSupport.legacyMode; 1355 if (_oldApi) { 1356 drawUsingOldAPI(rc); 1357 } else { 1358 drawUsingNewAPI(rc); 1359 } 1360 } 1361 1362 /// Legacy API example (glBegin/glEnd) 1363 void drawUsingOldAPI(Rect rc) { 1364 /* 1365 static bool _initCalled; 1366 if (!_initCalled) { 1367 Log.d("GlGears: calling init()"); 1368 _initCalled = true; 1369 glxgears_init(); 1370 } 1371 glxgears_reshape(rc); 1372 glEnable(GL_LIGHTING); 1373 glEnable(GL_LIGHT0); 1374 glEnable(GL_DEPTH_TEST); 1375 glxgears_draw(); 1376 glDisable(GL_LIGHTING); 1377 glDisable(GL_LIGHT0); 1378 glDisable(GL_DEPTH_TEST); 1379 */ 1380 } 1381 1382 /// New API example (OpenGL3+, shaders) 1383 void drawUsingNewAPI(Rect rc) { 1384 // TODO: put some sample code here 1385 } 1386 /// returns true is widget is being animated - need to call animate() and redraw 1387 @property override bool animating() { return true; } 1388 /// animates window; interval is time left from previous draw, in hnsecs (1/10000000 of second) 1389 override void animate(long interval) { 1390 if (_oldApi) { 1391 // animate legacy API example 1392 // rotate gears 1393 angle += interval * 0.000002f; 1394 } else { 1395 // TODO: animate new API example 1396 } 1397 invalidate(); 1398 } 1399 } 1400 1401 static __gshared GLfloat angle = 0.0; 1402 1403 version (GLLegacyAPI) { 1404 1405 // Sample project for old API: GlxGears 1406 1407 import std.math; 1408 static __gshared GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; 1409 static __gshared GLint gear1, gear2, gear3; 1410 alias M_PI = std.math.PI; 1411 1412 /* 1413 * 1414 * Draw a gear wheel. You'll probably want to call this function when 1415 * building a display list since we do a lot of trig here. 1416 * 1417 * Input: inner_radius - radius of hole at center 1418 * outer_radius - radius at center of teeth 1419 * width - width of gear 1420 * teeth - number of teeth 1421 * tooth_depth - depth of tooth 1422 */ 1423 1424 static void 1425 gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, 1426 GLint teeth, GLfloat tooth_depth) 1427 { 1428 GLint i; 1429 GLfloat r0, r1, r2; 1430 GLfloat angle, da; 1431 GLfloat u, v, len; 1432 1433 r0 = inner_radius; 1434 r1 = outer_radius - tooth_depth / 2.0; 1435 r2 = outer_radius + tooth_depth / 2.0; 1436 1437 da = 2.0 * M_PI / teeth / 4.0; 1438 1439 glShadeModel(GL_FLAT); 1440 1441 glNormal3f(0.0, 0.0, 1.0); 1442 1443 /* draw front face */ 1444 glBegin(GL_QUAD_STRIP); 1445 for (i = 0; i <= teeth; i++) { 1446 angle = i * 2.0 * M_PI / teeth; 1447 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 1448 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 1449 if (i < teeth) { 1450 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 1451 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 1452 width * 0.5); 1453 } 1454 } 1455 glEnd(); 1456 1457 /* draw front sides of teeth */ 1458 glBegin(GL_QUADS); 1459 da = 2.0 * M_PI / teeth / 4.0; 1460 for (i = 0; i < teeth; i++) { 1461 angle = i * 2.0 * M_PI / teeth; 1462 1463 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 1464 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); 1465 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 1466 width * 0.5); 1467 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 1468 width * 0.5); 1469 } 1470 glEnd(); 1471 1472 glNormal3f(0.0, 0.0, -1.0); 1473 1474 /* draw back face */ 1475 glBegin(GL_QUAD_STRIP); 1476 for (i = 0; i <= teeth; i++) { 1477 angle = i * 2.0 * M_PI / teeth; 1478 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 1479 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 1480 if (i < teeth) { 1481 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 1482 -width * 0.5); 1483 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 1484 } 1485 } 1486 glEnd(); 1487 1488 /* draw back sides of teeth */ 1489 glBegin(GL_QUADS); 1490 da = 2.0 * M_PI / teeth / 4.0; 1491 for (i = 0; i < teeth; i++) { 1492 angle = i * 2.0 * M_PI / teeth; 1493 1494 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 1495 -width * 0.5); 1496 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 1497 -width * 0.5); 1498 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); 1499 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 1500 } 1501 glEnd(); 1502 1503 /* draw outward faces of teeth */ 1504 glBegin(GL_QUAD_STRIP); 1505 for (i = 0; i < teeth; i++) { 1506 angle = i * 2.0 * M_PI / teeth; 1507 1508 glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); 1509 glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); 1510 u = r2 * cos(angle + da) - r1 * cos(angle); 1511 v = r2 * sin(angle + da) - r1 * sin(angle); 1512 len = sqrt(u * u + v * v); 1513 u /= len; 1514 v /= len; 1515 glNormal3f(v, -u, 0.0); 1516 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); 1517 glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); 1518 glNormal3f(cos(angle), sin(angle), 0.0); 1519 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 1520 width * 0.5); 1521 glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), 1522 -width * 0.5); 1523 u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); 1524 v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); 1525 glNormal3f(v, -u, 0.0); 1526 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 1527 width * 0.5); 1528 glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), 1529 -width * 0.5); 1530 glNormal3f(cos(angle), sin(angle), 0.0); 1531 } 1532 1533 glVertex3f(r1 * cos(0.0), r1 * sin(0.0), width * 0.5); 1534 glVertex3f(r1 * cos(0.0), r1 * sin(0.0), -width * 0.5); 1535 1536 glEnd(); 1537 1538 glShadeModel(GL_SMOOTH); 1539 1540 /* draw inside radius cylinder */ 1541 glBegin(GL_QUAD_STRIP); 1542 for (i = 0; i <= teeth; i++) { 1543 angle = i * 2.0 * M_PI / teeth; 1544 glNormal3f(-cos(angle), -sin(angle), 0.0); 1545 glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); 1546 glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); 1547 } 1548 glEnd(); 1549 } 1550 1551 1552 static void glxgears_draw() 1553 { 1554 glClear(/*GL_COLOR_BUFFER_BIT | */GL_DEPTH_BUFFER_BIT); 1555 1556 glPushMatrix(); 1557 glRotatef(view_rotx, 1.0, 0.0, 0.0); 1558 glRotatef(view_roty, 0.0, 1.0, 0.0); 1559 glRotatef(view_rotz, 0.0, 0.0, 1.0); 1560 1561 glPushMatrix(); 1562 glTranslatef(-3.0, -2.0, 0.0); 1563 glRotatef(angle, 0.0, 0.0, 1.0); 1564 glCallList(gear1); 1565 glPopMatrix(); 1566 1567 glPushMatrix(); 1568 glTranslatef(3.1, -2.0, 0.0); 1569 glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); 1570 glCallList(gear2); 1571 glPopMatrix(); 1572 1573 glPushMatrix(); 1574 glTranslatef(-3.1, 4.2, 0.0); 1575 glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); 1576 glCallList(gear3); 1577 glPopMatrix(); 1578 1579 glPopMatrix(); 1580 } 1581 1582 1583 /* new window size or exposure */ 1584 static void 1585 glxgears_reshape(Rect rc) 1586 { 1587 GLfloat h = cast(GLfloat) rc.height / cast(GLfloat) rc.width; 1588 glMatrixMode(GL_PROJECTION); 1589 glLoadIdentity(); 1590 glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); 1591 glMatrixMode(GL_MODELVIEW); 1592 glLoadIdentity(); 1593 glTranslatef(0.0, 0.0, -40.0); 1594 } 1595 1596 1597 static void glxgears_init() 1598 { 1599 static GLfloat[4] pos = [ 5.0, 5.0, 10.0, 0.0 ]; 1600 static GLfloat[4] red = [ 0.8, 0.1, 0.0, 1.0 ]; 1601 static GLfloat[4] green = [ 0.0, 0.8, 0.2, 1.0 ]; 1602 static GLfloat[4] blue = [ 0.2, 0.2, 1.0, 1.0 ]; 1603 1604 glLightfv(GL_LIGHT0, GL_POSITION, pos.ptr); 1605 glEnable(GL_CULL_FACE); 1606 glEnable(GL_LIGHTING); 1607 glEnable(GL_LIGHT0); 1608 glEnable(GL_DEPTH_TEST); 1609 1610 /* make the gears */ 1611 gear1 = glGenLists(1); 1612 glNewList(gear1, GL_COMPILE); 1613 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red.ptr); 1614 gear(1.0, 4.0, 1.0, 20, 0.7); 1615 glEndList(); 1616 1617 gear2 = glGenLists(1); 1618 glNewList(gear2, GL_COMPILE); 1619 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green.ptr); 1620 gear(0.5, 2.0, 2.0, 10, 0.7); 1621 glEndList(); 1622 1623 gear3 = glGenLists(1); 1624 glNewList(gear3, GL_COMPILE); 1625 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue.ptr); 1626 gear(1.3, 2.0, 0.5, 10, 0.7); 1627 glEndList(); 1628 1629 glEnable(GL_NORMALIZE); 1630 } 1631 1632 } 1633 }