1 module ws.gui.inputField;
2 
3 import
4 	std.conv,
5 	ws.event,
6 	ws.io,
7 	ws.time,
8 	ws.math.math,
9 	ws.gl.draw,
10 	ws.gui.base,
11 	ws.gui.text;
12 
13 
14 class InputField: Base {
15 	
16 	bool hasFocus = false;
17 	Event!string onEnter;
18 
19 	string rawText;
20 	size_t cursor;
21 
22 	string error;
23 	double errorTime;
24 	bool blockChar;
25 	string font;
26 	size_t fontSize;
27 
28 	this(){
29 		setCursor(Mouse.cursor.text);
30 		onEnter = new Event!string;
31 	}
32 
33 	string text(){
34 		return rawText;
35 	}
36 
37 	void text(string text){
38 		rawText = text;
39 		cursor = cursor.min(text.length).max(0);
40 	}
41 
42 	void setFont(string font, size_t size){
43 		this.font = font;
44 		this.fontSize = size;
45 	}
46 
47 	override void onKeyboard(dchar c){
48 		if(!blockChar){
49 			text = text[0..cursor] ~ c.to!string ~ text[cursor..$];
50 			cursor++;
51 			blockChar = false;
52 		}
53 	}
54 
55 	override void onKeyboard(Keyboard.key key, bool pressed){
56 		if(!pressed)
57 			return;
58 		blockChar = true;
59 		switch(key){
60 			case Keyboard.backspace:
61 				if(cursor > 0){
62 					rawText = rawText[0..cursor-1] ~ rawText[cursor..$];
63 					cursor--;
64 				}
65 				break;
66 				
67 			case Keyboard.del:
68 				if(cursor < rawText.length){
69 					rawText = rawText[0..cursor] ~ rawText[cursor+1..$];
70 				}
71 				break;
72 				
73 			case Keyboard.enter:
74 				try
75 					onEnter(rawText);
76 				catch(InputException e){
77 					error = e.msg;
78 					errorTime = now;
79 				}
80 				break;
81 				
82 			case Keyboard.right:
83 				if(Keyboard.get(Keyboard.control))
84 					while(cursor < rawText.length && rawText[cursor+1] != ' ')
85 						++cursor;
86 				else if(cursor < rawText.length)
87 					++cursor;
88 				break;
89 				
90 			case Keyboard.left:
91 				if(Keyboard.get(Keyboard.control))
92 					while(cursor > 0 && rawText[cursor-1] != ' ')
93 						--cursor;
94 				else if(cursor > 0)
95 					--cursor;
96 				break;
97 				
98 			default:
99 				blockChar = false;
100 				break;
101 		}
102 
103 	}
104 
105 
106 	override void onKeyboardFocus(bool hasFocus){
107 		this.hasFocus = hasFocus;
108 	}
109 
110 
111 	override void onDraw(){
112 		auto color = style.fg.normal;
113 		if(hasFocus || hasMouseFocus){
114 			auto alpha = (sin(now*PI*2)+0.5).min(1).max(0);
115 			draw.setColor([1,1,1,alpha]);
116 			int x = draw.width(text[0..cursor]);
117 			draw.rect(pos.a + [x+4, 4], [1, size.h-8]);
118 		}
119 		auto t = now;
120 		if(errorTime+2 > t){
121 			auto alpha = clamp!float(errorTime+2 - t, 0, 1)/1;
122 			draw.setColor([1,0,0,alpha]);
123 			draw.rect(pos, size);
124 			draw.setFont("Consolas", 9);
125 			draw.setColor([1,1,1,alpha]);
126 			draw.text(pos.a + [2, 0], size.h, error);
127 		}
128 		draw.setColor([1,1,1]);
129 		draw.text(pos, size.h, text);
130 	}
131 
132 
133 }
134 
135 
136 class InputException: Exception {
137 	InputField text;
138 	this(InputField t, string msg, string file = __FILE__, size_t line = __LINE__){
139 		text = t;
140 		super(msg, null, file, line);
141 	}
142 	this(InputField t, string msg, Exception cause, string file = __FILE__, size_t line = __LINE__){
143 		text = t;
144 		super(msg, cause, file, line);
145 	}
146 }