ui/winui/text.cpp

branch
newapi
changeset 225
097f45f9c1fa
parent 219
527a66c0afb2
child 231
e160bb392148
equal deleted inserted replaced
224:88bc21b19213 225:097f45f9c1fa
31 #include "text.h" 31 #include "text.h"
32 32
33 #include "../common/context.h" 33 #include "../common/context.h"
34 #include "../common/object.h" 34 #include "../common/object.h"
35 35
36 #include <cx/string.h>
37 #include <cx/allocator.h>
38
36 #include "util.h" 39 #include "util.h"
37 #include "container.h" 40 #include "container.h"
41
42
38 43
39 using namespace winrt; 44 using namespace winrt;
40 using namespace Microsoft::UI::Xaml; 45 using namespace Microsoft::UI::Xaml;
41 using namespace Microsoft::UI::Xaml::Controls; 46 using namespace Microsoft::UI::Xaml::Controls;
42 using namespace Windows::UI::Xaml::Interop; 47 using namespace Windows::UI::Xaml::Interop;
43 using namespace winrt::Windows::Foundation; 48 using namespace winrt::Windows::Foundation;
49 using namespace Microsoft::UI::Xaml::Markup;
50 using namespace Microsoft::UI::Xaml::Media;
44 using namespace winrt::Microsoft::UI::Xaml::Controls::Primitives; 51 using namespace winrt::Microsoft::UI::Xaml::Controls::Primitives;
45 52 using namespace winrt::Windows::UI::Xaml::Input;
46 53
47 UIWIDGET ui_textfield_create(UiObject* obj, UiTextFieldArgs args) { 54 UIWIDGET ui_textfield_create(UiObject* obj, UiTextFieldArgs args) {
48 UiObject* current = uic_current_obj(obj); 55 UiObject* current = uic_current_obj(obj);
49 56
50 // create textbox and toolkit wrapper 57 // create textbox and toolkit wrapper
158 void ui_passwordfield_set(UiString * str, const char* newvalue) { 165 void ui_passwordfield_set(UiString * str, const char* newvalue) {
159 UiWidget* widget = (UiWidget*)str->obj; 166 UiWidget* widget = (UiWidget*)str->obj;
160 PasswordBox box = widget->uielement.as<PasswordBox>(); 167 PasswordBox box = widget->uielement.as<PasswordBox>();
161 box.Password(ui_string_set(str, newvalue)); 168 box.Password(ui_string_set(str, newvalue));
162 } 169 }
170
171
172 // ------------------------ path textfield --------------------------------------
173
174 extern "C" static void destroy_ui_pathtextfield(void* ptr) {
175 UiPathTextField* pb = (UiPathTextField*)ptr;
176 delete pb;
177 }
178
179 static void ui_context_add_pathtextfield_destructor(UiContext* ctx, UiPathTextField* pb) {
180 cxMempoolRegister(ctx->mp, pb, destroy_ui_pathtextfield);
181 }
182
183 static void ui_pathtextfield_clear(StackPanel& buttons) {
184 for (int i = buttons.Children().Size() - 1; i >= 0; i--) {
185 buttons.Children().RemoveAt(i);
186 }
187 }
188
189 static void ui_pathfield_free_pathelms(UiPathElm* elms, size_t nelm) {
190 if (!elms) {
191 return;
192 }
193 for (int i = 0; i < nelm; i++) {
194 UiPathElm e = elms[i];
195 free(e.name);
196 free(e.path);
197 }
198 free(elms);
199 }
200
201 UiPathTextField::~UiPathTextField() {
202 ui_pathfield_free_pathelms(this->current_path, this->current_path_nelms);
203 }
204
205 static UiPathElm* default_pathelm_func(const char* full_path, size_t len, size_t* ret_nelm, void* data) {
206 cxstring *pathelms;
207 size_t nelm = cx_strsplit_a(cxDefaultAllocator, cx_strn(full_path, len), CX_STR("/"), 4096, &pathelms);
208
209 if (nelm == 0) {
210 *ret_nelm = 0;
211 return nullptr;
212 }
213
214 UiPathElm* elms = (UiPathElm*)calloc(nelm, sizeof(UiPathElm));
215 size_t n = nelm;
216 int j = 0;
217 for (int i = 0; i < nelm; i++) {
218 cxstring c = pathelms[i];
219 if (c.length == 0) {
220 if (i == 0) {
221 c.length = 1;
222 }
223 else {
224 n--;
225 continue;
226 }
227 }
228
229 cxmutstr m = cx_strdup(c);
230 elms[j].name = m.ptr;
231 elms[j].name_len = m.length;
232
233 size_t elm_path_len = c.ptr + c.length - full_path;
234 cxmutstr elm_path = cx_strdup(cx_strn(full_path, elm_path_len));
235 elms[j].path = elm_path.ptr;
236 elms[j].path_len = elm_path.length;
237
238 j++;
239 }
240 *ret_nelm = n;
241
242 return elms;
243 }
244
245 void ui_pathtextfield_update(UiPathTextField* pb, const char *full_path) {
246 Grid grid = pb->grid;
247
248 ui_pathelm_func getpathelm = pb->getpathelm;
249 void* getpathelmdata = pb->getpathelmdata;
250
251 // hide textbox, show button panel
252 pb->textbox.Visibility(Visibility::Collapsed);
253 pb->buttons.Visibility(Visibility::Visible);
254
255 // clear old buttons
256 ui_pathtextfield_clear(pb->buttons);
257
258 size_t full_path_len = full_path ? strlen(full_path) : 0;
259
260 size_t nelm = 0;
261 UiPathElm* path_elm = getpathelm(full_path, full_path_len, &nelm, getpathelmdata);
262 ui_pathfield_free_pathelms(pb->current_path, pb->current_path_nelms);
263 pb->current_path = path_elm;
264 pb->current_path_nelms = nelm;
265
266 // add new buttons
267 int j = 0;
268 for (int i = 0; i < nelm;i++) {
269 UiPathElm elm = path_elm[i];
270 wchar_t* wstr = str2wstr_len(elm.name, elm.name_len, nullptr);
271 Button button = Button();
272 button.Content(box_value(wstr));
273 free(wstr);
274
275 if (pb->onactivate) {
276 button.Click([pb, j, elm](IInspectable const& sender, RoutedEventArgs) {
277 // copy elm.path because it could be a non-terminated string
278 cxmutstr elmpath = cx_strdup(cx_strn(elm.path, elm.path_len));
279
280 UiEvent evt;
281 evt.obj = pb->obj;
282 evt.window = evt.obj->window;
283 evt.document = evt.obj->ctx->document;
284 evt.eventdata = elmpath.ptr;
285 evt.intval = j;
286 pb->onactivate(&evt, pb->onactivatedata);
287
288 free(elmpath.ptr);
289 });
290 }
291
292 Thickness t = { 0, 0, 1, 0 };
293 CornerRadius c = { 0 ,0, 0, 0 };
294 button.BorderThickness(t);
295 button.CornerRadius(c);
296
297 pb->buttons.Children().Append(button);
298
299 j++;
300 }
301 }
302
303 char* ui_path_textfield_get(UiString * str) {
304 UiPathTextField* widget = (UiPathTextField*)str->obj;
305 TextBox box = widget->textbox;
306 std::wstring wstr(box.Text());
307 return ui_string_get(str, wstr);
308 }
309
310 void ui_path_textfield_set(UiString* str, const char* newvalue) {
311 UiPathTextField* widget = (UiPathTextField*)str->obj;
312 TextBox box = widget->textbox;
313 box.Text(ui_string_set(str, newvalue));
314 ui_pathtextfield_update(widget, newvalue);
315 }
316
317 UIEXPORT UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args) {
318 UiObject* current = uic_current_obj(obj);
319
320 // create view and toolkit wrapper
321 Border pathbar = Border();
322
323 IInspectable bgRes = Application::Current().Resources().Lookup(box_value(L"TextControlBackground"));
324 IInspectable borderThicknessRes = Application::Current().Resources().Lookup(box_value(L"TextControlBorderThemeThickness"));
325 IInspectable borderBrushRes = Application::Current().Resources().Lookup(box_value(L"TextControlBorderBrush"));
326 // IInspectable cornerRes = Application::Current().Resources().Lookup(box_value(L"TextControlCornerRadius"));
327
328 Brush bgBrush = unbox_value<Brush>(bgRes);
329 Thickness border = unbox_value<Thickness>(borderThicknessRes);
330 Brush borderBrush = unbox_value<Brush>(borderBrushRes);
331 CornerRadius cornerRadius = { 4, 4, 4, 4 }; //unbox_value<CornerRadius>(cornerRes);
332
333 pathbar.Background(bgBrush);
334 pathbar.BorderBrush(borderBrush);
335 pathbar.BorderThickness(border);
336 pathbar.CornerRadius(cornerRadius);
337
338 Grid content = Grid();
339 pathbar.Child(content);
340
341 GridLength gl;
342 gl.Value = 0;
343 gl.GridUnitType = GridUnitType::Auto;
344
345 ColumnDefinition coldef = ColumnDefinition();
346 coldef.Width(gl);
347 content.ColumnDefinitions().Append(coldef);
348
349 gl.Value = 1;
350 gl.GridUnitType = GridUnitType::Star;
351
352 ColumnDefinition coldef2 = ColumnDefinition();
353 coldef2.Width(gl);
354 content.ColumnDefinitions().Append(coldef2);
355
356 TextBox pathTextBox = TextBox();
357 Thickness t = { 0, 0, 0, 0 };
358 CornerRadius c = { 0 ,0, 0, 0 };
359 pathTextBox.BorderThickness(t);
360 //pathTextBox.CornerRadius(c);
361
362
363 pathTextBox.HorizontalAlignment(HorizontalAlignment::Stretch);
364 content.SetColumn(pathTextBox, 0);
365 content.SetColumnSpan(pathTextBox, 2);
366
367 content.Children().Append(pathTextBox);
368
369 // stackpanel for buttons
370 StackPanel buttons = StackPanel();
371 buttons.Orientation(Orientation::Horizontal);
372 buttons.Visibility(Visibility::Collapsed);
373 content.SetColumn(buttons, 0);
374 content.Children().Append(buttons);
375
376 TextBlock filler = TextBlock();
377 filler.VerticalAlignment(VerticalAlignment::Stretch);
378 //filler.Text(winrt::hstring(L"hello filler"));
379
380 filler.HorizontalAlignment(HorizontalAlignment::Stretch);
381 filler.VerticalAlignment(VerticalAlignment::Stretch);
382 content.SetColumn(filler, 1);
383 content.Children().Append(filler);
384
385 filler.PointerPressed(
386 winrt::Microsoft::UI::Xaml::Input::PointerEventHandler(
387 [=](IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::PointerRoutedEventArgs const& args) {
388 pathTextBox.Visibility(Visibility::Visible);
389 buttons.Visibility(Visibility::Collapsed);
390 filler.Visibility(Visibility::Collapsed);
391 pathTextBox.SelectionStart(pathTextBox.Text().size());
392 pathTextBox.SelectionLength(0);
393 pathTextBox.Focus(FocusState::Keyboard);
394 })
395 );
396
397 //pathTextBox.Visibility(Visibility::Collapsed);
398
399 UiPathTextField* uipathbar = new UiPathTextField;
400 ui_context_add_pathtextfield_destructor(current->ctx, uipathbar);
401 uipathbar->grid = content;
402 uipathbar->buttons = buttons;
403 uipathbar->textbox = pathTextBox;
404 uipathbar->filler = filler;
405 uipathbar->obj = obj;
406 uipathbar->getpathelm = args.getpathelm ? args.getpathelm : default_pathelm_func;
407 uipathbar->getpathelmdata = args.getpathelmdata;
408 uipathbar->onactivate = args.onactivate;
409 uipathbar->onactivatedata = args.onactivatedata;
410 uipathbar->ondragstart = args.ondragstart;
411 uipathbar->ondragstartdata = args.ondragstartdata;
412 uipathbar->ondragcomplete = args.ondragcomplete;
413 uipathbar->ondragcompletedata = args.ondragcompletedata;
414 uipathbar->ondrop = args.ondrop;
415 uipathbar->ondropdata = args.ondropsdata;
416
417
418 pathTextBox.KeyDown(
419 winrt::Microsoft::UI::Xaml::Input::KeyEventHandler(
420 [=](winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::Input::KeyRoutedEventArgs const& e) {
421 auto key = e.Key();
422 bool showButtons = false;
423 bool update = false;
424 if (key == Windows::System::VirtualKey::Escape) {
425 showButtons = true;
426 }
427 else if (key == Windows::System::VirtualKey::Enter) {
428 showButtons = true;
429 update = true;
430 }
431
432 if (showButtons) {
433 pathTextBox.Visibility(Visibility::Collapsed);
434 buttons.Visibility(Visibility::Visible);
435 filler.Visibility(Visibility::Visible);
436 if (update) {
437 std::wstring value(pathTextBox.Text());
438 char* full_path = wchar2utf8(value.c_str(), value.length());
439 ui_pathtextfield_update(uipathbar, full_path);
440 free(full_path);
441 }
442
443 //buttons.Focus(FocusState::Keyboard);
444 }
445 })
446 );
447
448
449 UIElement elm = pathbar;
450 UiWidget* widget = new UiWidget(elm);
451 widget->data1 = uipathbar;
452 ui_context_add_widget_destructor(current->ctx, widget);
453
454 // bind var
455 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_LIST);
456 if (var) {
457 UiString* value = (UiString*)var->value;
458 value->obj = uipathbar;
459 value->get = ui_path_textfield_get;
460 value->set = ui_path_textfield_set;
461 }
462
463 // add listview to current container
464 UI_APPLY_LAYOUT1(current, args);
465
466 current->container->Add(pathbar, false);
467
468 return widget;
469 }

mercurial