SectorZone: add attribute arc_boundary
[xcsoar.git] / src / Dialogs / dlgTextEntry_Keyboard.cpp
blobd9b9af3a1d8f4f24429c1c8496aa4ddc72325b35
1 /*
2 Copyright_License {
4 XCSoar Glide Computer - http://www.xcsoar.org/
5 Copyright (C) 2000-2013 The XCSoar Project
6 A detailed list of copyright holders can be found in the file "AUTHORS".
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 #include "Dialogs/TextEntry.hpp"
25 #include "Form/Form.hpp"
26 #include "Form/Button.hpp"
27 #include "Form/Keyboard.hpp"
28 #include "Form/Edit.hpp"
29 #include "Screen/Layout.hpp"
30 #include "Screen/Key.h"
31 #include "Util/StringUtil.hpp"
32 #include "UIGlobals.hpp"
33 #include "Language/Language.hpp"
35 #include <algorithm>
36 #include <assert.h>
38 static WndProperty *editor;
39 static KeyboardControl *kb = NULL;
41 static AllowedCharacters AllowedCharactersCallback;
43 static constexpr size_t MAX_TEXTENTRY = 40;
44 static unsigned int cursor = 0;
45 static size_t max_width;
46 static TCHAR edittext[MAX_TEXTENTRY];
48 static void
49 UpdateAllowedCharacters()
51 if (AllowedCharactersCallback)
52 kb->SetAllowedCharacters(AllowedCharactersCallback(edittext));
55 static void
56 UpdateTextboxProp()
58 editor->SetText(edittext);
60 UpdateAllowedCharacters();
63 static bool
64 DoBackspace()
66 if (cursor < 1)
67 return false;
69 cursor--;
70 edittext[cursor] = 0;
71 UpdateTextboxProp();
72 return true;
75 static void
76 OnBackspace()
78 DoBackspace();
81 static bool
82 DoCharacter(TCHAR character)
84 if (cursor >= max_width - 1)
85 return false;
87 edittext[cursor++] = character;
88 edittext[cursor] = 0;
89 UpdateTextboxProp();
90 return true;
93 static void
94 OnCharacter(TCHAR character)
96 DoCharacter(character);
99 static bool
100 FormKeyDown(unsigned key_code)
102 switch (key_code) {
103 case KEY_RIGHT:
104 return true;
105 case KEY_LEFT:
106 case KEY_BACK:
107 DoBackspace();
108 return true;
111 return false;
114 static bool
115 FormCharacter(unsigned ch)
117 if (ch < 0x20)
118 return false;
120 #ifndef _UNICODE
121 if (ch >= 0x80)
122 /* TODO: ASCII only for now, because we don't have proper UTF-8
123 support yet */
124 return false;
125 #endif
127 DoCharacter((TCHAR)ch);
128 return true;
131 static void
132 ClearText()
134 cursor = 0;
135 edittext[0] = 0;
136 UpdateTextboxProp();
139 bool
140 dlgTextEntryKeyboardShowModal(TCHAR *text, size_t width,
141 const TCHAR* caption,
142 AllowedCharacters accb)
144 if (width == 0)
145 width = MAX_TEXTENTRY;
147 max_width = std::min(MAX_TEXTENTRY, width);
149 const DialogLook &look = UIGlobals::GetDialogLook();
150 WndForm form(look);
151 form.Create(UIGlobals::GetMainWindow(), caption);
152 form.SetKeyDownFunction(FormKeyDown);
153 form.SetCharacterFunction(FormCharacter);
155 ContainerWindow &client_area = form.GetClientAreaWindow();
156 const PixelRect rc = client_area.GetClientRect();
158 const PixelScalar client_height = rc.bottom - rc.top;
160 const PixelScalar padding = Layout::Scale(2);
161 const PixelScalar backspace_width = Layout::Scale(36);
162 const PixelScalar backspace_left = rc.right - padding - backspace_width;
163 const PixelScalar editor_height = Layout::Scale(22);
164 const PixelScalar editor_bottom = padding + editor_height;
165 const PixelScalar button_height = Layout::Scale(40);
166 constexpr unsigned keyboard_rows = 5;
167 const PixelScalar keyboard_top = editor_bottom + padding;
168 const PixelScalar keyboard_height = keyboard_rows * button_height;
169 const PixelScalar keyboard_bottom = keyboard_top + keyboard_height;
171 const bool vertical = client_height >= keyboard_bottom + button_height;
173 const PixelScalar button_top = vertical
174 ? rc.bottom - button_height
175 : keyboard_bottom - button_height;
176 const PixelScalar button_bottom = vertical
177 ? rc.bottom
178 : keyboard_bottom;
180 const PixelScalar ok_left = vertical ? 0 : padding;
181 const PixelScalar ok_right = vertical
182 ? rc.right / 3
183 : ok_left + Layout::Scale(80);
185 const PixelScalar cancel_left = vertical
186 ? ok_right
187 : Layout::Scale(175);
188 const PixelScalar cancel_right = vertical
189 ? rc.right * 2 / 3
190 : cancel_left + Layout::Scale(60);
192 const PixelScalar clear_left = vertical
193 ? cancel_right
194 : Layout::Scale(235);
195 const PixelScalar clear_right = vertical
196 ? rc.right
197 : clear_left + Layout::Scale(50);
199 WndProperty _editor(client_area, look, _T(""),
200 { 0, padding, backspace_left - padding, editor_bottom },
201 0, WindowStyle());
202 _editor.SetReadOnly();
203 editor = &_editor;
205 ButtonWindowStyle button_style;
206 button_style.TabStop();
208 WndButton ok_button(client_area, look, _("OK"),
209 { ok_left, button_top, ok_right, button_bottom },
210 button_style, form, mrOK);
212 WndButton cancel_button(client_area, look, _("Cancel"),
213 { cancel_left, button_top,
214 cancel_right, button_bottom },
215 button_style, form, mrCancel);
217 WndButton clear_button(client_area, look, _("Clear"),
218 { clear_left, button_top,
219 clear_right, button_bottom },
220 button_style, ClearText);
222 KeyboardControl keyboard(client_area, look,
223 { padding, keyboard_top,
224 rc.right - padding,
225 keyboard_bottom },
226 OnCharacter);
227 kb = &keyboard;
229 WndButton backspace_button(client_area, look, _T("<-"),
230 { backspace_left, padding, rc.right - padding,
231 editor_bottom },
232 button_style, OnBackspace);
234 AllowedCharactersCallback = accb;
236 cursor = 0;
237 ClearText();
239 if (!StringIsEmpty(text)) {
240 CopyString(edittext, text, width);
241 cursor = _tcslen(text);
244 UpdateTextboxProp();
245 bool result = form.ShowModal() == mrOK;
247 if (result) {
248 CopyString(text, edittext, width);
251 return result;