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 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
24 | ToggleWidget::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 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
44 | void ToggleWidget::handleMouseEntered() |
45 | { |
46 | setFlags(Widget::FLAG_HILITED); |
47 | setDirty(); |
48 | } |
49 | |
50 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
51 | void ToggleWidget::handleMouseLeft() |
52 | { |
53 | clearFlags(Widget::FLAG_HILITED); |
54 | setDirty(); |
55 | } |
56 | |
57 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
58 | void 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 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
79 | void 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 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
96 | int 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 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
108 | bool 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 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
214 | void 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 | |