diff --git a/README.md b/README.md
index b5b38e28..570b438e 100644
--- a/README.md
+++ b/README.md
@@ -188,8 +188,9 @@ Third party components used
* DerelictGL3 - for OpenGL support
* DerelictFT + FreeType library support under linux and optionally under Windows.
* DerelictFI + FreeImage library support for decoding of images
+* DerelictSDL2 + SDL2 for cross platform support
* WindowsAPI bindings from http://www.dsource.org/projects/bindings/wiki/WindowsApi (patched)
-* XCB and X11 bindings (patched) TODO: provide links
+* XCB and X11 bindings (patched) when SDL2 is not used; TODO: provide links
Hello World
diff --git a/dlanguilib.visualdproj b/dlanguilib.visualdproj
index 466a77aa..5e780b00 100644
--- a/dlanguilib.visualdproj
+++ b/dlanguilib.visualdproj
@@ -66,7 +66,7 @@
0
0
- Unicode USE_OPENGL USE_SDL
+ Unicode USE_SDL
0
0
1
@@ -217,14 +217,6 @@
-
-
-
-
-
-
-
-
@@ -234,6 +226,14 @@
+
+
+
+
+
+
+
+
diff --git a/examples/example1/example1.visualdproj b/examples/example1/example1.visualdproj
index 03c3ef63..b04fc227 100644
--- a/examples/example1/example1.visualdproj
+++ b/examples/example1/example1.visualdproj
@@ -66,7 +66,7 @@
0
0
- Unicode USE_OPENGL USE_SDL
+ Unicode USE_SDL
0
3
0
diff --git a/examples/example1/src/main.d b/examples/example1/src/main.d
index bb8f316c..0cc34d45 100644
--- a/examples/example1/src/main.d
+++ b/examples/example1/src/main.d
@@ -158,7 +158,95 @@ extern (C) int UIAppMain(string[] args) {
tabs.addTab(list, "Long List"d);
}
- tabs.addTab((new TextWidget()).id("tab3").textColor(0x00802000).text("Tab 3 contents"), "Tab 3"d);
+ {
+ LinearLayout layout3 = new LinearLayout("tab3");
+ layout3.addChild(new TextWidget(null, "Buttons in HorizontalLayout"d));
+ WidgetGroup buttons1 = new HorizontalLayout();
+ buttons1.addChild(new Button("btn1", "Button 1"d));
+ buttons1.addChild(new Button("btn2", "Button 2"d));
+ buttons1.addChild(new Button("btn3", "Button 3"d));
+ buttons1.addChild(new Button("btn4", "Button 4"d));
+ layout3.addChild(buttons1);
+ layout3.addChild(new VSpacer());
+ layout3.addChild(new TextWidget(null, "CheckBoxes in HorizontalLayout"d));
+ WidgetGroup buttons2 = new HorizontalLayout();
+ buttons2.addChild(new CheckBox("btn1", "CheckBox 1"d));
+ buttons2.addChild(new CheckBox("btn2", "CheckBox 2"d));
+ buttons2.addChild(new CheckBox("btn3", "CheckBox 3"d));
+ buttons2.addChild(new CheckBox("btn4", "CheckBox 4"d));
+ layout3.addChild(buttons2);
+
+ layout3.addChild(new VSpacer());
+ layout3.addChild(new TextWidget(null, "RadioButtons in HorizontalLayout"d));
+ WidgetGroup buttons3 = new HorizontalLayout();
+ buttons3.addChild(new RadioButton("btn1", "RadioButton 1"d));
+ buttons3.addChild(new RadioButton("btn2", "RadioButton 2"d));
+ buttons3.addChild(new RadioButton("btn3", "RadioButton 3"d));
+ buttons3.addChild(new RadioButton("btn4", "RadioButton 4"d));
+ layout3.addChild(buttons3);
+
+ layout3.addChild(new VSpacer());
+ layout3.addChild(new TextWidget(null, "ImageButtons HorizontalLayout"d));
+ WidgetGroup buttons4 = new HorizontalLayout();
+ buttons4.addChild(new ImageButton("btn1", "fileclose"));
+ buttons4.addChild(new ImageButton("btn2", "fileopen"));
+ buttons4.addChild(new ImageButton("btn3", "exit"));
+ layout3.addChild(buttons4);
+
+ layout3.addChild(new VSpacer());
+ layout3.addChild(new TextWidget(null, "In vertical layouts:"d));
+ HorizontalLayout hlayout2 = new HorizontalLayout();
+ hlayout2.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
+
+ buttons1 = new VerticalLayout();
+ buttons1.addChild(new TextWidget(null, "Buttons"d));
+ buttons1.addChild(new Button("btn1", "Button 1"d));
+ buttons1.addChild(new Button("btn2", "Button 2"d));
+ buttons1.addChild((new Button("btn3", "Button 3 - disabled"d)).enabled(false));
+ buttons1.addChild(new Button("btn4", "Button 4"d));
+ hlayout2.addChild(buttons1);
+ hlayout2.addChild(new HSpacer());
+
+ buttons2 = new VerticalLayout();
+ buttons2.addChild(new TextWidget(null, "CheckBoxes"d));
+ buttons2.addChild(new CheckBox("btn1", "CheckBox 1"d));
+ buttons2.addChild(new CheckBox("btn2", "CheckBox 2"d));
+ buttons2.addChild(new CheckBox("btn3", "CheckBox 3"d));
+ buttons2.addChild(new CheckBox("btn4", "CheckBox 4"d));
+ hlayout2.addChild(buttons2);
+ hlayout2.addChild(new HSpacer());
+
+ buttons3 = new VerticalLayout();
+ buttons3.addChild(new TextWidget(null, "RadioButtons"d));
+ buttons3.addChild(new RadioButton("btn1", "RadioButton 1"d));
+ buttons3.addChild(new RadioButton("btn2", "RadioButton 2"d));
+ buttons3.addChild(new RadioButton("btn3", "RadioButton 3"d));
+ buttons3.addChild(new RadioButton("btn4", "RadioButton 4"d));
+ hlayout2.addChild(buttons3);
+ hlayout2.addChild(new HSpacer());
+
+ buttons4 = new VerticalLayout();
+ buttons4.addChild(new TextWidget(null, "ImageButtons"d));
+ buttons4.addChild(new ImageButton("btn1", "fileclose"));
+ buttons4.addChild(new ImageButton("btn2", "fileopen"));
+ buttons4.addChild(new ImageButton("btn3", "exit"));
+ hlayout2.addChild(buttons4);
+ hlayout2.addChild(new HSpacer());
+
+ WidgetGroup buttons5 = new VerticalLayout();
+ buttons5.addChild(new TextWidget(null, "ImageTextButtons"d));
+ buttons5.addChild(new ImageTextButton("btn1", "fileclose", "Close"d));
+ buttons5.addChild(new ImageTextButton("btn2", "fileopen", "Open"d));
+ buttons5.addChild(new ImageTextButton("btn3", "exit", "Exit"d));
+ hlayout2.addChild(buttons5);
+
+
+ layout3.addChild(hlayout2);
+
+ layout3.addChild(new VSpacer());
+ layout3.layoutWidth(FILL_PARENT).layoutHeight(FILL_PARENT);
+ tabs.addTab(layout3, "Buttons"d);
+ }
tabs.addTab((new TextWidget()).id("tab4").textColor(0x00802000).text("Tab 4 contents some long string"), "Tab 4"d);
tabs.addTab((new TextWidget()).id("tab5").textColor(0x00802000).text("Tab 5 contents"), "Tab 5"d);
@@ -201,7 +289,7 @@ extern (C) int UIAppMain(string[] args) {
//==========================================================================
- tabs.selectTab("tab1");
+ tabs.selectTab("tab3");
contentLayout.addChild(tabs);
window.mainWidget = contentLayout;
diff --git a/res/mdpi/btn_default_small_normal.9.png b/res/mdpi/btn_default_small_normal.9.png
index 5dddd464..ca9bfd6f 100644
Binary files a/res/mdpi/btn_default_small_normal.9.png and b/res/mdpi/btn_default_small_normal.9.png differ
diff --git a/res/mdpi/btn_default_small_normal_disable.9.png b/res/mdpi/btn_default_small_normal_disable.9.png
index 6ab5c4a2..83d9af53 100644
Binary files a/res/mdpi/btn_default_small_normal_disable.9.png and b/res/mdpi/btn_default_small_normal_disable.9.png differ
diff --git a/res/mdpi/btn_default_small_normal_disable_focused.9.png b/res/mdpi/btn_default_small_normal_disable_focused.9.png
index c65bace3..f57bb3df 100644
Binary files a/res/mdpi/btn_default_small_normal_disable_focused.9.png and b/res/mdpi/btn_default_small_normal_disable_focused.9.png differ
diff --git a/res/mdpi/btn_default_small_pressed.9.png b/res/mdpi/btn_default_small_pressed.9.png
index 43e82f97..c9a14601 100644
Binary files a/res/mdpi/btn_default_small_pressed.9.png and b/res/mdpi/btn_default_small_pressed.9.png differ
diff --git a/res/mdpi/btn_default_small_selected.9.png b/res/mdpi/btn_default_small_selected.9.png
index 7a376a97..ee71e01d 100644
Binary files a/res/mdpi/btn_default_small_selected.9.png and b/res/mdpi/btn_default_small_selected.9.png differ
diff --git a/src/dlangui/platforms/sdl/sdlapp.d b/src/dlangui/platforms/sdl/sdlapp.d
index 8181617e..64f258a0 100644
--- a/src/dlangui/platforms/sdl/sdlapp.d
+++ b/src/dlangui/platforms/sdl/sdlapp.d
@@ -2,7 +2,6 @@ module src.dlangui.platforms.sdl.sdlapp;
version(USE_SDL) {
import core.runtime;
- import std.string;
import std.conv;
import std.string;
import std.utf;
@@ -13,7 +12,7 @@ version(USE_SDL) {
import dlangui.core.logger;
import dlangui.core.events;
import dlangui.graphics.drawbuf;
- import dlangui.graphics.fonts;
+ import dlangui.graphics.fonts;
import dlangui.graphics.ftfonts;
import dlangui.graphics.resources;
import dlangui.widgets.styles;
@@ -21,13 +20,13 @@ version(USE_SDL) {
import dlangui.platforms.common.platform;
import derelict.sdl2.sdl;
+ import derelict.opengl3.gl3;
version (USE_OPENGL) {
+ import dlangui.graphics.gldrawbuf;
import dlangui.graphics.glsupport;
}
- import derelict.opengl3.gl3;
- import derelict.opengl3.glx;
// pragma(lib, "xcb");
// pragma(lib, "xcb-shm");
@@ -49,22 +48,67 @@ version(USE_SDL) {
debug Log.d("Destroying SDL window");
if (_renderer)
SDL_DestroyRenderer(_renderer);
+ version(USE_OPENGL) {
+ if (_context)
+ SDL_GL_DeleteContext(_context);
+ }
if (_win)
SDL_DestroyWindow(_win);
}
-
+
+ version(USE_OPENGL) {
+ static private bool _gl3Reloaded = false;
+ private SDL_GLContext _context;
+ }
+
bool create() {
- _win = SDL_CreateWindow(_caption.toStringz, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 700, 500, SDL_WINDOW_RESIZABLE);
+ uint windowFlags = SDL_WINDOW_RESIZABLE;
+ version(USE_OPENGL) {
+ if (_enableOpengl)
+ windowFlags |= SDL_WINDOW_OPENGL;
+ }
+ _win = SDL_CreateWindow(_caption.toStringz, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+ 700, 500,
+ windowFlags);
+ version(USE_OPENGL) {
+ if (!_win) {
+ if (_enableOpengl) {
+ Log.e("SDL_CreateWindow failed - cannot create OpenGL window: ", fromStringz(SDL_GetError()));
+ _enableOpengl = false;
+ // recreate w/o OpenGL
+ windowFlags &= ~SDL_WINDOW_OPENGL;
+ _win = SDL_CreateWindow(_caption.toStringz, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+ 700, 500,
+ windowFlags);
+ }
+ }
+ }
if (!_win) {
Log.e("SDL2: Failed to create window");
return false;
}
- _renderer = SDL_CreateRenderer(_win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
- if (!_renderer) {
- Log.e("SDL2: Failed to create renderer");
- return false;
- }
- //windowCaption = _caption;
+ version(USE_OPENGL) {
+ if (_enableOpengl) {
+ _context = SDL_GL_CreateContext(_win); // Create the actual context and make it current
+ if (!_context) {
+ Log.e("SDL_GL_CreateContext failed: ", fromStringz(SDL_GetError()));
+ _enableOpengl = false;
+ } else if (!_gl3Reloaded) {
+ DerelictGL3.reload();
+ _gl3Reloaded = true;
+ if (!initShaders())
+ _enableOpengl = false;
+ }
+ }
+ }
+ if (!_enableOpengl) {
+ _renderer = SDL_CreateRenderer(_win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
+ if (!_renderer) {
+ Log.e("SDL2: Failed to create renderer");
+ return false;
+ }
+ }
+ windowCaption = _caption;
return true;
}
@@ -75,7 +119,6 @@ version(USE_SDL) {
}
- bool _derelictgl3Reloaded;
override void show() {
Log.d("SDLWindow.show()");
SDL_ShowWindow(_win);
@@ -127,20 +170,35 @@ version(USE_SDL) {
//Log.e("Widget instance count in SDLWindow.redraw: ", Widget.instanceCount());
// check if size has been changed
int w, h;
- SDL_GetWindowSize(_win,
- &w,
- &h);
+ SDL_GetWindowSize(_win, &w, &h);
onResize(w, h);
-
if (_enableOpengl) {
version(USE_OPENGL) {
+ SDL_GL_MakeCurrent(_win, _context);
+ glDisable(GL_DEPTH_TEST);
+ glViewport(0, 0, _dx, _dy);
+ float a = 1.0f;
+ float r = ((_backgroundColor >> 16) & 255) / 255.0f;
+ float g = ((_backgroundColor >> 8) & 255) / 255.0f;
+ float b = ((_backgroundColor >> 0) & 255) / 255.0f;
+ glClearColor(r, g, b, a);
+ glClear(GL_COLOR_BUFFER_BIT);
+ GLDrawBuf buf = new GLDrawBuf(_dx, _dy, false);
+ buf.beforeDrawing();
+ onDraw(buf);
+ buf.afterDrawing();
+ SDL_GL_SwapWindow(_win);
+ destroy(buf);
}
} else {
- // Select the color for drawing. It is set to red here.
- //SDL_SetRenderDrawColor(_renderer, 255, 0, 0, 255);
+ // Select the color for drawing.
+ ubyte r = cast(ubyte)((_backgroundColor >> 16) & 255);
+ ubyte g = cast(ubyte)((_backgroundColor >> 8) & 255);
+ ubyte b = cast(ubyte)((_backgroundColor >> 0) & 255);
+ SDL_SetRenderDrawColor(_renderer, r, g, b, 255);
// Clear the entire screen to our selected color.
- //SDL_RenderClear(_renderer);
+ SDL_RenderClear(_renderer);
if (!_drawbuf)
_drawbuf = new ColorDrawBuf(_dx, _dy);
@@ -446,12 +504,6 @@ version(USE_SDL) {
}
bool connect() {
- try {
- //DerelictGL3.load();
- _enableOpengl = false;
- } catch (Exception e) {
- Log.e("Cannot load opengl library", e);
- }
return true;
}
@@ -698,13 +750,6 @@ version(USE_SDL) {
string[] args = splitCmdLine(cmdline);
Log.i("Command line params: ", args);
- try {
- // Load the SDL 2 library.
- DerelictSDL2.load();
- } catch (Exception e) {
- Log.e("Cannot load SDL2 library", e);
- return 1;
- }
//_cmdShow = iCmdShow;
//_hInstance = hInstance;
@@ -721,22 +766,6 @@ version(USE_SDL) {
setStderrLogger();
setLogLevel(LogLevel.Trace);
- try {
- // Load the SDL 2 library.
- DerelictSDL2.load();
- } catch (Exception e) {
- Log.e("Cannot load SDL2 library", e);
- return 1;
- }
-
- SDL_DisplayMode displayMode;
- if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTS) != 0) {
- Log.e("Cannot init SDL2");
- return 2;
- }
- scope(exit)SDL_Quit();
- int request = SDL_GetDesktopDisplayMode(0,&displayMode);
-
FreeTypeFontManager ft = new FreeTypeFontManager();
// TODO: use FontConfig
@@ -750,6 +779,40 @@ version(USE_SDL) {
int sdlmain(string[] args) {
currentTheme = createDefaultTheme();
+ try {
+ // Load the SDL 2 library.
+ DerelictSDL2.load();
+ } catch (Exception e) {
+ Log.e("Cannot load SDL2 library", e);
+ return 1;
+ }
+
+ version(USE_OPENGL) {
+ try {
+ DerelictGL3.load();
+ _enableOpengl = true;
+ } catch (Exception e) {
+ Log.e("Cannot load opengl library", e);
+ }
+ }
+
+ SDL_DisplayMode displayMode;
+ if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTS) != 0) {
+ Log.e("Cannot init SDL2");
+ return 2;
+ }
+ scope(exit)SDL_Quit();
+ int request = SDL_GetDesktopDisplayMode(0,&displayMode);
+
+ version(USE_OPENGL) {
+ // we want OpenGL 3.3
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,3);
+ SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,2);
+ // Set OpenGL attributes
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
+ }
+
SDLPlatform sdl = new SDLPlatform();
if (!sdl.connect()) {
return 1;
diff --git a/src/dlangui/widgets/controls.d b/src/dlangui/widgets/controls.d
index 88d1eadb..730dd198 100644
--- a/src/dlangui/widgets/controls.d
+++ b/src/dlangui/widgets/controls.d
@@ -35,15 +35,21 @@ import dlangui.widgets.layouts;
/// vertical spacer to fill empty space in vertical layouts
class VSpacer : Widget {
this() {
- styleId = "VSpacer";
+ styleId = "VSPACER";
}
+ //override void measure(int parentWidth, int parentHeight) {
+ // measuredContent(parentWidth, parentHeight, 8, 8);
+ //}
}
/// horizontal spacer to fill empty space in horizontal layouts
class HSpacer : Widget {
this() {
- styleId = "HSpacer";
+ styleId = "HSPACER";
}
+ //override void measure(int parentWidth, int parentHeight) {
+ // measuredContent(parentWidth, parentHeight, 8, 8);
+ //}
}
/// static text widget
@@ -291,6 +297,22 @@ class Button : Widget {
focusable = true;
trackHover = true;
}
+ this(string ID, dstring label) {
+ super(ID);
+ _text = label;
+ styleId = "BUTTON";
+ clickable = true;
+ focusable = true;
+ trackHover = true;
+ }
+ this(string ID, string labelResourceId) {
+ super(ID);
+ _text = labelResourceId;
+ styleId = "BUTTON";
+ clickable = true;
+ focusable = true;
+ trackHover = true;
+ }
override void measure(int parentWidth, int parentHeight) {
FontRef font = font();