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 }