1 //============================================================================ 2 // 3 // SSSS tt lll lll 4 // SS SS tt ll ll 5 // SS tttttt eeee ll ll aaaa 6 // SSSS tt ee ee ll ll aa 7 // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" 8 // SS SS tt ee ll ll aa aa 9 // SSSS ttt eeeee llll llll aaaaa 10 // 11 // Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony 12 // and the Stella Team 13 // 14 // See the file "License.txt" for information on usage and redistribution of 15 // this file, and for a DISCLAIMER OF ALL WARRANTIES. 16 // 17 // Based on code from ScummVM - Scumm Interpreter 18 // Copyright (C) 2002-2004 The ScummVM project 19 //============================================================================ 20 21 #ifndef WIDGET_HXX 22 #define WIDGET_HXX 23 24 class Dialog; 25 26 #include <cassert> 27 28 #include "bspf.hxx" 29 #include "Rect.hxx" 30 #include "Event.hxx" 31 #include "EventHandlerConstants.hxx" 32 #include "FrameBufferConstants.hxx" 33 #include "StellaKeys.hxx" 34 #include "GuiObject.hxx" 35 #include "Font.hxx" 36 37 /** 38 This is the base class for all widgets. 39 40 @author Stephen Anthony 41 */ 42 class Widget : public GuiObject 43 { 44 friend class Dialog; 45 46 public: 47 Widget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h); 48 ~Widget() override; 49 getAbsX() const50 virtual int getAbsX() const override { return _x + _boss->getChildX(); } getAbsY() const51 virtual int getAbsY() const override { return _y + _boss->getChildY(); } getLeft() const52 virtual int getLeft() const { return _x; } getTop() const53 virtual int getTop() const { return _y; } getRight() const54 virtual int getRight() const { return _x + getWidth(); } getBottom() const55 virtual int getBottom() const { return _y + getHeight(); } 56 virtual void setPosX(int x); 57 virtual void setPosY(int y); 58 virtual void setPos(int x, int y); 59 virtual void setPos(const Common::Point& pos); 60 void setWidth(int w) override; 61 void setHeight(int h) override; 62 virtual void setSize(int w, int h); 63 virtual void setSize(const Common::Point& pos); 64 handleText(char text)65 virtual bool handleText(char text) { return false; } handleKeyDown(StellaKey key,StellaMod mod)66 virtual bool handleKeyDown(StellaKey key, StellaMod mod) { return false; } handleKeyUp(StellaKey key,StellaMod mod)67 virtual bool handleKeyUp(StellaKey key, StellaMod mod) { return false; } handleMouseDown(int x,int y,MouseButton b,int clickCount)68 virtual void handleMouseDown(int x, int y, MouseButton b, int clickCount) { } handleMouseUp(int x,int y,MouseButton b,int clickCount)69 virtual void handleMouseUp(int x, int y, MouseButton b, int clickCount) { } 70 virtual void handleMouseEntered(); 71 virtual void handleMouseLeft(); handleMouseMoved(int x,int y)72 virtual void handleMouseMoved(int x, int y) { } handleMouseWheel(int x,int y,int direction)73 virtual void handleMouseWheel(int x, int y, int direction) { } handleMouseClicks(int x,int y,MouseButton b)74 virtual bool handleMouseClicks(int x, int y, MouseButton b) { return false; } handleJoyDown(int stick,int button,bool longPress=false)75 virtual void handleJoyDown(int stick, int button, bool longPress = false) { } handleJoyUp(int stick,int button)76 virtual void handleJoyUp(int stick, int button) { } handleJoyAxis(int stick,JoyAxis axis,JoyDir adir,int button=JOY_CTRL_NONE)77 virtual void handleJoyAxis(int stick, JoyAxis axis, JoyDir adir, int button = JOY_CTRL_NONE) { } handleJoyHat(int stick,int hat,JoyHatDir hdir,int button=JOY_CTRL_NONE)78 virtual bool handleJoyHat(int stick, int hat, JoyHatDir hdir, int button = JOY_CTRL_NONE) { return false; } handleEvent(Event::Type event)79 virtual bool handleEvent(Event::Type event) { return false; } 80 81 void tick() override; 82 83 void setDirty() override; 84 void setDirtyChain() override; 85 void draw() override; 86 void drawChain() override; 87 void receivedFocus(); 88 void lostFocus(); addFocusWidget(Widget * w)89 void addFocusWidget(Widget* w) override { _focusList.push_back(w); } addToFocusList(const WidgetArray & list)90 void addToFocusList(const WidgetArray& list) override { 91 Vec::append(_focusList, list); 92 } 93 94 /** Set/clear FLAG_ENABLED */ 95 void setEnabled(bool e); 96 isEnabled() const97 bool isEnabled() const { return _flags & FLAG_ENABLED; } isVisible() const98 bool isVisible() const override { return !(_flags & FLAG_INVISIBLE); } isHighlighted() const99 bool isHighlighted() const { return _flags & FLAG_HILITED; } hasMouseFocus() const100 bool hasMouseFocus() const { return _flags & FLAG_MOUSE_FOCUS; } wantsFocus() const101 virtual bool wantsFocus() const { return _flags & FLAG_RETAIN_FOCUS; } wantsTab() const102 bool wantsTab() const { return _flags & FLAG_WANTS_TAB; } wantsRaw() const103 bool wantsRaw() const { return _flags & FLAG_WANTS_RAWDATA; } 104 setID(uInt32 id)105 void setID(uInt32 id) { _id = id; } getID() const106 uInt32 getID() const { return _id; } 107 font() const108 virtual const GUI::Font& font() const { return _font; } 109 setTextColor(ColorId color)110 void setTextColor(ColorId color) { _textcolor = color; setDirty(); } setTextColorHi(ColorId color)111 void setTextColorHi(ColorId color) { _textcolorhi = color; setDirty(); } setBGColor(ColorId color)112 void setBGColor(ColorId color) { _bgcolor = color; setDirty(); } setBGColorHi(ColorId color)113 void setBGColorHi(ColorId color) { _bgcolorhi = color; setDirty(); } setShadowColor(ColorId color)114 void setShadowColor(ColorId color) { _shadowcolor = color; setDirty(); } 115 116 void setToolTip(const string& text); getToolTip(const Common::Point & pos) const117 virtual string getToolTip(const Common::Point& pos) const { return _toolTipText; } changedToolTip(const Common::Point & oldPos,const Common::Point & newPos) const118 virtual bool changedToolTip(const Common::Point& oldPos, 119 const Common::Point& newPos) const { return false; } 120 121 void setHelpAnchor(const string& helpAnchor, bool debugger = false); 122 void setHelpURL(const string& helpURL); 123 loadConfig()124 virtual void loadConfig() { } 125 126 protected: drawWidget(bool hilite)127 virtual void drawWidget(bool hilite) { } 128 receivedFocusWidget()129 virtual void receivedFocusWidget() { } lostFocusWidget()130 virtual void lostFocusWidget() { } 131 findWidget(int x,int y)132 virtual Widget* findWidget(int x, int y) { return this; } 133 releaseFocus()134 void releaseFocus() override { assert(_boss); _boss->releaseFocus(); } 135 wantsToolTip() const136 virtual bool wantsToolTip() const { return hasMouseFocus() && hasToolTip(); } hasToolTip() const137 virtual bool hasToolTip() const { return !_toolTipText.empty(); } 138 139 // By default, delegate unhandled commands to the boss handleCommand(CommandSender * sender,int cmd,int data,int id)140 void handleCommand(CommandSender* sender, int cmd, int data, int id) override 141 { assert(_boss); _boss->handleCommand(sender, cmd, data, id); } 142 143 const string getHelpURL() const override; hasHelp() const144 bool hasHelp() const override { return !getHelpURL().empty(); } 145 146 protected: 147 GuiObject* _boss{nullptr}; 148 const GUI::Font& _font; 149 Widget* _next{nullptr}; 150 uInt32 _id{0}; 151 bool _hasFocus{false}; 152 int _fontWidth{0}; 153 int _lineHeight{0}; 154 ColorId _bgcolor{kWidColor}; 155 ColorId _bgcolorhi{kWidColor}; 156 ColorId _bgcolorlo{kBGColorLo}; 157 ColorId _textcolor{kTextColor}; 158 ColorId _textcolorhi{kTextColorHi}; 159 ColorId _textcolorlo{kBGColorLo}; 160 ColorId _shadowcolor{kShadowColor}; 161 string _toolTipText; 162 string _helpAnchor; 163 string _helpURL; 164 bool _debuggerHelp{false}; 165 166 public: 167 static Widget* findWidgetInChain(Widget* start, int x, int y); 168 169 /** Determine if 'find' is in the chain pointed to by 'start' */ 170 static bool isWidgetInChain(Widget* start, Widget* find); 171 172 /** Determine if 'find' is in the widget array */ 173 static bool isWidgetInChain(const WidgetArray& list, Widget* find); 174 175 /** Select either previous, current, or next widget in chain to have 176 focus, and deselects all others */ 177 static Widget* setFocusForChain(GuiObject* boss, WidgetArray& arr, 178 Widget* w, int direction, 179 bool emitFocusEvents = true); 180 181 /** Sets all widgets in this chain to be dirty (must be redrawn) */ 182 static void setDirtyInChain(Widget* start); 183 184 private: 185 // Following constructors and assignment operators not supported 186 Widget() = delete; 187 Widget(const Widget&) = delete; 188 Widget(Widget&&) = delete; 189 Widget& operator=(const Widget&) = delete; 190 Widget& operator=(Widget&&) = delete; 191 }; 192 193 /* StaticTextWidget */ 194 class StaticTextWidget : public Widget, public CommandSender 195 { 196 public: 197 enum { 198 kClickedCmd = 'STcl', 199 kOpenUrlCmd = 'STou' 200 }; 201 202 public: 203 StaticTextWidget(GuiObject* boss, const GUI::Font& font, 204 int x, int y, int w, int h, 205 const string& text = "", TextAlign align = TextAlign::Left, 206 ColorId shadowColor = kNone); 207 StaticTextWidget(GuiObject* boss, const GUI::Font& font, 208 int x, int y, 209 const string& text = "", TextAlign align = TextAlign::Left, 210 ColorId shadowColor = kNone); 211 ~StaticTextWidget() override = default; 212 setCmd(int cmd)213 void setCmd(int cmd) { _cmd = cmd; } 214 215 void setValue(int value); 216 void setLabel(const string& label); setAlign(TextAlign align)217 void setAlign(TextAlign align) { _align = align; setDirty(); } getLabel() const218 const string& getLabel() const { return _label; } isEditable() const219 bool isEditable() const { return _editable; } 220 221 void setLink(size_t start = string::npos, int len = 0, bool underline = false); 222 bool setUrl(const string& url = EmptyString, const string& label = EmptyString, 223 const string& placeHolder = EmptyString); getUrl() const224 const string& getUrl() const { return _url; } 225 226 protected: 227 void handleMouseEntered() override; 228 void handleMouseLeft() override; 229 void handleMouseUp(int x, int y, MouseButton b, int clickCount) override; 230 231 void drawWidget(bool hilite) override; 232 233 protected: 234 string _label; 235 bool _editable{false}; 236 TextAlign _align{TextAlign::Left}; 237 int _cmd{0}; 238 size_t _linkStart{string::npos}; 239 int _linkLen{0}; 240 bool _linkUnderline{false}; 241 string _url; 242 243 private: 244 // Following constructors and assignment operators not supported 245 StaticTextWidget() = delete; 246 StaticTextWidget(const StaticTextWidget&) = delete; 247 StaticTextWidget(StaticTextWidget&&) = delete; 248 StaticTextWidget& operator=(const StaticTextWidget&) = delete; 249 StaticTextWidget& operator=(StaticTextWidget&&) = delete; 250 }; 251 252 /* ButtonWidget */ 253 class ButtonWidget : public StaticTextWidget 254 { 255 public: 256 ButtonWidget(GuiObject* boss, const GUI::Font& font, 257 int x, int y, int w, int h, 258 const string& label, int cmd = 0, bool repeat = false); 259 ButtonWidget(GuiObject* boss, const GUI::Font& font, 260 int x, int y, int dw, 261 const string& label, int cmd = 0, bool repeat = false); 262 ButtonWidget(GuiObject* boss, const GUI::Font& font, 263 int x, int y, 264 const string& label, int cmd = 0, bool repeat = false); 265 ButtonWidget(GuiObject* boss, const GUI::Font& font, 266 int x, int y, int dw, int dh, 267 const uInt32* bitmap, int bmw, int bmh, 268 int cmd = 0, bool repeat = false); 269 ~ButtonWidget() override = default; 270 271 bool handleEvent(Event::Type event) override; 272 setCmd(int cmd)273 void setCmd(int cmd) { _cmd = cmd; } getCmd() const274 int getCmd() const { return _cmd; } 275 /* Sets/changes the button's bitmap **/ 276 void setBitmap(const uInt32* bitmap, int bmw, int bmh); 277 278 protected: 279 bool handleMouseClicks(int x, int y, MouseButton b) override; 280 void handleMouseDown(int x, int y, MouseButton b, int clickCount) override; 281 void handleMouseUp(int x, int y, MouseButton b, int clickCount) override; 282 void handleMouseEntered() override; 283 void handleMouseLeft() override; 284 285 void drawWidget(bool hilite) override; 286 287 protected: 288 bool _repeat{false}; // button repeats 289 bool _useBitmap{false}; 290 const uInt32* _bitmap{nullptr}; 291 int _bmw{0}, _bmh{0}; 292 293 private: 294 // Following constructors and assignment operators not supported 295 ButtonWidget() = delete; 296 ButtonWidget(const ButtonWidget&) = delete; 297 ButtonWidget(ButtonWidget&&) = delete; 298 ButtonWidget& operator=(const ButtonWidget&) = delete; 299 ButtonWidget& operator=(ButtonWidget&&) = delete; 300 }; 301 302 /* CheckboxWidget */ 303 class CheckboxWidget : public ButtonWidget 304 { 305 public: 306 enum { kCheckActionCmd = 'CBAC' }; 307 enum class FillType { Normal, Inactive, Circle }; 308 309 public: 310 CheckboxWidget(GuiObject* boss, const GUI::Font& font, int x, int y, 311 const string& label, int cmd = 0); 312 ~CheckboxWidget() override = default; 313 314 void setEditable(bool editable); 315 void setFill(FillType type); 316 317 void setState(bool state, bool changed = false); toggleState()318 void toggleState() { setState(!_state); } getState() const319 bool getState() const { return _state; } 320 321 void handleMouseUp(int x, int y, MouseButton b, int clickCount) override; 322 boxSize(const GUI::Font & font)323 static int boxSize(const GUI::Font& font) 324 { 325 return font.getFontHeight() < 24 ? 14 : 22; // box is square 326 } prefixSize(const GUI::Font & font)327 static int prefixSize(const GUI::Font& font) 328 { 329 return boxSize(font) + font.getMaxCharWidth() * 0.75; 330 } 331 332 protected: 333 void drawWidget(bool hilite) override; 334 335 protected: 336 bool _state{false}; 337 bool _holdFocus{true}; 338 bool _drawBox{true}; 339 bool _changed{false}; 340 341 const uInt32* _outerCircle{nullptr}; 342 const uInt32* _innerCircle{nullptr}; 343 const uInt32* _img{nullptr}; 344 ColorId _fillColor{kColor}; 345 int _boxY{0}; 346 int _textY{0}; 347 int _boxSize{14}; 348 349 private: 350 // Following constructors and assignment operators not supported 351 CheckboxWidget() = delete; 352 CheckboxWidget(const CheckboxWidget&) = delete; 353 CheckboxWidget(CheckboxWidget&&) = delete; 354 CheckboxWidget& operator=(const CheckboxWidget&) = delete; 355 CheckboxWidget& operator=(CheckboxWidget&&) = delete; 356 }; 357 358 /* SliderWidget */ 359 class SliderWidget : public ButtonWidget 360 { 361 public: 362 SliderWidget(GuiObject* boss, const GUI::Font& font, 363 int x, int y, int w, int h, 364 const string& label = "", int labelWidth = 0, int cmd = 0, 365 int valueLabelWidth = 0, const string& valueUnit = "", 366 int valueLabelGap = 0, bool forceLabelSign = false); 367 SliderWidget(GuiObject* boss, const GUI::Font& font, 368 int x, int y, 369 const string& label = "", int labelWidth = 0, int cmd = 0, 370 int valueLabelWidth = 0, const string& valueUnit = "", 371 int valueLabelGap = 0, bool forceLabelSign = false); 372 ~SliderWidget() override = default; 373 374 void setValue(int value); getValue() const375 int getValue() const { return BSPF::clamp(_value, _valueMin, _valueMax); } 376 377 void setMinValue(int value); getMinValue() const378 int getMinValue() const { return _valueMin; } 379 void setMaxValue(int value); getMaxValue() const380 int getMaxValue() const { return _valueMax; } 381 void setStepValue(int value); getStepValue() const382 int getStepValue() const { return _stepValue; } 383 void setValueLabel(const string& valueLabel); 384 void setValueLabel(int value); getValueLabel() const385 const string& getValueLabel() const { return _valueLabel; } 386 void setValueUnit(const string& valueUnit); 387 388 void setTickmarkIntervals(int numIntervals); 389 390 protected: 391 void handleMouseMoved(int x, int y) override; 392 void handleMouseDown(int x, int y, MouseButton b, int clickCount) override; 393 void handleMouseUp(int x, int y, MouseButton b, int clickCount) override; 394 void handleMouseWheel(int x, int y, int direction) override; 395 bool handleEvent(Event::Type event) override; 396 397 void drawWidget(bool hilite) override; 398 399 int valueToPos(int value) const; 400 int posToValue(int pos) const; 401 402 protected: 403 int _value{-INT_MAX}, _stepValue{1}; 404 int _valueMin{0}, _valueMax{100}; 405 bool _isDragging{false}; 406 int _labelWidth{0}; 407 string _valueLabel; 408 string _valueUnit; 409 int _valueLabelGap{0}; 410 int _valueLabelWidth{0}; 411 bool _forceLabelSign{false}; 412 int _numIntervals{0}; 413 414 private: 415 // Following constructors and assignment operators not supported 416 SliderWidget() = delete; 417 SliderWidget(const SliderWidget&) = delete; 418 SliderWidget(SliderWidget&&) = delete; 419 SliderWidget& operator=(const SliderWidget&) = delete; 420 SliderWidget& operator=(SliderWidget&&) = delete; 421 }; 422 423 #endif 424