diff --git a/doomsday/plugins/common/common.pri b/doomsday/plugins/common/common.pri index fa2f7b4e4b..369e781849 100644 --- a/doomsday/plugins/common/common.pri +++ b/doomsday/plugins/common/common.pri @@ -78,6 +78,7 @@ HEADERS += \ $$common_inc/menu/widgets/cvarinlinelistwidget.h \ $$common_inc/menu/widgets/cvarlineeditwidget.h \ $$common_inc/menu/widgets/cvarsliderwidget.h \ + $$common_inc/menu/widgets/cvartextualsliderwidget.h \ $$common_inc/menu/widgets/cvartogglewidget.h \ $$common_inc/menu/widgets/inlinelistwidget.h \ $$common_inc/menu/widgets/inputbindingwidget.h \ @@ -87,7 +88,6 @@ HEADERS += \ $$common_inc/menu/widgets/mobjpreviewwidget.h \ $$common_inc/menu/widgets/rectwidget.h \ $$common_inc/menu/widgets/sliderwidget.h \ - $$common_inc/menu/widgets/textualsliderwidget.h \ $$common_inc/menu/widgets/widget.h SOURCES += \ @@ -158,6 +158,7 @@ SOURCES += \ $$common_src/menu/widgets/cvarinlinelistwidget.cpp \ $$common_src/menu/widgets/cvarlineeditwidget.cpp \ $$common_src/menu/widgets/cvarsliderwidget.cpp \ + $$common_src/menu/widgets/cvartextualsliderwidget.cpp \ $$common_src/menu/widgets/cvartogglewidget.cpp \ $$common_src/menu/widgets/buttonwidget.cpp \ $$common_src/menu/widgets/inlinelistwidget.cpp \ @@ -168,5 +169,4 @@ SOURCES += \ $$common_src/menu/widgets/mobjpreviewwidget.cpp \ $$common_src/menu/widgets/rectwidget.cpp \ $$common_src/menu/widgets/sliderwidget.cpp \ - $$common_src/menu/widgets/textualsliderwidget.cpp \ $$common_src/menu/widgets/widget.cpp diff --git a/doomsday/plugins/common/include/menu/widgets/textualsliderwidget.h b/doomsday/plugins/common/include/menu/widgets/cvartextualsliderwidget.h similarity index 58% rename from doomsday/plugins/common/include/menu/widgets/textualsliderwidget.h rename to doomsday/plugins/common/include/menu/widgets/cvartextualsliderwidget.h index 1fc162134b..99e8761369 100644 --- a/doomsday/plugins/common/include/menu/widgets/textualsliderwidget.h +++ b/doomsday/plugins/common/include/menu/widgets/cvartextualsliderwidget.h @@ -1,4 +1,4 @@ -/** @file textualsliderwidget.h UI widget for a textual slider. +/** @file cvartextualsliderwidget.h UI widget for a textual slider. * * @authors Copyright © 2005-2014 Jaakko Keränen * @authors Copyright © 2005-2014 Daniel Swanson @@ -18,36 +18,37 @@ * 02110-1301 USA */ -#ifndef LIBCOMMON_UI_TEXTUALSLIDERWIDGET -#define LIBCOMMON_UI_TEXTUALSLIDERWIDGET +#ifndef LIBCOMMON_UI_CVARTEXTUALSLIDERWIDGET +#define LIBCOMMON_UI_CVARTEXTUALSLIDERWIDGET -#include "sliderwidget.h" +#include "cvarsliderwidget.h" namespace common { namespace menu { /** - * UI widget for manipulating a value with a textual slider. + * UI widget for manipulating a console variable with a textual slider. * * @ingroup menu */ -struct TextualSliderWidget : public SliderWidget +struct CVarTextualSliderWidget : public CVarSliderWidget { public: - TextualSliderWidget(float min = 0.0f, float max = 1.0f, float step = 0.1f, bool floatMode = true); - virtual ~TextualSliderWidget(); + CVarTextualSliderWidget(char const *cvarPath, float min = 0.0f, float max = 1.0f, + float step = 0.1f, bool floatMode = true); + virtual ~CVarTextualSliderWidget(); void draw(Point2Raw const *origin); void updateGeometry(Page *pagePtr); - void setEmptyText(char const *newEmptyText); - char const *emptyText() const; + void setEmptyText(de::String const &newEmptyText); + de::String emptyText() const; - void setOnethSuffix(char const *newOnethSuffix); - char const *onethSuffix() const; + void setOnethSuffix(de::String const &newOnethSuffix); + de::String onethSuffix() const; - void setNthSuffix(char const *newNthSuffix); - char const *nthSuffix() const; + void setNthSuffix(de::String const &newNthSuffix); + de::String nthSuffix() const; private: DENG2_PRIVATE(d) @@ -56,4 +57,4 @@ struct TextualSliderWidget : public SliderWidget } // namespace menu } // namespace common -#endif // LIBCOMMON_UI_TEXTUALSLIDERWIDGET +#endif // LIBCOMMON_UI_CVARTEXTUALSLIDERWIDGET diff --git a/doomsday/plugins/common/src/hu_menu.cpp b/doomsday/plugins/common/src/hu_menu.cpp index e392c80798..5258642fea 100644 --- a/doomsday/plugins/common/src/hu_menu.cpp +++ b/doomsday/plugins/common/src/hu_menu.cpp @@ -51,13 +51,13 @@ #include "menu/widgets/cvarinlinelistwidget.h" #include "menu/widgets/cvarlineeditwidget.h" #include "menu/widgets/cvarsliderwidget.h" +#include "menu/widgets/cvartextualsliderwidget.h" #include "menu/widgets/cvartogglewidget.h" #include "menu/widgets/inputbindingwidget.h" #include "menu/widgets/labelwidget.h" #include "menu/widgets/mobjpreviewwidget.h" #include "menu/widgets/rectwidget.h" #include "menu/widgets/sliderwidget.h" -#include "menu/widgets/textualsliderwidget.h" using namespace de; @@ -1474,11 +1474,10 @@ void Hu_MenuInitHUDOptionsPage() page->widgets() << new LabelWidget("AutoHide"); { - auto *sld = new TextualSliderWidget(0, 60, 1); + auto *sld = new CVarTextualSliderWidget("hud-timer", 0, 60, 1); sld->setEmptyText("Disabled"); sld->setOnethSuffix(" second"); sld->setNthSuffix(" seconds"); - sld->data1 = (void *)"hud-timer"; page->widgets() << sld; } @@ -1599,12 +1598,11 @@ void Hu_MenuInitHUDOptionsPage() page->widgets() << text; } { - auto *sld = new TextualSliderWidget(0, 60, 1); + auto *sld = new CVarTextualSliderWidget("msg-uptime", 0, 60, 1); sld->setEmptyText("Disabled"); sld->setOnethSuffix(" second"); sld->setNthSuffix(" seconds"); sld->setGroup(2); - sld->data1 = (void *)"msg-uptime"; page->widgets() << sld; } { @@ -2337,12 +2335,11 @@ void Hu_MenuInitInventoryOptionsPage() page->widgets() << new LabelWidget("AutoHide"); { - auto *sld = new TextualSliderWidget(0, 30, 1.f); + auto *sld = new CVarTextualSliderWidget("hud-inventory-timer", 0, 30, 1.f); sld->setEmptyText("Disabled"); sld->setOnethSuffix(" second"); sld->setNthSuffix(" seconds"); sld->setShortcut('h'); - sld->data1 = (void *)"hud-inventory-timer"; page->widgets() << sld; } @@ -2358,11 +2355,10 @@ void Hu_MenuInitInventoryOptionsPage() page->widgets() << text; } { - auto *sld = new TextualSliderWidget(0, 16, 1, false); + auto *sld = new CVarTextualSliderWidget("hud-inventory-slot-max", 0, 16, 1, false); sld->setGroup(1); sld->setShortcut('v'); sld->setEmptyText("Automatic"); - sld->data1 = (void *)"hud-inventory-slot-max"; page->widgets() << sld; } { diff --git a/doomsday/plugins/common/src/menu/page.cpp b/doomsday/plugins/common/src/menu/page.cpp index 60e524560e..360b7ef510 100644 --- a/doomsday/plugins/common/src/menu/page.cpp +++ b/doomsday/plugins/common/src/menu/page.cpp @@ -28,12 +28,12 @@ #include "menu/widgets/cvarinlinelistwidget.h" #include "menu/widgets/cvarlineeditwidget.h" #include "menu/widgets/cvarsliderwidget.h" +#include "menu/widgets/cvartextualsliderwidget.h" #include "menu/widgets/colorpreviewwidget.h" #include "menu/widgets/inlinelistwidget.h" #include "menu/widgets/inputbindingwidget.h" #include "menu/widgets/labelwidget.h" #include "menu/widgets/mobjpreviewwidget.h" -#include "menu/widgets/textualsliderwidget.h" using namespace de; @@ -272,7 +272,7 @@ void Page::applyLayout() nextWi->is() || nextWi->is() || nextWi->is() || - nextWi->is())) + nextWi->is())) { int const margin = lineOffset * 2; diff --git a/doomsday/plugins/common/src/menu/widgets/cvartextualsliderwidget.cpp b/doomsday/plugins/common/src/menu/widgets/cvartextualsliderwidget.cpp new file mode 100644 index 0000000000..8712f54db6 --- /dev/null +++ b/doomsday/plugins/common/src/menu/widgets/cvartextualsliderwidget.cpp @@ -0,0 +1,200 @@ +/** @file cvartextualsliderwidget.cpp UI widget for a textual slider. + * + * @authors Copyright © 2005-2014 Jaakko Keränen + * @authors Copyright © 2005-2014 Daniel Swanson + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include "common.h" +#include "menu/widgets/cvartextualsliderwidget.h" + +#include "hu_menu.h" // Hu_MenuMergeEffectWithDrawTextFlags +#include "menu/page.h" // mnRendState + +using namespace de; + +namespace common { +namespace menu { + +DENG2_PIMPL(CVarTextualSliderWidget) +{ + //String templateString; + String onethSuffix; + String nthSuffix; + String emptyText; + + Instance(Public *i) : Base(i) {} + + inline bool valueIsOne(float value) + { + if(self.floatMode()) + { + return INRANGE_OF(1, value, .0001f); + } + return (value > 0 && 1 == int(value + .5f)); + } + + String chooseSuffix(float value) + { + if(!onethSuffix.isEmpty() && valueIsOne(value)) + { + return onethSuffix; + } + if(!nthSuffix.isEmpty()) + { + return nthSuffix; + } + return ""; + } + + String composeTextualValue(float value, int precision = 0) + { + if(self.floatMode() && !valueIsOne(value)) + { + return String::number(value, 'f', de::max(0, precision)); + } + else + { + return String::number(int(value)); + } + } + + String valueAsText(float emptyValue = 0, int precision = 0) + { + float const value = de::clamp(self.min(), self.value(), self.max()); /// @todo clamp necessary? + + // Is the empty-value-string in use? + if(!emptyText.isEmpty() && INRANGE_OF(value, emptyValue, .0001f)) + { + return emptyText; + } + + String const suffix = chooseSuffix(value); + String const valueAsText = composeTextualValue(value, precision); + +#if 0 + // Are we substituting the textual value into a template? + if(!templateString.isEmpty()) + { + // Reserve a conservative amount of storage, we assume the caller + // knows best and take the value given as the output buffer size. + AutoStr *compStr = AutoStr_NewStd(); + Str_Reserve(compStr, bufSize); + + // Composite the final string. + char const *c; + char *beginSubstring = templateString; + for(c = beginSubstring; *c; c++) + { + if(c[0] == '%' && c[1] == '1') + { + Str_PartAppend(compStr, beginSubstring, 0, c - beginSubstring); + Str_Appendf(compStr, "%s%s", textualValue, suffix); + // Next substring will begin from here. + beginSubstring = c + 2; + c += 1; + } + } + // Anything remaining? + if(beginSubstring != c) + Str_Append(compStr, beginSubstring); + + return String(Str_Text(compStr)); + } + else +#endif + { + return valueAsText + suffix; + } + } +}; + +CVarTextualSliderWidget::CVarTextualSliderWidget(char const *cvarPath, float min, float max, + float step, bool floatMode) + : CVarSliderWidget(cvarPath, min, max, step, floatMode) + , d(new Instance(this)) +{ + Widget::_pageColorIdx = MENU_COLOR3; +} + +CVarTextualSliderWidget::~CVarTextualSliderWidget() +{} + +void CVarTextualSliderWidget::draw(Point2Raw const *origin) +{ + DENG2_ASSERT(origin != 0); + + String const valueAsText = d->valueAsText(); + + DGL_MatrixMode(DGL_MODELVIEW); + DGL_Translatef(origin->x, origin->y, 0); + + DGL_Enable(DGL_TEXTURE_2D); + + FR_SetFont(mnRendState->textFonts[_pageFontIdx]); + FR_SetColorAndAlphav(mnRendState->textColors[_pageColorIdx]); + FR_DrawTextXY3(valueAsText.toUtf8().constData(), 0, 0, ALIGN_TOPLEFT, Hu_MenuMergeEffectWithDrawTextFlags(0)); + + DGL_Disable(DGL_TEXTURE_2D); + + DGL_MatrixMode(DGL_MODELVIEW); + DGL_Translatef(-origin->x, -origin->y, 0); +} + +void CVarTextualSliderWidget::updateGeometry(Page *page) +{ + DENG2_ASSERT(page != 0); + + String const valueAsText = d->valueAsText(); + + FR_SetFont(page->predefinedFont(mn_page_fontid_t(_pageFontIdx))); + Size2Raw size; FR_TextSize(&size, valueAsText.toUtf8().constData()); + + Rect_SetWidthHeight(_geometry, size.width, size.height); +} + +void CVarTextualSliderWidget::setEmptyText(String const &newEmptyText) +{ + d->emptyText = newEmptyText; +} + +String CVarTextualSliderWidget::emptyText() const +{ + return d->emptyText; +} + +void CVarTextualSliderWidget::setOnethSuffix(String const &newOnethSuffix) +{ + d->onethSuffix = newOnethSuffix; +} + +String CVarTextualSliderWidget::onethSuffix() const +{ + return d->onethSuffix; +} + +void CVarTextualSliderWidget::setNthSuffix(String const &newNthSuffix) +{ + d->nthSuffix = newNthSuffix; +} + +String CVarTextualSliderWidget::nthSuffix() const +{ + return d->nthSuffix; +} + +} // namespace menu +} // namespace common diff --git a/doomsday/plugins/common/src/menu/widgets/textualsliderwidget.cpp b/doomsday/plugins/common/src/menu/widgets/textualsliderwidget.cpp deleted file mode 100644 index 3c7953d798..0000000000 --- a/doomsday/plugins/common/src/menu/widgets/textualsliderwidget.cpp +++ /dev/null @@ -1,230 +0,0 @@ -/** @file textualsliderwidget.cpp UI widget for a textual slider. - * - * @authors Copyright © 2005-2014 Jaakko Keränen - * @authors Copyright © 2005-2014 Daniel Swanson - * - * @par License - * GPL: http://www.gnu.org/licenses/gpl.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. This program is distributed in the hope that it - * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the GNU - * General Public License along with this program; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include "common.h" -#include "menu/widgets/textualsliderwidget.h" - -#include "hu_menu.h" // Hu_MenuMergeEffectWithDrawTextFlags -#include "menu/page.h" // mnRendState - -/// @todo remove me -#include "menu/widgets/cvarsliderwidget.h" // CVarSliderWidget_UpdateCVar - -using namespace de; - -namespace common { -namespace menu { - -DENG2_PIMPL(TextualSliderWidget) -{ - void *data1 = nullptr; - //char const *templateString = nullptr; - char const *onethSuffix = nullptr; - char const *nthSuffix = nullptr; - char const *emptyText = nullptr; - - Instance(Public *i) : Base(i) {} - - inline bool valueIsOne(float value) - { - if(self.floatMode()) - { - return INRANGE_OF(1, value, .0001f); - } - return (value > 0 && 1 == int(value + .5f)); - } - - char *composeTextualValue(float value, int precision, size_t bufSize, char *buf) - { - DENG2_ASSERT(0 != bufSize && buf); - precision = de::max(0, precision); - if(self.floatMode() && !valueIsOne(value)) - { - dd_snprintf(buf, bufSize, "%.*f", precision, value); - } - else - { - dd_snprintf(buf, bufSize, "%.*i", precision, int(value)); - } - return buf; - } - - char *composeValueString(float value, float defaultValue, int precision, - size_t bufSize, char *buf) - { - DENG2_ASSERT(0 != bufSize && buf); - - //dd_bool const haveTemplateString = (templateString && templateString[0]); - bool const haveOnethSuffix = (onethSuffix && onethSuffix[0]); - bool const haveNthSuffix = (nthSuffix && nthSuffix[0]); - bool const haveEmptyText = (emptyText && emptyText[0]); - char const *suffix = 0; - char textualValue[11]; - - // Is the default-value-string in use? - if(haveEmptyText && INRANGE_OF(value, defaultValue, .0001f)) - { - strncpy(buf, emptyText, bufSize); - buf[bufSize] = '\0'; - return buf; - } - - composeTextualValue(value, precision, 10, textualValue); - - // Choose a suffix. - if(haveOnethSuffix && valueIsOne(value)) - { - suffix = onethSuffix; - } - else if(haveNthSuffix) - { - suffix = nthSuffix; - } - else - { - suffix = ""; - } - -#if 0 - // Are we substituting the textual value into a template? - if(haveTemplateString) - { - char const *c, *beginSubstring = 0; - ddstring_t compStr; - - // Reserve a conservative amount of storage, we assume the caller - // knows best and take the value given as the output buffer size. - Str_Init(&compStr); - Str_Reserve(&compStr, bufSize); - - // Composite the final string. - beginSubstring = templateString; - for(c = beginSubstring; *c; c++) - { - if(c[0] == '%' && c[1] == '1') - { - Str_PartAppend(&compStr, beginSubstring, 0, c - beginSubstring); - Str_Appendf(&compStr, "%s%s", textualValue, suffix); - // Next substring will begin from here. - beginSubstring = c + 2; - c += 1; - } - } - // Anything remaining? - if(beginSubstring != c) - Str_Append(&compStr, beginSubstring); - - strncpy(buf, Str_Text(&compStr), bufSize); - buf[bufSize] = '\0'; - Str_Free(&compStr); - } - else -#endif - { - dd_snprintf(buf, bufSize, "%s%s", textualValue, suffix); - } - - return buf; - } -}; - -TextualSliderWidget::TextualSliderWidget(float min, float max, float step, bool floatMode) - : SliderWidget(min, max, step, floatMode) - , d(new Instance(this)) -{ - Widget::_pageColorIdx = MENU_COLOR3; - Widget::actions[Widget::MNA_MODIFIED].callback = CVarSliderWidget_UpdateCVar; - Widget::actions[Widget::MNA_FOCUS ].callback = Hu_MenuDefaultFocusAction; -} - -TextualSliderWidget::~TextualSliderWidget() -{} - -void TextualSliderWidget::draw(Point2Raw const *origin) -{ - DENG2_ASSERT(origin != 0); - - float const val = de::clamp(min(), value(), max()); - char textualValue[41]; - char const *str = d->composeValueString(val, 0, 0, 40, textualValue); - - DGL_MatrixMode(DGL_MODELVIEW); - DGL_Translatef(origin->x, origin->y, 0); - - DGL_Enable(DGL_TEXTURE_2D); - - FR_SetFont(mnRendState->textFonts[_pageFontIdx]); - FR_SetColorAndAlphav(mnRendState->textColors[_pageColorIdx]); - FR_DrawTextXY3(str, 0, 0, ALIGN_TOPLEFT, Hu_MenuMergeEffectWithDrawTextFlags(0)); - - DGL_Disable(DGL_TEXTURE_2D); - - DGL_MatrixMode(DGL_MODELVIEW); - DGL_Translatef(-origin->x, -origin->y, 0); -} - -void TextualSliderWidget::updateGeometry(Page *page) -{ - DENG2_ASSERT(page != 0); - - fontid_t const font = page->predefinedFont(mn_page_fontid_t(_pageFontIdx)); - float const val = de::clamp(min(), value(), max()); - char textualValue[41]; - char const *str = d->composeValueString(val, 0, 0, 40, textualValue); - - FR_SetFont(font); - - Size2Raw size; FR_TextSize(&size, str); - - Rect_SetWidthHeight(_geometry, size.width, size.height); -} - -void TextualSliderWidget::setEmptyText(char const *newEmptyText) -{ - d->emptyText = newEmptyText; -} - -char const *TextualSliderWidget::emptyText() const -{ - return d->emptyText; -} - -void TextualSliderWidget::setOnethSuffix(char const *newOnethSuffix) -{ - d->onethSuffix = newOnethSuffix; -} - -char const *TextualSliderWidget::onethSuffix() const -{ - return d->onethSuffix; -} - -void TextualSliderWidget::setNthSuffix(char const *newNthSuffix) -{ - d->nthSuffix = newNthSuffix; -} - -char const *TextualSliderWidget::nthSuffix() const -{ - return d->nthSuffix; -} - -} // namespace menu -} // namespace common