1 module pixelperfectengine.concrete.elements.base; 2 3 public import pixelperfectengine.concrete.interfaces; 4 public import pixelperfectengine.concrete.types.stylesheet; 5 public import pixelperfectengine.concrete.types.event; 6 public import pixelperfectengine.system.input.handler; 7 //import pixelperfectengine.system.input.types : MouseMotionEvent; 8 9 10 /** 11 * Definies values about whether a WindowElement is enabled or not. 12 */ 13 public enum ElementState : ubyte { 14 Enabled = 0, ///Means the element is enabled. 15 DisabledWOGray = 1, ///Disabled without grayout, should be only used by elements contained within other elements. 16 Disabled = 2, ///Means the element is disabled. 17 } 18 /** 19 * All Window elements inherit from this class. Provides basic interfacing with containers. 20 */ 21 abstract class WindowElement : Focusable, MouseEventReceptor { 22 public static InputHandler inputHandler; ///Common input handler, must be set upon program initialization for text input, etc. 23 ///Contains the position of the element. 24 ///Should be only modified with functions to ensure consistency. 25 protected Box position; 26 ///Points to the container for two-way communication 27 public ElementContainer parent; 28 ///Contains the text of the element if any. 29 ///Should be modified with functions to ensure redraws. 30 protected Text text; 31 /** 32 * Passed with other event informations when event is caused. 33 * Can be something like the name of the instance. 34 * 35 * Should not be modified after creation. 36 */ 37 protected string source; 38 ///Contains various status flags. 39 protected uint flags; 40 protected static enum ENABLE_MOUSE_PRESS = 1<<3; 41 protected static enum IS_CLICKED = 1<<4; 42 protected static enum ENABLE_RCLICK_FLAG = 1<<5; 43 protected static enum IS_PRESSED = 1<<6; 44 protected static enum IS_CHECKED = 1<<7; 45 protected static enum IS_FOCUSED = 1<<8; 46 protected static enum IS_LHS = 1<<30; 47 ///Sets a custom style for this element. 48 ///If not set, then it'll get the style from it's parent. 49 public StyleSheet customStyle; 50 //protected ElementState _state; 51 52 53 //public static PopUpHandler popUpHandler; ///Common pop-up handler 54 //public static StyleSheet styleSheet; ///Basic stylesheet, all elements default to this if no alternative found 55 56 public static void delegate() onDraw; ///Called when drawing is finished 57 58 public EventDeleg onMouseLClick; ///Called on left mouseclick released 59 public EventDeleg onMouseRClick; ///Called on right mouseclick released 60 public EventDeleg onMouseMClick; ///Called on middle mouseclick released 61 public EventDeleg onMouseMove; ///Called if mouse is moved on object 62 public EventDeleg onMouseScroll; ///Called if mouse is scrolled on object 63 64 protected MouseMotionEvent lastMousePosition; ///Stores the last known mouse position for future reference 65 ///Returns the text of this element. 66 public @nogc Text getText(){ 67 return text; 68 } 69 public void setText(Text s) { 70 text = s; 71 //parent.clearArea(position); 72 draw(); 73 } 74 public void setText(dstring s) { 75 text.text = s; 76 text.next = null; 77 //parent.clearArea(position); 78 draw(); 79 } 80 /** 81 * Sets whether the element is enabled or not. 82 */ 83 public @property ElementState state(ElementState state) { 84 flags &= ~0x3; 85 flags |= cast(ubyte)state; 86 draw(); 87 return state; 88 } 89 /** 90 * Returns whether the element is enabled or not. 91 */ 92 public @property ElementState state() @nogc @safe const pure nothrow { 93 return cast(ElementState)(flags & 0x3); 94 } 95 public void setParent(ElementContainer parent) { 96 this.parent = parent; 97 } 98 /** 99 * Updates the output. Every subclass must override it. 100 */ 101 public abstract void draw(); 102 public Box getPosition() { 103 return position; 104 } 105 public Box setPosition(Box position) { 106 this.position = position; 107 draw(); 108 return position; 109 } 110 /** 111 * Returns the source string. 112 */ 113 @property public string getSource(){ 114 return source; 115 } 116 /** 117 * Returns true if the element will generate events on mouse press and mouse release. 118 * By default, only release is used. 119 */ 120 public @property bool mousePressEvent() @nogc @safe pure nothrow { 121 return flags & ENABLE_MOUSE_PRESS ? true : false; 122 } 123 /+/** 124 * Returns true if middle mouse button events are enabled. 125 */ 126 public @property bool mouseMClickEvent() @nogc @safe pure nothrow { 127 return flags & ENABLE_MCLICK_FLAG ? true : false; 128 } 129 /** 130 * Returns true if right mouse button events are enabled. 131 */ 132 public @property bool mouseRClickEvent() @nogc @safe pure nothrow { 133 return flags & ENABLE_RCLICK_FLAG ? true : false; 134 }+/ 135 /** 136 * Returns true if the element will generate events on mouse press and mouse release. 137 * By default, only release is used. 138 */ 139 public @property bool mousePressEvent(bool val) @nogc @safe pure nothrow { 140 if (val) flags |= ENABLE_MOUSE_PRESS; 141 else flags &= ~ENABLE_MOUSE_PRESS; 142 return flags & ENABLE_MOUSE_PRESS ? true : false; 143 } 144 /+/** 145 * Returns true if middle mouse button events are enabled. 146 */ 147 public @property bool mouseMClickEvent(bool val) @nogc @safe pure nothrow { 148 if (val) flags |= ENABLE_MCLICK_FLAG; 149 else flags &= ~ENABLE_MCLICK_FLAG; 150 return flags & ENABLE_MCLICK_FLAG ? true : false; 151 } 152 /** 153 * Returns true if right mouse button events are enabled. 154 */ 155 public @property bool mouseRClickEvent(bool val) @nogc @safe pure nothrow { 156 if (val) flags |= ENABLE_RCLICK_FLAG; 157 else flags &= ~ENABLE_RCLICK_FLAG; 158 return flags & ENABLE_RCLICK_FLAG ? true : false; 159 }+/ 160 /** 161 * Returns the next available StyleSheet. 162 */ 163 public StyleSheet getStyleSheet() { 164 if(customStyle !is null) return customStyle; 165 else if(parent !is null) return parent.getStyleSheet(); 166 else return globalDefaultStyle; 167 } 168 ///Called when an object receives focus. 169 public void focusGiven() { 170 flags |= IS_FOCUSED; 171 draw; 172 } 173 ///Called when an object loses focus. 174 public void focusTaken() { 175 flags &= ~IS_FOCUSED; 176 draw; 177 } 178 ///Cycles the focus on a single element. 179 ///Returns -1 if end is reached, or the number of remaining elements that 180 ///are cycleable in the direction. 181 public int cycleFocus(int direction) { 182 return -1; 183 } 184 ///Passes key events to the focused element when not in text editing mode. 185 public void passKey(uint keyCode, ubyte mod) { 186 187 } 188 /** 189 * Returns whether the element is focused 190 */ 191 public @property bool isFocused() @nogc @safe pure nothrow const { 192 return flags & IS_FOCUSED ? true : false; 193 } 194 /** 195 * Returns whether the element is pressed 196 */ 197 public @property bool isPressed() @nogc @safe pure nothrow const { 198 return flags & IS_PRESSED ? true : false; 199 } 200 /** 201 * Returns whether the element is checked 202 */ 203 public @property bool isChecked() @nogc @safe pure nothrow const { 204 return flags & IS_CHECKED ? true : false; 205 } 206 protected @property bool isChecked(bool val) @nogc @safe pure nothrow { 207 if (val) flags |= IS_CHECKED; 208 else flags &= ~IS_CHECKED; 209 return flags & IS_CHECKED ? true : false; 210 } 211 public void passMCE(MouseEventCommons mec, MouseClickEvent mce) { 212 if (state != ElementState.Enabled) return; 213 if (!mce.state && !(isPressed)) return; 214 215 parent.requestFocus(this); 216 217 if (mce.state == ButtonState.Pressed) { 218 if (mce.button == MouseButton.Left) flags |= IS_PRESSED; 219 if (!(mousePressEvent )) { 220 draw; 221 return; 222 } 223 } else if (mce.button == MouseButton.Left) { 224 flags &= ~IS_PRESSED; 225 } 226 227 MouseEvent me = new MouseEvent(this, EventType.MouseClick, SourceType.WindowElement); 228 me.mec = mec; 229 me.mce = mce; 230 231 switch (mce.button) { 232 case MouseButton.Left: 233 if (onMouseLClick !is null && (!mce.state || mousePressEvent)) 234 onMouseLClick(me); 235 break; 236 case MouseButton.Right: 237 if (onMouseRClick !is null && (!mce.state || mousePressEvent)) 238 onMouseRClick(me); 239 break; 240 case MouseButton.Mid: 241 if (onMouseMClick !is null && (!mce.state || mousePressEvent)) 242 onMouseMClick(me); 243 break; 244 default: 245 break; 246 } 247 248 draw; 249 } 250 251 public void passMME(MouseEventCommons mec, MouseMotionEvent mme) { 252 253 if (onMouseMove !is null) { 254 MouseEvent me = new MouseEvent(this, EventType.MouseMotion, SourceType.WindowElement); 255 me.mme = mme; 256 me.mec = mec; 257 onMouseMove(me); 258 } 259 } 260 261 public void passMWE(MouseEventCommons mec, MouseWheelEvent mwe) { 262 if (onMouseScroll !is null) { 263 MouseEvent me = new MouseEvent(this, EventType.MouseScroll, SourceType.WindowElement); 264 me.mec = mec; 265 me.mwe = mwe; 266 onMouseScroll(me); 267 } 268 } 269 270 }