From 5c9f2d22c63ada7914cc6351608cdd174dc89996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Kera=CC=88nen?= Date: Mon, 24 Sep 2018 20:10:29 +0300 Subject: [PATCH] Menu|Controls|All Games: Improve control bindings menu layout Wrap bindings on multiple lines per menu item. --- .../include/menu/widgets/cvartogglewidget.h | 6 +- .../include/menu/widgets/inputbindingwidget.h | 12 +- .../common/include/menu/widgets/listwidget.h | 2 + .../common/include/menu/widgets/widget.h | 2 + doomsday/apps/plugins/common/src/m_ctrl.cpp | 8 +- .../apps/plugins/common/src/menu/page.cpp | 21 +- .../src/menu/widgets/cvartogglewidget.cpp | 6 + .../src/menu/widgets/inputbindingwidget.cpp | 370 ++++++++++-------- .../common/src/menu/widgets/listwidget.cpp | 8 + .../common/src/menu/widgets/widget.cpp | 3 + 10 files changed, 258 insertions(+), 180 deletions(-) diff --git a/doomsday/apps/plugins/common/include/menu/widgets/cvartogglewidget.h b/doomsday/apps/plugins/common/include/menu/widgets/cvartogglewidget.h index abb5a9f38c..cb77ea3068 100644 --- a/doomsday/apps/plugins/common/include/menu/widgets/cvartogglewidget.h +++ b/doomsday/apps/plugins/common/include/menu/widgets/cvartogglewidget.h @@ -42,9 +42,9 @@ class CVarToggleWidget : public ButtonWidget CVarToggleWidget(char const *cvarPath, int cvarValueMask = 0, de::String const &downText = "Yes", de::String const &upText = "No"); - virtual ~CVarToggleWidget(); + virtual ~CVarToggleWidget() override; - int handleCommand(menucommand_e command); + int handleCommand(menucommand_e command) override; void setState(State newState); State state() const; @@ -63,6 +63,8 @@ class CVarToggleWidget : public ButtonWidget void setStateChangeCallback(const std::function &stateChanged); + void pageActivated() override; + private: DENG2_PRIVATE(d) }; diff --git a/doomsday/apps/plugins/common/include/menu/widgets/inputbindingwidget.h b/doomsday/apps/plugins/common/include/menu/widgets/inputbindingwidget.h index b4c2b5d1d9..08995a6217 100644 --- a/doomsday/apps/plugins/common/include/menu/widgets/inputbindingwidget.h +++ b/doomsday/apps/plugins/common/include/menu/widgets/inputbindingwidget.h @@ -40,16 +40,18 @@ class InputBindingWidget : public Widget public: InputBindingWidget(); - virtual ~InputBindingWidget(); + virtual ~InputBindingWidget() override; - void draw() const; - void updateGeometry(); - int handleEvent_Privileged(event_t const &event); - int handleCommand(menucommand_e command); + void draw() const override; + void updateGeometry() override; + int handleEvent_Privileged(event_t const &event) override; + int handleCommand(menucommand_e command) override; char const *controlName() const; de::String bindContext() const; + void pageActivated() override; + private: DENG2_PRIVATE(d) }; diff --git a/doomsday/apps/plugins/common/include/menu/widgets/listwidget.h b/doomsday/apps/plugins/common/include/menu/widgets/listwidget.h index 8395a02439..da5e26d2a4 100644 --- a/doomsday/apps/plugins/common/include/menu/widgets/listwidget.h +++ b/doomsday/apps/plugins/common/include/menu/widgets/listwidget.h @@ -123,6 +123,8 @@ class ListWidget : public Widget void updateVisibleSelection(); + void pageActivated() override; + private: DENG2_PRIVATE(d) }; diff --git a/doomsday/apps/plugins/common/include/menu/widgets/widget.h b/doomsday/apps/plugins/common/include/menu/widgets/widget.h index 20aabf18ff..fa8b5c8f53 100644 --- a/doomsday/apps/plugins/common/include/menu/widgets/widget.h +++ b/doomsday/apps/plugins/common/include/menu/widgets/widget.h @@ -235,6 +235,8 @@ class Widget float scrollingFadeout(int yTop, int yBottom) const; de::Vector4f selectionFlashColor(const de::Vector4f &noFlashColor) const; + virtual void pageActivated(); + private: DENG2_PRIVATE(d) }; diff --git a/doomsday/apps/plugins/common/src/m_ctrl.cpp b/doomsday/apps/plugins/common/src/m_ctrl.cpp index 0a9197d542..bc934050ca 100644 --- a/doomsday/apps/plugins/common/src/m_ctrl.cpp +++ b/doomsday/apps/plugins/common/src/m_ctrl.cpp @@ -104,13 +104,13 @@ static controlconfig_t controlConfig[] = #endif #ifdef __JHERETIC__ - { (char const *) TXT_TXT_INV_INVULNERABILITY, 0, 0, "impulse invulnerability", 0 }, + { /* (char const *) TXT_TXT_INV_INVULNERABILITY */ "Invincibility", 0, 0, "impulse invulnerability", 0 }, { (char const *) TXT_TXT_INV_INVISIBILITY, 0, 0, "impulse invisibility", 0 }, { (char const *) TXT_TXT_INV_HEALTH, 0, 0, "impulse health", 0 }, { (char const *) TXT_TXT_INV_SUPERHEALTH, 0, 0, "impulse superhealth", 0 }, { (char const *) TXT_TXT_INV_TOMEOFPOWER, 0, 0, "impulse tome", 0 }, { (char const *) TXT_TXT_INV_TORCH, 0, 0, "impulse torch", 0 }, - { (char const *) TXT_TXT_INV_FIREBOMB, 0, 0, "impulse firebomb", 0 }, + { /* (char const *) TXT_TXT_INV_FIREBOMB */ "Time Bomb", 0, 0, "impulse firebomb", 0 }, { (char const *) TXT_TXT_INV_EGG, 0, 0, "impulse egg", 0 }, { (char const *) TXT_TXT_INV_FLY, 0, 0, "impulse fly", 0 }, { (char const *) TXT_TXT_INV_TELEPORT, 0, 0, "impulse teleport", 0 }, @@ -182,7 +182,7 @@ static controlconfig_t controlConfig[] = { "Smaller View", 0, 0, "sub view-size 1", CCF_REPEAT }, { "Larger View", 0, 0, "add view-size 1", CCF_REPEAT }, - { "Message Refresh", 0, 0, "impulse msgrefresh", 0 }, + { "Msg Refresh", 0, 0, "impulse msgrefresh", 0 }, { "Shortcuts", 0, 0, 0, 0 }, { "Pause Game", 0, 0, "pause", 0 }, @@ -196,7 +196,7 @@ static controlconfig_t controlConfig[] = { "Quick Load", "shortcut", 0, "quickload", 0 }, { "Sound Options", "shortcut", 0, "menu soundoptions", 0 }, { "Toggle Messages", "shortcut", 0, "toggle msg-show", 0 }, - { "Gamma Correction", "shortcut", 0, "togglegamma", 0 }, + { "Gamma Adjust", "shortcut", 0, "togglegamma", 0 }, { "Screenshot", "shortcut", 0, "screenshot", 0 }, { "Quit", "shortcut", 0, "quit", 0 }, diff --git a/doomsday/apps/plugins/common/src/menu/page.cpp b/doomsday/apps/plugins/common/src/menu/page.cpp index aa7c0af8e1..3bad731f36 100644 --- a/doomsday/apps/plugins/common/src/menu/page.cpp +++ b/doomsday/apps/plugins/common/src/menu/page.cpp @@ -714,21 +714,15 @@ void Page::activate() // Reset page timer. d->timer = 0; - if(d->children.isEmpty()) + if (d->children.empty()) + { return; // Presumably the widgets will be added later... + } - // (Re)init widgets. - for(Widget *wi : d->children) + // Notify widgets on the page. + for (Widget *wi : d->children) { - if(CVarToggleWidget *tog = maybeAs(wi)) - { - tog->setFlags(Widget::Active, tog->isDown()? SetFlags : UnsetFlags); - } - if(ListWidget *list = maybeAs(wi)) - { - // Determine number of potentially visible items. - list->updateVisibleSelection(); - } + wi->pageActivated(); } d->refocus(); @@ -742,11 +736,10 @@ void Page::activate() void Page::tick() { // Call the ticker of each child widget. - for(Widget *wi : d->children) + for (Widget *wi : d->children) { wi->tick(); } - d->timer++; } diff --git a/doomsday/apps/plugins/common/src/menu/widgets/cvartogglewidget.cpp b/doomsday/apps/plugins/common/src/menu/widgets/cvartogglewidget.cpp index 8f5a866220..0ecbde35a0 100644 --- a/doomsday/apps/plugins/common/src/menu/widgets/cvartogglewidget.cpp +++ b/doomsday/apps/plugins/common/src/menu/widgets/cvartogglewidget.cpp @@ -179,5 +179,11 @@ void CVarToggleWidget::setStateChangeCallback(const std::function d->stateChangeCallback = stateChanged; } +void CVarToggleWidget::pageActivated() +{ + ButtonWidget::pageActivated(); + setFlags(Active, isDown()? SetFlags : UnsetFlags); +} + } // namespace menu } // namespace common diff --git a/doomsday/apps/plugins/common/src/menu/widgets/inputbindingwidget.cpp b/doomsday/apps/plugins/common/src/menu/widgets/inputbindingwidget.cpp index eec86c9caf..da8b6bb368 100644 --- a/doomsday/apps/plugins/common/src/menu/widgets/inputbindingwidget.cpp +++ b/doomsday/apps/plugins/common/src/menu/widgets/inputbindingwidget.cpp @@ -26,6 +26,9 @@ #include "m_ctrl.h" // controlconfig_t, etc.. #include "menu/page.h" // mnRendState +#include +#include + using namespace de; namespace common { @@ -60,8 +63,29 @@ static char const *findInString(char const *str, char const *token, int n) return 0; } +static void drawSmallText(char const *string, int x, int y, float alpha) +{ + int height = FR_TextHeight(string); + + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); + + DGL_Translatef(x, y + height/2, 0); + DGL_Scalef(SMALL_SCALE, SMALL_SCALE, 1); + DGL_Translatef(-x, -y - height/2, 0); + + FR_SetColorAndAlpha(1, 1, 1, alpha); + FR_DrawTextXY3(string, x, y, ALIGN_TOPLEFT, DTF_NO_EFFECTS); + + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); +} + DENG2_PIMPL(InputBindingWidget) { + bool needGeometry = true; ///< Recalculate geometry based on bindings. + const int maxWidth = SCREENWIDTH * 55 / 100; + Impl(Public *i) : Base(i) {} @@ -69,37 +93,41 @@ DENG2_PIMPL(InputBindingWidget) int flags, const std::function< void(bindingitertype_t type, int bid, char const *ev, dd_bool isInverse)> - &callback) + &callback) const { + // Bindings are collected to this map so they're iterated in order. + std::map>> bindings; + const controlconfig_t *binds = self().binds; - DENG2_ASSERT(binds != 0); + DENG2_ASSERT(binds != nullptr); - char bindings[1024]; + char bindingsBuf[1024]; if (binds->controlName) { - B_BindingsForControl(0, binds->controlName, BFCI_BOTH, bindings, sizeof(bindings)); + B_BindingsForControl( + 0, binds->controlName, BFCI_BOTH, bindingsBuf, sizeof(bindingsBuf)); } else { - B_BindingsForCommand(binds->command, bindings, sizeof(bindings)); + B_BindingsForCommand(binds->command, bindingsBuf, sizeof(bindingsBuf)); } - char const *ptr = strchr(bindings, ':'); - char const *begin, *end, *end2, *k, *bindingStart, *bindingEnd; + const char *ptr = strchr(bindingsBuf, ':'); + const char *begin, *end, *end2, *k, *bindingStart, *bindingEnd; char buf[80], *b; dd_bool isInverse; int bid; std::memset(buf, 0, sizeof(buf)); - while(ptr) + while (ptr) { // Read the binding identifier. - for(k = ptr; k > bindings && *k != '@'; --k); + for (k = ptr; k > bindingsBuf && *k != '@'; --k) {;} - if(*k == '@') + if (*k == '@') { - for(begin = k - 1; begin > bindings && isdigit(*(begin - 1)); --begin) {} + for (begin = k - 1; begin > bindingsBuf && isdigit(*(begin - 1)); --begin) {;} bid = strtol(begin, NULL, 10); } else @@ -110,8 +138,8 @@ DENG2_PIMPL(InputBindingWidget) // Find the end of the entire binding. bindingStart = k + 1; - bindingEnd = strchr(bindingStart, '@'); - if(!bindingEnd) + bindingEnd = strchr(bindingStart, '@'); + if (!bindingEnd) { // Then point to the end of the string. bindingEnd = strchr(k + 1, 0); @@ -119,65 +147,185 @@ DENG2_PIMPL(InputBindingWidget) ptr++; end = strchr(ptr, '-'); - if(!end) - return; + if (!end) return; end++; b = buf; - while(*end && *end != ' ' && *end != '-' && *end != '+') + while (*end && *end != ' ' && *end != '-' && *end != '+') { *b++ = *end++; } *b = 0; end2 = strchr(end, ' '); - if(!end2) + if (!end2) + { end = end + strlen(end); // Then point to the end. + } else + { end = end2; + } - if(!findInString(bindingStart, "modifier-1-down", bindingEnd - bindingStart) && - (!(flags & MIBF_IGNORE_REPEATS) || !findInString(ptr, "-repeat", end - ptr))) + if (!findInString(bindingStart, "modifier-1-down", bindingEnd - bindingStart) && + (!(flags & MIBF_IGNORE_REPEATS) || !findInString(ptr, "-repeat", end - ptr))) { isInverse = (findInString(ptr, "-inverse", end - ptr) != NULL); - if(!strncmp(ptr, "key", 3) || - !strncmp(ptr, "joy-button", 10) || - !strncmp(ptr, "mouse-left", 10) || - !strncmp(ptr, "mouse-middle", 12) || - !strncmp(ptr, "mouse-right", 11)) + if (!strncmp(ptr, "key", 3) || !strncmp(ptr, "joy-button", 10) || + !strncmp(ptr, "mouse-left", 10) || !strncmp(ptr, "mouse-middle", 12) || + !strncmp(ptr, "mouse-right", 11)) { - if(((binds->flags & CCF_INVERSE) && isInverse) || - ((binds->flags & CCF_NON_INVERSE) && !isInverse) || - !(binds->flags & (CCF_INVERSE | CCF_NON_INVERSE))) + if (((binds->flags & CCF_INVERSE) && isInverse) || + ((binds->flags & CCF_NON_INVERSE) && !isInverse) || + !(binds->flags & (CCF_INVERSE | CCF_NON_INVERSE))) { - callback(!strncmp(ptr, "key", 3)? MIBT_KEY : - !strncmp(ptr, "mouse", 5)? MIBT_MOUSE : MIBT_JOY, bid, buf, - isInverse); + bindings[!strncmp(ptr, "key", 3) + ? MIBT_KEY + : !strncmp(ptr, "mouse", 5) ? MIBT_MOUSE : MIBT_JOY] + .emplace_back(bid, buf, isInverse); } } else { - if(!(binds->flags & (CCF_INVERSE | CCF_NON_INVERSE)) || (binds->flags & CCF_INVERSE)) + if (!(binds->flags & (CCF_INVERSE | CCF_NON_INVERSE)) || + (binds->flags & CCF_INVERSE)) { isInverse = !isInverse; } - if(!strncmp(ptr, "joy", 3)) + if (!strncmp(ptr, "joy", 3)) { - callback(MIBT_JOY, bid, buf, isInverse); + bindings[MIBT_JOY].emplace_back(bid, buf, isInverse); } - else if(!strncmp(ptr, "mouse", 5)) + else if (!strncmp(ptr, "mouse", 5)) { - callback(MIBT_MOUSE, bid, buf, isInverse); + bindings[MIBT_MOUSE].emplace_back(bid, buf, isInverse); } } } ptr = end; - while(*ptr == ' ') { ptr++; } - + while (*ptr == ' ') + { + ptr++; + } ptr = strchr(ptr, ':'); } + + for (auto iterType = bindings.begin(); iterType != bindings.end(); ++iterType) + { + for (const auto &bind : iterType->second) + { + callback(iterType->first, + std::get<0>(bind), + std::get<1>(bind).c_str(), + std::get<2>(bind)); + } + } + } + + Vector2ui measureAndDraw(bool drawing = true) const + { + const auto widgetTopLeft = self().geometry().topLeft; + + struct { + bool drawing; + float alpha; + Vector2i widgetTopLeft; + Vector2i origin; + Vector2i size; + } ctx = {drawing, + mnRendState->pageAlpha * self().scrollingFadeout(), + widgetTopLeft, + {0, 0}, + {0, 0}}; + + if (drawing) + { + if (ctx.alpha < .001f) return {}; + } + + iterateBindings( + MIBF_IGNORE_REPEATS, + [this, &ctx](bindingitertype_t type, int /*bid*/, const char *name, dd_bool isInverse) { + static const int BIND_GAP = 2; +#if __JHERETIC__ + static float const bgRGB[] = {0, .5f, 0}; +#elif __JHEXEN__ + static float const bgRGB[] = {.5f, 0, 0}; +#else + static float const bgRGB[] = {0, 0, 0}; +#endif + FR_SetFont(FID(GF_FONTA)); + const int lineHeight = FR_TextHeight("W"); + + if (type == MIBT_KEY) + { + const int width = FR_TextWidth(name) * SMALL_SCALE; + + if (ctx.origin.x + width > maxWidth) + { + ctx.origin.x = 0; + ctx.origin.y += lineHeight + 1; + } + + if (ctx.drawing) + { + DGL_SetNoMaterial(); + DGL_DrawRectf2Color(ctx.widgetTopLeft.x + ctx.origin.x, + ctx.widgetTopLeft.y + ctx.origin.y, + width + 2, + lineHeight, + bgRGB[0], + bgRGB[1], + bgRGB[2], + ctx.alpha * .6f); + + DGL_Enable(DGL_TEXTURE_2D); + drawSmallText(name, + ctx.widgetTopLeft.x + ctx.origin.x + 1, + ctx.widgetTopLeft.y + ctx.origin.y, + ctx.alpha); + DGL_Disable(DGL_TEXTURE_2D); + } + + ctx.origin.x += width + 2 + BIND_GAP; + } + else + { + char buf[256]; + sprintf(buf, + "%s%c%s", + type == MIBT_MOUSE ? "mouse" : "joy", + isInverse ? '-' : '+', + name); + + int const width = FR_TextWidth(buf) * SMALL_SCALE; + + if (ctx.origin.x + width > maxWidth) + { + ctx.origin.x = 0; + ctx.origin.y += lineHeight + 1; + } + + if (ctx.drawing) + { + DGL_Enable(DGL_TEXTURE_2D); + drawSmallText(buf, + ctx.widgetTopLeft.x + ctx.origin.x, + ctx.widgetTopLeft.y + ctx.origin.y, + ctx.alpha); + DGL_Disable(DGL_TEXTURE_2D); + } + + ctx.origin.x += width + BIND_GAP; + } + + // Update dimensions as we go. + ctx.size = ctx.size.max({ctx.origin.x, ctx.origin.y + lineHeight}); + }); + + return (ctx.size).toVector2ui(); } }; @@ -193,122 +341,28 @@ InputBindingWidget::InputBindingWidget() InputBindingWidget::~InputBindingWidget() {} -static void drawSmallText(char const *string, int x, int y, float alpha) -{ - int height = FR_TextHeight(string); - - DGL_MatrixMode(DGL_MODELVIEW); - DGL_PushMatrix(); - - DGL_Translatef(x, y + height/2, 0); - DGL_Scalef(SMALL_SCALE, SMALL_SCALE, 1); - DGL_Translatef(-x, -y - height/2, 0); - - FR_SetColorAndAlpha(1, 1, 1, alpha); - FR_DrawTextXY3(string, x, y, ALIGN_TOPLEFT, DTF_NO_EFFECTS); - - DGL_MatrixMode(DGL_MODELVIEW); - DGL_PopMatrix(); -} - void InputBindingWidget::draw() const { - struct { - Point2Raw origin; - float alpha; - } draw = {{geometry().topLeft.x, geometry().topLeft.y}, - mnRendState->pageAlpha * scrollingFadeout()}; - - if (draw.alpha < .001f) return; - - d->iterateBindings(MIBF_IGNORE_REPEATS, - [&draw](bindingitertype_t type, - int /*bid*/, - const char *name, - dd_bool isInverse) { - static const int BIND_GAP = 2; -#if __JHERETIC__ - static float const bgRGB[] = {0, .5f, 0}; -#elif __JHEXEN__ - static float const bgRGB[] = {.5f, 0, 0}; -#else - static float const bgRGB[] = {0, 0, 0}; -#endif - - auto *d = &draw; - - FR_SetFont(FID(GF_FONTA)); - - if (type == MIBT_KEY) - { - int const width = FR_TextWidth(name); - int const height = FR_TextHeight(name); - - DGL_SetNoMaterial(); - DGL_DrawRectf2Color(d->origin.x, - d->origin.y, - width * SMALL_SCALE + 2, - height, - bgRGB[0], - bgRGB[1], - bgRGB[2], - d->alpha * .6f); - - DGL_Enable(DGL_TEXTURE_2D); - drawSmallText(name, d->origin.x + 1, d->origin.y, d->alpha); - DGL_Disable(DGL_TEXTURE_2D); - - d->origin.x += width * SMALL_SCALE + 2 + BIND_GAP; - } - else - { - char buf[256]; - sprintf(buf, - "%s%c%s", - type == MIBT_MOUSE ? "mouse" : "joy", - isInverse ? '-' : '+', - name); - - int const width = FR_TextWidth(buf); - ///int const height = FR_TextHeight(temp); - - DGL_Enable(DGL_TEXTURE_2D); - drawSmallText(buf, d->origin.x, d->origin.y, d->alpha); - DGL_Disable(DGL_TEXTURE_2D); - - d->origin.x += width * SMALL_SCALE + BIND_GAP; - } - }); + d->measureAndDraw(true); } int InputBindingWidget::handleCommand(menucommand_e cmd) { switch(cmd) { - case MCMD_DELETE: { -// char buf[1024]; - + case MCMD_DELETE: S_LocalSound(SFX_MENU_CANCEL, NULL); - /*if (binds->controlName) - { - B_BindingsForControl(0, binds->controlName, BFCI_BOTH, buf, sizeof(buf)); - } - else - { - B_BindingsForCommand(binds->command, buf, sizeof(buf)); - }*/ - d->iterateBindings(0, [](bindingitertype_t, int bid, const char *, dd_bool) { DD_Executef(true, "delbind %i", bid); }); - + d->needGeometry = true; // If deleting the menuselect binding, automatically rebind it Return; // otherwise the user would be stuck without a way to make further bindings. if (binds->command && !strcmp(binds->command, "menuselect")) { DD_Execute(true, "bindevent menu:key-return menuselect"); } - return true; } + return true; case MCMD_SELECT: S_LocalSound(SFX_MENU_CYCLE, NULL); @@ -328,10 +382,12 @@ int InputBindingWidget::handleCommand(menucommand_e cmd) void InputBindingWidget::updateGeometry() { - // @todo calculate visible dimensions properly! - - - geometry().setSize(Vector2ui(SCREENWIDTH * 5 / 10, 10 * SMALL_SCALE)); + if (d->needGeometry) + { + d->needGeometry = false; + geometry().setSize(d->measureAndDraw(false /* just measure */)); + geometry().setWidth(d->maxWidth); + } } /** @@ -359,11 +415,11 @@ int InputBindingWidget::handleEvent_Privileged(event_t const &event) LOG_AS("InputBindingWidget"); // Only handle events when active. - if(!isActive()) return false; + if (!isActive()) return false; // We're only interested in events with an echoed, symbolic descriptor. String symbol = symbolicDescriptor(event); - if(symbol.isEmpty()) return false; + if (symbol.isEmpty()) return false; // We're only interested in button down events. if((symbol.beginsWith("key-") || @@ -385,7 +441,7 @@ int InputBindingWidget::handleEvent_Privileged(event_t const &event) } String cmd; - if(binds->command) + if (binds->command) { cmd = String("bindevent {%1:%2%3} {%4}") .arg(context) @@ -394,7 +450,7 @@ int InputBindingWidget::handleEvent_Privileged(event_t const &event) .arg(binds->command); // Check for repeats. - if((binds->flags & CCF_REPEAT) && symbol.endsWith("-down")) + if ((binds->flags & CCF_REPEAT) && symbol.endsWith("-down")) { cmd += String("; bindevent {%1:%2-repeat} {%3}") .arg(context) @@ -402,27 +458,25 @@ int InputBindingWidget::handleEvent_Privileged(event_t const &event) .arg(binds->command); } } - else if(binds->controlName) + else if (binds->controlName) { String stateFlags; // Extract the symbolic key/button name (exclude the state part). int const endOfName = symbol.indexOf('-', symbol.indexOf('-') + 1); - if(endOfName < 0) + if (endOfName < 0) { throw Error("InputBindingWidget::handleEvent_Privileged", "Invalid symbol:" + symbol); } String const name = symbol.left(endOfName); // Staged? - if(binds->flags & CCF_STAGED) + if (binds->flags & CCF_STAGED) { // Staging is buttons. - if(name.beginsWith("key-") || - name.beginsWith("joy-button") || - name.beginsWith("mouse-left") || - name.beginsWith("mouse-middle") || - name.beginsWith("mouse-right")) + if (name.beginsWith("key-") || name.beginsWith("joy-button") || + name.beginsWith("mouse-left") || name.beginsWith("mouse-middle") || + name.beginsWith("mouse-right")) { stateFlags += "-staged"; } @@ -430,11 +484,11 @@ int InputBindingWidget::handleEvent_Privileged(event_t const &event) // Inverted? bool inv = (binds->flags & CCF_INVERSE) != 0; - if(symbol.substr(endOfName).beginsWith("-neg")) + if (symbol.substr(endOfName).beginsWith("-neg")) { inv = !inv; } - if(inv) + if (inv) { stateFlags += "-inverse"; } @@ -460,6 +514,7 @@ int InputBindingWidget::handleEvent_Privileged(event_t const &event) setFlags(Active, UnsetFlags); DD_SetInteger(DD_SYMBOLIC_ECHO, false); S_LocalSound(SFX_MENU_ACCEPT, nullptr); + d->needGeometry = true; return true; } @@ -467,7 +522,7 @@ char const *InputBindingWidget::controlName() const { DENG2_ASSERT(binds); // Map to a text definition? - if(PTR2INT(binds->text) > 0 && PTR2INT(binds->text) < NUMTEXT) + if (PTR2INT(binds->text) > 0 && PTR2INT(binds->text) < NUMTEXT) { return GET_TXT(PTR2INT(binds->text)); } @@ -477,7 +532,12 @@ char const *InputBindingWidget::controlName() const String InputBindingWidget::bindContext() const { DENG2_ASSERT(binds); - return (binds->bindContext? binds->bindContext : "game"); + return (binds->bindContext ? binds->bindContext : "game"); +} + +void InputBindingWidget::pageActivated() +{ + d->needGeometry = true; } } // namespace menu diff --git a/doomsday/apps/plugins/common/src/menu/widgets/listwidget.cpp b/doomsday/apps/plugins/common/src/menu/widgets/listwidget.cpp index 5f648e85a5..0bafe5a64d 100644 --- a/doomsday/apps/plugins/common/src/menu/widgets/listwidget.cpp +++ b/doomsday/apps/plugins/common/src/menu/widgets/listwidget.cpp @@ -266,6 +266,14 @@ void ListWidget::updateVisibleSelection() } } +void ListWidget::pageActivated() +{ + Widget::pageActivated(); + + // Determine number of potentially visible items. + updateVisibleSelection(); +} + int ListWidget::itemData(int index) const { if (index >= 0 && index < itemCount()) diff --git a/doomsday/apps/plugins/common/src/menu/widgets/widget.cpp b/doomsday/apps/plugins/common/src/menu/widgets/widget.cpp index 6af3a44d80..5ef1bd00d4 100644 --- a/doomsday/apps/plugins/common/src/menu/widgets/widget.cpp +++ b/doomsday/apps/plugins/common/src/menu/widgets/widget.cpp @@ -340,5 +340,8 @@ Vector4f Widget::selectionFlashColor(const Vector4f &noFlashColor) const return noFlashColor; } +void Widget::pageActivated() +{} + } // namespace menu } // namespace common