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 "OSystem.hxx"
19#include "StellaKeys.hxx"
20#include "Widget.hxx"
21#include "ToggleWidget.hxx"
22
23// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
24ToggleWidget::ToggleWidget(GuiObject* boss, const GUI::Font& font,
25 int x, int y, int cols, int rows,
26 int clicksToChange)
27 : Widget(boss, font, x, y, 16, 16),
28 CommandSender(boss),
29 _rows(rows),
30 _cols(cols),
31 _currentRow(0),
32 _currentCol(0),
33 _rowHeight(0),
34 _colWidth(0),
35 _selectedItem(0),
36 _clicksToChange(clicksToChange),
37 _editable(true)
38{
39 _flags = Widget::FLAG_ENABLED | Widget::FLAG_CLEARBG | Widget::FLAG_RETAIN_FOCUS |
40 Widget::FLAG_WANTS_RAWDATA;
41}
42
43// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
44void ToggleWidget::handleMouseEntered()
45{
46 setFlags(Widget::FLAG_HILITED);
47 setDirty();
48}
49
50// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
51void ToggleWidget::handleMouseLeft()
52{
53 clearFlags(Widget::FLAG_HILITED);
54 setDirty();
55}
56
57// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
58void ToggleWidget::handleMouseDown(int x, int y, MouseButton b, int clickCount)
59{
60 if (!isEnabled())
61 return;
62
63 // First check whether the selection changed
64 int newSelectedItem;
65 newSelectedItem = findItem(x, y);
66 if (newSelectedItem > int(_stateList.size()) - 1)
67 newSelectedItem = -1;
68
69 if (_selectedItem != newSelectedItem)
70 {
71 _selectedItem = newSelectedItem;
72 _currentRow = _selectedItem / _cols;
73 _currentCol = _selectedItem - (_currentRow * _cols);
74 setDirty();
75 }
76}
77
78// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
79void ToggleWidget::handleMouseUp(int x, int y, MouseButton b, int clickCount)
80{
81 if (!isEnabled() || !_editable)
82 return;
83
84 // If this was a double click and the mouse is still over the selected item,
85 // send the double click command
86 if (clickCount == _clicksToChange && (_selectedItem == findItem(x, y)))
87 {
88 _stateList[_selectedItem] = !_stateList[_selectedItem];
89 _changedList[_selectedItem] = !_changedList[_selectedItem];
90 sendCommand(ToggleWidget::kItemDataChangedCmd, _selectedItem, _id);
91 setDirty();
92 }
93}
94
95// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
96int ToggleWidget::findItem(int x, int y)
97{
98 int row = (y - 1) / _rowHeight;
99 if(row >= _rows) row = _rows - 1;
100
101 int col = x / _colWidth;
102 if(col >= _cols) col = _cols - 1;
103
104 return row * _cols + col;
105}
106
107// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
108bool ToggleWidget::handleKeyDown(StellaKey key, StellaMod mod)
109{
110 // Ignore all mod keys
111 if(StellaModTest::isControl(mod) || StellaModTest::isAlt(mod))
112 return true;
113
114 bool handled = true;
115 bool dirty = false, toggle = false;
116
117 switch(key)
118 {
119 case KBDK_RETURN:
120 case KBDK_KP_ENTER:
121 if (_currentRow >= 0 && _currentCol >= 0)
122 {
123 dirty = true;
124 toggle = true;
125 }
126 break;
127
128 case KBDK_UP:
129 if (_currentRow > 0)
130 {
131 _currentRow--;
132 dirty = true;
133 }
134 break;
135
136 case KBDK_DOWN:
137 if (_currentRow < int(_rows) - 1)
138 {
139 _currentRow++;
140 dirty = true;
141 }
142 break;
143
144 case KBDK_LEFT:
145 if (_currentCol > 0)
146 {
147 _currentCol--;
148 dirty = true;
149 }
150 break;
151
152 case KBDK_RIGHT:
153 if (_currentCol < int(_cols) - 1)
154 {
155 _currentCol++;
156 dirty = true;
157 }
158 break;
159
160 case KBDK_PAGEUP:
161 if (_currentRow > 0)
162 {
163 _currentRow = 0;
164 dirty = true;
165 }
166 break;
167
168 case KBDK_PAGEDOWN:
169 if (_currentRow < int(_rows) - 1)
170 {
171 _currentRow = _rows - 1;
172 dirty = true;
173 }
174 break;
175
176 case KBDK_HOME:
177 if (_currentCol > 0)
178 {
179 _currentCol = 0;
180 dirty = true;
181 }
182 break;
183
184 case KBDK_END:
185 if (_currentCol < int(_cols) - 1)
186 {
187 _currentCol = _cols - 1;
188 dirty = true;
189 }
190 break;
191
192 default:
193 handled = false;
194 }
195
196 if (dirty)
197 {
198 _selectedItem = _currentRow*_cols + _currentCol;
199
200 if(toggle && _editable)
201 {
202 _stateList[_selectedItem] = !_stateList[_selectedItem];
203 _changedList[_selectedItem] = !_changedList[_selectedItem];
204 sendCommand(ToggleWidget::kItemDataChangedCmd, _selectedItem, _id);
205 }
206
207 setDirty();
208 }
209
210 return handled;
211}
212
213// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
214void ToggleWidget::handleCommand(CommandSender* sender, int cmd,
215 int data, int id)
216{
217 switch (cmd)
218 {
219 case GuiObject::kSetPositionCmd:
220 if (_selectedItem != data)
221 {
222 _selectedItem = data;
223 setDirty();
224 }
225 break;
226 }
227}
228