1 module iota.controls.types;
2 
3 public import iota.etc.window;
4 import std.conv : to;
5 /*
6  * If `iota_hi_prec_timestamp` is supplied as a version identifier, then MonoTime will be used for timestamps, 
7  * otherwise uint will be used.
8  *
9  * However it's not ensured that higher precision will be actually provided, or that it'll be useful.
10  */
11 version (iota_hi_prec_timestamp) {
12 	public import core.time;
13 	alias Timestamp = MonoTime;
14 } else {
15 	alias Timestamp = uint;
16 }
17 /** 
18  * Defines the types of the input devices.
19  */
20 public enum InputDeviceType : ubyte {
21 	init,
22 	Keyboard,
23 	Mouse,
24 	GameController,		///Joysticks, gamepads, etc.
25 	Pen,				///Graphics tablet, etc.
26 	TouchScreen,
27 	Gyro,				///Built-in Gyro device.
28 	System,				///Misc. system related input devices and events.
29 	MIDI,				///If enabled, MIDI devices can function as regular input devices creating regular input events from key press and control change commands.
30 }
31 /**
32  * Defines possible input event types.
33  */
34 public enum InputEventType {
35 	init,
36 	Keyboard,
37 	TextInput,
38 	TextCommand,
39 	TextEdit,
40 	MouseClick,
41 	MouseMove,
42 	MouseScroll,
43 	GCButton,
44 	GCAxis,
45 	GCHat,
46 	Pen,
47 	DeviceAdded,
48 	DeviceRemoved,
49 	Clipboard,
50 	WindowClose,
51 	WindowResize,
52 	WindowMinimize,
53 	WindowMaximize,
54 	WindowRestore,
55 	WindowMove,
56 	ApplExit,
57 }
58 /** 
59  * Defines text command event types.
60  */
61 public enum TextCommandType {
62 	init,
63 	Cursor,
64 	CursorV,
65 
66 	Home,
67 	End,
68 	PageUp,
69 	PageDown,
70 
71 	Delete,
72 
73 	Insert,
74 
75 	NewLine,
76 	NewPara,
77 	
78 }
79 /** 
80  * Defines return codes for event polling.
81  */
82 public enum EventPollStatus {
83 	Done			=	0,
84 	HasMore			=	1,
85 	DeviceInvalidated,
86 	DeviceError,
87 	NoDevsFound,
88 }
89 /** 
90  * Defines text edit event flags.
91  */
92 public enum TextCommandFlags {
93 	PerWord = 1<<0,		///Modifies cursor and delete to work on a per-word basis (essentially holding down the Ctrl key)
94 	Select = 1<<1,		///Modifies cursor and other nav commands
95 }
96 /**
97  * Contains basic info about the input device.
98  * Child classes might also contain references to OS variables and pointers.
99  */
100 public abstract class InputDevice {
101 	protected InputDeviceType	_type;		/// Defines the type of the input device
102 	protected ubyte				_devNum;	/// Defines the number of the input device within the group of same types
103 	protected ubyte				_battP;		/// Current percentage of the battery
104 	/// Status flags of the device.
105 	/// Bits 0-7 are common, 8-15 are special to each device/interface type.
106 	/// Note: flags related to indicators/etc should be kept separately.
107 	protected ushort			status;
108 	/**
109 	 * Defines common status codes
110 	 */
111 	public enum StatusFlags : ushort {
112 		IsConnected		=	1<<0,
113 		IsInvalidated	=	1<<1,
114 		HasBattery		=	1<<2,
115 		IsAnalog		=	1<<3,
116 		IsVirtual		=	1<<4,
117 	}
118 	/** 
119 	 * Returns the type of the device.
120 	 */
121 	public InputDeviceType type() @nogc @safe pure nothrow const @property {
122 		return _type;
123 	}
124 	/** 
125 	 * Returns the device number.
126 	 */
127 	public ubyte devNum() @nogc @safe pure nothrow const @property {
128 		return _devNum;
129 	}
130 	/**
131 	 * Returns true if the device is connected.
132 	 */
133 	public bool isConnected() @nogc @safe pure nothrow const @property {
134 		return (status & StatusFlags.IsConnected);
135 	}
136 	/** 
137 	 * Returns true if device got invalidated (disconnected, etc).
138 	 */
139 	public bool isInvalidated() @nogc @safe pure nothrow const @property {
140 		return (status & StatusFlags.IsInvalidated) != 0;
141 	}
142 	/** 
143 	 * Returns true if device has analog capabilities.
144 	 */
145 	public bool isAnalog() @nogc @safe pure nothrow const @property {
146 		return (status & StatusFlags.IsAnalog) != 0;
147 	}
148 	/** 
149 	 * Returns true if device is virtual, emulated, etc.
150 	 */
151 	public bool isVirtual() @nogc @safe pure nothrow const @property {
152 		return (status & StatusFlags.IsVirtual) != 0;
153 	}
154 	/** 
155 	 * Returns the battery percentage of the device, or ubyte.max if it doesn't have a battery.
156 	 */
157 	public ubyte battP() @nogc @safe pure nothrow const @property {
158 		if (status & StatusFlags.HasBattery) 
159 			return _battP;
160 		else
161 			return ubyte.max;
162 	}
163 	/** 
164 	 * Polls the device for events.
165 	 * Params:
166 	 *   output = InputEvents outputted by the 
167 	 * Returns: 1 if there's still events to be polled, 0 if no events left. Other values are error codes.
168 	 */
169 	public abstract int poll(ref InputEvent output) @nogc nothrow;
170 }
171 /** 
172  * Defines a button (keyboard, game controller) event data.
173  */
174 public struct ButtonEvent {
175 	ubyte		dir;	///Up (0) or down (1)
176 	ubyte		repeat;	///Used for repetition if supported by source
177 	ushort		aux;	///Used to identify modifier keys on keyboard, etc.
178 	uint		id;		///Button ID
179 	float		auxF;	///Placeholder for pressure-sensitive buttons, NaN otherwise
180 	string toString() @safe pure const {
181 		return "Direction: " ~ to!string(dir) ~" ; repeat: " ~ to!string(repeat) ~ " ; aux: " ~ to!string(aux) ~ " ; ID: " ~ 
182 				to!string(id) ~ " ; ";
183 	}
184 }
185 /** 
186  * Defines the contents of a text input data.
187  *
188  * Version label `iota_use_utf8` will make the middleware to convert text input to UTF8 on non-UTF8 systems, leaving
189  * it out will make UTF32 as the standard
190  */
191 public struct TextInputEvent {
192 	version (iota_use_utf8) {
193 		char[]	text;
194 	} else {
195 		dchar[]	text;
196 	}
197 	bool		isClipboard;///True if the text input originates from a clipboard event.
198 	string toString() @safe pure const {
199 		return "Text: \"" ~ to!string(text) ~ "\" isClipboard: " ~ to!string(isClipboard) ~ " ; "; 
200 	}
201 }
202 /** 
203  * Defines text editing command events that could happen during a text input.
204  */
205 public struct TextCommandEvent {
206 	TextCommandType	type;	///The type of the text editing event.
207 	int			amount;		///Amount of the event + direction, if applicable.
208 	uint		flags;		///Extra flags for text edit events.
209 }
210 /**
211  * Defines an axis event.
212  * Per-axis IDs are being used.
213  */
214 public struct AxisEvent {
215 	uint		id;		///Identifier number of the axis.
216 	float		val;	///Current value of the axis (either -1.0 to 1.0 or 0.0 to 1.0)
217 	string toString() @safe pure const {
218 		return "ID: " ~ to!string(id)  ~ " ; val: " ~ to!string(val) ~ " ; ";
219 	}
220 }
221 /**
222  * Defines a mouse click event.
223  * Also supplies the screen coordinates of the click event.
224  */
225 public struct MouseClickEvent {
226 	ubyte		dir;	///Up or down
227 	ubyte		repeat;	///Non-zero if multiple clicks occured.
228 	ushort		button;	///Button ID
229 	int			x;		///X coordinate
230 	int			y;		///Y coordinate
231 	string toString() @safe pure const {
232 		return "Direction: " ~ to!string(dir) ~ " ; repeat: " ~ to!string(repeat) ~ " ; button: " ~ to!string(button) ~ 
233 				" ; x: " ~ to!string(x) ~ " y; " ~ to!string(y) ~" ; ";
234 	}
235 }
236 /**
237  * Defines a mouse motion event with the buttons that are held down.
238  */
239 public struct MouseMotionEvent {
240 	///If a bit high, it indicates that button is being held down.
241 	///See enum MouseButtonFlags to identify each button.
242 	uint		buttons;
243 	int			x;		///X position of the cursor
244 	int			y;		///Y position of the cursor
245 	int			xD;		///X amount of the motion
246 	int			yD;		///Y amount of the motion
247 	string toString() @safe pure const {
248 		return "Buttons: " ~ to!string(buttons) ~ " ; x: " ~ to!string(x) ~ " ; y: " ~ to!string(y) ~ " ; xD: " ~ 
249 				to!string(xD) ~ " ; yD " ~ to!string(yD) ~ " ; ";
250 	}
251 }
252 /**
253  * Defines a mouse scroll event.
254  */
255 public struct MouseScrollEvent {
256 	int			xS;		///Amount of horizontal scroll
257 	int			yS;		///Amount of vertical scroll
258 	int			x;		///X position of the cursor
259 	int			y;		///Y position of the cursor
260 	string toString() @safe pure const {
261 		return "xS: " ~ to!string(xS) ~ " ; yS: " ~ to!string(yS) ~ " ; x: " ~ to!string(x) ~ " ; y: " ~ to!string(y) ~ " ; ";
262 	}
263 }
264 /**
265  * Defines a pen event of a graphic tablet, screen, etc.
266  */
267 public struct PenEvent {
268 	int			x;			/// X position of the event
269 	int			y;			/// Y position of the event
270 	float		tilt;		/// The tilt amount of the pen 
271 	float		pDir;		/// The direction of the pen
272 	float		tDir;		/// The tilt direction of the pen
273 }
274 public struct WindowEvent {
275 	int			x;
276 	int			y;
277 	int			width;
278 	int			height;
279 }
280 /**
281  * Contains data generated by input devices.
282  */
283 public struct InputEvent {
284 	InputDevice				source;		///Pointer to the source input device class.
285 	WindowH					handle;		///Window handle for GUI applications if there's any, null otherwise.
286 	Timestamp				timestamp;	///Timestamp for when the event have happened.
287 	InputEventType			type;		///Type of the input event.
288 	union {
289 		ButtonEvent			button;
290 		TextInputEvent		textIn;
291 		TextCommandEvent	textCmd;
292 		AxisEvent			axis;
293 		MouseClickEvent		mouseCE;
294 		MouseMotionEvent	mouseME;
295 		MouseScrollEvent	mouseSE;
296 		PenEvent			pen;
297 	}
298 	string toString() {
299 		string result = "Source: " ~ source.toString ~ " ; Window handle: " ~ to!string(handle) ~ " ; Timestamp: " ~ 
300 				to!string(timestamp) ~ " ; Type: " ~ to!string(type) ~ " ; Rest: [";
301 		switch (type) {
302 			case InputEventType.Keyboard, InputEventType.GCButton:
303 				result ~= button.toString();
304 				break;
305 			case InputEventType.TextInput:
306 				result ~= textIn.toString();
307 				break;
308 			case InputEventType.MouseClick:
309 				result ~= mouseCE.toString();
310 				break;
311 			case InputEventType.MouseMove:
312 				result ~= mouseME.toString();
313 				break;
314 			case InputEventType.MouseScroll:
315 				result ~= mouseSE.toString();
316 				break;
317 			default:
318 				break;
319 		}
320 		result ~= "]";
321 		return result;
322 	}
323 }