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