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 "Widget.hxx" |
20 | #include "Font.hxx" |
21 | #include "Debugger.hxx" |
22 | #include "FBSurface.hxx" |
23 | #include "TogglePixelWidget.hxx" |
24 | |
25 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
26 | TogglePixelWidget::TogglePixelWidget(GuiObject* boss, const GUI::Font& font, |
27 | int x, int y, int cols, int rows) |
28 | : ToggleWidget(boss, font, x, y, cols, rows, 1), |
29 | _pixelColor(kNone), |
30 | _backgroundColor(kDlgColor), |
31 | _swapBits(false), |
32 | _crossBits(false) |
33 | { |
34 | _rowHeight = _colWidth = font.getLineHeight(); |
35 | |
36 | // Calculate real dimensions |
37 | _w = _colWidth * cols + 1; |
38 | _h = _rowHeight * rows + 1; |
39 | |
40 | // Changed state isn't used, but we still need to fill it |
41 | while(int(_changedList.size()) < rows * cols) |
42 | _changedList.push_back(false); |
43 | // prepare _stateList for change tracking |
44 | while(int(_stateList.size()) < rows * cols) |
45 | _stateList.push_back(false); |
46 | } |
47 | |
48 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
49 | void TogglePixelWidget::setState(const BoolArray& state) |
50 | { |
51 | // track changes automatically |
52 | for(int row = 0; row < _rows; row++) |
53 | { |
54 | for(int col = 0; col < _cols; col++) |
55 | { |
56 | int pos = row * _cols + col; |
57 | |
58 | _changedList[pos] = _stateList[pos] != state[pos]; |
59 | } |
60 | } |
61 | |
62 | _stateList.clear(); |
63 | _stateList = state; |
64 | |
65 | setDirty(); |
66 | } |
67 | |
68 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
69 | void TogglePixelWidget::setIntState(int value, bool swap) |
70 | { |
71 | uInt32 size = _rows * _cols; |
72 | _swapBits = swap; |
73 | |
74 | // Create array of required size |
75 | BoolArray b; |
76 | while(b.size() < size) |
77 | b.push_back(false); |
78 | |
79 | // Bits in an int increase from right to left, but a BoolArray |
80 | // is scanned from left to right. |
81 | // |
82 | // Swap off means treat the above as normal (ie, contruct the |
83 | // BoolArray as we read the int from right to left). |
84 | // |
85 | // Swap on means reverse of swap off! Sorry if this is |
86 | // confusing. |
87 | for(uInt32 i = 0; i < size; ++i) |
88 | { |
89 | bool bitIsSet = value & (1 << i); |
90 | if(_swapBits) |
91 | b[i] = bitIsSet; |
92 | else |
93 | b[size-i-1] = bitIsSet; |
94 | } |
95 | |
96 | setState(b); |
97 | } |
98 | |
99 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
100 | int TogglePixelWidget::getIntState() |
101 | { |
102 | // Construct int based on current state and swap |
103 | uInt32 value = 0, size = int(_stateList.size()); |
104 | |
105 | for(uInt32 i = 0; i < size; ++i) |
106 | { |
107 | if(_stateList[i]) |
108 | { |
109 | if(_swapBits) |
110 | value |= 1 << i; |
111 | else |
112 | value |= 1 << (size-i-1); |
113 | } |
114 | } |
115 | |
116 | return value; |
117 | } |
118 | |
119 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
120 | void TogglePixelWidget::drawWidget(bool hilite) |
121 | { |
122 | //cerr << "TogglePixelWidget::drawWidget\n"; |
123 | FBSurface& s = dialog().surface(); |
124 | bool onTop = _boss->dialog().isOnTop(); |
125 | int row, col; |
126 | |
127 | s.frameRect(_x, _y, _w, _h, hilite && isEnabled() && isEditable() ? kWidColorHi : kColor); |
128 | |
129 | // Draw the internal grid and labels |
130 | int linewidth = _cols * _colWidth; |
131 | for (row = 1; row <= _rows - 1; row++) |
132 | s.hLine(_x, _y + (row * _rowHeight), _x + linewidth, kColor); |
133 | int lineheight = _rows * _rowHeight; |
134 | for (col = 1; col <= _cols - 1; col++) |
135 | s.vLine(_x + (col * _colWidth), _y, _y + lineheight, kColor); |
136 | |
137 | // Draw the pixels |
138 | for (row = 0; row < _rows; row++) |
139 | { |
140 | for (col = 0; col < _cols; col++) |
141 | { |
142 | int x = _x + 4 + (col * _colWidth); |
143 | int y = _y + 2 + (row * _rowHeight); |
144 | int pos = row*_cols + col; |
145 | |
146 | // Draw the selected item inverted, on a highlighted background. |
147 | if (_currentRow == row && _currentCol == col && _hasFocus) |
148 | s.fillRect(x - 4, y - 2, _colWidth+1, _rowHeight+1, kTextColorHi); |
149 | |
150 | // Either draw the pixel in given color, or erase (show background) |
151 | s.fillRect(x - 3, y - 1, _colWidth-1, _rowHeight-1, |
152 | _stateList[pos] ? onTop ? _pixelColor : kColor : onTop ? _backgroundColor : kBGColorLo); |
153 | if (_changedList[pos]) |
154 | s.frameRect(x - 3, y - 1, _colWidth - 1, _rowHeight - 1, kDbgChangedColor); |
155 | } |
156 | } |
157 | |
158 | // Cross out the bits? |
159 | if(_crossBits) |
160 | { |
161 | for(col = 0; col < _cols; ++col) |
162 | { |
163 | int x = _x + col * _colWidth; |
164 | |
165 | s.line(x + 1, _y + 1, x + _colWidth - 1, _y + lineheight - 1, kColor); |
166 | s.line(x + _colWidth - 1, _y + 1, x + 1, _y + lineheight - 1, kColor); |
167 | } |
168 | } |
169 | } |
170 | |