1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef GUI_WIDGET_H 24 #define GUI_WIDGET_H 25 26 #include "common/scummsys.h" 27 #include "common/array.h" 28 #include "common/str.h" 29 #include "common/keyboard.h" 30 #include "graphics/font.h" 31 #include "graphics/surface.h" 32 #include "gui/object.h" 33 #include "gui/ThemeEngine.h" 34 35 namespace GUI { 36 37 enum { 38 WIDGET_ENABLED = 1 << 0, 39 WIDGET_INVISIBLE = 1 << 1, 40 WIDGET_HILITED = 1 << 2, 41 WIDGET_BORDER = 1 << 3, 42 WIDGET_PRESSED = 1 << 4, 43 //WIDGET_INV_BORDER = 1 << 4, 44 WIDGET_CLEARBG = 1 << 5, 45 WIDGET_WANT_TICKLE = 1 << 7, 46 WIDGET_TRACK_MOUSE = 1 << 8, 47 // Retain focus on mouse up. By default widgets lose focus on mouseup, 48 // but some widgets might want to retain it - widgets where you enter 49 // text, for instance 50 WIDGET_RETAIN_FOCUS = 1 << 9, 51 // Usually widgets would lock mouse input when the user pressed the 52 // left mouse button till the user releases it. 53 // The PopUpWidget for example does not want this behavior, since the 54 // mouse down will open up a new dialog which silently eats the mouse 55 // up event for its own purposes. 56 WIDGET_IGNORE_DRAG = 1 << 10 57 }; 58 59 enum { 60 kStaticTextWidget = 'TEXT', 61 kEditTextWidget = 'EDIT', 62 kButtonWidget = 'BTTN', 63 kCheckboxWidget = 'CHKB', 64 kRadiobuttonWidget = 'RDBT', 65 kSliderWidget = 'SLDE', 66 kListWidget = 'LIST', 67 kScrollBarWidget = 'SCRB', 68 kPopUpWidget = 'POPU', 69 kTabWidget = 'TABW', 70 kGraphicsWidget = 'GFXW', 71 kContainerWidget = 'CTNR', 72 kScrollContainerWidget = 'SCTR' 73 }; 74 75 enum { 76 kCaretBlinkTime = 300 77 }; 78 79 enum { 80 kPressedButtonTime = 200 81 }; 82 83 enum { 84 kPicButtonStateEnabled = 0, 85 kPicButtonHighlight = 1, 86 kPicButtonStateDisabled = 2, 87 kPicButtonStatePressed = 3, 88 89 kPicButtonStateMax = 3 90 }; 91 92 /* Widget */ 93 class Widget : public GuiObject { 94 friend class Dialog; 95 protected: 96 uint32 _type; 97 GuiObject *_boss; 98 Widget *_next; 99 uint16 _id; 100 bool _hasFocus; 101 ThemeEngine::WidgetStateInfo _state; 102 Common::String _tooltip; 103 104 private: 105 uint16 _flags; 106 107 public: 108 static Widget *findWidgetInChain(Widget *start, int x, int y); 109 static Widget *findWidgetInChain(Widget *start, const char *name); 110 static bool containsWidgetInChain(Widget *start, Widget *search); 111 112 public: 113 Widget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0); 114 Widget(GuiObject *boss, const Common::String &name, const char *tooltip = 0); 115 virtual ~Widget(); 116 117 void init(); 118 void resize(int x, int y, int w, int h); 119 setNext(Widget * w)120 void setNext(Widget *w) { _next = w; } next()121 Widget *next() { return _next; } 122 getAbsX()123 virtual int16 getAbsX() const { return _x + _boss->getChildX(); } getAbsY()124 virtual int16 getAbsY() const { return _y + _boss->getChildY(); } 125 virtual Common::Rect getBossClipRect() const; 126 setPos(int x,int y)127 virtual void setPos(int x, int y) { _x = x; _y = y; } setSize(int w,int h)128 virtual void setSize(int w, int h) { _w = w; _h = h; } 129 handleMouseDown(int x,int y,int button,int clickCount)130 virtual void handleMouseDown(int x, int y, int button, int clickCount) {} handleMouseUp(int x,int y,int button,int clickCount)131 virtual void handleMouseUp(int x, int y, int button, int clickCount) {} handleMouseEntered(int button)132 virtual void handleMouseEntered(int button) {} handleMouseLeft(int button)133 virtual void handleMouseLeft(int button) {} handleMouseMoved(int x,int y,int button)134 virtual void handleMouseMoved(int x, int y, int button) {} handleMouseWheel(int x,int y,int direction)135 virtual void handleMouseWheel(int x, int y, int direction) {} handleKeyDown(Common::KeyState state)136 virtual bool handleKeyDown(Common::KeyState state) { return false; } // Return true if the event was handled handleKeyUp(Common::KeyState state)137 virtual bool handleKeyUp(Common::KeyState state) { return false; } // Return true if the event was handled handleTickle()138 virtual void handleTickle() {} 139 140 void draw(); receivedFocus()141 void receivedFocus() { _hasFocus = true; receivedFocusWidget(); } lostFocus()142 void lostFocus() { _hasFocus = false; lostFocusWidget(); } wantsFocus()143 virtual bool wantsFocus() { return false; } 144 145 void setFlags(int flags); 146 void clearFlags(int flags); getFlags()147 int getFlags() const { return _flags; } 148 149 void setEnabled(bool e); 150 bool isEnabled() const; 151 152 void setVisible(bool e); 153 bool isVisible() const; 154 155 uint8 parseHotkey(const Common::String &label); 156 Common::String cleanupHotkey(const Common::String &label); 157 hasTooltip()158 bool hasTooltip() const { return !_tooltip.empty(); } getTooltip()159 const Common::String &getTooltip() const { return _tooltip; } setTooltip(const Common::String & tooltip)160 void setTooltip(const Common::String &tooltip) { _tooltip = tooltip; } 161 containsWidget(Widget *)162 virtual bool containsWidget(Widget *) const { return false; } 163 164 protected: 165 void updateState(int oldFlags, int newFlags); 166 167 virtual void drawWidget() = 0; 168 receivedFocusWidget()169 virtual void receivedFocusWidget() {} lostFocusWidget()170 virtual void lostFocusWidget() {} 171 findWidget(int x,int y)172 virtual Widget *findWidget(int x, int y) { return this; } 173 releaseFocus()174 void releaseFocus() { assert(_boss); _boss->releaseFocus(); } 175 176 // By default, delegate unhandled commands to the boss handleCommand(CommandSender * sender,uint32 cmd,uint32 data)177 void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { assert(_boss); _boss->handleCommand(sender, cmd, data); } 178 }; 179 180 /* StaticTextWidget */ 181 class StaticTextWidget : public Widget { 182 protected: 183 Common::String _label; 184 Graphics::TextAlign _align; 185 ThemeEngine::FontStyle _font; 186 public: 187 StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align, const char *tooltip = 0, ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold); 188 StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip = 0, ThemeEngine::FontStyle font = ThemeEngine::kFontStyleBold); 189 void setValue(int value); 190 void setLabel(const Common::String &label); getLabel()191 const Common::String &getLabel() const { return _label; } 192 void setAlign(Graphics::TextAlign align); getAlign()193 Graphics::TextAlign getAlign() const { return _align; } 194 195 protected: 196 void drawWidget(); 197 }; 198 199 /* ButtonWidget */ 200 class ButtonWidget : public StaticTextWidget, public CommandSender { 201 friend class Dialog; // Needed for the hotkey handling 202 protected: 203 uint32 _cmd; 204 uint8 _hotkey; 205 public: 206 ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); 207 ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); 208 setCmd(uint32 cmd)209 void setCmd(uint32 cmd) { _cmd = cmd; } getCmd()210 uint32 getCmd() const { return _cmd; } 211 212 void setLabel(const Common::String &label); 213 214 void handleMouseUp(int x, int y, int button, int clickCount); 215 void handleMouseDown(int x, int y, int button, int clickCount); handleMouseEntered(int button)216 void handleMouseEntered(int button) { if (_duringPress) { setFlags(WIDGET_PRESSED); } else { setFlags(WIDGET_HILITED); } draw(); } handleMouseLeft(int button)217 void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED | WIDGET_PRESSED); draw(); } 218 219 void setHighLighted(bool enable); 220 void setPressedState(); 221 void setUnpressedState(); 222 protected: 223 void drawWidget(); 224 bool _duringPress; 225 private: 226 uint32 _lastTime; 227 }; 228 229 /* PicButtonWidget */ 230 class PicButtonWidget : public ButtonWidget { 231 public: 232 PicButtonWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); 233 PicButtonWidget(GuiObject *boss, const Common::String &name, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); 234 ~PicButtonWidget(); 235 236 void setGfx(const Graphics::Surface *gfx, int statenum = kPicButtonStateEnabled); 237 void setAGfx(const Graphics::TransparentSurface *gfx, int statenum = kPicButtonStateEnabled, ThemeEngine::AutoScaleMode mode = ThemeEngine::kAutoScaleNone); 238 void setGfx(int w, int h, int r, int g, int b, int statenum = kPicButtonStateEnabled); 239 useAlpha(int alpha)240 void useAlpha(int alpha) { _alpha = alpha; } useThemeTransparency(bool enable)241 void useThemeTransparency(bool enable) { _transparency = enable; } setButtonDisplay(bool enable)242 void setButtonDisplay(bool enable) {_showButton = enable; } 243 244 protected: 245 void drawWidget(); 246 247 Graphics::Surface _gfx[kPicButtonStateMax + 1]; 248 Graphics::TransparentSurface _agfx[kPicButtonStateMax + 1]; 249 int _alpha; 250 bool _transparency; 251 bool _showButton; 252 bool _isAlpha; 253 ThemeEngine::AutoScaleMode _mode; 254 }; 255 256 /* CheckboxWidget */ 257 class CheckboxWidget : public ButtonWidget { 258 protected: 259 bool _state; 260 public: 261 CheckboxWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); 262 CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); 263 264 void handleMouseUp(int x, int y, int button, int clickCount); handleMouseEntered(int button)265 virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } handleMouseLeft(int button)266 virtual void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } 267 268 void setState(bool state); toggleState()269 void toggleState() { setState(!_state); } getState()270 bool getState() const { return _state; } 271 272 protected: 273 void drawWidget(); 274 }; 275 276 class RadiobuttonWidget; 277 278 class RadiobuttonGroup : public CommandSender { 279 public: 280 RadiobuttonGroup(GuiObject *boss, uint32 cmd = 0); ~RadiobuttonGroup()281 ~RadiobuttonGroup() {} 282 addButton(RadiobuttonWidget * button)283 void addButton(RadiobuttonWidget *button) { _buttons.push_back(button); } getButtonList()284 Common::Array<RadiobuttonWidget *> getButtonList() const { return _buttons; } 285 286 void setValue(int state); getValue()287 int getValue() const { return _value; } 288 289 void setEnabled(bool ena); 290 setCmd(uint32 cmd)291 void setCmd(uint32 cmd) { _cmd = cmd; } getCmd()292 uint32 getCmd() const { return _cmd; } 293 294 protected: 295 Common::Array<RadiobuttonWidget *> _buttons; 296 int _value; 297 uint32 _cmd; 298 }; 299 300 /* RadiobuttonWidget */ 301 class RadiobuttonWidget : public ButtonWidget { 302 protected: 303 bool _state; 304 int _value; 305 306 public: 307 RadiobuttonWidget(GuiObject *boss, int x, int y, int w, int h, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip = 0, uint8 hotkey = 0); 308 RadiobuttonWidget(GuiObject *boss, const Common::String &name, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip = 0, uint8 hotkey = 0); 309 310 void handleMouseUp(int x, int y, int button, int clickCount); handleMouseEntered(int button)311 virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } handleMouseLeft(int button)312 virtual void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } 313 314 void setState(bool state, bool setGroup = true); toggleState()315 void toggleState() { setState(!_state); } getState()316 bool getState() const { return _state; } getValue()317 int getValue() const { return _value; } 318 319 protected: 320 void drawWidget(); 321 322 RadiobuttonGroup *_group; 323 }; 324 325 /* SliderWidget */ 326 class SliderWidget : public Widget, public CommandSender { 327 protected: 328 uint32 _cmd; 329 int _value, _oldValue; 330 int _valueMin, _valueMax; 331 bool _isDragging; 332 uint _labelWidth; 333 public: 334 SliderWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0, uint32 cmd = 0); 335 SliderWidget(GuiObject *boss, const Common::String &name, const char *tooltip = 0, uint32 cmd = 0); 336 setCmd(uint32 cmd)337 void setCmd(uint32 cmd) { _cmd = cmd; } getCmd()338 uint32 getCmd() const { return _cmd; } 339 setValue(int value)340 void setValue(int value) { _value = value; } getValue()341 int getValue() const { return _value; } 342 setMinValue(int value)343 void setMinValue(int value) { _valueMin = value; } getMinValue()344 int getMinValue() const { return _valueMin; } setMaxValue(int value)345 void setMaxValue(int value) { _valueMax = value; } getMaxValue()346 int getMaxValue() const { return _valueMax; } 347 348 void handleMouseMoved(int x, int y, int button); 349 void handleMouseDown(int x, int y, int button, int clickCount); 350 void handleMouseUp(int x, int y, int button, int clickCount); handleMouseEntered(int button)351 void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } handleMouseLeft(int button)352 void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } 353 void handleMouseWheel(int x, int y, int direction); 354 355 protected: 356 void drawWidget(); 357 358 int valueToPos(int value); 359 int posToValue(int pos); 360 int valueToBarWidth(int value); 361 }; 362 363 /* GraphicsWidget */ 364 class GraphicsWidget : public Widget { 365 public: 366 GraphicsWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0); 367 GraphicsWidget(GuiObject *boss, const Common::String &name, const char *tooltip = 0); 368 ~GraphicsWidget(); 369 370 void setGfx(const Graphics::Surface *gfx); 371 void setGfx(int w, int h, int r, int g, int b); 372 void setAGfx(const Graphics::TransparentSurface *gfx, ThemeEngine::AutoScaleMode mode = ThemeEngine::kAutoScaleNone); 373 useAlpha(int alpha)374 void useAlpha(int alpha) { _alpha = alpha; } useThemeTransparency(bool enable)375 void useThemeTransparency(bool enable) { _transparency = enable; } 376 377 protected: 378 void drawWidget(); 379 380 Graphics::Surface _gfx; 381 Graphics::TransparentSurface _agfx; 382 int _alpha; 383 bool _transparency; 384 ThemeEngine::AutoScaleMode _mode; 385 }; 386 387 /* ContainerWidget */ 388 class ContainerWidget : public Widget { 389 public: 390 ContainerWidget(GuiObject *boss, int x, int y, int w, int h); 391 ContainerWidget(GuiObject *boss, const Common::String &name); 392 ~ContainerWidget(); 393 394 virtual bool containsWidget(Widget *) const; 395 virtual Widget *findWidget(int x, int y); 396 virtual void removeWidget(Widget *widget); 397 protected: 398 void drawWidget(); 399 }; 400 401 ButtonWidget *addClearButton(GuiObject *boss, const Common::String &name, uint32 cmd, int x=0, int y=0, int w=0, int h=0); 402 403 } // End of namespace GUI 404 405 #endif 406