1 module dlangui.platforms.dsfml.dsfmlapp; 2 3 public import dlangui.core.config; 4 5 static if (BACKEND_DSFML): 6 7 import dlangui.platforms.common.platform; 8 import dsfml.graphics; 9 import std.array; 10 11 import dlangui.core.collections; 12 import dlangui.core.logger; 13 import dlangui.widgets.widget; 14 import dlangui.widgets.popup; 15 import dlangui.graphics.drawbuf; 16 import dlangui.core.stdaction; 17 import dlangui.dialogs.msgbox; 18 19 private import dlangui.graphics.gldrawbuf; 20 21 /** 22 * Window abstraction layer. Widgets can be shown only inside window. 23 * 24 */ 25 class DSFMLWindow : dlangui.platforms.common.platform.Window { 26 27 private RenderWindow _wnd; 28 private bool _ownRenderWindow; 29 static private bool _gl3Reloaded = false; 30 31 @property RenderWindow wnd() { return _wnd; } 32 33 this(RenderWindow wnd, bool own) { 34 _wnd = wnd; 35 _ownRenderWindow = own; 36 super(); 37 auto sz = wnd.size; 38 onResize(sz.x, sz.y); 39 } 40 41 ~this() { 42 if (_ownRenderWindow) { 43 destroy(_wnd); 44 } 45 _wnd = null; 46 } 47 48 override void show() { 49 } 50 51 /// returns window caption 52 override @property dstring windowCaption() const { 53 // TODO 54 return ""d; 55 } 56 /// sets window caption 57 override @property void windowCaption(dstring caption) { 58 // TODO 59 } 60 /// sets window icon 61 override @property void windowIcon(DrawBufRef icon) { 62 // TODO 63 } 64 /// request window redraw 65 override void invalidate() { 66 // TODO 67 } 68 /// close window 69 override void close() { 70 // TODO 71 } 72 73 void draw() { 74 paintUsingOpenGL(); 75 } 76 77 private void paintUsingOpenGL() { 78 import derelict.opengl3.gl3; 79 80 glDisable(GL_DEPTH_TEST); 81 glViewport(0, 0, _dx, _dy); 82 float a = 1.0f; 83 float r = ((_backgroundColor >> 16) & 255) / 255.0f; 84 float g = ((_backgroundColor >> 8) & 255) / 255.0f; 85 float b = ((_backgroundColor >> 0) & 255) / 255.0f; 86 //glClearColor(r, g, b, a); 87 //glClear(GL_COLOR_BUFFER_BIT); 88 89 GLDrawBuf buf = new GLDrawBuf(_dx, _dy, false); 90 91 buf.beforeDrawing(); 92 onDraw(buf); 93 buf.afterDrawing(); 94 } 95 96 private MouseButton translateButton(uint btn) { 97 switch(btn) with(Mouse.Button) { 98 default: 99 case Left: 100 return MouseButton.Left; 101 case Right: 102 return MouseButton.Right; 103 case Middle: 104 return MouseButton.Middle; 105 case XButton1: 106 return MouseButton.XButton1; 107 case XButton2: 108 return MouseButton.XButton2; 109 } 110 } 111 112 private uint translateKey(uint key) { 113 switch(key) with(Keyboard.Key) 114 { 115 case A: return KeyCode.KEY_A; 116 case B: return KeyCode.KEY_B; 117 case C: return KeyCode.KEY_C; 118 case D: return KeyCode.KEY_D; 119 case E: return KeyCode.KEY_E; 120 case F: return KeyCode.KEY_F; 121 case G: return KeyCode.KEY_G; 122 case H: return KeyCode.KEY_H; 123 case I: return KeyCode.KEY_I; 124 case J: return KeyCode.KEY_J; 125 case K: return KeyCode.KEY_K; 126 case L: return KeyCode.KEY_L; 127 case M: return KeyCode.KEY_M; 128 case N: return KeyCode.KEY_N; 129 case O: return KeyCode.KEY_O; 130 case P: return KeyCode.KEY_P; 131 case Q: return KeyCode.KEY_Q; 132 case R: return KeyCode.KEY_R; 133 case S: return KeyCode.KEY_S; 134 case T: return KeyCode.KEY_T; 135 case U: return KeyCode.KEY_U; 136 case V: return KeyCode.KEY_V; 137 case W: return KeyCode.KEY_W; 138 case X: return KeyCode.KEY_X; 139 case Y: return KeyCode.KEY_Y; 140 case Z: return KeyCode.KEY_Z; 141 case Num0: return KeyCode.KEY_0; 142 case Num1: return KeyCode.KEY_1; 143 case Num2: return KeyCode.KEY_2; 144 case Num3: return KeyCode.KEY_3; 145 case Num4: return KeyCode.KEY_4; 146 case Num5: return KeyCode.KEY_5; 147 case Num6: return KeyCode.KEY_6; 148 case Num7: return KeyCode.KEY_7; 149 case Num8: return KeyCode.KEY_8; 150 case Num9: return KeyCode.KEY_9; 151 case Escape: return KeyCode.ESCAPE; 152 case LControl: return KeyCode.LCONTROL; 153 case LShift: return KeyCode.LSHIFT; 154 case LAlt: return KeyCode.LALT; 155 case RControl: return KeyCode.RCONTROL; 156 case RShift: return KeyCode.RSHIFT; 157 case RAlt: return KeyCode.RALT; 158 159 ///The [ key 160 case LBracket: return KeyCode.KEY_BRACKETOPEN; 161 ///The ] key 162 case RBracket: return KeyCode.KEY_BRACKETCLOSE; 163 ///The ; key 164 case SemiColon: return KeyCode.KEY_BRACKETOPEN; 165 ///The , key 166 case Comma: return KeyCode.KEY_COMMA; 167 ///The . key 168 case Period: return KeyCode.KEY_PERIOD; 169 ///The ' key 170 case Quote: return KeyCode.QUOTE; 171 ///The / key 172 case Slash: return KeyCode.KEY_DIVIDE; 173 ///The \ key 174 case BackSlash: return KeyCode.BACKSLASH; 175 ///The ~ key 176 case Tilde: return KeyCode.TILDE; 177 ///The = key 178 case Equal: return KeyCode.EQUAL; 179 ///The - key 180 case Dash: return KeyCode.SUB; 181 ///The Space key 182 case Space: return KeyCode.SPACE; 183 184 case Numpad0: return KeyCode.NUM_0; 185 case Numpad1: return KeyCode.NUM_1; 186 case Numpad2: return KeyCode.NUM_2; 187 case Numpad3: return KeyCode.NUM_3; 188 case Numpad4: return KeyCode.NUM_4; 189 case Numpad5: return KeyCode.NUM_5; 190 case Numpad6: return KeyCode.NUM_6; 191 case Numpad7: return KeyCode.NUM_7; 192 case Numpad8: return KeyCode.NUM_8; 193 case Numpad9: return KeyCode.NUM_9; 194 195 case F1: return KeyCode.F1; 196 case F2: return KeyCode.F2; 197 case F3: return KeyCode.F3; 198 case F4: return KeyCode.F4; 199 case F5: return KeyCode.F5; 200 case F6: return KeyCode.F6; 201 case F7: return KeyCode.F7; 202 case F8: return KeyCode.F8; 203 case F9: return KeyCode.F9; 204 case F10: return KeyCode.F10; 205 case F11: return KeyCode.F11; 206 case F12: return KeyCode.F12; 207 case F13: return KeyCode.F13; 208 case F14: return KeyCode.F14; 209 case F15: return KeyCode.F15; 210 211 case Return: return KeyCode.RETURN; 212 case BackSpace: return KeyCode.BACK; 213 case Tab: return KeyCode.TAB; 214 case PageUp: return KeyCode.PAGEUP; 215 case PageDown: return KeyCode.PAGEDOWN; 216 case End: return KeyCode.END; 217 case Home: return KeyCode.HOME; 218 case Insert: return KeyCode.INS; 219 case Delete: return KeyCode.DEL; 220 case Add: return KeyCode.ADD; 221 case Subtract: return KeyCode.SUB; 222 case Multiply: return KeyCode.MUL; 223 case Divide: return KeyCode.DIV; 224 case Left: return KeyCode.LEFT; 225 case Right: return KeyCode.RIGHT; 226 case Up: return KeyCode.UP; 227 case Down: return KeyCode.DOWN; 228 default: return 0x8000_0000 | key; 229 } 230 } 231 232 private ushort mouseFlags; 233 private ushort keyFlags; 234 235 bool handleEvent(ref Event event) { 236 switch (event.type) with(event.EventType) { 237 case Closed: { 238 break; 239 } 240 case Resized: { 241 onResize(event.size.width, event.size.height); 242 break; 243 } 244 case MouseButtonPressed: { 245 auto btn = translateButton(event.mouseButton.button); 246 mouseFlags |= mouseButtonToFlag(btn); 247 MouseEvent ev = new MouseEvent(MouseAction.ButtonDown, btn, mouseFlags, cast(short)event.mouseButton.x, cast(short)event.mouseButton.y); 248 return dispatchMouseEvent(ev); 249 } 250 case MouseButtonReleased: { 251 auto btn = translateButton(event.mouseButton.button); 252 mouseFlags &= ~mouseButtonToFlag(btn); 253 MouseEvent ev = new MouseEvent(MouseAction.ButtonUp, btn, mouseFlags, cast(short)event.mouseButton.x, cast(short)event.mouseButton.y); 254 return dispatchMouseEvent(ev); 255 } 256 case MouseMoved: { 257 MouseEvent ev = new MouseEvent(MouseAction.Move, MouseButton.None, mouseFlags, cast(short)event.mouseMove.x, cast(short)event.mouseMove.y); 258 return dispatchMouseEvent(ev); 259 } 260 case MouseEntered: { 261 break; 262 } 263 case MouseLeft: { 264 mouseFlags = 0; 265 break; 266 } 267 case MouseWheelMoved: { 268 break; 269 } 270 case TextEntered: { 271 KeyEvent ev = new KeyEvent(KeyAction.Text, 0, 0, [event.text.unicode]); 272 return dispatchKeyEvent(ev); 273 } 274 case KeyReleased: 275 case KeyPressed: { 276 keyFlags = 0; 277 if (event.key.alt) 278 keyFlags |= KeyFlag.Alt; 279 if (event.key.control) 280 keyFlags |= KeyFlag.Control; 281 if (event.key.shift) 282 keyFlags |= KeyFlag.Shift; 283 KeyEvent ev = new KeyEvent(event.type == event.EventType.KeyPressed ? KeyAction.KeyDown : KeyAction.KeyUp, translateKey(event.key.code), keyFlags, [event.text.unicode]); 284 return dispatchKeyEvent(ev); 285 } 286 default: 287 break; 288 } 289 return true; 290 } 291 292 } 293 294 /** 295 * Platform abstraction layer. 296 * 297 * Represents application. 298 * 299 */ 300 class DSFMLPlatform : Platform { 301 302 private DSFMLWindow[] _activeWindows; 303 304 /// register DSFML window created outside dlangui 305 DSFMLWindow registerWindow(RenderWindow window) { 306 DSFMLWindow w = new DSFMLWindow(window, false); 307 _activeWindows ~= w; 308 return w; 309 } 310 311 /** 312 * create window 313 * Args: 314 * windowCaption = window caption text 315 * parent = parent Window, or null if no parent 316 * flags = WindowFlag bit set, combination of Resizable, Modal, Fullscreen 317 * 318 * Window w/o Resizable nor Fullscreen will be created with size based on measurement of its content widget 319 */ 320 override dlangui.platforms.common.platform.Window createWindow(dstring windowCaption, 321 dlangui.platforms.common.platform.Window parent, 322 uint flags = WindowFlag.Resizable, uint width = 0, uint height = 0) { 323 auto window = new RenderWindow(VideoMode(800, 600, 32), "Hello DSFML!", dsfml.window.window.Window.Style.Titlebar | dsfml.window.window.Window.Style.Close | dsfml.window.window.Window.Style.Resize); 324 window.setFramerateLimit(60); 325 DSFMLWindow w = new DSFMLWindow(window, true); 326 _activeWindows ~= w; 327 return w; 328 } 329 330 /** 331 * close window 332 * 333 * Closes window earlier created with createWindow() 334 */ 335 override void closeWindow(dlangui.platforms.common.platform.Window w) { 336 DSFMLWindow win = cast(DSFMLWindow)w; 337 // TODO: support more than one window 338 _activeWindows[0] = null; 339 _activeWindows.length = 0;// = _activeWindows.remove(win); 340 win.wnd.close(); 341 } 342 /** 343 * Starts application message loop. 344 * 345 * When returned from this method, application is shutting down. 346 */ 347 override int enterMessageLoop() { 348 // TODO: support more than one window 349 if (_activeWindows.length < 1) 350 return 1; 351 DSFMLWindow w = _activeWindows[0]; 352 RenderWindow window = w.wnd; 353 354 while (window.isOpen()) 355 { 356 Event event; 357 358 while(window.pollEvent(event)) 359 { 360 if(event.type == event.EventType.Closed) 361 { 362 closeWindow(w); 363 //window.close(); 364 } 365 } 366 367 window.clear(); 368 369 //window.draw(head); 370 //window.draw(leftEye); 371 //window.draw(rightEye); 372 //window.draw(smile); 373 //window.draw(smileCover); 374 375 window.display(); 376 } 377 return 0; 378 } 379 /// retrieves text from clipboard (when mouseBuffer == true, use mouse selection clipboard - under linux) 380 override dstring getClipboardText(bool mouseBuffer = false) { 381 // TODO: implement if necessary 382 return ""d; 383 } 384 /// check has clipboard text 385 override bool hasClipboardText(bool mouseBuffer = false) { 386 // TODO: implement if necessary 387 return false; 388 } 389 /// sets text to clipboard (when mouseBuffer == true, use mouse selection clipboard - under linux) 390 override void setClipboardText(dstring text, bool mouseBuffer = false) { 391 // TODO: implement if necessary 392 } 393 394 /// calls request layout for all windows 395 override void requestLayout() { 396 // TODO: 397 } 398 399 } 400 401 /// shortcut to current DSFMLPlatform instance 402 @property DSFMLPlatform dsfmlPlatform() { 403 return cast(DSFMLPlatform)Platform.instance; 404 } 405 406 // entry point 407 extern(C) int UIAppMain(string[] args); 408 409 void initDSFMLApp() { 410 initLogs(); 411 Log.d("Initializing DSFML platform"); 412 DSFMLPlatform p = new DSFMLPlatform(); 413 Platform.setInstance(p); 414 initResourceManagers(); 415 initFontManager(); 416 417 currentTheme = createDefaultTheme(); 418 419 import dlangui.graphics.glsupport; 420 initGLSupport(false); 421 422 Platform.instance.uiTheme = "theme_dark"; 423 } 424 425 426 void uninitDSFMLApp() { 427 Log.d("Destroying DSFML platform"); 428 Platform.setInstance(null); 429 430 releaseResourcesOnAppExit(); 431 }