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