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
18#include "FBSurface.hxx"
19#include "Font.hxx"
20#include "Dialog.hxx"
21#include "RadioButtonWidget.hxx"
22
23/* Radiobutton bitmaps */
24static uInt32 radio_img_outercircle[14] =
25{
26 0b00001111110000,
27 0b00110000001100,
28 0b01000000000010,
29 0b01000000000010,
30 0b10000000000001,
31 0b10000000000001,
32 0b10000000000001,
33 0b10000000000001,
34 0b10000000000001,
35 0b10000000000001,
36 0b01000000000010,
37 0b01000000000010,
38 0b00110000001100,
39 0b00001111110000
40};
41
42static uInt32 radio_img_innercircle[12] =
43{
44 0b000111111000,
45 0b011111111110,
46 0b011111111110,
47 0b111111111111,
48 0b111111111111,
49 0b111111111111,
50 0b111111111111,
51 0b111111111111,
52 0b111111111111,
53 0b011111111110,
54 0b011111111110,
55 0b000111111000
56};
57
58static uInt32 radio_img_active[10] =
59{
60 0b0011111100,
61 0b0111111110,
62 0b1111111111,
63 0b1111111111,
64 0b1111111111,
65 0b1111111111,
66 0b1111111111,
67 0b1111111111,
68 0b0111111110,
69 0b0011111100,
70};
71
72static uInt32 radio_img_inactive[10] =
73{
74 0b0011111100,
75 0b0111111110,
76 0b1111001111,
77 0b1110000111,
78 0b1100000011,
79 0b1100000011,
80 0b1110000111,
81 0b1111001111,
82 0b0111111110,
83 0b0011111100
84};
85
86// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
87RadioButtonWidget::RadioButtonWidget(GuiObject* boss, const GUI::Font& font,
88 int x, int y, const string& label,
89 RadioButtonGroup* group,
90 int cmd)
91 : CheckboxWidget(boss, font, x, y, label, cmd),
92 myGroup(group)
93{
94 _flags = Widget::FLAG_ENABLED;
95 _bgcolor = _bgcolorhi = kWidColor;
96
97 _editable = true;
98
99 if(label == "")
100 _w = 14;
101 else
102 _w = font.getStringWidth(label) + 20;
103 _h = font.getFontHeight() < 14 ? 14 : font.getFontHeight();
104
105
106 // Depending on font size, either the font or box will need to be
107 // centered vertically
108 if(_h > 14) // center box
109 _boxY = (_h - 14) / 2;
110 else // center text
111 _textY = (14 - _font.getFontHeight()) / 2;
112
113 setFill(CheckboxWidget::FillType::Normal);
114 myGroup->addWidget(this);
115}
116
117// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
118void RadioButtonWidget::handleMouseUp(int x, int y, MouseButton b, int clickCount)
119{
120 if(isEnabled() && _editable && x >= 0 && x < _w && y >= 0 && y < _h)
121 {
122 if(!_state)
123 setState(true);
124 }
125}
126
127// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
128void RadioButtonWidget::setState(bool state, bool send)
129{
130 if(_state != state)
131 {
132 _state = state;
133 setDirty();
134 if(_state && send)
135 sendCommand(_cmd, _state, _id);
136 if (state)
137 myGroup->select(this);
138 }
139}
140
141// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
142void RadioButtonWidget::setFill(FillType type)
143{
144 switch(type)
145 {
146 case CheckboxWidget::FillType::Normal:
147 _img = radio_img_active;
148 break;
149 case CheckboxWidget::FillType::Inactive:
150 _img = radio_img_inactive;
151 break;
152 default:
153 break;
154 }
155}
156
157// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
158void RadioButtonWidget::drawWidget(bool hilite)
159{
160 FBSurface& s = _boss->dialog().surface();
161
162 // Draw the outer bounding circle
163 s.drawBitmap(radio_img_outercircle, _x, _y + _boxY, hilite ? kWidColorHi : kColor, 14, 14);
164
165 // Draw the inner bounding circle with enabled color
166 s.drawBitmap(radio_img_innercircle, _x + 1, _y + _boxY + 1, isEnabled()
167 ? _bgcolor : kColor, 12, 12);
168
169 // draw state
170 if(_state)
171 s.drawBitmap(_img, _x + 2, _y + _boxY + 2, isEnabled()
172 ? hilite ? kWidColorHi : kCheckColor
173 : kColor, 10);
174
175 // Finally draw the label
176 s.drawString(_font, _label, _x + 20, _y + _textY, _w,
177 isEnabled() ? kTextColor : kColor);
178}
179
180// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
181void RadioButtonGroup::addWidget(RadioButtonWidget* widget)
182{
183 myWidgets.push_back(widget);
184 // set first button as default
185 widget->setState(myWidgets.size() == 1, false);
186 mySelected = 0;
187}
188
189// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
190void RadioButtonGroup::select(RadioButtonWidget* widget)
191{
192 uInt32 i = 0;
193
194 for(const auto& w : myWidgets)
195 {
196 if(w == widget)
197 {
198 setSelected(i);
199 break;
200 }
201 ++i;
202 }
203}
204
205// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
206void RadioButtonGroup::setSelected(uInt32 selected)
207{
208 uInt32 i = 0;
209
210 mySelected = selected;
211 for(const auto& w : myWidgets)
212 {
213 (static_cast<RadioButtonWidget*>(w))->setState(i == mySelected);
214 ++i;
215 }
216}
217