introduce ES_PANEL_RADIO_GROUP

This commit is contained in:
nakst 2021-09-18 11:31:42 +01:00
parent 05ebe296e3
commit b535f73640
5 changed files with 59 additions and 24 deletions

View File

@ -1093,7 +1093,7 @@ void _start() {
userNameTextbox->messageUser = UserNameTextboxMessage;
EsTextDisplayCreate(table, ES_CELL_H_RIGHT | ES_CELL_V_TOP, ES_STYLE_TEXT_RADIO_GROUP_LABEL, INTERFACE_STRING(InstallerSystemFont));
EsPanel *fonts = EsPanelCreate(table, ES_CELL_H_LEFT);
EsPanel *fonts = EsPanelCreate(table, ES_CELL_H_LEFT | ES_PANEL_RADIO_GROUP);
EsButton *button = EsButtonCreate(fonts, ES_BUTTON_RADIOBOX | ES_CELL_H_EXPAND, 0, INTERFACE_STRING(InstallerFontDefault));
button->userData = (void *) "Inter";
EsButtonOnCommand(button, ButtonFont);

View File

@ -118,6 +118,7 @@ void InspectorNotifyElementContentChanged(EsElement *element);
#define UI_STATE_USE_MEASUREMENT_CACHE (1 << 20)
#define UI_STATE_CHECK_VISIBLE (1 << 21)
#define UI_STATE_INSPECTING (1 << 22)
#define UI_STATE_RADIO_GROUP (1 << 23)
struct EsElement : EsElementPublic {
EsUICallback messageClass;
@ -197,6 +198,10 @@ struct EsElement : EsElementPublic {
return true;
}
bool IsTabTraversable() {
return IsFocusable() && (~flags & ES_ELEMENT_NOT_TAB_TRAVERSABLE) && (!parent || ~parent->state & UI_STATE_RADIO_GROUP);
}
bool RefreshStyleState(); // Returns true if any observed bits have changed.
void RefreshStyle(UIStyleKey *oldStyleKey = nullptr, bool alreadyRefreshStyleState = false, bool force = false);
bool StartAnimating();
@ -3162,15 +3167,21 @@ int ProcessPanelMessage(EsElement *element, EsMessage *message) {
}
} else if (message->type == ES_MSG_KEY_DOWN) {
if (!(panel->flags & (ES_PANEL_TABLE | ES_PANEL_SWITCHER))
&& panel->window->focused && panel->window->focused->parent == panel
&& (panel->flags & ES_PANEL_HORIZONTAL)) {
bool reverse = panel->flags & ES_PANEL_REVERSE,
left = message->keyboard.scancode == ES_SCANCODE_LEFT_ARROW,
right = message->keyboard.scancode == ES_SCANCODE_RIGHT_ARROW;
&& panel->window->focused && panel->window->focused->parent == panel) {
bool reverse = panel->flags & ES_PANEL_REVERSE;
bool left = message->keyboard.scancode == ES_SCANCODE_LEFT_ARROW;
bool right = message->keyboard.scancode == ES_SCANCODE_RIGHT_ARROW;
bool up = message->keyboard.scancode == ES_SCANCODE_UP_ARROW;
bool down = message->keyboard.scancode == ES_SCANCODE_DOWN_ARROW;
if (~panel->flags & ES_PANEL_HORIZONTAL) {
left = up;
right = down;
}
EsElement *focus = nullptr;
if ((left && !reverse) || (right && reverse)) {
EsElement *focus = nullptr;
for (uintptr_t i = 0; i < panel->GetChildCount(); i++) {
EsElement *child = panel->GetChild(i);
@ -3184,13 +3195,7 @@ int ProcessPanelMessage(EsElement *element, EsMessage *message) {
focus = child;
}
}
if (focus) {
EsElementFocus(focus);
}
} else if ((left && reverse) || (right && !reverse)) {
EsElement *focus = nullptr;
for (uintptr_t i = panel->GetChildCount(); i > 0; i--) {
EsElement *child = panel->GetChild(i - 1);
@ -3204,13 +3209,18 @@ int ProcessPanelMessage(EsElement *element, EsMessage *message) {
focus = child;
}
}
if (focus) {
EsElementFocus(focus);
}
} else {
return 0;
}
if (focus) {
EsElementFocus(focus);
if (panel->flags & ES_PANEL_RADIO_GROUP) {
EsMessage m = { .type = ES_MSG_MOUSE_LEFT_CLICK };
EsMessageSend(focus, &m);
}
}
} else {
return 0;
}
@ -3322,9 +3332,10 @@ EsPanel *EsPanelCreate(EsElement *parent, uint64_t flags, const EsStyle *style)
panel->Initialise(parent, flags, ProcessPanelMessage, style);
panel->cName = "panel";
if (flags & ES_PANEL_Z_STACK) panel->state |= UI_STATE_Z_STACK;
if (flags & ES_PANEL_HORIZONTAL) panel->flags |= ES_ELEMENT_LAYOUT_HINT_HORIZONTAL;
if (flags & ES_PANEL_REVERSE) panel->flags |= ES_ELEMENT_LAYOUT_HINT_REVERSE;
if (flags & ES_PANEL_Z_STACK) panel->state |= UI_STATE_Z_STACK;
if (flags & ES_PANEL_RADIO_GROUP) panel->state |= UI_STATE_RADIO_GROUP, panel->flags |= ES_ELEMENT_FOCUSABLE;
if (flags & ES_PANEL_HORIZONTAL) panel->flags |= ES_ELEMENT_LAYOUT_HINT_HORIZONTAL;
if (flags & ES_PANEL_REVERSE) panel->flags |= ES_ELEMENT_LAYOUT_HINT_REVERSE;
panel->scroll.Setup(panel,
((flags & ES_PANEL_H_SCROLL_FIXED) ? SCROLL_MODE_FIXED : (flags & ES_PANEL_H_SCROLL_AUTO) ? SCROLL_MODE_AUTO : SCROLL_MODE_NONE),
@ -3507,6 +3518,20 @@ void EsPanelStartMovementAnimation(EsPanel *panel, float timeMultiplier) {
EsElementRelayout(panel);
}
EsButton *EsPanelRadioGroupGetChecked(EsPanel *panel) {
EsMessageMutexCheck();
EsAssert(panel->state & UI_STATE_RADIO_GROUP);
EsAssert(panel->GetChildCount());
for (uintptr_t i = 0; i < panel->GetChildCount(); i++) {
if (ES_CHECK_CHECKED == EsButtonGetCheck((EsButton *) panel->GetChild(i))) {
return (EsButton *) panel->GetChild(i);
}
}
return (EsButton *) panel->GetChild(0);
}
// --------------------------------- Canvas panes.
struct EsCanvasPane : EsElement {
@ -6641,8 +6666,13 @@ bool UIHandleKeyMessage(EsWindow *window, EsMessage *message) {
EsElement *element = window->focused ?: window;
EsElement *start = element;
do element = UITabTraversalDo(element, message->keyboard.modifiers & ES_MODIFIER_SHIFT);
while ((!element->IsFocusable() || (element->flags & ES_ELEMENT_NOT_TAB_TRAVERSABLE)) && element != start);
do {
element = UITabTraversalDo(element, message->keyboard.modifiers & ES_MODIFIER_SHIFT);
} while (!element->IsTabTraversable() && element != start);
if (element->state & UI_STATE_RADIO_GROUP) {
element = EsPanelRadioGroupGetChecked((EsPanel *) element);
}
EsElementFocus(element, ES_ELEMENT_FOCUS_ENSURE_VISIBLE | ES_ELEMENT_FOCUS_FROM_KEYBOARD);
return true;

View File

@ -484,6 +484,8 @@ define ES_PANEL_V_BOTTOM (1 << 21)
define ES_PANEL_V_CENTER (1 << 22)
define ES_PANEL_V_JUSTIFY (1 << 23)
define ES_PANEL_RADIO_GROUP (1 << 30) // Determines how arrow keys/tabs behave.
define ES_TEXTBOX_MULTILINE (1 << 0)
define ES_TEXTBOX_EDIT_BASED (1 << 1)
define ES_TEXTBOX_MARGIN (1 << 2)
@ -2432,6 +2434,8 @@ function void EsPanelTableSetChildCells(EsPanel *panel); // Automatically set th
function void EsPanelSwitchTo(EsPanel *panel, EsElement *targetChild, EsTransitionType transitionType, uint32_t flags = ES_FLAGS_DEFAULT, float timeMultiplier = 1); // TODO More customization of transitions?
function void EsPanelStartMovementAnimation(EsPanel *panel, float timeMultiplier = 1); // TODO More customization.
function EsButton *EsPanelRadioGroupGetChecked(EsPanel *panel);
// Static displays.
function EsIconDisplay *EsIconDisplayCreate(EsElement *parent, uint64_t flags = ES_FLAGS_DEFAULT, const EsStyle *style = ES_NULL, uint32_t iconID = 0);

View File

@ -681,7 +681,7 @@ void SettingsPageTheme(EsElement *element, SettingsPage *page) {
};
EsTextDisplayCreate(table, ES_CELL_H_RIGHT, 0, INTERFACE_STRING(DesktopSettingsThemeWindowColor));
EsPanel *panel = EsPanelCreate(table, ES_CELL_H_LEFT | ES_PANEL_HORIZONTAL);
EsPanel *panel = EsPanelCreate(table, ES_CELL_H_LEFT | ES_PANEL_HORIZONTAL | ES_PANEL_RADIO_GROUP);
uint8_t windowColor = EsSystemConfigurationReadInteger(EsLiteral("general"), EsLiteral("window_color"));
for (uintptr_t i = 0; i < sizeof(windowColors) / sizeof(windowColors[0]); i++) {

View File

@ -455,3 +455,4 @@ _EsWindowGetHandle=453
_EsUISetFont=454
EsWorkQueue=455
EsWorkIsExiting=456
EsPanelRadioGroupGetChecked=457