ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

widget.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/scummsys.h"
00024 #include "common/system.h"
00025 #include "common/rect.h"
00026 #include "common/textconsole.h"
00027 #include "common/translation.h"
00028 #include "graphics/pixelformat.h"
00029 #include "gui/widget.h"
00030 #include "gui/gui-manager.h"
00031 
00032 #include "gui/ThemeEval.h"
00033 
00034 #include "gui/dialog.h"
00035 #include "gui/widgets/popup.h"
00036 #include "gui/widgets/scrollcontainer.h"
00037 
00038 namespace GUI {
00039 
00040 Widget::Widget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip)
00041     : GuiObject(x, y, w, h), _type(0), _boss(boss), _tooltip(tooltip),
00042       _flags(0), _hasFocus(false), _state(ThemeEngine::kStateEnabled) {
00043     init();
00044 }
00045 
00046 Widget::Widget(GuiObject *boss, const Common::String &name, const char *tooltip)
00047     : GuiObject(name), _type(0), _boss(boss), _tooltip(tooltip),
00048       _flags(0), _hasFocus(false), _state(ThemeEngine::kStateDisabled) {
00049     init();
00050 }
00051 
00052 void Widget::init() {
00053     // Insert into the widget list of the boss
00054     _next = _boss->_firstWidget;
00055     _boss->_firstWidget = this;
00056     _needsRedraw = true;
00057 }
00058 
00059 Widget::~Widget() {
00060     delete _next;
00061     _next = nullptr;
00062 }
00063 
00064 void Widget::resize(int x, int y, int w, int h) {
00065     _x = x;
00066     _y = y;
00067     _w = w;
00068     _h = h;
00069 }
00070 
00071 void Widget::setFlags(int flags) {
00072     updateState(_flags, _flags | flags);
00073     _flags |= flags;
00074 }
00075 
00076 void Widget::clearFlags(int flags) {
00077     updateState(_flags, _flags & ~flags);
00078     _flags &= ~flags;
00079 }
00080 
00081 void Widget::updateState(int oldFlags, int newFlags) {
00082     if (newFlags & WIDGET_ENABLED) {
00083         _state = ThemeEngine::kStateEnabled;
00084         if (newFlags & WIDGET_HILITED)
00085             _state = ThemeEngine::kStateHighlight;
00086         if (newFlags & WIDGET_PRESSED)
00087             _state = ThemeEngine::kStatePressed;
00088     } else {
00089         _state = ThemeEngine::kStateDisabled;
00090     }
00091 }
00092 
00093 void Widget::markAsDirty() {
00094     _needsRedraw = true;
00095 
00096     Widget *w = _firstWidget;
00097     while (w) {
00098         w->markAsDirty();
00099         w = w->next();
00100     }
00101 }
00102 
00103 void Widget::draw() {
00104     if (!isVisible() || !_boss->isVisible())
00105         return;
00106 
00107     if (_needsRedraw) {
00108         int oldX = _x, oldY = _y;
00109 
00110         // Account for our relative position in the dialog
00111         _x = getAbsX();
00112         _y = getAbsY();
00113 
00114         Common::Rect oldClip = g_gui.theme()->swapClipRect(_boss->getClipRect());
00115 
00116         if (g_gui.useRTL()) {
00117             _x = g_system->getOverlayWidth() - _x - _w;
00118 
00119             if (this->_name.contains("GameOptions") || this->_name.contains("GlobalOptions") || this->_name.contains("Browser") || this->_name.empty()) {
00123                 _x = _x + g_gui.getOverlayOffset();
00124             }
00125 
00126             Common::Rect r = _boss->getClipRect();
00127             r.moveTo(_x, r.top);
00128 
00129             g_gui.theme()->swapClipRect(r);
00130         }
00131 
00132         // Draw border
00133         if (_flags & WIDGET_BORDER) {
00134             g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h),
00135                                                 ThemeEngine::kWidgetBackgroundBorder);
00136             _x += 4;
00137             _y += 4;
00138             _w -= 8;
00139             _h -= 8;
00140         }
00141 
00142         // Now perform the actual widget draw
00143         drawWidget();
00144 
00145         g_gui.theme()->swapClipRect(oldClip);
00146 
00147         // Restore x/y
00148         if (_flags & WIDGET_BORDER) {
00149             _x -= 4;
00150             _y -= 4;
00151             _w += 8;
00152             _h += 8;
00153         }
00154 
00155         _x = oldX;
00156         _y = oldY;
00157 
00158         _needsRedraw = false;
00159     }
00160 
00161     // Draw all children
00162     Widget *w = _firstWidget;
00163     while (w) {
00164         w->draw();
00165         w = w->_next;
00166     }
00167 }
00168 
00169 Widget *Widget::findWidgetInChain(Widget *w, int x, int y) {
00170     while (w) {
00171         // Stop as soon as we find a widget that contains the point (x,y)
00172         if (x >= w->_x && x < w->_x + w->_w && y >= w->_y && y < w->_y + w->getHeight())
00173             break;
00174         w = w->_next;
00175     }
00176     if (w)
00177         w = w->findWidget(x - w->_x, y - w->_y);
00178     return w;
00179 }
00180 
00181 Widget *Widget::findWidgetInChain(Widget *w, const char *name) {
00182     while (w) {
00183         if (w->_name == name) {
00184             return w;
00185         }
00186         w = w->_next;
00187     }
00188     return nullptr;
00189 }
00190 
00191 bool Widget::containsWidgetInChain(Widget *w, Widget *search) {
00192     while (w) {
00193         if (w == search || w->containsWidget(search))
00194             return true;
00195         w = w->_next;
00196     }
00197     return false;
00198 }
00199 
00200 void Widget::setEnabled(bool e) {
00201     if ((_flags & WIDGET_ENABLED) != e) {
00202         if (e)
00203             setFlags(WIDGET_ENABLED);
00204         else
00205             clearFlags(WIDGET_ENABLED);
00206 
00207         g_gui.scheduleTopDialogRedraw();
00208     }
00209 }
00210 
00211 bool Widget::isEnabled() const {
00212     return ((_flags & WIDGET_ENABLED) != 0);
00213 }
00214 
00215 void Widget::setVisible(bool e) {
00216     if (e)
00217         clearFlags(WIDGET_INVISIBLE);
00218     else
00219         setFlags(WIDGET_INVISIBLE);
00220 }
00221 
00222 bool Widget::isVisible() const {
00223     if (g_gui.xmlEval()->getVar("Dialog." + _name + ".Visible", 1) == 0)
00224         return false;
00225 
00226     return !(_flags & WIDGET_INVISIBLE);
00227 }
00228 
00229 bool Widget::useRTL() const {
00230     return _useRTL;
00231 }
00232 
00233 uint8 Widget::parseHotkey(const Common::String &label) {
00234     if (!label.contains('~'))
00235         return 0;
00236 
00237     int state = 0;
00238     uint8 hotkey = 0;
00239 
00240     for (uint i = 0; i < label.size() && state != 3; i++) {
00241         switch (state) {
00242         case 0:
00243             if (label[i] == '~')
00244                 state = 1;
00245             break;
00246         case 1:
00247             if (label[i] != '~') {
00248                 state = 2;
00249                 hotkey = label[i];
00250             } else
00251                 state = 0;
00252             break;
00253         case 2:
00254             if (label[i] == '~')
00255                 state = 3;
00256             else
00257                 state = 0;
00258             break;
00259         default:
00260             break;
00261         }
00262     }
00263 
00264     if (state == 3)
00265         return hotkey;
00266 
00267     return 0;
00268 }
00269 
00270 Common::String Widget::cleanupHotkey(const Common::String &label) {
00271     Common::String res;
00272 
00273     for (uint i = 0; i < label.size(); i++)
00274         if (label[i] != '~')
00275             res = res + label[i];
00276 
00277     return res;
00278 }
00279 
00280 void Widget::read(Common::String str) {
00281 #ifdef USE_TTS
00282     if (ConfMan.hasKey("tts_enabled", "residualvm") &&
00283             ConfMan.getBool("tts_enabled", "residualvm")) {
00284         Common::TextToSpeechManager *ttsMan = g_system->getTextToSpeechManager();
00285         if (ttsMan == nullptr)
00286             return;
00287         ttsMan->say(str);
00288     }
00289 #endif
00290 }
00291 
00292 #pragma mark -
00293 
00294 StaticTextWidget::StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align, const char *tooltip, ThemeEngine::FontStyle font)
00295     : Widget(boss, x, y, w, h, tooltip) {
00296     setFlags(WIDGET_ENABLED);
00297     _type = kStaticTextWidget;
00298     _label = text;
00299     _font = font;
00300     _align = Graphics::convertTextAlignH(align, g_gui.useRTL() && _useRTL);
00301 }
00302 
00303 StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip, ThemeEngine::FontStyle font)
00304     : Widget(boss, name, tooltip) {
00305     setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
00306     _type = kStaticTextWidget;
00307     _label = text;
00308 
00309     _align = Graphics::convertTextAlignH(g_gui.xmlEval()->getWidgetTextHAlign(name), g_gui.useRTL() && _useRTL);
00310 
00311     _font = font;
00312 }
00313 
00314 void StaticTextWidget::setValue(int value) {
00315     _label = Common::String::format("%d", value);
00316 }
00317 
00318 void StaticTextWidget::setLabel(const Common::String &label) {
00319     if (_label != label) {
00320         _label = label;
00321 
00322         markAsDirty();
00323     }
00324 }
00325 
00326 void StaticTextWidget::setAlign(Graphics::TextAlign align) {
00327     align = Graphics::convertTextAlignH(align, g_gui.useRTL() && _useRTL);
00328     if (_align != align){
00329         _align = align;
00330 
00331         markAsDirty();
00332     }
00333 }
00334 
00335 
00336 void StaticTextWidget::drawWidget() {
00337     g_gui.theme()->drawText(
00338             Common::Rect(_x, _y, _x + _w, _y + _h),
00339             _label, _state, _align, ThemeEngine::kTextInversionNone, 0, true, _font
00340     );
00341 }
00342 
00343 #pragma mark -
00344 
00345 ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey)
00346     : StaticTextWidget(boss, x, y, w, h, cleanupHotkey(label), Graphics::kTextAlignCenter, tooltip), CommandSender(boss),
00347       _cmd(cmd), _hotkey(hotkey), _duringPress(false) {
00348 
00349     if (hotkey == 0)
00350         _hotkey = parseHotkey(label);
00351 
00352     setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
00353     _type = kButtonWidget;
00354 }
00355 
00356 ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey)
00357     : StaticTextWidget(boss, name, cleanupHotkey(label), tooltip), CommandSender(boss),
00358       _cmd(cmd), _hotkey(hotkey), _duringPress(false) {
00359     if (hotkey == 0)
00360         _hotkey = parseHotkey(label);
00361     setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
00362     _type = kButtonWidget;
00363 }
00364 
00365 void ButtonWidget::getMinSize(int &minWidth, int &minHeight) {
00366     const Graphics::Font &font = g_gui.getFont(_font);
00367 
00368     minWidth  = font.getStringWidth(_label);
00369     minHeight = font.getFontHeight();
00370 }
00371 
00372 void ButtonWidget::handleMouseUp(int x, int y, int button, int clickCount) {
00373     if (isEnabled() && _duringPress && x >= 0 && x < _w && y >= 0 && y < _h) {
00374         setUnpressedState();
00375         sendCommand(_cmd, 0);
00376     }
00377     _duringPress = false;
00378 }
00379 
00380 void ButtonWidget::handleMouseDown(int x, int y, int button, int clickCount) {
00381     _duringPress = true;
00382     setPressedState();
00383 }
00384 
00385 void ButtonWidget::drawWidget() {
00386     g_gui.theme()->drawButton(Common::Rect(_x, _y, _x + _w, _y + _h), _label, _state, getFlags());
00387 }
00388 
00389 void ButtonWidget::setLabel(const Common::String &label) {
00390     StaticTextWidget::setLabel(cleanupHotkey(label));
00391 }
00392 
00393 ButtonWidget *addClearButton(GuiObject *boss, const Common::String &name, uint32 cmd, int x, int y, int w, int h) {
00394     ButtonWidget *button;
00395 
00396 #ifndef DISABLE_FANCY_THEMES
00397     if (g_gui.xmlEval()->getVar("Globals.ShowSearchPic") == 1 && g_gui.theme()->supportsImages()) {
00398         if (!name.empty())
00399             button = new PicButtonWidget(boss, name, _("Clear value"), cmd);
00400         else
00401             button = new PicButtonWidget(boss, x, y, w, h, _("Clear value"), cmd);
00402         ((PicButtonWidget *)button)->useThemeTransparency(true);
00403         ((PicButtonWidget *)button)->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageEraser));
00404     } else
00405 #endif
00406         if (!name.empty())
00407             button = new ButtonWidget(boss, name, "C", _("Clear value"), cmd);
00408         else
00409             button = new ButtonWidget(boss, x, y, w, h, "C", _("Clear value"), cmd);
00410 
00411     return button;
00412 }
00413 
00414 void ButtonWidget::setHighLighted(bool enable) {
00415     (enable) ? setFlags(WIDGET_HILITED) : clearFlags(WIDGET_HILITED);
00416     markAsDirty();
00417 }
00418 
00419 void ButtonWidget::setPressedState() {
00420     setFlags(WIDGET_PRESSED);
00421     clearFlags(WIDGET_HILITED);
00422     markAsDirty();
00423 }
00424 
00425 void ButtonWidget::setUnpressedState() {
00426     clearFlags(WIDGET_PRESSED);
00427     markAsDirty();
00428 }
00429 
00430 #pragma mark -
00431 
00432 DropdownButtonWidget::DropdownButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey) :
00433         ButtonWidget(boss, x, y, w, h, label, tooltip, cmd, hotkey) {
00434     setFlags(getFlags() | WIDGET_TRACK_MOUSE);
00435 
00436     reset();
00437 }
00438 
00439 DropdownButtonWidget::DropdownButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey) :
00440         ButtonWidget(boss, name, label, tooltip, cmd, hotkey) {
00441     setFlags(getFlags() | WIDGET_TRACK_MOUSE);
00442 
00443     reset();
00444 }
00445 
00446 void DropdownButtonWidget::reset() {
00447     _inDropdown = false;
00448     _inButton   = false;
00449     _dropdownWidth = g_gui.xmlEval()->getVar("Globals.DropdownButton.Width", 13);
00450 }
00451 
00452 bool DropdownButtonWidget::isInDropDown(int x, int y) const {
00453     Common::Rect dropdownRect(_w - _dropdownWidth, 0, _w, _h);
00454     return dropdownRect.contains(x, y);
00455 }
00456 
00457 void DropdownButtonWidget::handleMouseMoved(int x, int y, int button) {
00458     if (_entries.empty()) {
00459         return;
00460     }
00461 
00462     // Detect which part of the button the cursor is over
00463     bool inDropdown = isInDropDown(x, y);
00464     bool inButton   = Common::Rect(_w, _h).contains(x, y) && !inDropdown;
00465 
00466     if (inDropdown != _inDropdown) {
00467         _inDropdown = inDropdown;
00468         markAsDirty();
00469     }
00470 
00471     if (inButton != _inButton) {
00472         _inButton = inButton;
00473         markAsDirty();
00474     }
00475 }
00476 
00477 void DropdownButtonWidget::handleMouseUp(int x, int y, int button, int clickCount) {
00478     if (isEnabled() && !_entries.empty() && _duringPress && isInDropDown(x, y)) {
00479 
00480         PopUpDialog popupDialog(this, "DropdownDialog", x + getAbsX(), y + getAbsY());
00481         popupDialog.setPosition(getAbsX(), getAbsY() + _h);
00482         popupDialog.setLineHeight(_h);
00483         popupDialog.setPadding(_dropdownWidth, _dropdownWidth);
00484 
00485         for (uint i = 0; i < _entries.size(); i++) {
00486             popupDialog.appendEntry(_entries[i].label);
00487         }
00488 
00489         int newSel = popupDialog.runModal();
00490         if (newSel != -1) {
00491             sendCommand(_entries[newSel].cmd, 0);
00492         }
00493 
00494         setUnpressedState();
00495         _duringPress = false;
00496     } else {
00497         ButtonWidget::handleMouseUp(x, y, button, clickCount);
00498     }
00499 }
00500 
00501 void DropdownButtonWidget::reflowLayout() {
00502     ButtonWidget::reflowLayout();
00503 
00504     reset();
00505 }
00506 
00507 void DropdownButtonWidget::getMinSize(int &minWidth, int &minHeight) {
00508     ButtonWidget::getMinSize(minWidth, minHeight);
00509 
00510     if (minWidth >= 0) {
00511         minWidth += _dropdownWidth * 2;
00512     }
00513 }
00514 
00515 void DropdownButtonWidget::appendEntry(const Common::String &label, uint32 cmd) {
00516     Entry e;
00517     e.label = label;
00518     e.cmd = cmd;
00519     _entries.push_back(e);
00520 }
00521 
00522 void DropdownButtonWidget::clearEntries() {
00523     _entries.clear();
00524 }
00525 
00526 void DropdownButtonWidget::drawWidget() {
00527     if (_entries.empty()) {
00528         // Degrade to a regular button
00529         g_gui.theme()->drawButton(Common::Rect(_x, _y, _x + _w, _y + _h), _label, _state);
00530     } else {
00531         g_gui.theme()->drawDropDownButton(Common::Rect(_x, _y, _x + _w, _y + _h), _dropdownWidth, _label,
00532                                           _state, _inButton, _inDropdown, (g_gui.useRTL() && _useRTL));
00533     }
00534 }
00535 
00536 #pragma mark -
00537 
00538 PicButtonWidget::PicButtonWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd, uint8 hotkey)
00539     : ButtonWidget(boss, x, y, w, h, "", tooltip, cmd, hotkey),
00540       _alpha(255), _transparency(false), _showButton(true) {
00541 
00542     setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
00543     _type = kButtonWidget;
00544 }
00545 
00546 PicButtonWidget::PicButtonWidget(GuiObject *boss, const Common::String &name, const char *tooltip, uint32 cmd, uint8 hotkey)
00547     : ButtonWidget(boss, name, "", tooltip, cmd, hotkey),
00548       _alpha(255), _transparency(false), _showButton(true) {
00549     setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG);
00550     _type = kButtonWidget;
00551 }
00552 
00553 PicButtonWidget::~PicButtonWidget() {
00554     for (int i = 0; i < kPicButtonStateMax + 1; i++)
00555         _gfx[i].free();
00556 }
00557 
00558 void PicButtonWidget::setGfx(const Graphics::Surface *gfx, int statenum) {
00559     _gfx[statenum].free();
00560 
00561     if (!gfx || !gfx->getPixels())
00562         return;
00563 
00564     if (gfx->format.bytesPerPixel == 1) {
00565         warning("PicButtonWidget::setGfx got paletted surface passed");
00566         return;
00567     }
00568 
00569     _gfx[statenum].copyFrom(*gfx);
00570 }
00571 
00572 void PicButtonWidget::setGfx(int w, int h, int r, int g, int b, int statenum) {
00573     if (w == -1)
00574         w = _w;
00575     if (h == -1)
00576         h = _h;
00577 
00578     const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
00579 
00580     _gfx[statenum].free();
00581     _gfx[statenum].create(w, h, requiredFormat);
00582     _gfx[statenum].fillRect(Common::Rect(0, 0, w, h), _gfx[statenum].format.RGBToColor(r, g, b));
00583 }
00584 
00585 void PicButtonWidget::drawWidget() {
00586     if (_showButton)
00587         g_gui.theme()->drawButton(Common::Rect(_x, _y, _x + _w, _y + _h), "", _state, getFlags());
00588 
00589     Graphics::Surface *gfx;
00590 
00591     if (_state == ThemeEngine::kStateHighlight)
00592         gfx = &_gfx[kPicButtonHighlight];
00593     else if (_state == ThemeEngine::kStateDisabled)
00594         gfx = &_gfx[kPicButtonStateDisabled];
00595     else if (_state == ThemeEngine::kStatePressed)
00596         gfx = &_gfx[kPicButtonStatePressed];
00597     else
00598         gfx = &_gfx[kPicButtonStateEnabled];
00599 
00600     if (!gfx->getPixels())
00601         gfx = &_gfx[kPicButtonStateEnabled];
00602 
00603     if (gfx->getPixels()) {
00604         // Check whether the set up surface needs to be converted to the GUI
00605         // color format.
00606         const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
00607         if (gfx->format != requiredFormat) {
00608             gfx->convertToInPlace(requiredFormat);
00609         }
00610 
00611         const int x = _x + (_w - gfx->w) / 2;
00612         const int y = _y + (_h - gfx->h) / 2;
00613 
00614         g_gui.theme()->drawSurface(Common::Point(x, y), *gfx, _transparency);
00615     }
00616 }
00617 
00618 #pragma mark -
00619 
00620 CheckboxWidget::CheckboxWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey)
00621     : ButtonWidget(boss, x, y, w, h, label, tooltip, cmd, hotkey), _state(false) {
00622     setFlags(WIDGET_ENABLED);
00623     _type = kCheckboxWidget;
00624 }
00625 
00626 CheckboxWidget::CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey)
00627     : ButtonWidget(boss, name, label, tooltip, cmd, hotkey), _state(false) {
00628     setFlags(WIDGET_ENABLED);
00629     _type = kCheckboxWidget;
00630 }
00631 
00632 void CheckboxWidget::handleMouseUp(int x, int y, int button, int clickCount) {
00633     if (isEnabled() && _duringPress && x >= 0 && x < _w && y >= 0 && y < _h) {
00634         toggleState();
00635     }
00636     _duringPress = false;
00637 }
00638 
00639 void CheckboxWidget::setState(bool state) {
00640     if (_state != state) {
00641         _state = state;
00642         //_flags ^= WIDGET_INV_BORDER;
00643         markAsDirty();
00644     }
00645     sendCommand(_cmd, _state);
00646 }
00647 
00648 void CheckboxWidget::drawWidget() {
00649     g_gui.theme()->drawCheckbox(Common::Rect(_x, _y, _x + _w, _y + _h), _label, _state, Widget::_state, (g_gui.useRTL() && _useRTL));
00650 }
00651 
00652 #pragma mark -
00653 RadiobuttonGroup::RadiobuttonGroup(GuiObject *boss, uint32 cmd) : CommandSender(boss) {
00654     _value = -1;
00655     _cmd = cmd;
00656 }
00657 
00658 void RadiobuttonGroup::setValue(int value) {
00659     Common::Array<RadiobuttonWidget *>::iterator button = _buttons.begin();
00660     while (button != _buttons.end()) {
00661         (*button)->setState((*button)->getValue() == value, false);
00662 
00663         button++;
00664     }
00665 
00666     _value = value;
00667 
00668     sendCommand(_cmd, _value);
00669 }
00670 
00671 void RadiobuttonGroup::setEnabled(bool ena) {
00672     Common::Array<RadiobuttonWidget *>::iterator button = _buttons.begin();
00673     while (button != _buttons.end()) {
00674         (*button)->setEnabled(ena);
00675 
00676         button++;
00677     }
00678 }
00679 
00680 #pragma mark -
00681 
00682 RadiobuttonWidget::RadiobuttonWidget(GuiObject *boss, int x, int y, int w, int h, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip, uint8 hotkey)
00683     : ButtonWidget(boss, x, y, w, h, label, tooltip, 0, hotkey), _state(false), _value(value), _group(group) {
00684     setFlags(WIDGET_ENABLED);
00685     _type = kRadiobuttonWidget;
00686     _group->addButton(this);
00687 }
00688 
00689 RadiobuttonWidget::RadiobuttonWidget(GuiObject *boss, const Common::String &name, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip, uint8 hotkey)
00690     : ButtonWidget(boss, name, label, tooltip, 0, hotkey), _state(false), _value(value), _group(group) {
00691     setFlags(WIDGET_ENABLED);
00692     _type = kRadiobuttonWidget;
00693     _group->addButton(this);
00694 }
00695 
00696 void RadiobuttonWidget::handleMouseUp(int x, int y, int button, int clickCount) {
00697     if (isEnabled() && _duringPress && x >= 0 && x < _w && y >= 0 && y < _h) {
00698         toggleState();
00699     }
00700     _duringPress = false;
00701 }
00702 
00703 void RadiobuttonWidget::setState(bool state, bool setGroup) {
00704     if (setGroup) {
00705         _group->setValue(_value);
00706         return;
00707     }
00708 
00709     if (_state != state) {
00710         _state = state;
00711         //_flags ^= WIDGET_INV_BORDER;
00712         markAsDirty();
00713     }
00714     sendCommand(_cmd, _state);
00715 }
00716 
00717 void RadiobuttonWidget::drawWidget() {
00718     g_gui.theme()->drawRadiobutton(Common::Rect(_x, _y, _x + _w, _y + _h), _label, _state, Widget::_state, (g_gui.useRTL() && _useRTL));
00719 }
00720 
00721 #pragma mark -
00722 
00723 SliderWidget::SliderWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd)
00724     : Widget(boss, x, y, w, h, tooltip), CommandSender(boss),
00725       _cmd(cmd), _value(0), _oldValue(0), _valueMin(0), _valueMax(100), _isDragging(false), _labelWidth(0) {
00726     setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG);
00727     _type = kSliderWidget;
00728 }
00729 
00730 SliderWidget::SliderWidget(GuiObject *boss, const Common::String &name, const char *tooltip, uint32 cmd)
00731     : Widget(boss, name, tooltip), CommandSender(boss),
00732       _cmd(cmd), _value(0), _oldValue(0), _valueMin(0), _valueMax(100), _isDragging(false), _labelWidth(0) {
00733     setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG);
00734     _type = kSliderWidget;
00735 }
00736 
00737 void SliderWidget::handleMouseMoved(int x, int y, int button) {
00738     if (g_gui.useRTL() && _useRTL == false) {
00739         x = _w - x;     // If internal flipping is off, adjust the mouse to behave as if it were LTR.
00740     }
00741     if (isEnabled() && _isDragging) {
00742         int newValue = posToValue(x);
00743         if (newValue < _valueMin)
00744             newValue = _valueMin;
00745         else if (newValue > _valueMax)
00746             newValue = _valueMax;
00747 
00748         if (newValue != _value) {
00749             _value = newValue;
00750             markAsDirty();
00751             sendCommand(_cmd, _value);  // FIXME - hack to allow for "live update" in sound dialog
00752         }
00753     }
00754 }
00755 
00756 void SliderWidget::handleMouseDown(int x, int y, int button, int clickCount) {
00757     if (isEnabled()) {
00758         _isDragging = true;
00759         handleMouseMoved(x, y, button);
00760     }
00761 }
00762 
00763 void SliderWidget::handleMouseUp(int x, int y, int button, int clickCount) {
00764     if (isEnabled() && _isDragging) {
00765         sendCommand(_cmd, _value);
00766     }
00767     _isDragging = false;
00768 }
00769 
00770 void SliderWidget::handleMouseWheel(int x, int y, int direction) {
00771     if (isEnabled() && !_isDragging) {
00772         // Increment or decrement by one
00773         int newValue = _value - direction;
00774 
00775         if (newValue < _valueMin)
00776             newValue = _valueMin;
00777         else if (newValue > _valueMax)
00778             newValue = _valueMax;
00779 
00780         if (newValue != _value) {
00781             _value = newValue;
00782             markAsDirty();
00783             sendCommand(_cmd, _value);  // FIXME - hack to allow for "live update" in sound dialog
00784         }
00785     }
00786 }
00787 
00788 void SliderWidget::drawWidget() {
00789     Common::Rect r1(_x, _y, _x + _w, _y + _h);
00790     g_gui.theme()->drawSlider(r1, valueToBarWidth(_value), _state, (g_gui.useRTL() && _useRTL));
00791 }
00792 
00793 int SliderWidget::valueToBarWidth(int value) {
00794     value = CLIP(value, _valueMin, _valueMax);
00795     return (_w * (value - _valueMin) / (_valueMax - _valueMin));
00796 }
00797 
00798 int SliderWidget::valueToPos(int value) {
00799     value = CLIP(value, _valueMin, _valueMax);
00800     return ((_w - 1) * (value - _valueMin + 1) / (_valueMax - _valueMin));
00801 }
00802 
00803 int SliderWidget::posToValue(int pos) {
00804     return (pos) * (_valueMax - _valueMin) / (_w - 1) + _valueMin;
00805 }
00806 
00807 #pragma mark -
00808 
00809 GraphicsWidget::GraphicsWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip)
00810     : Widget(boss, x, y, w, h, tooltip), _gfx(), _alpha(255), _transparency(false) {
00811     setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
00812     _type = kGraphicsWidget;
00813 }
00814 
00815 GraphicsWidget::GraphicsWidget(GuiObject *boss, const Common::String &name, const char *tooltip)
00816     : Widget(boss, name, tooltip), _gfx(), _alpha(255), _transparency(false) {
00817     setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
00818     _type = kGraphicsWidget;
00819 }
00820 
00821 GraphicsWidget::~GraphicsWidget() {
00822     _gfx.free();
00823 }
00824 
00825 void GraphicsWidget::setGfx(const Graphics::Surface *gfx) {
00826     _gfx.free();
00827 
00828     if (!gfx || !gfx->getPixels())
00829         return;
00830 
00831     if (gfx->format.bytesPerPixel == 1) {
00832         warning("GraphicsWidget::setGfx got paletted surface passed");
00833         return;
00834     }
00835 
00836     _gfx.copyFrom(*gfx);
00837 }
00838 
00839 void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) {
00840     if (w == -1)
00841         w = _w;
00842     if (h == -1)
00843         h = _h;
00844 
00845     const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
00846 
00847     _gfx.free();
00848     _gfx.create(w, h, requiredFormat);
00849     _gfx.fillRect(Common::Rect(0, 0, w, h), _gfx.format.RGBToColor(r, g, b));
00850 }
00851 
00852 void GraphicsWidget::drawWidget() {
00853     if (_gfx.getPixels()) {
00854         // Check whether the set up surface needs to be converted to the GUI
00855         // color format.
00856         const Graphics::PixelFormat &requiredFormat = g_gui.theme()->getPixelFormat();
00857         if (_gfx.format != requiredFormat) {
00858             _gfx.convertToInPlace(requiredFormat);
00859         }
00860 
00861         const int x = _x + (_w - _gfx.w) / 2;
00862         const int y = _y + (_h - _gfx.h) / 2;
00863 
00864         g_gui.theme()->drawSurface(Common::Point(x, y), _gfx, _transparency);
00865     }
00866 }
00867 
00868 #pragma mark -
00869 
00870 ContainerWidget::ContainerWidget(GuiObject *boss, int x, int y, int w, int h) :
00871         Widget(boss, x, y, w, h),
00872         _backgroundType(ThemeEngine::kWidgetBackgroundBorder) {
00873     setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
00874     _type = kContainerWidget;
00875 }
00876 
00877 ContainerWidget::ContainerWidget(GuiObject *boss, const Common::String &name) :
00878         Widget(boss, name),
00879         _backgroundType(ThemeEngine::kWidgetBackgroundBorder) {
00880     setFlags(WIDGET_ENABLED | WIDGET_CLEARBG);
00881     _type = kContainerWidget;
00882 }
00883 
00884 ContainerWidget::~ContainerWidget() {
00885     // We also remove the widget from the boss to avoid segfaults, when the
00886     // deleted widget is an active widget in the boss.
00887     for (Widget *w = _firstWidget; w; w = w->next()) {
00888         _boss->removeWidget(w);
00889     }
00890 }
00891 
00892 bool ContainerWidget::containsWidget(Widget *w) const {
00893     return containsWidgetInChain(_firstWidget, w);
00894 }
00895 
00896 Widget *ContainerWidget::findWidget(int x, int y) {
00897     Widget *w = findWidgetInChain(_firstWidget, x, y);
00898     if (w)
00899         return w;
00900     return this;
00901 }
00902 
00903 void ContainerWidget::removeWidget(Widget *widget) {
00904     // We also remove the widget from the boss to avoid a reference to a
00905     // widget not in the widget chain anymore.
00906     _boss->removeWidget(widget);
00907 
00908     Widget::removeWidget(widget);
00909 }
00910 
00911 void ContainerWidget::setBackgroundType(ThemeEngine::WidgetBackground backgroundType) {
00912     _backgroundType = backgroundType;
00913 }
00914 
00915 void ContainerWidget::drawWidget() {
00916     g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), _backgroundType);
00917 }
00918 
00919 #pragma mark -
00920 
00921 OptionsContainerWidget::OptionsContainerWidget(GuiObject *boss, const Common::String &name, const Common::String &dialogLayout,
00922                                                bool scrollable, const Common::String &domain) :
00923         Widget(boss, name),
00924         _domain(domain),
00925         _dialogLayout(dialogLayout),
00926         _parentDialog(nullptr),
00927         _scrollContainer(nullptr) {
00928 
00929     if (scrollable) {
00930         _scrollContainer = new ScrollContainerWidget(this, 0, 0, 0, 0, kReflowCmd);
00931         _scrollContainer->setTarget(this);
00932         _scrollContainer->setBackgroundType(GUI::ThemeEngine::kWidgetBackgroundNo);
00933     }
00934 }
00935 
00936 OptionsContainerWidget::~OptionsContainerWidget() {
00937 }
00938 
00939 void OptionsContainerWidget::reflowLayout() {
00940     Widget::reflowLayout();
00941 
00942     if (!_dialogLayout.empty()) {
00943         if (!g_gui.xmlEval()->hasDialog(_dialogLayout)) {
00944             defineLayout(*g_gui.xmlEval(), _dialogLayout, _name);
00945         }
00946 
00947         g_gui.xmlEval()->reflowDialogLayout(_dialogLayout, _firstWidget);
00948     }
00949 
00950     if (_scrollContainer) {
00951         _scrollContainer->resize(_x, _y, _w, _h);
00952     }
00953 
00954     Widget *w = _firstWidget;
00955     while (w) {
00956         w->reflowLayout();
00957         w = w->next();
00958     }
00959 }
00960 
00961 bool OptionsContainerWidget::containsWidget(Widget *widget) const {
00962     return containsWidgetInChain(_firstWidget, widget);
00963 }
00964 
00965 Widget *OptionsContainerWidget::findWidget(int x, int y) {
00966     // Iterate over all child widgets and find the one which was clicked
00967     return Widget::findWidgetInChain(_firstWidget, x, y);
00968 }
00969 
00970 void OptionsContainerWidget::removeWidget(Widget *widget) {
00971     _boss->removeWidget(widget);
00972     Widget::removeWidget(widget);
00973 }
00974 
00975 GuiObject *OptionsContainerWidget::widgetsBoss() {
00976     if (_scrollContainer) {
00977         return _scrollContainer;
00978     }
00979 
00980     return this;
00981 }
00982 
00983 } // End of namespace GUI


Generated on Sat Jun 27 2020 05:00:53 for ResidualVM by doxygen 1.7.1
curved edge   curved edge