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