1 // Written in the D programming language.
2 
3 /**
4 DLANGUI library.
5 
6 This module contains dlangui event types declarations.
7 
8 
9 Synopsis:
10 
11 ----
12 import dlangui.core.events;
13 
14 ----
15 
16 Copyright: Vadim Lopatin, 2014
17 License:   $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
18 Authors:   $(WEB coolreader.org, Vadim Lopatin)
19 */
20 module dlangui.core.events;
21 
22 import dlangui.core.i18n;
23 private import dlangui.widgets.widget;
24 
25 import std.conv;
26 
27 /// UI action
28 class Action {
29     protected int _id;
30     protected UIString _label;
31     protected string _iconId;
32     this(int id, string labelResourceId, string iconResourceId = null) {
33         _id = id;
34         _label = labelResourceId;
35         _iconId = iconResourceId;
36     }
37     this(int id, dstring label, string iconResourceId = null) {
38         _id = id;
39         _label = label;
40         _iconId = iconResourceId;
41     }
42     @property int id() const {
43         return _id;
44     }
45     @property Action id(int newId) {
46         _id = newId;
47         return this;
48     }
49     @property Action label(string resourceId) {
50         _label = resourceId;
51         return this;
52     }
53     @property Action label(dstring text) {
54         _label = text;
55         return this;
56     }
57     @property dstring label() const {
58         return _label.value;
59     }
60     @property ref const (UIString) labelValue() const {
61         return _label;
62     }
63     @property string iconId() const {
64         return _iconId;
65     }
66     @property Action iconId(string id) {
67         _iconId = id;
68         return this;
69     }
70 }
71 
72 
73 enum MouseAction : ubyte {
74     Cancel,   // button down handling is cancelled
75 	ButtonDown, // button is down
76 	ButtonUp, // button is up
77 	Move,     // mouse pointer is moving
78 	FocusIn,  // pointer is back inside widget while button is down after FocusOut
79 	FocusOut, // pointer moved outside of widget while button was down (if handler returns true, Move events will be sent even while pointer is outside widget)
80     Wheel,    // scroll wheel movement
81     //Hover,    // pointer entered widget which while button was not down (return true to track Hover state)
82     Leave     // pointer left widget which has before processed Move message, while button was not down
83 }
84 
85 enum MouseFlag : ushort {
86 	Control = 0x0008,
87 	LButton = 0x0001,
88 	MButton = 0x0010,
89 	RButton = 0x0002,
90 	Shift   = 0x0004,
91 	XButton1= 0x0020,
92 	XButton2= 0x0040,
93 	Alt     = 0x0080
94 }
95 
96 /// mouse button state details
97 struct ButtonDetails {
98 	/// Clock.currStdTime() for down event of this button (0 if button is up).
99 	long  _downTs;
100 	/// Clock.currStdTime() for up event of this button (0 if button is still down).
101 	long  _upTs;
102 	/// x coordinates of down event
103 	short _downX;
104 	/// y coordinates of down event
105 	short _downY;
106 	/// mouse button flags when down event occured
107 	ushort _downFlags;
108 	/// update for button down
109 	void down(short x, short y, ushort flags) {
110 		_downX = x;
111 		_downY = y;
112 		_downFlags = flags;
113         _upTs = 0;
114 		_downTs = std.datetime.Clock.currStdTime;
115 	}
116 	/// update for button up
117 	void up(short x, short y, ushort flags) {
118         _upTs = std.datetime.Clock.currStdTime;
119 	}
120 	@property bool isDown() { return _downTs != 0 && _upTs == 0; }
121     /// returns button down state duration in hnsecs (1/10000 of second).
122     @property int downDuration() {
123         if (_downTs == 0)
124             return 0;
125         if (_downTs != 0 && _upTs != 0)
126             return cast(int)(_upTs - _downTs);
127         long ts = std.datetime.Clock.currStdTime;
128         return cast(int)(ts - _downTs);
129     }
130     @property short downX() { return _downX; }
131     @property short downY() { return _downY; }
132     @property ushort downFlags() { return _downFlags; }
133 }
134 
135 enum MouseButton : ubyte {
136     None,
137     Left,
138     Right,
139     Middle
140     //XButton1, // additional button
141     //XButton2, // additional button
142 }
143 
144 class MouseEvent {
145     protected long _eventTimestamp;
146 	protected MouseAction _action;
147 	protected MouseButton _button;
148 	protected short _x;
149 	protected short _y;
150 	protected ushort _flags;
151 	protected short _wheelDelta;
152     protected Widget _trackingWidget;
153 	protected ButtonDetails _lbutton;
154 	protected ButtonDetails _mbutton;
155 	protected ButtonDetails _rbutton;
156 	protected bool _doNotTrackButtonDown;
157     @property ref ButtonDetails lbutton() { return _lbutton; }
158     @property ref ButtonDetails rbutton() { return _rbutton; }
159     @property ref ButtonDetails mbutton() { return _mbutton; }
160     @property MouseButton button() { return _button; }
161 	@property MouseAction action() { return _action; }
162 	void changeAction(MouseAction a) { _action = a; }
163 	@property ushort flags() { return _flags; }
164 	@property short wheelDelta() { return _wheelDelta; }
165 	@property short x() { return _x; }
166 	@property short y() { return _y; }
167     /// get event tracking widget to override
168 	@property Widget trackingWidget() { return _trackingWidget; }
169 	@property bool doNotTrackButtonDown() { return _doNotTrackButtonDown; }
170 	@property void doNotTrackButtonDown(bool flg) { _doNotTrackButtonDown = flg; }
171     /// override mouse tracking widget
172     void track(Widget w) {
173         _trackingWidget = w;
174     }
175     this (MouseEvent e) {
176         _eventTimestamp = e._eventTimestamp;
177 		_action = e._action;
178         _button = e._button;
179 		_flags = e._flags;
180 		_x = e._x;
181 		_y = e._y;
182         _lbutton = e._lbutton;
183         _rbutton = e._rbutton;
184         _mbutton = e._mbutton;
185         _wheelDelta = e._wheelDelta;
186     }
187 	this (MouseAction a, MouseButton b, ushort f, short x, short y, short wheelDelta = 0) {
188         _eventTimestamp = std.datetime.Clock.currStdTime;
189 		_action = a;
190         _button = b;
191 		_flags = f;
192 		_x = x;
193 		_y = y;
194         _wheelDelta = wheelDelta;
195 	}
196 }
197 
198 
199 enum KeyAction : uint {
200     KeyDown,
201     KeyUp,
202     Text,
203     Repeat,
204 }
205 
206 enum KeyFlag : uint {
207 	Control = 0x0008,
208 	Shift   = 0x0004,
209 	Alt     = 0x0080,
210     RControl = 0x0108,
211 	RShift   = 0x0104,
212 	RAlt     = 0x0180
213 }
214 
215 enum KeyCode : uint {
216     BACK = 8,
217     TAB = 9,
218     RETURN = 0x0D,
219     SHIFT = 0x10,
220     CONTROL = 0x11,
221     ALT = 0x12, // VK_MENU
222     PAUSE = 0x13,
223     CAPS = 0x14, // VK_CAPITAL, caps lock
224     ESCAPE = 0x1B, // esc
225     SPACE = 0x20,
226     PAGEUP = 0x21, // VK_PRIOR
227     PAGEDOWN = 0x22, // VK_NEXT
228     END = 0x23, // VK_END
229     HOME = 0x24, // VK_HOME
230     LEFT = 0x25,
231     UP = 0x26,
232     RIGHT = 0x27,
233     DOWN = 0x28,
234     INS = 0x2D,
235     DEL = 0x2E,
236     KEY_0 = 0x30,
237     KEY_1 = 0x31,
238     KEY_2 = 0x32,
239     KEY_3 = 0x33,
240     KEY_4 = 0x34,
241     KEY_5 = 0x35,
242     KEY_6 = 0x36,
243     KEY_7 = 0x37,
244     KEY_8 = 0x38,
245     KEY_9 = 0x39,
246     KEY_A = 0x41,
247     KEY_B = 0x42,
248     KEY_C = 0x43,
249     KEY_D = 0x44,
250     KEY_E = 0x45,
251     KEY_F = 0x46,
252     KEY_G = 0x47,
253     KEY_H = 0x48,
254     KEY_I = 0x49,
255     KEY_J = 0x4a,
256     KEY_K = 0x4b,
257     KEY_L = 0x4c,
258     KEY_M = 0x4d,
259     KEY_N = 0x4e,
260     KEY_O = 0x4f,
261     KEY_P = 0x50,
262     KEY_Q = 0x51,
263     KEY_R = 0x52,
264     KEY_S = 0x53,
265     KEY_T = 0x54,
266     KEY_U = 0x55,
267     KEY_V = 0x56,
268     KEY_W = 0x57,
269     KEY_X = 0x58,
270     KEY_Y = 0x59,
271     KEY_Z = 0x5a,
272     LWIN = 0x5b,
273     RWIN = 0x5c,
274     NUM_0 = 0x60,
275     NUM_1 = 0x61,
276     NUM_2 = 0x62,
277     NUM_3 = 0x63,
278     NUM_4 = 0x64,
279     NUM_5 = 0x65,
280     NUM_6 = 0x66,
281     NUM_7 = 0x67,
282     NUM_8 = 0x68,
283     NUM_9 = 0x69,
284     MUL = 0x6A,
285     ADD = 0x6B,
286     DIV = 0x6F,
287     SUB = 0x6D,
288     DECIMAL = 0x6E,
289     F1 = 0x70,
290     F2 = 0x71,
291     F3 = 0x72,
292     F4 = 0x73,
293     F5 = 0x74,
294     F6 = 0x75,
295     F7 = 0x76,
296     F8 = 0x77,
297     F9 = 0x78,
298     F10 = 0x79,
299     F11 = 0x7a,
300     F12 = 0x7b,
301     F13 = 0x7c,
302     F14 = 0x7d,
303     F15 = 0x7e,
304     F16 = 0x7f,
305     F17 = 0x80,
306     F18 = 0x81,
307     F19 = 0x82,
308     F20 = 0x83,
309     F21 = 0x84,
310     F22 = 0x85,
311     F23 = 0x86,
312     F24 = 0x87,
313     NUMLOCK = 0x90,
314     SCROLL = 0x91, // scroll lock
315     LSHIFT = 0xA0,
316     RSHIFT = 0xA1,
317     LCONTROL = 0xA2,
318     RCONTROL = 0xA3,
319     LALT = 0xA4,
320     RALT = 0xA5,
321 }
322 
323 /// keyboard event
324 class KeyEvent {
325     protected KeyAction _action;
326     protected uint _keyCode;
327     protected uint _flags;
328     protected dstring _text;
329     /// key action (KeyDown, KeyUp, Text, Repeat)
330     @property KeyAction action() { return _action; }
331     /// key code
332     @property uint keyCode() { return _keyCode; }
333     /// flags (shift, ctrl, alt...)
334     @property uint flags() { return _flags; }
335     /// entered text, for Text action
336     @property dstring text() { return _text; }
337     /// create key event
338     this(KeyAction action, uint keyCode, uint flags, dstring text = null) {
339         _action = action;
340         _keyCode = keyCode;
341         _flags = flags;
342         _text = text;
343     }
344 }
345 
346 enum ScrollAction : ubyte {
347     /// space above indicator pressed
348     PageUp,
349     /// space below indicator pressed
350     PageDown, 
351     /// up/left button pressed
352     LineUp,
353     /// down/right button pressed
354     LineDown,
355     /// slider pressed
356     SliderPressed,
357     /// dragging in progress
358     SliderMoved,
359     /// dragging finished
360     SliderReleased
361 }
362 
363 /// slider/scrollbar event
364 class ScrollEvent {
365     private ScrollAction _action;
366     private int _minValue;
367     private int _maxValue;
368     private int _pageSize;
369     private int _position;
370     private bool _positionChanged;
371     @property ScrollAction action() { return _action; }
372     @property int minValue() { return _minValue; }
373     @property int maxValue() { return _maxValue; }
374     @property int pageSize() { return _pageSize; }
375     @property int position() { return _position; }
376     @property bool positionChanged() { return _positionChanged; }
377     /// change position in event handler to update slider position
378     @property void position(int newPosition) { _position = newPosition; _positionChanged = true; }
379     this(ScrollAction action, int minValue, int maxValue, int pageSize, int position) {
380         _action = action;
381         _minValue = minValue;
382         _maxValue = maxValue;
383         _pageSize = pageSize;
384         _position = position;
385     }
386     /// default update position for actions like PageUp/PageDown, LineUp/LineDown
387     int defaultUpdatePosition() {
388         int delta = 0;
389         switch (_action) {
390             case ScrollAction.LineUp:
391                 delta = _pageSize / 20;
392                 if (delta < 1)
393                     delta = 1;
394                 delta = -delta;
395                 break;
396             case ScrollAction.LineDown:
397                 delta = _pageSize / 20;
398                 if (delta < 1)
399                     delta = 1;
400                 break;
401             case ScrollAction.PageUp:
402                 delta = _pageSize * 3 / 4;
403                 if (delta < 1)
404                     delta = 1;
405                 delta = -delta;
406                 break;
407             case ScrollAction.PageDown:
408                 delta = _pageSize * 3 / 4;
409                 if (delta < 1)
410                     delta = 1;
411                 break;
412             default:
413                 return position;
414         }
415         int newPosition = _position + delta;
416         if (newPosition > _maxValue - _pageSize)
417             newPosition = _maxValue - _pageSize;
418         if (newPosition < _minValue)
419             newPosition = _minValue;
420         if (_position != newPosition)
421             position = newPosition;
422         return position;
423     }
424 }