1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include "pch.h"
30
31 #include "text.h"
32
33 #include "../common/context.h"
34 #include "../common/object.h"
35
36 #include <cx/string.h>
37 #include <cx/allocator.h>
38
39 #include "util.h"
40 #include "container.h"
41
42
43
44 using namespace winrt;
45 using namespace Microsoft::
UI::Xaml;
46 using namespace Microsoft::
UI::Xaml::Controls;
47 using namespace Windows::
UI::Xaml::Interop;
48 using namespace winrt::Windows::Foundation;
49 using namespace Microsoft::
UI::Xaml::Markup;
50 using namespace Microsoft::
UI::Xaml::Media;
51 using namespace winrt::Microsoft::
UI::Xaml::Controls::Primitives;
52 using namespace winrt::Windows::
UI::Xaml::Input;
53
54
55 UIEXPORT UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args) {
56 UiObject* current = uic_current_obj(obj);
57
58
59 TextBox textarea = TextBox();
60 textarea.AcceptsReturn(true);
61 ScrollViewer::SetVerticalScrollBarVisibility(textarea, ScrollBarVisibility::Auto);
62 UIElement elm = textarea;
63 UiWidget* widget = new UiWidget(elm);
64 ui_context_add_widget_destructor(current->ctx, widget);
65 ui_set_widget_groups(current->ctx, widget, args.groups);
66
67 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname,
UI_VAR_TEXT);
68 if (var) {
69 UiText* value = (UiText*)var->value;
70 value->obj = widget;
71 value->set = ui_textarea_set;
72 value->get = ui_textarea_get;
73 value->getsubstr = ui_textarea_getsubstr;
74 value->insert = ui_textarea_insert;
75 value->setposition = ui_textarea_setposition;
76 value->position = ui_textarea_position;
77 value->selection = ui_textarea_selection;
78 value->length = ui_textarea_length;
79 value->remove = ui_textarea_remove;
80 }
81
82
83 UI_APPLY_LAYOUT1(current, args);
84
85 current->container->Add(textarea, true);
86
87 return widget;
88 }
89
90 UIEXPORT UIWIDGET ui_textarea_gettextwidget(
UIWIDGET textarea) {
91 return textarea;
92 }
93
94 UIEXPORT void ui_text_undo(UiText *value) {
95
96 }
97
98 UIEXPORT void ui_text_redo(UiText *value) {
99
100 }
101
102
103
104 char* ui_wtext_get(UiText *text, std::wstring &value) {
105 if (text->value.ptr) {
106 text->value.free(text->value.ptr);
107 }
108
109 text->value.ptr = wchar2utf8(value.c_str(), value.length());
110 text->value.free = free;
111
112 return text->value.ptr;
113 }
114
115 std::wstring ui_wtext_set(UiText *text,
const char* value) {
116 if (text->value.ptr) {
117 text->value.free(text->value.ptr);
118 }
119
120 text->value.ptr = _strdup(value);
121 text->value.free = free;
122
123 int len;
124 wchar_t* wstr = str2wstr(value, &len);
125 std::wstring s(wstr);
126 free(wstr);
127
128 return s;
129 }
130
131 extern "C" char* ui_textarea_get(UiText *text) {
132 UiWidget* widget = (UiWidget*)text->obj;
133 TextBox box = widget->uielement.as<TextBox>();
134 std::wstring wstr(box.Text());
135 return ui_wtext_get(text, wstr);
136 }
137
138 extern "C" void ui_textarea_set(UiText *text,
const char *newvalue) {
139 UiWidget* widget = (UiWidget*)text->obj;
140 TextBox box = widget->uielement.as<TextBox>();
141 box.Text(ui_wtext_set(text, newvalue));
142 }
143
144 extern "C" char* ui_textarea_getsubstr(UiText *text,
int begin,
int end) {
145 return NULL;
146 }
147
148 extern "C" void ui_textarea_insert(UiText *text,
int pos,
char *str) {
149
150 }
151
152 extern "C" void ui_textarea_setposition(UiText *text,
int pos) {
153
154 }
155
156 extern "C" int ui_textarea_position(UiText *text) {
157 return 0;
158 }
159
160 extern "C" void ui_textarea_selection(UiText *text,
int *begin,
int *end) {
161
162 }
163
164 extern "C" int ui_textarea_length(UiText *text) {
165 return 0;
166 }
167
168 extern "C" void ui_textarea_remove(UiText *text,
int begin,
int end) {
169
170 }
171
172
173
174
175 UIWIDGET ui_textfield_create(UiObject* obj, UiTextFieldArgs args) {
176 UiObject* current = uic_current_obj(obj);
177
178
179 TextBox textfield = TextBox();
180 UIElement elm = textfield;
181 UiWidget* widget = new UiWidget(elm);
182 ui_context_add_widget_destructor(current->ctx, widget);
183 ui_set_widget_groups(current->ctx, widget, args.groups);
184
185 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname,
UI_VAR_STRING);
186 if (var) {
187 UiString* value = (UiString*)var->value;
188 value->obj = widget;
189 value->get = ui_textfield_get;
190 value->set = ui_textfield_set;
191
192
193
194 }
195
196
197 UI_APPLY_LAYOUT1(current, args);
198
199 current->container->Add(textfield, false);
200
201 return widget;
202 }
203
204 UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs args) {
205 return ui_textfield_create(obj, args);
206 }
207
208 UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs args) {
209 UiObject* current = uic_current_obj(obj);
210
211
212 PasswordBox textfield = PasswordBox();
213 UIElement elm = textfield;
214 UiWidget* widget = new UiWidget(elm);
215 ui_context_add_widget_destructor(current->ctx, widget);
216 ui_set_widget_groups(current->ctx, widget, args.groups);
217
218 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname,
UI_VAR_STRING);
219 if (var) {
220 UiString* value = (UiString*)var->value;
221 value->obj = widget;
222 value->get = ui_passwordfield_get;
223 value->set = ui_passwordfield_set;
224
225
226
227 }
228
229
230 UI_APPLY_LAYOUT1(current, args);
231
232 current->container->Add(textfield, false);
233
234 return widget;
235 }
236
237
238
239
240 char* ui_wstring_get(UiString* str, std::wstring &value) {
241 if (str->value.ptr) {
242 str->value.free(str->value.ptr);
243 }
244
245 str->value.ptr = wchar2utf8(value.c_str(), value.length());
246 str->value.free = free;
247
248 return str->value.ptr;
249 }
250
251 std::wstring ui_wstring_set(UiString* str,
const char* value) {
252 if (str->value.ptr) {
253 str->value.free(str->value.ptr);
254 }
255
256 str->value.ptr = _strdup(value);
257 str->value.free = free;
258
259 int len;
260 wchar_t* wstr = str2wstr(value, &len);
261 std::wstring s(wstr);
262 free(wstr);
263
264 return s;
265 }
266
267 char* ui_textfield_get(UiString * str) {
268 UiWidget* widget = (UiWidget*)str->obj;
269 TextBox box = widget->uielement.as<TextBox>();
270 std::wstring wstr(box.Text());
271 return ui_wstring_get(str, wstr);
272 }
273
274 void ui_textfield_set(UiString * str,
const char* newvalue) {
275 UiWidget* widget = (UiWidget*)str->obj;
276 TextBox box = widget->uielement.as<TextBox>();
277 box.Text(ui_wstring_set(str, newvalue));
278 }
279
280
281 char* ui_passwordfield_get(UiString * str) {
282 UiWidget* widget = (UiWidget*)str->obj;
283 PasswordBox box = widget->uielement.as<PasswordBox>();
284 std::wstring wstr(box.Password());
285 return ui_wstring_get(str, wstr);
286 }
287
288 void ui_passwordfield_set(UiString * str,
const char* newvalue) {
289 UiWidget* widget = (UiWidget*)str->obj;
290 PasswordBox box = widget->uielement.as<PasswordBox>();
291 box.Password(ui_wstring_set(str, newvalue));
292 }
293
294
295
296
297 extern "C" static void destroy_ui_pathtextfield(
void* ptr) {
298 UiPathTextField* pb = (UiPathTextField*)ptr;
299 delete pb;
300 }
301
302 static void ui_context_add_pathtextfield_destructor(UiContext* ctx, UiPathTextField* pb) {
303 cxMempoolRegister(ctx->mp, pb, destroy_ui_pathtextfield);
304 }
305
306 static void ui_pathtextfield_clear(StackPanel& buttons) {
307 for (
int i = buttons.Children().Size() -
1; i >=
0; i--) {
308 buttons.Children().RemoveAt(i);
309 }
310 }
311
312 static void ui_pathfield_free_pathelms(UiPathElm* elms,
size_t nelm) {
313 if (!elms) {
314 return;
315 }
316 for (
int i =
0; i < nelm; i++) {
317 UiPathElm e = elms[i];
318 free(e.name);
319 free(e.path);
320 }
321 free(elms);
322 }
323
324 UiPathTextField::~UiPathTextField() {
325 ui_pathfield_free_pathelms(this->current_path, this->current_path_nelms);
326 }
327
328 static UiPathElm* default_pathelm_func(
const char* full_path,
size_t len,
size_t* ret_nelm,
void* data) {
329 cxstring *pathelms;
330 size_t nelm = cx_strsplit_a(cxDefaultAllocator, cx_strn(full_path, len),
CX_STR(
"/"),
4096, &pathelms);
331
332 if (nelm ==
0) {
333 *ret_nelm =
0;
334 return nullptr;
335 }
336
337 UiPathElm* elms = (UiPathElm*)calloc(nelm,
sizeof(UiPathElm));
338 size_t n = nelm;
339 int j =
0;
340 for (
int i =
0; i < nelm; i++) {
341 cxstring c = pathelms[i];
342 if (c.length ==
0) {
343 if (i ==
0) {
344 c.length =
1;
345 }
346 else {
347 n--;
348 continue;
349 }
350 }
351
352 cxmutstr m = cx_strdup(c);
353 elms[j].name = m.ptr;
354 elms[j].name_len = m.length;
355
356 size_t elm_path_len = c.ptr + c.length - full_path;
357 cxmutstr elm_path = cx_strdup(cx_strn(full_path, elm_path_len));
358 elms[j].path = elm_path.ptr;
359 elms[j].path_len = elm_path.length;
360
361 j++;
362 }
363 *ret_nelm = n;
364
365 return elms;
366 }
367
368 int ui_pathtextfield_update(UiPathTextField* pb,
const char *full_path) {
369 Grid grid = pb->grid;
370
371 ui_pathelm_func getpathelm = pb->getpathelm;
372 void* getpathelmdata = pb->getpathelmdata;
373
374 size_t full_path_len = full_path ? strlen(full_path) :
0;
375
376 size_t nelm =
0;
377 UiPathElm* path_elm = getpathelm(full_path, full_path_len, &nelm, getpathelmdata);
378 if (!path_elm) {
379 return 1;
380 }
381
382
383 pb->textbox.Visibility(Visibility::Collapsed);
384 pb->buttons.Visibility(Visibility::Visible);
385
386
387 ui_pathtextfield_clear(pb->buttons);
388
389 ui_pathfield_free_pathelms(pb->current_path, pb->current_path_nelms);
390 pb->current_path = path_elm;
391 pb->current_path_nelms = nelm;
392
393
394 int j =
0;
395 for (
int i =
0; i < nelm;i++) {
396 UiPathElm elm = path_elm[i];
397 wchar_t* wstr = str2wstr_len(elm.name, elm.name_len, nullptr);
398 Button button = Button();
399 button.Content(box_value(wstr));
400 free(wstr);
401
402 if (pb->onactivate) {
403 button.Click([pb, j, elm](IInspectable
const& sender, RoutedEventArgs) {
404
405 cxmutstr elmpath = cx_strdup(cx_strn(elm.path, elm.path_len));
406
407 UiEvent evt;
408 evt.obj = pb->obj;
409 evt.window = evt.obj->window;
410 evt.document = evt.obj->ctx->document;
411 evt.eventdata = elmpath.ptr;
412 evt.intval = j;
413 pb->onactivate(&evt, pb->onactivatedata);
414
415 free(elmpath.ptr);
416 });
417 }
418
419 Thickness t = {
0,
0,
1,
0 };
420 CornerRadius c = {
0 ,
0,
0,
0 };
421 button.BorderThickness(t);
422 button.CornerRadius(c);
423
424 pb->buttons.Children().Append(button);
425
426 j++;
427 }
428
429 return 0;
430 }
431
432 char* ui_path_textfield_get(UiString * str) {
433 UiPathTextField* widget = (UiPathTextField*)str->obj;
434 TextBox box = widget->textbox;
435 std::wstring wstr(box.Text());
436 return ui_wstring_get(str, wstr);
437 }
438
439 void ui_path_textfield_set(UiString* str,
const char* newvalue) {
440 UiPathTextField* widget = (UiPathTextField*)str->obj;
441 TextBox box = widget->textbox;
442 box.Text(ui_wstring_set(str, newvalue));
443 ui_pathtextfield_update(widget, newvalue);
444 }
445
446 UIEXPORT UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args) {
447 UiObject* current = uic_current_obj(obj);
448
449
450 Border pathbar = Border();
451
452 IInspectable bgRes = Application::Current().Resources().Lookup(box_value(
"TextControlBackground"L));
453 IInspectable borderThicknessRes = Application::Current().Resources().Lookup(box_value(
"TextControlBorderThemeThickness"L));
454 IInspectable borderBrushRes = Application::Current().Resources().Lookup(box_value(
"TextControlBorderBrush"L));
455
456
457 Brush bgBrush = unbox_value<Brush>(bgRes);
458 Thickness border = unbox_value<Thickness>(borderThicknessRes);
459 Brush borderBrush = unbox_value<Brush>(borderBrushRes);
460 CornerRadius cornerRadius = {
4,
4,
4,
4 };
461
462 pathbar.Background(bgBrush);
463 pathbar.BorderBrush(borderBrush);
464 pathbar.BorderThickness(border);
465 pathbar.CornerRadius(cornerRadius);
466
467 Grid content = Grid();
468 pathbar.Child(content);
469
470 GridLength gl;
471 gl.Value =
0;
472 gl.GridUnitType = GridUnitType::Auto;
473
474 ColumnDefinition coldef = ColumnDefinition();
475 coldef.Width(gl);
476 content.ColumnDefinitions().Append(coldef);
477
478 gl.Value =
1;
479 gl.GridUnitType = GridUnitType::Star;
480
481 ColumnDefinition coldef2 = ColumnDefinition();
482 coldef2.Width(gl);
483 content.ColumnDefinitions().Append(coldef2);
484
485 TextBox pathTextBox = TextBox();
486 Thickness t = {
0,
0,
0,
0 };
487 CornerRadius c = {
0 ,
0,
0,
0 };
488 pathTextBox.BorderThickness(t);
489
490
491
492 pathTextBox.HorizontalAlignment(HorizontalAlignment::Stretch);
493 content.SetColumn(pathTextBox,
0);
494 content.SetColumnSpan(pathTextBox,
2);
495
496 content.Children().Append(pathTextBox);
497
498
499 StackPanel buttons = StackPanel();
500 buttons.Orientation(Orientation::Horizontal);
501 buttons.Visibility(Visibility::Collapsed);
502 content.SetColumn(buttons,
0);
503 content.Children().Append(buttons);
504
505 TextBlock filler = TextBlock();
506 filler.VerticalAlignment(VerticalAlignment::Stretch);
507
508
509 filler.HorizontalAlignment(HorizontalAlignment::Stretch);
510 filler.VerticalAlignment(VerticalAlignment::Stretch);
511 content.SetColumn(filler,
1);
512 content.Children().Append(filler);
513
514 filler.PointerPressed(
515 winrt::Microsoft::
UI::Xaml::Input::PointerEventHandler(
516 [=](IInspectable
const& sender, winrt::Microsoft::
UI::Xaml::Input::PointerRoutedEventArgs
const& args) {
517 pathTextBox.Visibility(Visibility::Visible);
518 buttons.Visibility(Visibility::Collapsed);
519 filler.Visibility(Visibility::Collapsed);
520 pathTextBox.SelectionStart(pathTextBox.Text().size());
521 pathTextBox.SelectionLength(
0);
522 pathTextBox.Focus(FocusState::Keyboard);
523 })
524 );
525
526
527
528 UiPathTextField* uipathbar = new UiPathTextField;
529 ui_context_add_pathtextfield_destructor(current->ctx, uipathbar);
530 uipathbar->grid = content;
531 uipathbar->buttons = buttons;
532 uipathbar->textbox = pathTextBox;
533 uipathbar->filler = filler;
534 uipathbar->obj = obj;
535 uipathbar->getpathelm = args.getpathelm ? args.getpathelm : default_pathelm_func;
536 uipathbar->getpathelmdata = args.getpathelmdata;
537 uipathbar->onactivate = args.onactivate;
538 uipathbar->onactivatedata = args.onactivatedata;
539 uipathbar->ondragstart = args.ondragstart;
540 uipathbar->ondragstartdata = args.ondragstartdata;
541 uipathbar->ondragcomplete = args.ondragcomplete;
542 uipathbar->ondragcompletedata = args.ondragcompletedata;
543 uipathbar->ondrop = args.ondrop;
544 uipathbar->ondropdata = args.ondropsdata;
545
546
547 pathTextBox.KeyDown(
548 winrt::Microsoft::
UI::Xaml::Input::KeyEventHandler(
549 [=](winrt::Windows::Foundation::IInspectable
const& sender, winrt::Microsoft::
UI::Xaml::Input::KeyRoutedEventArgs
const& e) {
550 auto key = e.Key();
551 bool showButtons = false;
552 bool update = false;
553 if (key == Windows::System::VirtualKey::Escape) {
554 showButtons = true;
555 }
556 else if (key == Windows::System::VirtualKey::Enter) {
557 showButtons = true;
558 update = true;
559 }
560
561 if (showButtons) {
562 pathTextBox.Visibility(Visibility::Collapsed);
563 buttons.Visibility(Visibility::Visible);
564 filler.Visibility(Visibility::Visible);
565 if (update) {
566 std::wstring value(pathTextBox.Text());
567 char* full_path = wchar2utf8(value.c_str(), value.length());
568
569 if (!ui_pathtextfield_update(uipathbar, full_path)) {
570 UiEvent evt;
571 evt.obj = obj;
572 evt.window = obj->window;
573 evt.document = obj->ctx->document;
574 evt.eventdata = full_path;
575 evt.intval =
-1;
576 args.onactivate(&evt, args.onactivatedata);
577 }
578
579 free(full_path);
580 }
581
582
583 }
584 })
585 );
586
587
588 UIElement elm = pathbar;
589 UiWidget* widget = new UiWidget(elm);
590 widget->data1 = uipathbar;
591 ui_context_add_widget_destructor(current->ctx, widget);
592
593
594 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname,
UI_VAR_STRING);
595 if (var) {
596 UiString* value = (UiString*)var->value;
597 value->obj = uipathbar;
598 value->get = ui_path_textfield_get;
599 value->set = ui_path_textfield_set;
600 }
601
602
603 UI_APPLY_LAYOUT1(current, args);
604
605 current->container->Add(pathbar, false);
606
607 return widget;
608 }
609