diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gmdocument.h | 1 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 3 | ||||
-rw-r--r-- | src/ui/labelwidget.c | 38 | ||||
-rw-r--r-- | src/ui/labelwidget.h | 4 | ||||
-rw-r--r-- | src/ui/mobile.c | 205 | ||||
-rw-r--r-- | src/ui/mobile.h | 11 | ||||
-rw-r--r-- | src/ui/util.c | 247 | ||||
-rw-r--r-- | src/ui/util.h | 5 | ||||
-rw-r--r-- | src/ui/widget.c | 1 | ||||
-rw-r--r-- | src/ui/window.c | 3 |
10 files changed, 426 insertions, 92 deletions
diff --git a/src/gmdocument.h b/src/gmdocument.h index 9f8ee2ef..332c3e00 100644 --- a/src/gmdocument.h +++ b/src/gmdocument.h | |||
@@ -59,6 +59,7 @@ enum iGmDocumentTheme { | |||
59 | white_GmDocumentTheme, | 59 | white_GmDocumentTheme, |
60 | sepia_GmDocumentTheme, | 60 | sepia_GmDocumentTheme, |
61 | highContrast_GmDocumentTheme, | 61 | highContrast_GmDocumentTheme, |
62 | max_GmDocumentTheme | ||
62 | }; | 63 | }; |
63 | 64 | ||
64 | iBool isDark_GmDocumentTheme(enum iGmDocumentTheme); | 65 | iBool isDark_GmDocumentTheme(enum iGmDocumentTheme); |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index e280bc84..6ca4fd8d 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -1010,6 +1010,9 @@ static void documentRunsInvalidated_DocumentWidget_(iDocumentWidget *d) { | |||
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | iBool isPinned_DocumentWidget_(const iDocumentWidget *d) { | 1012 | iBool isPinned_DocumentWidget_(const iDocumentWidget *d) { |
1013 | if (deviceType_App() == phone_AppDeviceType) { | ||
1014 | return iFalse; | ||
1015 | } | ||
1013 | if (d->flags & otherRootByDefault_DocumentWidgetFlag) { | 1016 | if (d->flags & otherRootByDefault_DocumentWidgetFlag) { |
1014 | return iTrue; | 1017 | return iTrue; |
1015 | } | 1018 | } |
diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index 3bfa600b..b84e17f4 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c | |||
@@ -44,11 +44,13 @@ struct Impl_LabelWidget { | |||
44 | iString command; | 44 | iString command; |
45 | iClick click; | 45 | iClick click; |
46 | struct { | 46 | struct { |
47 | uint8_t alignVisual : 1; /* align according to visible bounds, not font metrics */ | 47 | uint8_t alignVisual : 1; /* align according to visible bounds, not font metrics */ |
48 | uint8_t noAutoMinHeight : 1; /* minimum height is not set automatically */ | 48 | uint8_t noAutoMinHeight : 1; /* minimum height is not set automatically */ |
49 | uint8_t drawAsOutline : 1; /* draw as outline, filled with background color */ | 49 | uint8_t drawAsOutline : 1; /* draw as outline, filled with background color */ |
50 | uint8_t noTopFrame : 1; | 50 | uint8_t noTopFrame : 1; |
51 | uint8_t wrap : 1; | 51 | uint8_t wrap : 1; |
52 | uint8_t allCaps : 1; | ||
53 | uint8_t removeTrailingColon : 1; | ||
52 | } flags; | 54 | } flags; |
53 | }; | 55 | }; |
54 | 56 | ||
@@ -442,11 +444,18 @@ void updateSize_LabelWidget(iLabelWidget *d) { | |||
442 | 444 | ||
443 | static void replaceVariables_LabelWidget_(iLabelWidget *d) { | 445 | static void replaceVariables_LabelWidget_(iLabelWidget *d) { |
444 | translate_Lang(&d->label); | 446 | translate_Lang(&d->label); |
447 | if (d->flags.allCaps) { | ||
448 | set_String(&d->label, collect_String(upper_String(&d->label))); | ||
449 | } | ||
450 | if (d->flags.removeTrailingColon && endsWith_String(&d->label, ":")) { | ||
451 | removeEnd_String(&d->label, 1); | ||
452 | } | ||
445 | } | 453 | } |
446 | 454 | ||
447 | void init_LabelWidget(iLabelWidget *d, const char *label, const char *cmd) { | 455 | void init_LabelWidget(iLabelWidget *d, const char *label, const char *cmd) { |
448 | iWidget *w = &d->widget; | 456 | iWidget *w = &d->widget; |
449 | init_Widget(w); | 457 | init_Widget(w); |
458 | iZap(d->flags); | ||
450 | d->font = uiLabel_FontId; | 459 | d->font = uiLabel_FontId; |
451 | d->forceFg = none_ColorId; | 460 | d->forceFg = none_ColorId; |
452 | d->icon = 0; | 461 | d->icon = 0; |
@@ -464,11 +473,6 @@ void init_LabelWidget(iLabelWidget *d, const char *label, const char *cmd) { | |||
464 | d->kmods = 0; | 473 | d->kmods = 0; |
465 | init_Click(&d->click, d, !isEmpty_String(&d->command) ? SDL_BUTTON_LEFT : 0); | 474 | init_Click(&d->click, d, !isEmpty_String(&d->command) ? SDL_BUTTON_LEFT : 0); |
466 | setFlags_Widget(w, hover_WidgetFlag, d->click.button != 0); | 475 | setFlags_Widget(w, hover_WidgetFlag, d->click.button != 0); |
467 | d->flags.alignVisual = iFalse; | ||
468 | d->flags.noAutoMinHeight = iFalse; | ||
469 | d->flags.drawAsOutline = iFalse; | ||
470 | d->flags.noTopFrame = iFalse; | ||
471 | d->flags.wrap = iFalse; | ||
472 | updateSize_LabelWidget(d); | 476 | updateSize_LabelWidget(d); |
473 | updateKey_LabelWidget_(d); /* could be bound to another key */ | 477 | updateKey_LabelWidget_(d); /* could be bound to another key */ |
474 | } | 478 | } |
@@ -525,6 +529,20 @@ void setOutline_LabelWidget(iLabelWidget *d, iBool drawAsOutline) { | |||
525 | } | 529 | } |
526 | } | 530 | } |
527 | 531 | ||
532 | void setAllCaps_LabelWidget(iLabelWidget *d, iBool allCaps) { | ||
533 | if (d) { | ||
534 | d->flags.allCaps = allCaps; | ||
535 | replaceVariables_LabelWidget_(d); | ||
536 | } | ||
537 | } | ||
538 | |||
539 | void setRemoveTrailingColon_LabelWidget(iLabelWidget *d, iBool removeTrailingColon) { | ||
540 | if (d) { | ||
541 | d->flags.removeTrailingColon = removeTrailingColon; | ||
542 | replaceVariables_LabelWidget_(d); | ||
543 | } | ||
544 | } | ||
545 | |||
528 | void updateText_LabelWidget(iLabelWidget *d, const iString *text) { | 546 | void updateText_LabelWidget(iLabelWidget *d, const iString *text) { |
529 | set_String(&d->label, text); | 547 | set_String(&d->label, text); |
530 | set_String(&d->srcLabel, text); | 548 | set_String(&d->srcLabel, text); |
diff --git a/src/ui/labelwidget.h b/src/ui/labelwidget.h index b8b6fd87..6275d2c8 100644 --- a/src/ui/labelwidget.h +++ b/src/ui/labelwidget.h | |||
@@ -30,10 +30,12 @@ iDeclareWidgetClass(LabelWidget) | |||
30 | iDeclareObjectConstructionArgs(LabelWidget, const char *label, const char *command) | 30 | iDeclareObjectConstructionArgs(LabelWidget, const char *label, const char *command) |
31 | 31 | ||
32 | void setAlignVisually_LabelWidget(iLabelWidget *, iBool alignVisual); | 32 | void setAlignVisually_LabelWidget(iLabelWidget *, iBool alignVisual); |
33 | void setNoAutoMinHeight_LabelWidget(iLabelWidget *, iBool noAutoMinHeight); | 33 | void setNoAutoMinHeight_LabelWidget (iLabelWidget *, iBool noAutoMinHeight); |
34 | void setNoTopFrame_LabelWidget (iLabelWidget *, iBool noTopFrame); | 34 | void setNoTopFrame_LabelWidget (iLabelWidget *, iBool noTopFrame); |
35 | void setWrap_LabelWidget (iLabelWidget *, iBool wrap); | 35 | void setWrap_LabelWidget (iLabelWidget *, iBool wrap); |
36 | void setOutline_LabelWidget (iLabelWidget *, iBool drawAsOutline); | 36 | void setOutline_LabelWidget (iLabelWidget *, iBool drawAsOutline); |
37 | void setAllCaps_LabelWidget (iLabelWidget *, iBool allCaps); | ||
38 | void setRemoveTrailingColon_LabelWidget (iLabelWidget *, iBool removeTrailingColon); | ||
37 | void setFont_LabelWidget (iLabelWidget *, int fontId); | 39 | void setFont_LabelWidget (iLabelWidget *, int fontId); |
38 | void setTextColor_LabelWidget (iLabelWidget *, int color); | 40 | void setTextColor_LabelWidget (iLabelWidget *, int color); |
39 | void setText_LabelWidget (iLabelWidget *, const iString *text); /* resizes widget */ | 41 | void setText_LabelWidget (iLabelWidget *, const iString *text); /* resizes widget */ |
diff --git a/src/ui/mobile.c b/src/ui/mobile.c index 168a92b8..4ccbb0cb 100644 --- a/src/ui/mobile.c +++ b/src/ui/mobile.c | |||
@@ -57,7 +57,6 @@ static enum iFontId labelBoldFont_(void) { | |||
57 | 57 | ||
58 | static void updatePanelSheetMetrics_(iWidget *sheet) { | 58 | static void updatePanelSheetMetrics_(iWidget *sheet) { |
59 | iWidget *navi = findChild_Widget(sheet, "panel.navi"); | 59 | iWidget *navi = findChild_Widget(sheet, "panel.navi"); |
60 | // iWidget *naviPad = child_Widget(navi, 0); | ||
61 | int naviHeight = lineHeight_Text(labelFont_()) + 4 * gap_UI; | 60 | int naviHeight = lineHeight_Text(labelFont_()) + 4 * gap_UI; |
62 | #if defined (iPlatformMobile) | 61 | #if defined (iPlatformMobile) |
63 | float left = 0.0f, right = 0.0f, top = 0.0f, bottom = 0.0f; | 62 | float left = 0.0f, right = 0.0f, top = 0.0f, bottom = 0.0f; |
@@ -339,7 +338,7 @@ static iWidget *makeValuePaddingWithHeading_(iLabelWidget *heading, iWidget *val | |||
339 | addChildFlags_Widget(div, iClob(new_Widget()), expand_WidgetFlag); | 338 | addChildFlags_Widget(div, iClob(new_Widget()), expand_WidgetFlag); |
340 | addChild_Widget(div, iClob(value)); | 339 | addChild_Widget(div, iClob(value)); |
341 | } | 340 | } |
342 | printTree_Widget(div); | 341 | // printTree_Widget(div); |
343 | return div; | 342 | return div; |
344 | } | 343 | } |
345 | 344 | ||
@@ -369,6 +368,205 @@ static iWidget *addChildPanel_(iWidget *parent, iLabelWidget *panelButton, | |||
369 | } | 368 | } |
370 | 369 | ||
371 | void finalizeSheet_Mobile(iWidget *sheet) { | 370 | void finalizeSheet_Mobile(iWidget *sheet) { |
371 | arrange_Widget(sheet); | ||
372 | // postRefresh_App(); | ||
373 | } | ||
374 | |||
375 | static size_t countItems_(const iMenuItem *itemsNullTerminated) { | ||
376 | size_t num = 0; | ||
377 | for (; itemsNullTerminated->label; num++, itemsNullTerminated++) {} | ||
378 | return num; | ||
379 | } | ||
380 | |||
381 | void makePanelItem_Mobile(iWidget *panel, const iMenuItem *item) { | ||
382 | const char * spec = item->label; | ||
383 | const char * id = cstr_Rangecc(range_Command(spec, "id")); | ||
384 | const char * label = format_CStr("${%s}", id); | ||
385 | iWidget * widget = NULL; | ||
386 | iLabelWidget *heading = NULL; | ||
387 | if (hasLabel_Command(spec, "device") && deviceType_App() != argLabel_Command(spec, "device")) { | ||
388 | return; | ||
389 | } | ||
390 | if (equal_Command(spec, "title")) { | ||
391 | iLabelWidget *title = addChildFlags_Widget(panel, | ||
392 | iClob(new_LabelWidget(label, NULL)), | ||
393 | alignLeft_WidgetFlag | frameless_WidgetFlag); | ||
394 | setFont_LabelWidget(title, uiLabelLargeBold_FontId); | ||
395 | setTextColor_LabelWidget(title, uiHeading_ColorId); | ||
396 | setAllCaps_LabelWidget(title, iTrue); | ||
397 | } | ||
398 | else if (equal_Command(spec, "heading")) { | ||
399 | addChild_Widget(panel, iClob(makePadding_Widget(lineHeight_Text(labelFont_())))); | ||
400 | heading = makeHeading_Widget(label); | ||
401 | setAllCaps_LabelWidget(heading, iTrue); | ||
402 | setRemoveTrailingColon_LabelWidget(heading, iTrue); | ||
403 | addChild_Widget(panel, iClob(heading)); | ||
404 | } | ||
405 | else if (equal_Command(spec, "toggle")) { | ||
406 | iLabelWidget *toggle = (iLabelWidget *) makeToggle_Widget(id); | ||
407 | setFont_LabelWidget(toggle, labelFont_()); | ||
408 | widget = makeValuePaddingWithHeading_(heading = makeHeading_Widget(label), | ||
409 | as_Widget(toggle)); | ||
410 | } | ||
411 | else if (equal_Command(spec, "dropdown")) { | ||
412 | const iMenuItem *dropItems = item->data; | ||
413 | iLabelWidget *drop = makeMenuButton_LabelWidget("", dropItems, countItems_(dropItems)); | ||
414 | setFont_LabelWidget(drop, labelFont_()); | ||
415 | setFlags_Widget(as_Widget(drop), | ||
416 | alignRight_WidgetFlag | noBackground_WidgetFlag | | ||
417 | frameless_WidgetFlag, iTrue); | ||
418 | setId_Widget(as_Widget(drop), id); | ||
419 | widget = makeValuePaddingWithHeading_(heading = makeHeading_Widget(label), as_Widget(drop)); | ||
420 | } | ||
421 | else if (equal_Command(spec, "radio")) { | ||
422 | addChild_Widget(panel, iClob(makePadding_Widget(lineHeight_Text(labelFont_())))); | ||
423 | iLabelWidget *head = makeHeading_Widget(label); | ||
424 | setAllCaps_LabelWidget(head, iTrue); | ||
425 | setRemoveTrailingColon_LabelWidget(head, iTrue); | ||
426 | addChild_Widget(panel, iClob(head)); | ||
427 | widget = new_Widget(); | ||
428 | setBackgroundColor_Widget(widget, uiBackgroundSidebar_ColorId); | ||
429 | setPadding_Widget(widget, 4 * gap_UI, 2 * gap_UI, 4 * gap_UI, 2 * gap_UI); | ||
430 | // setFlags_Widget(widget, arrangeWidth_WidgetFlag, iFalse); | ||
431 | setFlags_Widget(widget, | ||
432 | borderBottom_WidgetFlag | | ||
433 | arrangeHorizontal_WidgetFlag | | ||
434 | arrangeHeight_WidgetFlag | | ||
435 | resizeToParentWidth_WidgetFlag | | ||
436 | resizeWidthOfChildren_WidgetFlag, | ||
437 | iTrue); | ||
438 | setId_Widget(widget, id); | ||
439 | for (const iMenuItem *radioItem = item->data; radioItem->label; radioItem++) { | ||
440 | const char * radId = cstr_Rangecc(range_Command(radioItem->label, "id")); | ||
441 | const char * radLabel = hasLabel_Command(radioItem->label, "label") | ||
442 | ? format_CStr("${%s}", cstr_Rangecc(range_Command(radioItem->label, "label"))) | ||
443 | : suffixPtr_Command(radioItem->label, "text"); | ||
444 | iLabelWidget *radButton = new_LabelWidget(radLabel, radioItem->command); | ||
445 | setId_Widget(as_Widget(radButton), radId); | ||
446 | setFont_LabelWidget(radButton, defaultMedium_FontId); | ||
447 | addChildFlags_Widget(widget, iClob(radButton), radio_WidgetFlag | noBackground_WidgetFlag); | ||
448 | } | ||
449 | } | ||
450 | else if (equal_Command(spec, "input")) { | ||
451 | iInputWidget *input = new_InputWidget(argU32Label_Command(spec, "maxlen")); | ||
452 | setId_Widget(as_Widget(input), id); | ||
453 | setFont_InputWidget(input, labelFont_()); | ||
454 | setContentPadding_InputWidget(input, 3 * gap_UI, 0); | ||
455 | setUrlContent_InputWidget(input, argLabel_Command(spec, "url")); | ||
456 | widget = makeValuePaddingWithHeading_(heading = makeHeading_Widget(label), | ||
457 | as_Widget(input)); | ||
458 | } | ||
459 | else if (equal_Command(spec, "padding")) { | ||
460 | widget = makePadding_Widget(lineHeight_Text(labelFont_()) * 1.5f); | ||
461 | } | ||
462 | if (heading) { | ||
463 | setRemoveTrailingColon_LabelWidget(heading, iTrue); | ||
464 | const iChar icon = toInt_String(string_Command(item->label, "icon")); | ||
465 | if (icon) { | ||
466 | setIcon_LabelWidget(heading, icon); | ||
467 | } | ||
468 | } | ||
469 | if (widget) { | ||
470 | addChild_Widget(panel, iClob(widget)); | ||
471 | } | ||
472 | } | ||
473 | |||
474 | void makePanelItems_Mobile(iWidget *panel, const iMenuItem *itemsNullTerminated) { | ||
475 | for (const iMenuItem *item = itemsNullTerminated; item->label; item++) { | ||
476 | makePanelItem_Mobile(panel, item); | ||
477 | } | ||
478 | } | ||
479 | |||
480 | iWidget *makeSplitMultiPanel_Mobile(const iMenuItem *itemsNullTerminated) { | ||
481 | /* A multipanel widget has a top panel and one or more detail panels. In a horizontal layout, | ||
482 | the detail panels slide in from the right and cover the top panel. In a landscape layout, | ||
483 | the detail panels are always visible on the side. */ | ||
484 | iWidget *sheet = new_Widget(); | ||
485 | setBackgroundColor_Widget(sheet, uiBackground_ColorId); | ||
486 | setFlags_Widget(sheet, | ||
487 | resizeToParentWidth_WidgetFlag | | ||
488 | resizeToParentHeight_WidgetFlag | | ||
489 | frameless_WidgetFlag | focusRoot_WidgetFlag | commandOnClick_WidgetFlag | | ||
490 | overflowScrollable_WidgetFlag | leftEdgeDraggable_WidgetFlag, | ||
491 | iTrue); | ||
492 | /* The top-level split between main and detail panels. */ | ||
493 | iWidget *mainDetailSplit = makeHDiv_Widget(); { | ||
494 | setCommandHandler_Widget(mainDetailSplit, mainDetailSplitHandler_); | ||
495 | setFlags_Widget(mainDetailSplit, resizeHeightOfChildren_WidgetFlag, iFalse); | ||
496 | setId_Widget(mainDetailSplit, "mdsplit"); | ||
497 | addChild_Widget(sheet, iClob(mainDetailSplit)); | ||
498 | } | ||
499 | /* The panel roots. */ | ||
500 | iWidget *topPanel = new_Widget(); { | ||
501 | setId_Widget(topPanel, "panel.top"); | ||
502 | setCommandHandler_Widget(topPanel, topPanelHandler_); | ||
503 | setFlags_Widget(topPanel, | ||
504 | arrangeVertical_WidgetFlag | resizeWidthOfChildren_WidgetFlag | | ||
505 | arrangeHeight_WidgetFlag | overflowScrollable_WidgetFlag | | ||
506 | commandOnClick_WidgetFlag, | ||
507 | iTrue); | ||
508 | addChild_Widget(mainDetailSplit, iClob(topPanel)); | ||
509 | setId_Widget(addChild_Widget(topPanel, iClob(makePadding_Widget(0))), "panel.toppad"); | ||
510 | } | ||
511 | iWidget *detailStack = new_Widget(); { | ||
512 | setId_Widget(detailStack, "detailstack"); | ||
513 | setFlags_Widget(detailStack, collapse_WidgetFlag | resizeWidthOfChildren_WidgetFlag, iTrue); | ||
514 | addChild_Widget(mainDetailSplit, iClob(detailStack)); | ||
515 | } | ||
516 | addChild_Widget(topPanel, iClob(makePadding_Widget(lineHeight_Text(labelFont_())))); | ||
517 | /* Slide top panel with detail panels. */ { | ||
518 | setFlags_Widget(topPanel, refChildrenOffset_WidgetFlag, iTrue); | ||
519 | topPanel->offsetRef = detailStack; | ||
520 | } | ||
521 | /* Navigation bar at the top. */ | ||
522 | iWidget *navi = new_Widget(); { | ||
523 | setId_Widget(navi, "panel.navi"); | ||
524 | setBackgroundColor_Widget(navi, uiBackground_ColorId); | ||
525 | addChild_Widget(navi, iClob(makePadding_Widget(0))); | ||
526 | iLabelWidget *back = addChildFlags_Widget( | ||
527 | navi, | ||
528 | iClob(new_LabelWidget(leftAngle_Icon " ${panel.back}", "panel.close")), | ||
529 | noBackground_WidgetFlag | frameless_WidgetFlag | alignLeft_WidgetFlag | | ||
530 | extraPadding_WidgetFlag); | ||
531 | checkIcon_LabelWidget(back); | ||
532 | setId_Widget(as_Widget(back), "panel.back"); | ||
533 | setFont_LabelWidget(back, labelFont_()); | ||
534 | addChildFlags_Widget(sheet, iClob(navi), | ||
535 | drawBackgroundToVerticalSafeArea_WidgetFlag | | ||
536 | arrangeHeight_WidgetFlag | resizeWidthOfChildren_WidgetFlag | | ||
537 | resizeToParentWidth_WidgetFlag | arrangeVertical_WidgetFlag); | ||
538 | } | ||
539 | /* Create panel contents based on provided items. */ | ||
540 | for (size_t i = 0; itemsNullTerminated[i].label; i++) { | ||
541 | const iMenuItem *item = &itemsNullTerminated[i]; | ||
542 | if (equal_Command(item->label, "panel")) { | ||
543 | const char *id = cstr_Rangecc(range_Command(item->label, "id")); | ||
544 | const iString *label = collectNewFormat_String("${%s}", id); | ||
545 | iLabelWidget *button = | ||
546 | addChildFlags_Widget(topPanel, | ||
547 | iClob(makePanelButton_(cstr_String(label), "panel.open")), | ||
548 | chevron_WidgetFlag | borderTop_WidgetFlag); | ||
549 | const iChar icon = toInt_String(string_Command(item->label, "icon")); | ||
550 | if (icon) { | ||
551 | setIcon_LabelWidget(button, icon); | ||
552 | } | ||
553 | iWidget *panel = addChildPanel_(detailStack, button, NULL); | ||
554 | makePanelItems_Mobile(panel, item->data); | ||
555 | } | ||
556 | else { | ||
557 | makePanelItem_Mobile(topPanel, item); | ||
558 | } | ||
559 | } | ||
560 | /* Finalize the layout. */ | ||
561 | addChild_Widget(sheet->root->widget, iClob(sheet)); | ||
562 | mainDetailSplitHandler_(mainDetailSplit, "window.resized"); /* make it resize the split */ | ||
563 | updatePanelSheetMetrics_(sheet); | ||
564 | arrange_Widget(sheet); | ||
565 | postCommand_App("widget.overflow"); /* with the correct dimensions */ | ||
566 | return sheet; | ||
567 | } | ||
568 | |||
569 | #if 0 | ||
372 | /* The sheet contents are completely rearranged and restyled on a phone. | 570 | /* The sheet contents are completely rearranged and restyled on a phone. |
373 | We'll set up a linear fullscreen arrangement of the widgets. Sheets are already | 571 | We'll set up a linear fullscreen arrangement of the widgets. Sheets are already |
374 | scrollable so they can be taller than the display. In hindsight, it may have been | 572 | scrollable so they can be taller than the display. In hindsight, it may have been |
@@ -399,7 +597,7 @@ void finalizeSheet_Mobile(iWidget *sheet) { | |||
399 | │ │ └┤ ││ │ │└┤ ││ | 597 | │ │ └┤ ││ │ │└┤ ││ |
400 | │ │ └───────────────────┘│ │ │ └──────┘ | 598 | │ │ └───────────────────┘│ │ │ └──────┘ |
401 | └─────────┴───────────────────────┘ └─────────┴ ─ ─ ─ ─ ┘ | 599 | └─────────┴───────────────────────┘ └─────────┴ ─ ─ ─ ─ ┘ |
402 | offscreen | 600 | underneath |
403 | */ | 601 | */ |
404 | /* Modify the top sheet to act as a fullscreen background. */ | 602 | /* Modify the top sheet to act as a fullscreen background. */ |
405 | setPadding1_Widget(sheet, 0); | 603 | setPadding1_Widget(sheet, 0); |
@@ -774,6 +972,7 @@ void finalizeSheet_Mobile(iWidget *sheet) { | |||
774 | } | 972 | } |
775 | postRefresh_App(); | 973 | postRefresh_App(); |
776 | } | 974 | } |
975 | #endif | ||
777 | 976 | ||
778 | void setupMenuTransition_Mobile(iWidget *sheet, iBool isIncoming) { | 977 | void setupMenuTransition_Mobile(iWidget *sheet, iBool isIncoming) { |
779 | if (!useMobileSheetLayout_()) { | 978 | if (!useMobileSheetLayout_()) { |
diff --git a/src/ui/mobile.h b/src/ui/mobile.h index 44134389..50b89e32 100644 --- a/src/ui/mobile.h +++ b/src/ui/mobile.h | |||
@@ -22,11 +22,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
22 | 22 | ||
23 | #pragma once | 23 | #pragma once |
24 | 24 | ||
25 | #include <the_Foundation/defs.h> | 25 | #include <the_Foundation/rect.h> |
26 | 26 | ||
27 | iDeclareType(Widget) | 27 | iDeclareType(Widget) |
28 | 28 | iDeclareType(MenuItem) | |
29 | void setupMenuTransition_Mobile (iWidget *menu, iBool isIncoming); | 29 | |
30 | void setupSheetTransition_Mobile (iWidget *sheet, iBool isIncoming); | 30 | iWidget * makeSplitMultiPanel_Mobile (const iMenuItem *itemsNullTerminated); |
31 | |||
32 | void setupMenuTransition_Mobile (iWidget *menu, iBool isIncoming); | ||
33 | void setupSheetTransition_Mobile (iWidget *sheet, iBool isIncoming); | ||
31 | 34 | ||
32 | void finalizeSheet_Mobile (iWidget *sheet); | 35 | void finalizeSheet_Mobile (iWidget *sheet); |
diff --git a/src/ui/util.c b/src/ui/util.c index 906d30ae..995b730e 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -707,6 +707,9 @@ iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) { | |||
707 | iBool haveIcons = iFalse; | 707 | iBool haveIcons = iFalse; |
708 | for (size_t i = 0; i < n; ++i) { | 708 | for (size_t i = 0; i < n; ++i) { |
709 | const iMenuItem *item = &items[i]; | 709 | const iMenuItem *item = &items[i]; |
710 | if (!item->label) { | ||
711 | break; | ||
712 | } | ||
710 | if (equal_CStr(item->label, "---")) { | 713 | if (equal_CStr(item->label, "---")) { |
711 | addChild_Widget(menu, iClob(makeMenuSeparator_())); | 714 | addChild_Widget(menu, iClob(makeMenuSeparator_())); |
712 | } | 715 | } |
@@ -1506,7 +1509,7 @@ static void addRadioButton_(iWidget *parent, const char *id, const char *label, | |||
1506 | id); | 1509 | id); |
1507 | } | 1510 | } |
1508 | 1511 | ||
1509 | static void addFontButtons_(iWidget *parent, const char *id) { | 1512 | static const iArray *makeFontItems_(const char *id) { |
1510 | const struct { | 1513 | const struct { |
1511 | const char * name; | 1514 | const char * name; |
1512 | enum iTextFont cfgId; | 1515 | enum iTextFont cfgId; |
@@ -1518,7 +1521,7 @@ static void addFontButtons_(iWidget *parent, const char *id) { | |||
1518 | { "Tinos", tinos_TextFont }, | 1521 | { "Tinos", tinos_TextFont }, |
1519 | { "---", -1 }, | 1522 | { "---", -1 }, |
1520 | { "Iosevka", iosevka_TextFont } }; | 1523 | { "Iosevka", iosevka_TextFont } }; |
1521 | iArray *items = new_Array(sizeof(iMenuItem)); | 1524 | iArray *items = collectNew_Array(sizeof(iMenuItem)); |
1522 | iForIndices(i, fonts) { | 1525 | iForIndices(i, fonts) { |
1523 | pushBack_Array(items, | 1526 | pushBack_Array(items, |
1524 | &(iMenuItem){ fonts[i].name, | 1527 | &(iMenuItem){ fonts[i].name, |
@@ -1528,11 +1531,18 @@ static void addFontButtons_(iWidget *parent, const char *id) { | |||
1528 | ? format_CStr("!%s.set arg:%d", id, fonts[i].cfgId) | 1531 | ? format_CStr("!%s.set arg:%d", id, fonts[i].cfgId) |
1529 | : NULL }); | 1532 | : NULL }); |
1530 | } | 1533 | } |
1531 | iLabelWidget *button = makeMenuButton_LabelWidget("Source Sans 3", data_Array(items), size_Array(items)); | 1534 | pushBack_Array(items, &(iMenuItem){ NULL }); /* terminator */ |
1532 | setBackgroundColor_Widget(findChild_Widget(as_Widget(button), "menu"), uiBackgroundMenu_ColorId); | 1535 | return items; |
1536 | } | ||
1537 | |||
1538 | static void addFontButtons_(iWidget *parent, const char *id) { | ||
1539 | const iArray *items = makeFontItems_(id); | ||
1540 | iLabelWidget *button = makeMenuButton_LabelWidget("Source Sans 3", | ||
1541 | constData_Array(items), size_Array(items)); | ||
1542 | setBackgroundColor_Widget(findChild_Widget(as_Widget(button), "menu"), | ||
1543 | uiBackgroundMenu_ColorId); | ||
1533 | setId_Widget(as_Widget(button), format_CStr("prefs.%s", id)); | 1544 | setId_Widget(as_Widget(button), format_CStr("prefs.%s", id)); |
1534 | addChildFlags_Widget(parent, iClob(button), alignLeft_WidgetFlag); | 1545 | addChildFlags_Widget(parent, iClob(button), alignLeft_WidgetFlag); |
1535 | delete_Array(items); | ||
1536 | } | 1546 | } |
1537 | 1547 | ||
1538 | #if 0 | 1548 | #if 0 |
@@ -1615,7 +1625,7 @@ static void addPrefsInputWithHeading_(iWidget *headings, iWidget *values, | |||
1615 | static size_t findWidestItemLabel_(const iMenuItem *items, size_t num) { | 1625 | static size_t findWidestItemLabel_(const iMenuItem *items, size_t num) { |
1616 | int widest = 0; | 1626 | int widest = 0; |
1617 | size_t widestPos = iInvalidPos; | 1627 | size_t widestPos = iInvalidPos; |
1618 | for (size_t i = 0; i < num; i++) { | 1628 | for (size_t i = 0; i < num && items[i].label; i++) { |
1619 | const int width = | 1629 | const int width = |
1620 | measure_Text(uiLabel_FontId, | 1630 | measure_Text(uiLabel_FontId, |
1621 | translateCStr_Lang(items[i].label)) | 1631 | translateCStr_Lang(items[i].label)) |
@@ -1629,6 +1639,153 @@ static size_t findWidestItemLabel_(const iMenuItem *items, size_t num) { | |||
1629 | } | 1639 | } |
1630 | 1640 | ||
1631 | iWidget *makePreferences_Widget(void) { | 1641 | iWidget *makePreferences_Widget(void) { |
1642 | /* Common items. */ | ||
1643 | const iMenuItem langItems[] = { { "${lang.de} - de", 0, 0, "uilang id:de" }, | ||
1644 | { "${lang.en} - en", 0, 0, "uilang id:en" }, | ||
1645 | { "${lang.es} - es", 0, 0, "uilang id:es" }, | ||
1646 | { "${lang.fi} - fi", 0, 0, "uilang id:fi" }, | ||
1647 | { "${lang.fr} - fr", 0, 0, "uilang id:fr" }, | ||
1648 | { "${lang.ia} - ia", 0, 0, "uilang id:ia" }, | ||
1649 | { "${lang.ie} - ie", 0, 0, "uilang id:ie" }, | ||
1650 | { "${lang.pl} - pl", 0, 0, "uilang id:pl" }, | ||
1651 | { "${lang.ru} - ru", 0, 0, "uilang id:ru" }, | ||
1652 | { "${lang.sr} - sr", 0, 0, "uilang id:sr" }, | ||
1653 | { "${lang.tok} - tok", 0, 0, "uilang id:tok" }, | ||
1654 | { "${lang.zh.hans} - zh", 0, 0, "uilang id:zh_Hans" }, | ||
1655 | { "${lang.zh.hant} - zh", 0, 0, "uilang id:zh_Hant" }, | ||
1656 | { NULL } }; | ||
1657 | const iMenuItem returnKeyBehaviors[] = { | ||
1658 | { "${prefs.returnkey.linebreak} " uiTextAction_ColorEscape shift_Icon return_Icon | ||
1659 | restore_ColorEscape | ||
1660 | " ${prefs.returnkey.accept} " uiTextAction_ColorEscape return_Icon, | ||
1661 | 0, | ||
1662 | 0, | ||
1663 | format_CStr("returnkey.set arg:%d", default_ReturnKeyBehavior) }, | ||
1664 | { "${prefs.returnkey.linebreak} " uiTextAction_ColorEscape return_Icon restore_ColorEscape | ||
1665 | " ${prefs.returnkey.accept} " uiTextAction_ColorEscape shift_Icon return_Icon, | ||
1666 | 0, | ||
1667 | 0, | ||
1668 | format_CStr("returnkey.set arg:%d", acceptWithShift_ReturnKeyBehavior) }, | ||
1669 | { "${prefs.returnkey.linebreak} " uiTextAction_ColorEscape return_Icon restore_ColorEscape | ||
1670 | " ${prefs.returnkey.accept} " uiTextAction_ColorEscape | ||
1671 | #if defined (iPlatformApple) | ||
1672 | "\u2318" return_Icon, | ||
1673 | #else | ||
1674 | "Ctrl" return_Icon, | ||
1675 | #endif | ||
1676 | 0, | ||
1677 | 0, | ||
1678 | format_CStr("returnkey.set arg:%d", acceptWithPrimaryMod_ReturnKeyBehavior) }, | ||
1679 | { NULL } | ||
1680 | }; | ||
1681 | iMenuItem docThemes[2][max_GmDocumentTheme + 1]; | ||
1682 | for (int i = 0; i < 2; ++i) { | ||
1683 | const iBool isDark = (i == 0); | ||
1684 | const char *mode = isDark ? "dark" : "light"; | ||
1685 | const iMenuItem items[max_GmDocumentTheme + 1] = { | ||
1686 | { "${prefs.doctheme.name.colorfuldark}", 0, 0, format_CStr("doctheme.%s.set arg:%d", mode, colorfulDark_GmDocumentTheme) }, | ||
1687 | { "${prefs.doctheme.name.colorfullight}", 0, 0, format_CStr("doctheme.%s.set arg:%d", mode, colorfulLight_GmDocumentTheme) }, | ||
1688 | { "${prefs.doctheme.name.black}", 0, 0, format_CStr("doctheme.%s.set arg:%d", mode, black_GmDocumentTheme) }, | ||
1689 | { "${prefs.doctheme.name.gray}", 0, 0, format_CStr("doctheme.%s.set arg:%d", mode, gray_GmDocumentTheme) }, | ||
1690 | { "${prefs.doctheme.name.white}", 0, 0, format_CStr("doctheme.%s.set arg:%d", mode, white_GmDocumentTheme) }, | ||
1691 | { "${prefs.doctheme.name.sepia}", 0, 0, format_CStr("doctheme.%s.set arg:%d", mode, sepia_GmDocumentTheme) }, | ||
1692 | { "${prefs.doctheme.name.highcontrast}", 0, 0, format_CStr("doctheme.%s.set arg:%d", mode, highContrast_GmDocumentTheme) }, | ||
1693 | { NULL } | ||
1694 | }; | ||
1695 | memcpy(docThemes[i], items, sizeof(items)); | ||
1696 | } | ||
1697 | const iMenuItem imgStyles[] = { | ||
1698 | { "${prefs.imagestyle.original}", 0, 0, format_CStr("imagestyle.set arg:%d", original_ImageStyle) }, | ||
1699 | { "${prefs.imagestyle.grayscale}", 0, 0, format_CStr("imagestyle.set arg:%d", grayscale_ImageStyle) }, | ||
1700 | { "${prefs.imagestyle.bgfg}", 0, 0, format_CStr("imagestyle.set arg:%d", bgFg_ImageStyle) }, | ||
1701 | { "${prefs.imagestyle.text}", 0, 0, format_CStr("imagestyle.set arg:%d", textColorized_ImageStyle) }, | ||
1702 | { "${prefs.imagestyle.preformat}", 0, 0, format_CStr("imagestyle.set arg:%d", preformatColorized_ImageStyle) }, | ||
1703 | { NULL } | ||
1704 | }; | ||
1705 | /* Create the Preferences UI. */ | ||
1706 | if (deviceType_App() != desktop_AppDeviceType) { | ||
1707 | const iMenuItem pinSplit[] = { | ||
1708 | { "button id:prefs.pinsplit.0 label:prefs.pinsplit.none", 0, 0, "pinsplit.set arg:0" }, | ||
1709 | { "button id:prefs.pinsplit.1 label:prefs.pinsplit.left", 0, 0, "pinsplit.set arg:1" }, | ||
1710 | { "button id:prefs.pinsplit.2 label:prefs.pinsplit.right", 0, 0, "pinsplit.set arg:2" }, | ||
1711 | { NULL } | ||
1712 | }; | ||
1713 | const iMenuItem themeItems[] = { | ||
1714 | { "button id:prefs.theme.0 label:prefs.theme.black", 0, 0, "theme.set arg:0" }, | ||
1715 | { "button id:prefs.theme.1 label:prefs.theme.dark", 0, 0, "theme.set arg:1" }, | ||
1716 | { "button id:prefs.theme.2 label:prefs.theme.light", 0, 0, "theme.set arg:2" }, | ||
1717 | { "button id:prefs.theme.3 label:prefs.theme.white", 0, 0, "theme.set arg:3" }, | ||
1718 | { NULL } | ||
1719 | }; | ||
1720 | const iMenuItem accentItems[] = { | ||
1721 | { "button id:prefs.accent.0 label:prefs.accent.teal", 0, 0, "accent.set arg:0" }, | ||
1722 | { "button id:prefs.accent.1 label:prefs.accent.orange", 0, 0, "accent.set arg:1" }, | ||
1723 | { NULL } | ||
1724 | }; | ||
1725 | const iMenuItem satItems[] = { | ||
1726 | { "button id:prefs.saturation.3 text:100 %", 0, 0, "saturation.set arg:100" }, | ||
1727 | { "button id:prefs.saturation.2 text:66 %", 0, 0, "saturation.set arg:66" }, | ||
1728 | { "button id:prefs.saturation.1 text:33 %", 0, 0, "saturation.set arg:33" }, | ||
1729 | { "button id:prefs.saturation.0 text:0 %", 0, 0, "saturation.set arg:0" }, | ||
1730 | { NULL } | ||
1731 | }; | ||
1732 | const iMenuItem generalItems[] = { | ||
1733 | { "title id:heading.prefs.general", 0, 0, NULL }, | ||
1734 | { "input id:prefs.searchurl url:1", 0, 0, NULL }, | ||
1735 | { "padding", 0, 0, NULL }, | ||
1736 | { "toggle id:prefs.hoverlink", 0, 0, NULL }, | ||
1737 | { "toggle id:prefs.archive.openindex", 0, 0, NULL }, | ||
1738 | { "radio device:1 id:prefs.pinsplit", 0, 0, (const void *) pinSplit }, | ||
1739 | { "padding", 0, 0, NULL }, | ||
1740 | { "dropdown id:prefs.uilang", 0, 0, (const void *) langItems }, | ||
1741 | { NULL } | ||
1742 | }; | ||
1743 | const iMenuItem uiItems[] = { | ||
1744 | { "title id:heading.prefs.interface", 0, 0, NULL }, | ||
1745 | { "dropdown device:1 id:prefs.returnkey", 0, 0, (const void *) returnKeyBehaviors }, | ||
1746 | { "padding device:1", 0, 0, NULL }, | ||
1747 | { "toggle device:2 id:prefs.hidetoolbarscroll", 0, 0, NULL }, | ||
1748 | { "heading id:heading.prefs.sizing", 0, 0, NULL }, | ||
1749 | { "input id:prefs.uiscale maxlen:8", 0, 0, NULL }, | ||
1750 | { NULL } | ||
1751 | }; | ||
1752 | const iMenuItem colorItems[] = { | ||
1753 | { "title id:heading.prefs.colors", 0, 0, NULL }, | ||
1754 | { "heading id:heading.prefs.uitheme", 0, 0, NULL }, | ||
1755 | { "toggle id:prefs.ostheme", 0, 0, NULL }, | ||
1756 | { "radio id:prefs.theme", 0, 0, (const void *) themeItems }, | ||
1757 | { "radio id:prefs.accent", 0, 0, (const void *) accentItems }, | ||
1758 | { "heading id:heading.prefs.pagecontent", 0, 0, NULL }, | ||
1759 | { "dropdown id:prefs.doctheme.dark", 0, 0, (const void *) docThemes[0] }, | ||
1760 | { "dropdown id:prefs.doctheme.light", 0, 0, (const void *) docThemes[1] }, | ||
1761 | { "radio id:prefs.saturation", 0, 0, (const void *) satItems }, | ||
1762 | { "padding", 0, 0, NULL }, | ||
1763 | { "dropdown id:prefs.imagestyle", 0, 0, (const void *) imgStyles }, | ||
1764 | { NULL } | ||
1765 | }; | ||
1766 | const iMenuItem fontItems[] = { | ||
1767 | { "title id:heading.prefs.fonts", 0, 0, NULL }, | ||
1768 | { "dropdown id:prefs.headingfont", 0, 0, (const void *) constData_Array(makeFontItems_("headingfont")) }, | ||
1769 | { "dropdown id:prefs.font", 0, 0, (const void *) constData_Array(makeFontItems_("font")) }, | ||
1770 | { NULL } | ||
1771 | }; | ||
1772 | const iMenuItem items[] = { { "panel icon:0x2699 id:heading.prefs.general", | ||
1773 | '1', 0, | ||
1774 | (const void *) generalItems }, | ||
1775 | { "panel icon:0x1f4f1 id:heading.prefs.interface", | ||
1776 | '2', 0, | ||
1777 | (const void *) uiItems }, | ||
1778 | { "panel icon:0x1f3a8 id:heading.prefs.colors", | ||
1779 | '3', 0, | ||
1780 | (const void *) colorItems }, | ||
1781 | { "panel icon:0x1f5da id:heading.prefs.fonts", | ||
1782 | '4', 0, | ||
1783 | (const void *) fontItems }, | ||
1784 | { NULL } }; | ||
1785 | iWidget *dlg = makeSplitMultiPanel_Mobile(items); | ||
1786 | setupSheetTransition_Mobile(dlg, iTrue); | ||
1787 | return dlg; | ||
1788 | } | ||
1632 | iWidget *dlg = makeSheet_Widget("prefs"); | 1789 | iWidget *dlg = makeSheet_Widget("prefs"); |
1633 | addChildFlags_Widget(dlg, | 1790 | addChildFlags_Widget(dlg, |
1634 | iClob(new_LabelWidget(uiHeading_ColorEscape "${heading.prefs}", NULL)), | 1791 | iClob(new_LabelWidget(uiHeading_ColorEscape "${heading.prefs}", NULL)), |
@@ -1666,22 +1823,7 @@ iWidget *makePreferences_Widget(void) { | |||
1666 | addChild_Widget(values, iClob(makePadding_Widget(bigGap))); | 1823 | addChild_Widget(values, iClob(makePadding_Widget(bigGap))); |
1667 | /* UI languages. */ { | 1824 | /* UI languages. */ { |
1668 | iArray *uiLangs = collectNew_Array(sizeof(iMenuItem)); | 1825 | iArray *uiLangs = collectNew_Array(sizeof(iMenuItem)); |
1669 | const iMenuItem langItems[] = { | 1826 | pushBackN_Array(uiLangs, langItems, iElemCount(langItems) - 1); |
1670 | { "${lang.de} - de", 0, 0, "uilang id:de" }, | ||
1671 | { "${lang.en} - en", 0, 0, "uilang id:en" }, | ||
1672 | { "${lang.es} - es", 0, 0, "uilang id:es" }, | ||
1673 | { "${lang.fi} - fi", 0, 0, "uilang id:fi" }, | ||
1674 | { "${lang.fr} - fr", 0, 0, "uilang id:fr" }, | ||
1675 | { "${lang.ia} - ia", 0, 0, "uilang id:ia" }, | ||
1676 | { "${lang.ie} - ie", 0, 0, "uilang id:ie" }, | ||
1677 | { "${lang.pl} - pl", 0, 0, "uilang id:pl" }, | ||
1678 | { "${lang.ru} - ru", 0, 0, "uilang id:ru" }, | ||
1679 | { "${lang.sr} - sr", 0, 0, "uilang id:sr" }, | ||
1680 | { "${lang.tok} - tok", 0, 0, "uilang id:tok" }, | ||
1681 | { "${lang.zh.hans} - zh", 0, 0, "uilang id:zh_Hans" }, | ||
1682 | { "${lang.zh.hant} - zh", 0, 0, "uilang id:zh_Hant" }, | ||
1683 | }; | ||
1684 | pushBackN_Array(uiLangs, langItems, iElemCount(langItems)); | ||
1685 | /* TODO: Add an arrange flag for resizing parent to widest child. */ | 1827 | /* TODO: Add an arrange flag for resizing parent to widest child. */ |
1686 | size_t widestPos = findWidestItemLabel_(data_Array(uiLangs), size_Array(uiLangs)); | 1828 | size_t widestPos = findWidestItemLabel_(data_Array(uiLangs), size_Array(uiLangs)); |
1687 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.uilang}"))); | 1829 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.uilang}"))); |
@@ -1702,39 +1844,12 @@ iWidget *makePreferences_Widget(void) { | |||
1702 | #endif | 1844 | #endif |
1703 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.returnkey}"))); | 1845 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.returnkey}"))); |
1704 | /* Return key behaviors. */ { | 1846 | /* Return key behaviors. */ { |
1705 | const iMenuItem returnKeyBehaviors[] = { | ||
1706 | { "${prefs.returnkey.linebreak} " | ||
1707 | uiTextAction_ColorEscape shift_Icon return_Icon restore_ColorEscape | ||
1708 | " ${prefs.returnkey.accept} " | ||
1709 | uiTextAction_ColorEscape return_Icon, | ||
1710 | 0, | ||
1711 | 0, | ||
1712 | format_CStr("returnkey.set arg:%d", default_ReturnKeyBehavior) }, | ||
1713 | { "${prefs.returnkey.linebreak} " | ||
1714 | uiTextAction_ColorEscape return_Icon restore_ColorEscape | ||
1715 | " ${prefs.returnkey.accept} " | ||
1716 | uiTextAction_ColorEscape shift_Icon return_Icon, | ||
1717 | 0, | ||
1718 | 0, | ||
1719 | format_CStr("returnkey.set arg:%d", acceptWithShift_ReturnKeyBehavior) }, | ||
1720 | { "${prefs.returnkey.linebreak} " | ||
1721 | uiTextAction_ColorEscape return_Icon restore_ColorEscape | ||
1722 | " ${prefs.returnkey.accept} " uiTextAction_ColorEscape | ||
1723 | #if defined (iPlatformApple) | ||
1724 | "\u2318" return_Icon, | ||
1725 | #else | ||
1726 | "Ctrl" return_Icon, | ||
1727 | #endif | ||
1728 | 0, | ||
1729 | 0, | ||
1730 | format_CStr("returnkey.set arg:%d", acceptWithPrimaryMod_ReturnKeyBehavior) }, | ||
1731 | }; | ||
1732 | iLabelWidget *returnKey = makeMenuButton_LabelWidget( | 1847 | iLabelWidget *returnKey = makeMenuButton_LabelWidget( |
1733 | returnKeyBehaviors[findWidestItemLabel_(returnKeyBehaviors, | 1848 | returnKeyBehaviors[findWidestItemLabel_(returnKeyBehaviors, |
1734 | iElemCount(returnKeyBehaviors))] | 1849 | iElemCount(returnKeyBehaviors) - 1)] |
1735 | .label, | 1850 | .label, |
1736 | returnKeyBehaviors, | 1851 | returnKeyBehaviors, |
1737 | iElemCount(returnKeyBehaviors)); | 1852 | iElemCount(returnKeyBehaviors) - 1); |
1738 | setBackgroundColor_Widget(findChild_Widget(as_Widget(returnKey), "menu"), | 1853 | setBackgroundColor_Widget(findChild_Widget(as_Widget(returnKey), "menu"), |
1739 | uiBackgroundMenu_ColorId); | 1854 | uiBackgroundMenu_ColorId); |
1740 | setId_Widget(addChildFlags_Widget(values, iClob(returnKey), alignLeft_WidgetFlag), | 1855 | setId_Widget(addChildFlags_Widget(values, iClob(returnKey), alignLeft_WidgetFlag), |
@@ -1804,20 +1919,13 @@ iWidget *makePreferences_Widget(void) { | |||
1804 | for (int i = 0; i < 2; ++i) { | 1919 | for (int i = 0; i < 2; ++i) { |
1805 | const iBool isDark = (i == 0); | 1920 | const iBool isDark = (i == 0); |
1806 | const char *mode = isDark ? "dark" : "light"; | 1921 | const char *mode = isDark ? "dark" : "light"; |
1807 | const iMenuItem themes[] = { | ||
1808 | { "${prefs.doctheme.name.colorfuldark}", 0, 0, format_CStr("doctheme.%s.set arg:%d", mode, colorfulDark_GmDocumentTheme) }, | ||
1809 | { "${prefs.doctheme.name.colorfullight}", 0, 0, format_CStr("doctheme.%s.set arg:%d", mode, colorfulLight_GmDocumentTheme) }, | ||
1810 | { "${prefs.doctheme.name.black}", 0, 0, format_CStr("doctheme.%s.set arg:%d", mode, black_GmDocumentTheme) }, | ||
1811 | { "${prefs.doctheme.name.gray}", 0, 0, format_CStr("doctheme.%s.set arg:%d", mode, gray_GmDocumentTheme) }, | ||
1812 | { "${prefs.doctheme.name.white}", 0, 0, format_CStr("doctheme.%s.set arg:%d", mode, white_GmDocumentTheme) }, | ||
1813 | { "${prefs.doctheme.name.sepia}", 0, 0, format_CStr("doctheme.%s.set arg:%d", mode, sepia_GmDocumentTheme) }, | ||
1814 | { "${prefs.doctheme.name.highcontrast}", 0, 0, format_CStr("doctheme.%s.set arg:%d", mode, highContrast_GmDocumentTheme) }, | ||
1815 | }; | ||
1816 | addChild_Widget(headings, iClob(makeHeading_Widget(isDark ? "${prefs.doctheme.dark}" : "${prefs.doctheme.light}"))); | 1922 | addChild_Widget(headings, iClob(makeHeading_Widget(isDark ? "${prefs.doctheme.dark}" : "${prefs.doctheme.light}"))); |
1817 | iLabelWidget *button = | 1923 | iLabelWidget *button = makeMenuButton_LabelWidget( |
1818 | makeMenuButton_LabelWidget(themes[1].label, themes, iElemCount(themes)); | 1924 | docThemes[i][findWidestItemLabel_(docThemes[i], max_GmDocumentTheme)].label, |
1819 | // setFrameColor_Widget(findChild_Widget(as_Widget(button), "menu"), | 1925 | docThemes[i], |
1820 | // uiBackgroundSelected_ColorId); | 1926 | max_GmDocumentTheme); |
1927 | // setFrameColor_Widget(findChild_Widget(as_Widget(button), "menu"), | ||
1928 | // uiBackgroundSelected_ColorId); | ||
1821 | setBackgroundColor_Widget(findChild_Widget(as_Widget(button), "menu"), uiBackgroundMenu_ColorId); | 1929 | setBackgroundColor_Widget(findChild_Widget(as_Widget(button), "menu"), uiBackgroundMenu_ColorId); |
1822 | setId_Widget(addChildFlags_Widget(values, iClob(button), alignLeft_WidgetFlag), | 1930 | setId_Widget(addChildFlags_Widget(values, iClob(button), alignLeft_WidgetFlag), |
1823 | format_CStr("prefs.doctheme.%s", mode)); | 1931 | format_CStr("prefs.doctheme.%s", mode)); |
@@ -1833,17 +1941,10 @@ iWidget *makePreferences_Widget(void) { | |||
1833 | addChildFlags_Widget(values, iClob(sats), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); | 1941 | addChildFlags_Widget(values, iClob(sats), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); |
1834 | /* Colorize images. */ { | 1942 | /* Colorize images. */ { |
1835 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.imagestyle}"))); | 1943 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.imagestyle}"))); |
1836 | const iMenuItem imgStyles[] = { | ||
1837 | { "${prefs.imagestyle.original}", 0, 0, format_CStr("imagestyle.set arg:%d", original_ImageStyle) }, | ||
1838 | { "${prefs.imagestyle.grayscale}", 0, 0, format_CStr("imagestyle.set arg:%d", grayscale_ImageStyle) }, | ||
1839 | { "${prefs.imagestyle.bgfg}", 0, 0, format_CStr("imagestyle.set arg:%d", bgFg_ImageStyle) }, | ||
1840 | { "${prefs.imagestyle.text}", 0, 0, format_CStr("imagestyle.set arg:%d", textColorized_ImageStyle) }, | ||
1841 | { "${prefs.imagestyle.preformat}", 0, 0, format_CStr("imagestyle.set arg:%d", preformatColorized_ImageStyle) }, | ||
1842 | }; | ||
1843 | iLabelWidget *button = makeMenuButton_LabelWidget( | 1944 | iLabelWidget *button = makeMenuButton_LabelWidget( |
1844 | imgStyles[findWidestItemLabel_(imgStyles, iElemCount(imgStyles))].label, | 1945 | imgStyles[findWidestItemLabel_(imgStyles, iElemCount(imgStyles) - 1)].label, |
1845 | imgStyles, | 1946 | imgStyles, |
1846 | iElemCount(imgStyles)); | 1947 | iElemCount(imgStyles) - 1); |
1847 | setBackgroundColor_Widget(findChild_Widget(as_Widget(button), "menu"), | 1948 | setBackgroundColor_Widget(findChild_Widget(as_Widget(button), "menu"), |
1848 | uiBackgroundMenu_ColorId); | 1949 | uiBackgroundMenu_ColorId); |
1849 | setId_Widget(addChildFlags_Widget(values, iClob(button), alignLeft_WidgetFlag), | 1950 | setId_Widget(addChildFlags_Widget(values, iClob(button), alignLeft_WidgetFlag), |
diff --git a/src/ui/util.h b/src/ui/util.h index 2423f834..87b72394 100644 --- a/src/ui/util.h +++ b/src/ui/util.h | |||
@@ -220,7 +220,10 @@ struct Impl_MenuItem { | |||
220 | const char *label; | 220 | const char *label; |
221 | int key; | 221 | int key; |
222 | int kmods; | 222 | int kmods; |
223 | const char *command; | 223 | union { |
224 | const char *command; | ||
225 | const void *data; | ||
226 | }; | ||
224 | }; | 227 | }; |
225 | 228 | ||
226 | iWidget * makeMenu_Widget (iWidget *parent, const iMenuItem *items, size_t n); /* returns no ref */ | 229 | iWidget * makeMenu_Widget (iWidget *parent, const iMenuItem *items, size_t n); /* returns no ref */ |
diff --git a/src/ui/widget.c b/src/ui/widget.c index 4f567989..0d6787ce 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -1402,6 +1402,7 @@ iAny *hitChild_Widget(const iWidget *d, iInt2 coord) { | |||
1402 | } | 1402 | } |
1403 | 1403 | ||
1404 | iAny *findChild_Widget(const iWidget *d, const char *id) { | 1404 | iAny *findChild_Widget(const iWidget *d, const char *id) { |
1405 | if (!d) return NULL; | ||
1405 | if (cmp_String(id_Widget(d), id) == 0) { | 1406 | if (cmp_String(id_Widget(d), id) == 0) { |
1406 | return iConstCast(iAny *, d); | 1407 | return iConstCast(iAny *, d); |
1407 | } | 1408 | } |
diff --git a/src/ui/window.c b/src/ui/window.c index 3ac02495..096853cc 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -1136,6 +1136,9 @@ void setTitle_Window(iWindow *d, const iString *title) { | |||
1136 | } | 1136 | } |
1137 | 1137 | ||
1138 | void setUiScale_Window(iWindow *d, float uiScale) { | 1138 | void setUiScale_Window(iWindow *d, float uiScale) { |
1139 | if (uiScale <= 0.0f) { | ||
1140 | uiScale = 1.0f; | ||
1141 | } | ||
1139 | uiScale = iClamp(uiScale, 0.5f, 4.0f); | 1142 | uiScale = iClamp(uiScale, 0.5f, 4.0f); |
1140 | if (d) { | 1143 | if (d) { |
1141 | if (iAbs(d->uiScale - uiScale) > 0.0001f) { | 1144 | if (iAbs(d->uiScale - uiScale) > 0.0001f) { |