1 /** @file buttonwidget.cpp  Button widget.
2  *
3  * @authors Copyright © 2005-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
4  * @authors Copyright © 2005-2014 Daniel Swanson <danij@dengine.net>
5  *
6  * @par License
7  * GPL: http://www.gnu.org/licenses/gpl.html
8  *
9  * <small>This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by the
11  * Free Software Foundation; either version 2 of the License, or (at your
12  * option) any later version. This program is distributed in the hope that it
13  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15  * Public License for more details. You should have received a copy of the GNU
16  * General Public License along with this program; if not, write to the Free
17  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18  * 02110-1301 USA</small>
19  */
20 
21 #include "common.h"
22 #include "menu/widgets/buttonwidget.h"
23 
24 #include "g_defs.h"
25 #include "hu_menu.h"   // menu sounds
26 #include "hu_stuff.h"
27 #include "menu/page.h" // mnRendState
28 
29 using namespace de;
30 
31 namespace common {
32 namespace menu {
33 
DENG2_PIMPL_NOREF(ButtonWidget)34 DENG2_PIMPL_NOREF(ButtonWidget)
35 {
36     String    text;           ///< Label text.
37     patchid_t patch     = -1; ///< Used when drawing this instead of text, if set.
38     bool      noAltText = false;
39     bool      silent    = false;
40 };
41 
ButtonWidget(String const & text,patchid_t patch)42 ButtonWidget::ButtonWidget(String const &text, patchid_t patch)
43     : Widget()
44     , d(new Impl)
45 {
46     setFont(MENU_FONT2);
47     setColor(MENU_COLOR1);
48 
49     setText(text);
50     setPatch(patch);
51 }
52 
~ButtonWidget()53 ButtonWidget::~ButtonWidget()
54 {}
55 
draw() const56 void ButtonWidget::draw() const
57 {
58     fontid_t const fontId     = mnRendState->textFonts[font()];
59     Vector4f const &textColor = mnRendState->textColors[color()];
60     //float t = (isFocused()? 1 : 0);
61 
62     const Vector4f color = selectionFlashColor(textColor);
63 
64 //    // Flash if focused.
65 //    if (isFocused() && cfg.common.menuTextFlashSpeed > 0)
66 //    {
67 //        float const speed = cfg.common.menuTextFlashSpeed / 2.f;
68 //        t = (1 + sin(page().timer() / (float)TICSPERSEC * speed * DD_PI)) / 2;
69 //    }
70 //    Vector4f const color = de::lerp(textColor, Vector4f(Vector3f(cfg.common.menuTextFlashColor), textColor.w), t);
71 
72     const float fadeout = scrollingFadeout();
73     if (fadeout < .001f) return;
74 
75     FR_SetFont(fontId);
76     FR_SetColorAndAlpha(color.x, color.y, color.z, color.w * fadeout);
77     DGL_Color4f(1, 1, 1, color.w * fadeout);
78 
79     if(d->patch >= 0)
80     {
81         String replacement;
82         if(!d->noAltText)
83         {
84             replacement = Hu_ChoosePatchReplacement(patchreplacemode_t(cfg.common.menuPatchReplaceMode), d->patch, d->text);
85         }
86 
87         DGL_Enable(DGL_TEXTURE_2D);
88         WI_DrawPatch(d->patch,
89                      replacement,
90                      geometry().topLeft,
91                      ALIGN_TOPLEFT,
92                      0,
93                      Hu_MenuMergeEffectWithDrawTextFlags(0));
94         DGL_Disable(DGL_TEXTURE_2D);
95 
96         return;
97     }
98 
99     DGL_Enable(DGL_TEXTURE_2D);
100     FR_DrawTextXY3(d->text.toUtf8().constData(), geometry().topLeft.x, geometry().topLeft.y,
101                    ALIGN_TOPLEFT, Hu_MenuMergeEffectWithDrawTextFlags(0));
102     DGL_Disable(DGL_TEXTURE_2D);
103 }
104 
handleCommand(menucommand_e cmd)105 int ButtonWidget::handleCommand(menucommand_e cmd)
106 {
107     if (cmd == MCMD_SELECT)
108     {
109         if (!isActive())
110         {
111             setFlags(Active);
112             execAction(Activated);
113         }
114         // We are not going to receive a separate "up event".
115         if (!d->silent)
116         {
117             S_LocalSound(SFX_MENU_ACCEPT, NULL);
118         }
119         setFlags(Active, UnsetFlags);
120         execAction(Deactivated);
121         return true;
122     }
123     return false; // Not eaten.
124 }
125 
setSilent(bool silent)126 void ButtonWidget::setSilent(bool silent)
127 {
128     d->silent = silent;
129 }
130 
updateGeometry()131 void ButtonWidget::updateGeometry()
132 {
133     String useText = d->text;
134 
135     // @todo What if patch replacement is disabled?
136     if(d->patch >= 0)
137     {
138         if(!d->noAltText)
139         {
140             // Use the replacement string?
141             useText = Hu_ChoosePatchReplacement(patchreplacemode_t(cfg.common.menuPatchReplaceMode), d->patch, d->text);
142         }
143 
144         if(useText.isEmpty())
145         {
146             // Use the original patch.
147             patchinfo_t info;
148             R_GetPatchInfo(d->patch, &info);
149             geometry().setSize(Vector2ui(info.geometry.size.width, info.geometry.size.height));
150             return;
151         }
152     }
153 
154     FR_PushAttrib();
155     Size2Raw size;
156     FR_SetFont(page().predefinedFont(mn_page_fontid_t(font())));
157     FR_TextSize(&size, useText.toUtf8().constData());
158     geometry().setSize(Vector2ui(size.width, size.height));
159     FR_PopAttrib();
160 }
161 
text() const162 String ButtonWidget::text() const
163 {
164     return d->text;
165 }
166 
setText(String const & newText)167 ButtonWidget &ButtonWidget::setText(String const &newText)
168 {
169     d->text = labelText(newText);
170     return *this;
171 }
172 
patch() const173 patchid_t ButtonWidget::patch() const
174 {
175     return d->patch;
176 }
177 
setPatch(patchid_t newPatch)178 ButtonWidget &ButtonWidget::setPatch(patchid_t newPatch)
179 {
180     d->patch = newPatch;
181     return *this;
182 }
183 
noAltText() const184 bool ButtonWidget::noAltText() const
185 {
186     return d->noAltText;
187 }
188 
setNoAltText(bool yes)189 ButtonWidget &ButtonWidget::setNoAltText(bool yes)
190 {
191     d->noAltText = yes;
192     return *this;
193 }
194 
195 } // namespace menu
196 } // namespace common
197