Working on keyboard control of GUI.
This commit is contained in:
parent
cd8da88df7
commit
2fdba061ce
2 changed files with 188 additions and 1 deletions
|
|
@ -320,22 +320,30 @@ static bool dispatchAccelKey(AppContextT *ctx, char key) {
|
|||
if (target) {
|
||||
switch (target->type) {
|
||||
case WidgetButtonE:
|
||||
widgetClearFocus(win->widgetRoot);
|
||||
target->focused = true;
|
||||
target->as.button.pressed = true;
|
||||
sAccelPressedBtn = target;
|
||||
wgtInvalidate(target);
|
||||
return true;
|
||||
|
||||
case WidgetCheckboxE:
|
||||
widgetClearFocus(win->widgetRoot);
|
||||
target->focused = true;
|
||||
widgetCheckboxOnMouse(target);
|
||||
wgtInvalidate(target);
|
||||
return true;
|
||||
|
||||
case WidgetRadioE:
|
||||
widgetClearFocus(win->widgetRoot);
|
||||
target->focused = true;
|
||||
widgetRadioOnMouse(target);
|
||||
wgtInvalidate(target);
|
||||
return true;
|
||||
|
||||
case WidgetImageButtonE:
|
||||
widgetClearFocus(win->widgetRoot);
|
||||
target->focused = true;
|
||||
if (target->onClick) {
|
||||
target->onClick(target);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ void widgetOnKey(WindowT *win, int32_t key, int32_t mod) {
|
|||
while (top > 0) {
|
||||
WidgetT *w = stack[--top];
|
||||
|
||||
if (w->focused && (w->type == WidgetTextInputE || w->type == WidgetComboBoxE || w->type == WidgetDropdownE || w->type == WidgetAnsiTermE || w->type == WidgetTreeViewE || w->type == WidgetListBoxE)) {
|
||||
if (w->focused && (w->type == WidgetTextInputE || w->type == WidgetComboBoxE || w->type == WidgetDropdownE || w->type == WidgetAnsiTermE || w->type == WidgetTreeViewE || w->type == WidgetListBoxE || w->type == WidgetButtonE || w->type == WidgetImageButtonE || w->type == WidgetCheckboxE || w->type == WidgetRadioE || w->type == WidgetSliderE)) {
|
||||
focus = w;
|
||||
break;
|
||||
}
|
||||
|
|
@ -156,6 +156,180 @@ void widgetOnKey(WindowT *win, int32_t key, int32_t mod) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Handle button keyboard activation
|
||||
if (focus->type == WidgetButtonE) {
|
||||
if (key == ' ' || key == 0x0D) {
|
||||
focus->as.button.pressed = true;
|
||||
wgtInvalidate(focus);
|
||||
focus->as.button.pressed = false;
|
||||
|
||||
if (focus->onClick) {
|
||||
focus->onClick(focus);
|
||||
}
|
||||
|
||||
wgtInvalidate(focus);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle image button keyboard activation
|
||||
if (focus->type == WidgetImageButtonE) {
|
||||
if (key == ' ' || key == 0x0D) {
|
||||
focus->as.imageButton.pressed = true;
|
||||
wgtInvalidate(focus);
|
||||
focus->as.imageButton.pressed = false;
|
||||
|
||||
if (focus->onClick) {
|
||||
focus->onClick(focus);
|
||||
}
|
||||
|
||||
wgtInvalidate(focus);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle checkbox keyboard toggle
|
||||
if (focus->type == WidgetCheckboxE) {
|
||||
if (key == ' ' || key == 0x0D) {
|
||||
focus->as.checkbox.checked = !focus->as.checkbox.checked;
|
||||
|
||||
if (focus->onChange) {
|
||||
focus->onChange(focus);
|
||||
}
|
||||
|
||||
wgtInvalidate(focus);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle radio button keyboard navigation
|
||||
if (focus->type == WidgetRadioE) {
|
||||
if (key == ' ' || key == 0x0D) {
|
||||
// Select this radio
|
||||
if (focus->parent && focus->parent->type == WidgetRadioGroupE) {
|
||||
focus->parent->as.radioGroup.selectedIdx = focus->as.radio.index;
|
||||
|
||||
if (focus->parent->onChange) {
|
||||
focus->parent->onChange(focus->parent);
|
||||
}
|
||||
}
|
||||
|
||||
wgtInvalidate(focus);
|
||||
} else if (key == (0x50 | 0x100) || key == (0x4D | 0x100)) {
|
||||
// Down or Right — next radio in group
|
||||
if (focus->parent && focus->parent->type == WidgetRadioGroupE) {
|
||||
WidgetT *next = NULL;
|
||||
|
||||
for (WidgetT *s = focus->nextSibling; s; s = s->nextSibling) {
|
||||
if (s->type == WidgetRadioE && s->visible && s->enabled) {
|
||||
next = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (next) {
|
||||
focus->focused = false;
|
||||
next->focused = true;
|
||||
next->parent->as.radioGroup.selectedIdx = next->as.radio.index;
|
||||
|
||||
if (next->parent->onChange) {
|
||||
next->parent->onChange(next->parent);
|
||||
}
|
||||
|
||||
wgtInvalidate(next);
|
||||
}
|
||||
}
|
||||
} else if (key == (0x48 | 0x100) || key == (0x4B | 0x100)) {
|
||||
// Up or Left — previous radio in group
|
||||
if (focus->parent && focus->parent->type == WidgetRadioGroupE) {
|
||||
WidgetT *prev = NULL;
|
||||
|
||||
for (WidgetT *s = focus->parent->firstChild; s && s != focus; s = s->nextSibling) {
|
||||
if (s->type == WidgetRadioE && s->visible && s->enabled) {
|
||||
prev = s;
|
||||
}
|
||||
}
|
||||
|
||||
if (prev) {
|
||||
focus->focused = false;
|
||||
prev->focused = true;
|
||||
prev->parent->as.radioGroup.selectedIdx = prev->as.radio.index;
|
||||
|
||||
if (prev->parent->onChange) {
|
||||
prev->parent->onChange(prev->parent);
|
||||
}
|
||||
|
||||
wgtInvalidate(prev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle slider keyboard adjustment
|
||||
if (focus->type == WidgetSliderE) {
|
||||
int32_t step = 1;
|
||||
int32_t range = focus->as.slider.maxValue - focus->as.slider.minValue;
|
||||
|
||||
if (range > 100) {
|
||||
step = range / 100;
|
||||
}
|
||||
|
||||
if (focus->as.slider.vertical) {
|
||||
if (key == (0x48 | 0x100)) {
|
||||
// Up — decrease value
|
||||
focus->as.slider.value -= step;
|
||||
} else if (key == (0x50 | 0x100)) {
|
||||
// Down — increase value
|
||||
focus->as.slider.value += step;
|
||||
} else if (key == (0x47 | 0x100)) {
|
||||
// Home — minimum
|
||||
focus->as.slider.value = focus->as.slider.minValue;
|
||||
} else if (key == (0x4F | 0x100)) {
|
||||
// End — maximum
|
||||
focus->as.slider.value = focus->as.slider.maxValue;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (key == (0x4B | 0x100)) {
|
||||
// Left — decrease value
|
||||
focus->as.slider.value -= step;
|
||||
} else if (key == (0x4D | 0x100)) {
|
||||
// Right — increase value
|
||||
focus->as.slider.value += step;
|
||||
} else if (key == (0x47 | 0x100)) {
|
||||
// Home — minimum
|
||||
focus->as.slider.value = focus->as.slider.minValue;
|
||||
} else if (key == (0x4F | 0x100)) {
|
||||
// End — maximum
|
||||
focus->as.slider.value = focus->as.slider.maxValue;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Clamp
|
||||
if (focus->as.slider.value < focus->as.slider.minValue) {
|
||||
focus->as.slider.value = focus->as.slider.minValue;
|
||||
}
|
||||
|
||||
if (focus->as.slider.value > focus->as.slider.maxValue) {
|
||||
focus->as.slider.value = focus->as.slider.maxValue;
|
||||
}
|
||||
|
||||
if (focus->onChange) {
|
||||
focus->onChange(focus);
|
||||
}
|
||||
|
||||
wgtInvalidate(focus);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle dropdown keyboard navigation
|
||||
if (focus->type == WidgetDropdownE) {
|
||||
if (focus->as.dropdown.open) {
|
||||
|
|
@ -655,14 +829,17 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
|
|||
}
|
||||
|
||||
if (hit->type == WidgetButtonE && hit->enabled) {
|
||||
hit->focused = true;
|
||||
widgetButtonOnMouse(hit);
|
||||
}
|
||||
|
||||
if (hit->type == WidgetCheckboxE && hit->enabled) {
|
||||
hit->focused = true;
|
||||
widgetCheckboxOnMouse(hit);
|
||||
}
|
||||
|
||||
if (hit->type == WidgetRadioE && hit->enabled) {
|
||||
hit->focused = true;
|
||||
widgetRadioOnMouse(hit);
|
||||
}
|
||||
|
||||
|
|
@ -671,6 +848,7 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
|
|||
}
|
||||
|
||||
if (hit->type == WidgetImageButtonE && hit->enabled) {
|
||||
hit->focused = true;
|
||||
widgetImageButtonOnMouse(hit);
|
||||
}
|
||||
|
||||
|
|
@ -695,6 +873,7 @@ void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) {
|
|||
}
|
||||
|
||||
if (hit->type == WidgetSliderE && hit->enabled) {
|
||||
hit->focused = true;
|
||||
widgetSliderOnMouse(hit, vx, vy);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue