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-2019 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
24class Dialog;
25
26namespace GUI {
27 class Font;
28}
29
30#include <cassert>
31
32#include "bspf.hxx"
33#include "Event.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*/
42class Widget : public GuiObject
43{
44 friend class Dialog;
45
46 public:
47 enum : uInt32 {
48 FLAG_ENABLED = 1 << 0,
49 FLAG_INVISIBLE = 1 << 1,
50 FLAG_HILITED = 1 << 2,
51 FLAG_BORDER = 1 << 3,
52 FLAG_CLEARBG = 1 << 4,
53 FLAG_TRACK_MOUSE = 1 << 5,
54 FLAG_RETAIN_FOCUS = 1 << 6,
55 FLAG_WANTS_TAB = 1 << 7,
56 FLAG_WANTS_RAWDATA = 1 << 8
57 };
58
59 public:
60 Widget(GuiObject* boss, const GUI::Font& font, int x, int y, int w, int h);
61 virtual ~Widget();
62
63 virtual int getAbsX() const override { return _x + _boss->getChildX(); }
64 virtual int getAbsY() const override { return _y + _boss->getChildY(); }
65 virtual int getLeft() const { return _x; }
66 virtual int getTop() const { return _y; }
67 virtual int getRight() const { return _x + getWidth(); }
68 virtual int getBottom() const { return _y + getHeight(); }
69
70 virtual bool handleText(char text) { return false; }
71 virtual bool handleKeyDown(StellaKey key, StellaMod mod) { return false; }
72 virtual bool handleKeyUp(StellaKey key, StellaMod mod) { return false; }
73 virtual void handleMouseDown(int x, int y, MouseButton b, int clickCount) { }
74 virtual void handleMouseUp(int x, int y, MouseButton b, int clickCount) { }
75 virtual void handleMouseEntered() { }
76 virtual void handleMouseLeft() { }
77 virtual void handleMouseMoved(int x, int y) { }
78 virtual void handleMouseWheel(int x, int y, int direction) { }
79 virtual bool handleMouseClicks(int x, int y, MouseButton b) { return false; }
80 virtual void handleJoyDown(int stick, int button, bool longPress = false) { }
81 virtual void handleJoyUp(int stick, int button) { }
82 virtual void handleJoyAxis(int stick, JoyAxis axis, JoyDir adir, int button = JOY_CTRL_NONE) { }
83 virtual bool handleJoyHat(int stick, int hat, JoyHatDir hdir, int button = JOY_CTRL_NONE) { return false; }
84 virtual bool handleEvent(Event::Type event) { return false; }
85
86 void setDirty() override;
87 void draw() override;
88 void receivedFocus();
89 void lostFocus();
90 void addFocusWidget(Widget* w) override { _focusList.push_back(w); }
91 void addToFocusList(WidgetArray& list) override {
92 Vec::append(_focusList, list);
93 }
94
95 /** Set/clear FLAG_ENABLED */
96 void setEnabled(bool e);
97
98 void setFlags(uInt32 flags) { _flags |= flags; setDirty(); }
99 void clearFlags(uInt32 flags) { _flags &= ~flags; setDirty(); }
100 uInt32 getFlags() const { return _flags; }
101
102 bool isEnabled() const { return _flags & FLAG_ENABLED; }
103 bool isVisible() const override { return !(_flags & FLAG_INVISIBLE); }
104 virtual bool wantsFocus() const { return _flags & FLAG_RETAIN_FOCUS; }
105 bool wantsTab() const { return _flags & FLAG_WANTS_TAB; }
106 bool wantsRaw() const { return _flags & FLAG_WANTS_RAWDATA; }
107
108 void setID(uInt32 id) { _id = id; }
109 uInt32 getID() const { return _id; }
110
111 virtual const GUI::Font& font() const { return _font; }
112
113 void setTextColor(ColorId color) { _textcolor = color; setDirty(); }
114 void setTextColorHi(ColorId color) { _textcolorhi = color; setDirty(); }
115 void setBGColor(ColorId color) { _bgcolor = color; setDirty(); }
116 void setBGColorHi(ColorId color) { _bgcolorhi = color; setDirty(); }
117 void setShadowColor(ColorId color) { _shadowcolor = color; setDirty(); }
118
119 virtual void loadConfig() { }
120
121 protected:
122 virtual void drawWidget(bool hilite) { }
123
124 virtual void receivedFocusWidget() { }
125 virtual void lostFocusWidget() { }
126
127 virtual Widget* findWidget(int x, int y) { return this; }
128
129 void releaseFocus() override { assert(_boss); _boss->releaseFocus(); }
130
131 // By default, delegate unhandled commands to the boss
132 void handleCommand(CommandSender* sender, int cmd, int data, int id) override
133 { assert(_boss); _boss->handleCommand(sender, cmd, data, id); }
134
135 protected:
136 GuiObject* _boss;
137 const GUI::Font& _font;
138 Widget* _next;
139 uInt32 _id;
140 uInt32 _flags;
141 bool _hasFocus;
142 int _fontWidth;
143 int _fontHeight;
144 ColorId _bgcolor;
145 ColorId _bgcolorhi;
146 ColorId _bgcolorlo;
147 ColorId _textcolor;
148 ColorId _textcolorhi;
149 ColorId _textcolorlo;
150 ColorId _shadowcolor;
151
152 public:
153 static Widget* findWidgetInChain(Widget* start, int x, int y);
154
155 /** Determine if 'find' is in the chain pointed to by 'start' */
156 static bool isWidgetInChain(Widget* start, Widget* find);
157
158 /** Determine if 'find' is in the widget array */
159 static bool isWidgetInChain(WidgetArray& list, Widget* find);
160
161 /** Select either previous, current, or next widget in chain to have
162 focus, and deselects all others */
163 static Widget* setFocusForChain(GuiObject* boss, WidgetArray& arr,
164 Widget* w, int direction,
165 bool emitFocusEvents = true);
166
167 /** Sets all widgets in this chain to be dirty (must be redrawn) */
168 static void setDirtyInChain(Widget* start);
169
170 private:
171 // Following constructors and assignment operators not supported
172 Widget() = delete;
173 Widget(const Widget&) = delete;
174 Widget(Widget&&) = delete;
175 Widget& operator=(const Widget&) = delete;
176 Widget& operator=(Widget&&) = delete;
177};
178
179/* StaticTextWidget */
180class StaticTextWidget : public Widget
181{
182 public:
183 StaticTextWidget(GuiObject* boss, const GUI::Font& font,
184 int x, int y, int w, int h,
185 const string& text = "", TextAlign align = TextAlign::Left,
186 ColorId shadowColor = kNone);
187 StaticTextWidget(GuiObject* boss, const GUI::Font& font,
188 int x, int y,
189 const string& text = "", TextAlign align = TextAlign::Left,
190 ColorId shadowColor = kNone);
191 void setValue(int value);
192 void setLabel(const string& label);
193 void setAlign(TextAlign align) { _align = align; setDirty(); }
194 const string& getLabel() const { return _label; }
195 bool isEditable() const { return _editable; }
196
197 protected:
198 void drawWidget(bool hilite) override;
199
200 protected:
201 string _label;
202 bool _editable;
203 TextAlign _align;
204
205 private:
206 // Following constructors and assignment operators not supported
207 StaticTextWidget() = delete;
208 StaticTextWidget(const StaticTextWidget&) = delete;
209 StaticTextWidget(StaticTextWidget&&) = delete;
210 StaticTextWidget& operator=(const StaticTextWidget&) = delete;
211 StaticTextWidget& operator=(StaticTextWidget&&) = delete;
212};
213
214/* ButtonWidget */
215class ButtonWidget : public StaticTextWidget, public CommandSender
216{
217 public:
218 ButtonWidget(GuiObject* boss, const GUI::Font& font,
219 int x, int y, int w, int h,
220 const string& label, int cmd = 0, bool repeat = false);
221 ButtonWidget(GuiObject* boss, const GUI::Font& font,
222 int x, int y, int dw,
223 const string& label, int cmd = 0, bool repeat = false);
224 ButtonWidget(GuiObject* boss, const GUI::Font& font,
225 int x, int y,
226 const string& label, int cmd = 0, bool repeat = false);
227 ButtonWidget(GuiObject* boss, const GUI::Font& font,
228 int x, int y, int dw, int dh,
229 uInt32* bitmap, int bmw, int bmh,
230 int cmd = 0, bool repeat = false);
231
232 void setCmd(int cmd) { _cmd = cmd; }
233 int getCmd() const { return _cmd; }
234 /* Sets/changes the button's bitmap **/
235 void setBitmap(uInt32* bitmap, int bmw, int bmh);
236
237 protected:
238 bool handleMouseClicks(int x, int y, MouseButton b) override;
239 void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
240 void handleMouseUp(int x, int y, MouseButton b, int clickCount) override;
241 void handleMouseEntered() override;
242 void handleMouseLeft() override;
243 bool handleEvent(Event::Type event) override;
244
245 void drawWidget(bool hilite) override;
246
247 protected:
248 int _cmd;
249 bool _repeat; // button repeats
250 bool _useBitmap;
251 uInt32* _bitmap;
252 int _bmw, _bmh;
253
254 private:
255 // Following constructors and assignment operators not supported
256 ButtonWidget() = delete;
257 ButtonWidget(const ButtonWidget&) = delete;
258 ButtonWidget(ButtonWidget&&) = delete;
259 ButtonWidget& operator=(const ButtonWidget&) = delete;
260 ButtonWidget& operator=(ButtonWidget&&) = delete;
261};
262
263/* CheckboxWidget */
264class CheckboxWidget : public ButtonWidget
265{
266 public:
267 enum { kCheckActionCmd = 'CBAC' };
268 enum class FillType { Normal, Inactive, Circle };
269
270 public:
271 CheckboxWidget(GuiObject* boss, const GUI::Font& font, int x, int y,
272 const string& label, int cmd = 0);
273
274 void setEditable(bool editable);
275 void setFill(FillType type);
276
277 void setState(bool state, bool changed = false);
278 void toggleState() { setState(!_state); }
279 bool getState() const { return _state; }
280
281 void handleMouseUp(int x, int y, MouseButton b, int clickCount) override;
282 void handleMouseEntered() override;
283 void handleMouseLeft() override;
284
285 static int boxSize() { return 14; } // box is square
286
287 protected:
288 void drawWidget(bool hilite) override;
289
290 protected:
291 bool _state;
292 bool _holdFocus;
293 bool _drawBox;
294 bool _changed;
295
296 uInt32* _img;
297 ColorId _fillColor;
298 int _boxY;
299 int _textY;
300
301 private:
302 // Following constructors and assignment operators not supported
303 CheckboxWidget() = delete;
304 CheckboxWidget(const CheckboxWidget&) = delete;
305 CheckboxWidget(CheckboxWidget&&) = delete;
306 CheckboxWidget& operator=(const CheckboxWidget&) = delete;
307 CheckboxWidget& operator=(CheckboxWidget&&) = delete;
308};
309
310/* SliderWidget */
311class SliderWidget : public ButtonWidget
312{
313 public:
314 SliderWidget(GuiObject* boss, const GUI::Font& font,
315 int x, int y, int w, int h,
316 const string& label = "", int labelWidth = 0, int cmd = 0,
317 int valueLabelWidth = 0, const string& valueUnit = "", int valueLabelGap = 4);
318 SliderWidget(GuiObject* boss, const GUI::Font& font,
319 int x, int y,
320 const string& label = "", int labelWidth = 0, int cmd = 0,
321 int valueLabelWidth = 0, const string& valueUnit = "", int valueLabelGap = 4);
322
323 void setValue(int value);
324 int getValue() const { return _value; }
325
326 void setMinValue(int value);
327 int getMinValue() const { return _valueMin; }
328 void setMaxValue(int value);
329 int getMaxValue() const { return _valueMax; }
330 void setStepValue(int value);
331 int getStepValue() const { return _stepValue; }
332 void setValueLabel(const string& valueLabel);
333 void setValueLabel(int value);
334 const string& getValueLabel() const { return _valueLabel; }
335 void setValueUnit(const string& valueUnit);
336
337 void setTickmarkIntervals(int numIntervals);
338
339 protected:
340 void handleMouseMoved(int x, int y) override;
341 void handleMouseDown(int x, int y, MouseButton b, int clickCount) override;
342 void handleMouseUp(int x, int y, MouseButton b, int clickCount) override;
343 void handleMouseWheel(int x, int y, int direction) override;
344 bool handleEvent(Event::Type event) override;
345
346 void drawWidget(bool hilite) override;
347
348 int valueToPos(int value) const;
349 int posToValue(int pos) const;
350
351 protected:
352 int _value, _stepValue;
353 int _valueMin, _valueMax;
354 bool _isDragging;
355 int _labelWidth;
356 string _valueLabel;
357 string _valueUnit;
358 int _valueLabelGap;
359 int _valueLabelWidth;
360 int _numIntervals;
361
362 private:
363 // Following constructors and assignment operators not supported
364 SliderWidget() = delete;
365 SliderWidget(const SliderWidget&) = delete;
366 SliderWidget(SliderWidget&&) = delete;
367 SliderWidget& operator=(const SliderWidget&) = delete;
368 SliderWidget& operator=(SliderWidget&&) = delete;
369};
370
371#endif
372