1 module poison.ui.window; 2 3 import dsfmlWindow = dsfml.window; 4 import dsfml.window : Event; 5 6 private alias ContextSettings = dsfmlWindow.ContextSettings; 7 private alias VideoMode = dsfmlWindow.VideoMode; 8 private alias WindowStyle = dsfmlWindow.Window.Style; 9 10 import poison.core : Point, Size, ActionArgs, KeyEventArgs, MouseEventArgs, TextEventArgs; 11 import poison.ui.container; 12 import poison.ui.component; 13 14 /// A window component. 15 class Window : Container { 16 private: 17 /// The context settings. 18 ContextSettings _context; 19 20 /// The video mode. 21 VideoMode _videoMode; 22 23 /// The render window. 24 RenderWindow _window; 25 26 /// The key event. 27 KeyEventArgs _keyEvent; 28 29 /// The mouse event. 30 MouseEventArgs _mouseEvent; 31 32 /// The text event. 33 TextEventArgs _textEvent; 34 35 /// The fps for the window. 36 uint _fps; 37 38 public: 39 /** 40 * Creates a new window. 41 * Params: 42 * name = The name of the window. 43 * title = The title of the window. 44 * size = The size of the window. 45 * layers = The layers of the window. (Defaults to 1) 46 */ 47 this(string name, dstring title, Size size, size_t layers = 1) { 48 super(name, size, layers); 49 50 _context.antialiasingLevel = 8; 51 _videoMode = VideoMode(cast(int)size.width, cast(int)size.height); 52 _keyEvent = new KeyEventArgs(); 53 _mouseEvent = new MouseEventArgs(); 54 _textEvent = new TextEventArgs(); 55 56 innerText = title; 57 _fps = 60; 58 59 addSelector("window"); 60 } 61 62 @property { 63 /// Gets the title of the window. 64 dstring title() { return super.innerText; } 65 66 /// Sets the title of the window. 67 void title(dstring newTitle) { 68 super.innerText = newTitle; 69 70 if (_window) { 71 _window.setTitle(super.innerText); 72 } 73 } 74 75 /// Gets a boolean determining whether the window is open or not. 76 bool isOpen() { 77 return _window && _window.isOpen(); 78 } 79 80 /** 81 * Gets the parent window. 82 * Returns: 83 * Always returns "this" where "this" is the window itself. 84 */ 85 override Window parentWindow() { 86 return this; 87 } 88 89 /// Gets or sets a boolean determining whether the window is hidden or not. 90 override void hidden(bool isHidden) { 91 if (_window) { 92 _window.setVisible(!isHidden); 93 } 94 95 super.hidden = isHidden; 96 } 97 98 /// Gets the fps of the window. 99 uint fps() { return _fps; } 100 101 /// Sets the fps of the window. 102 void fps(uint newFps) { 103 _fps = newFps; 104 105 if (_window) { 106 _window.setFramerateLimit(_fps); 107 } 108 } 109 } 110 111 /// Shows the window. 112 override void show() { 113 if (!_window) { 114 _window = new RenderWindow(_videoMode, title, (WindowStyle.Titlebar | WindowStyle.Resize | WindowStyle.Close), _context); 115 116 if (_fps) { 117 _window.setFramerateLimit(_fps); 118 } 119 120 _windowComponents[super.id] = this; 121 } 122 123 super.show(); 124 } 125 126 /// Closes the window. 127 void close() { 128 assert(_window !is null); 129 130 _window.close(); 131 } 132 133 package(poison): 134 /// Components for event handling 135 Component[size_t] _windowComponents; 136 137 /// Processes the window cycle. 138 void process() { 139 Event event; 140 while(_window.pollEvent(event)) { 141 switch (event.type) { 142 case Event.EventType.Closed: { 143 _window.close(); 144 return; 145 } 146 147 case Event.EventType.KeyPressed: { 148 _keyEvent.press(event.key.code); 149 150 if (_windowComponents) { 151 foreach (component; _windowComponents) { 152 if (component && !component.disabled) { 153 component.fireEvent("keyDown", _keyEvent); 154 } 155 } 156 } 157 158 break; 159 } 160 161 case Event.EventType.KeyReleased: { 162 _keyEvent.release(event.key.code); 163 164 if (_windowComponents) { 165 foreach (component; _windowComponents) { 166 167 if (component && !component.disabled) { 168 component.fireEvent("keyUp", _keyEvent); 169 } 170 } 171 } 172 173 break; 174 } 175 176 case Event.EventType.MouseButtonPressed: { 177 _mouseEvent.press(event.mouseButton.button); 178 179 if (_windowComponents) { 180 foreach (component; _windowComponents) { 181 if (component && !component.disabled && component.intersect(_mouseEvent.position)) { 182 component.fireEvent("mouseDown", _mouseEvent); 183 } 184 } 185 } 186 187 break; 188 } 189 190 case Event.EventType.MouseButtonReleased: { 191 _mouseEvent.release(event.mouseButton.button); 192 193 if (_windowComponents) { 194 foreach (component; _windowComponents) { 195 if (component && !component.disabled && component.intersect(_mouseEvent.position)) { 196 component.fireEvent("mouseUp", _mouseEvent); 197 } 198 } 199 } 200 201 break; 202 } 203 204 case Event.EventType.MouseMoved: { 205 _mouseEvent.position = new Point(event.mouseMove.x, event.mouseMove.y); 206 207 if (_windowComponents) { 208 foreach (component; _windowComponents) { 209 if (component) { 210 component.fireEvent("mouseMoved", _mouseEvent); 211 } 212 } 213 } 214 215 break; 216 } 217 218 case Event.EventType.TextEntered: { 219 _textEvent.enter(event.text.unicode); 220 221 if (_windowComponents) { 222 foreach (component; _windowComponents) { 223 if (component && !component.disabled) { 224 component.fireEvent("textEntered", _textEvent); 225 } 226 } 227 } 228 229 break; 230 } 231 232 default: break; 233 } 234 } 235 236 _window.clear(super.graphics.backgroundPaint.sfmlColor); 237 super.process(_window); 238 _window.display(); 239 } 240 }