1 module pixelperfectengine.concrete.popup.popuptextinput;
2 
3 public import pixelperfectengine.concrete.popup.base;
4 
5 /**
6  * Text input in pop-up fashion.
7  */
8 public class PopUpTextInput : PopUpElement, TextInputListener {
9 	protected bool enableEdit, insert;
10 	protected size_t cursorPos;
11 	protected int horizTextOffset, select;
12 	public void delegate(Event ev) onTextInput;
13 
14 	public this(string source, Text text, Coordinate position){
15 		this.source = source;
16 		this.text = text;
17 		this.position = position;
18 		enableEdit = true;
19 		output = new BitmapDrawer(position.width, position.height);
20 		inputhandler.startTextInput(this, false, position);
21 	}
22 	public override void draw(){
23 		StyleSheet ss = getStyleSheet();
24 		const Box mainPos = Box(0,0,position.width - 1, position.height - 1);
25 		output.drawFilledBox(mainPos, ss.getColor("window"));
26 		output.drawBox(mainPos, ss.getColor("windowascent"));
27 		const int textPadding = getStyleSheet.drawParameters["TextSpacingSides"];
28 		Coordinate textPos = Coordinate(textPadding,(position.height / 2) - (text.font.size / 2) ,
29 				position.width,position.height - textPadding);
30 		
31 		const int y = text.font.size;
32 		//if(x > textPos.width ) xOffset = horizTextOffset;
33 		//draw cursor
34 		if(enableEdit) {
35 			const int x0 = text.getWidth(0,cursorPos) + textPadding - horizTextOffset;
36 			if(!insert){
37 				//output.drawLine(x0, x0, 2, 2 + y, getStyleSheet().getColor("selection"));
38 				output.drawLine(Point(x0, 2), Point(x0, 2 + y), ss.getColor("selection"));
39 			}else{
40 				const int x1 = cursorPos == text.charLength ? text.font.chars(' ').xadvance :
41 						text.getWidth(cursorPos,cursorPos + 1);
42 				//output.drawFilledRectangle(x0, x1 + x0, 2, 2 + y, getStyleSheet().getColor("selection"));
43 				output.drawFilledBox(Box(x0, 2, x1, 2 + y), ss.getColor("selection"));
44 			}
45 		}
46 
47 		
48 		output.drawSingleLineText(textPos, text, horizTextOffset);
49 		//parent.drawUpdate(this);
50 		if(onDraw !is null){
51 			onDraw();
52 		}
53 	}
54 	private void deleteCharacter(size_t n){
55 		text.removeChar(n);
56 	}
57 	public void textInputEvent(uint timestamp, uint windowID, dstring text){
58 		for(int j ; j < text.length ; j++){
59 			this.text.insertChar(cursorPos++, text[j]);
60 		}
61 		const int textPadding = getStyleSheet().drawParameters["TextSpacingSides"];
62 		const Coordinate textPos = Coordinate(textPadding,(position.height / 2) - (this.text.font.size / 2) ,
63 				position.width,position.height - textPadding);
64 		const int x = this.text.getWidth(), cursorPixelPos = this.text.getWidth(0, cursorPos);
65 		if(x > textPos.width) {
66 			 if(cursorPos == this.text.text.length) {
67 				horizTextOffset = x - textPos.width;
68 			 } else if(cursorPixelPos < horizTextOffset) { //Test for whether the cursor would fall out from the current text area
69 				horizTextOffset = cursorPixelPos;
70 			 } else if(cursorPixelPos > horizTextOffset + textPos.width) {
71 				horizTextOffset = horizTextOffset + textPos.width;
72 			 }
73 		}
74 		draw();
75 	}
76 	/**
77      * Passes text editing events to the target, alongside with a window ID and a timestamp.
78      */
79 	public void textEditingEvent(uint timestamp, uint windowID, dstring text, int start, int length) {
80 		for (int i ; i < length ; i++) {
81 			this.text.overwriteChar(start + i, text[i]);
82 		}
83 		cursorPos = start + length;
84 	}
85 	/**
86      * Passes text input key events to the target, e.g. cursor keys.
87      */
88 	public void textInputKeyEvent(uint timestamp, uint windowID, TextInputKey key, ushort modifier = 0){
89 		switch(key){
90 			case TextInputKey.Escape:
91 				inputhandler.stopTextInput();
92 				break;
93 			case TextInputKey.Enter:
94 				inputhandler.stopTextInput();
95 				//invokeActionEvent(new Event(source, null, null, null, text, text.length, EventType.TEXTINPUT));
96 				if(onTextInput !is null)
97 					onTextInput(new Event(this, text, EventType.TextInput, SourceType.PopUpElement));
98 				break;
99 			case TextInputKey.Backspace:
100 				if(cursorPos > 0){
101 					deleteCharacter(cursorPos - 1);
102 					cursorPos--;
103 					draw();
104 				}
105 				break;
106 			case TextInputKey.Delete:
107 				deleteCharacter(cursorPos);
108 				draw();
109 				break;
110 			case TextInputKey.CursorLeft:
111 				if(cursorPos > 0){
112 					--cursorPos;
113 					draw();
114 				}
115 				break;
116 			case TextInputKey.CursorRight:
117 				if(cursorPos < text.charLength){
118 					++cursorPos;
119 					draw();
120 				}
121 				break;
122 			case TextInputKey.Insert:
123 				insert = !insert;
124 				draw();
125 				break;
126 			case TextInputKey.Home:
127 				cursorPos = 0;
128 				draw();
129 				break;
130 			case TextInputKey.End:
131 				cursorPos = text.charLength;
132 				draw();
133 				break;
134 			default:
135 				break;
136 
137 		}
138 	}
139 	public void dropTextInput(){
140 		parent.endPopUpSession(this);
141 		
142 	}
143 	public void initTextInput() {
144 	}
145 }