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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
26TogglePixelWidget::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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
49void 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
69void 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
100int 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// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
120void 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