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 }