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 /** 125 * Returns true if the element will generate events on mouse press and mouse release. 126 * By default, only release is used. 127 */ 128 public @property bool mousePressEvent(bool val) @nogc @safe pure nothrow { 129 if (val) flags |= ENABLE_MOUSE_PRESS; 130 else flags &= ~ENABLE_MOUSE_PRESS; 131 return flags & ENABLE_MOUSE_PRESS ? true : false; 132 } 133 134 /** 135 * Returns the next available StyleSheet. 136 */ 137 public StyleSheet getStyleSheet() { 138 if(customStyle !is null) return customStyle; 139 else if(parent !is null) return parent.getStyleSheet(); 140 else return globalDefaultStyle; 141 } 142 ///Called when an object receives focus. 143 public void focusGiven() { 144 flags |= IS_FOCUSED; 145 draw; 146 } 147 ///Called when an object loses focus. 148 public void focusTaken() { 149 flags &= ~IS_FOCUSED; 150 draw; 151 } 152 ///Cycles the focus on a single element. 153 ///Returns -1 if end is reached, or the number of remaining elements that 154 ///are cycleable in the direction. 155 public int cycleFocus(int direction) { 156 return -1; 157 } 158 ///Passes key events to the focused element when not in text editing mode. 159 public void passKey(uint keyCode, ubyte mod) { 160 161 } 162 /** 163 * Returns whether the element is focused 164 */ 165 public @property bool isFocused() @nogc @safe pure nothrow const { 166 return flags & IS_FOCUSED ? true : false; 167 } 168 /** 169 * Returns whether the element is pressed 170 */ 171 public @property bool isPressed() @nogc @safe pure nothrow const { 172 return flags & IS_PRESSED ? true : false; 173 } 174 /** 175 * Returns whether the element is checked 176 */ 177 public @property bool isChecked() @nogc @safe pure nothrow const { 178 return flags & IS_CHECKED ? true : false; 179 } 180 /** 181 * Sets whether the element is checked 182 */ 183 protected @property bool isChecked(bool val) @nogc @safe pure nothrow { 184 if (val) flags |= IS_CHECKED; 185 else flags &= ~IS_CHECKED; 186 return flags & IS_CHECKED ? true : false; 187 } 188 public void passMCE(MouseEventCommons mec, MouseClickEvent mce) { 189 if (state != ElementState.Enabled) return; 190 if (!mce.state && !(isPressed)) return; 191 192 parent.requestFocus(this); 193 194 if (mce.state == ButtonState.Pressed) { 195 if (mce.button == MouseButton.Left) flags |= IS_PRESSED; 196 if (!(mousePressEvent )) { 197 draw; 198 return; 199 } 200 } else if (mce.button == MouseButton.Left) { 201 flags &= ~IS_PRESSED; 202 } 203 204 MouseEvent me = new MouseEvent(this, EventType.MouseClick, SourceType.WindowElement); 205 me.mec = mec; 206 me.mce = mce; 207 208 switch (mce.button) { 209 case MouseButton.Left: 210 if (onMouseLClick !is null && (!mce.state || mousePressEvent)) 211 onMouseLClick(me); 212 break; 213 case MouseButton.Right: 214 if (onMouseRClick !is null && (!mce.state || mousePressEvent)) 215 onMouseRClick(me); 216 break; 217 case MouseButton.Mid: 218 if (onMouseMClick !is null && (!mce.state || mousePressEvent)) 219 onMouseMClick(me); 220 break; 221 default: 222 break; 223 } 224 225 draw; 226 } 227 228 public void passMME(MouseEventCommons mec, MouseMotionEvent mme) { 229 230 if (onMouseMove !is null) { 231 MouseEvent me = new MouseEvent(this, EventType.MouseMotion, SourceType.WindowElement); 232 me.mme = mme; 233 me.mec = mec; 234 onMouseMove(me); 235 } 236 } 237 238 public void passMWE(MouseEventCommons mec, MouseWheelEvent mwe) { 239 if (onMouseScroll !is null) { 240 MouseEvent me = new MouseEvent(this, EventType.MouseScroll, SourceType.WindowElement); 241 me.mec = mec; 242 me.mwe = mwe; 243 onMouseScroll(me); 244 } 245 } 246 247 }