Implement customizable cursor fill color
[pulseview.git] / pv / widgets / wellarray.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QPaintEvent>
43 #include <QPainter>
44 #include <QStyle>
45 #include <QStyleOptionFrame>
46
47 #include "wellarray.hpp"
48
49 namespace pv {
50 namespace widgets {
51
52 void WellArray::paintEvent(QPaintEvent *event)
53 {
54     QRect r = event->rect();
55     int cx = r.x();
56     int cy = r.y();
57     int ch = r.height();
58     int cw = r.width();
59     int colfirst = columnAt(cx);
60     int collast = columnAt(cx + cw);
61     int rowfirst = rowAt(cy);
62     int rowlast = rowAt(cy + ch);
63
64     if (isRightToLeft()) {
65         int t = colfirst;
66         colfirst = collast;
67         collast = t;
68     }
69
70     QPainter painter(this);
71     QPainter *p = &painter;
72     QRect rect(0, 0, cellWidth(), cellHeight());
73
74
75     if (collast < 0 || collast >= ncols)
76         collast = ncols-1;
77     if (rowlast < 0 || rowlast >= nrows)
78         rowlast = nrows-1;
79
80     // Go through the rows
81     for (int r = rowfirst; r <= rowlast; ++r) {
82         // get row position and height
83         int rowp = rowY(r);
84
85         // Go through the columns in the row r
86         // if we know from where to where, go through [colfirst, collast],
87         // else go through all of them
88         for (int c = colfirst; c <= collast; ++c) {
89             // get position and width of column c
90             int colp = columnX(c);
91             // Translate painter and draw the cell
92             rect.translate(colp, rowp);
93             paintCell(p, r, c, rect);
94             rect.translate(-colp, -rowp);
95         }
96     }
97 }
98
99 struct WellArrayData {
100     QBrush *brush;
101 };
102
103 WellArray::WellArray(int rows, int cols, QWidget *parent)
104     : QWidget(parent)
105         ,nrows(rows), ncols(cols)
106 {
107     d = nullptr;
108     setFocusPolicy(Qt::StrongFocus);
109     cellw = 28;
110     cellh = 24;
111     curCol = 0;
112     curRow = 0;
113     selCol = -1;
114     selRow = -1;
115 }
116
117 QSize WellArray::sizeHint() const
118 {
119     ensurePolished();
120     return gridSize().boundedTo(QSize(640, 480));
121 }
122
123
124 void WellArray::paintCell(QPainter* p, int row, int col, const QRect &rect)
125 {
126     int b = 3; //margin
127
128     const QPalette& g = palette();
129     QStyleOptionFrame opt;
130     int dfw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
131     opt.lineWidth = dfw;
132     opt.midLineWidth = 1;
133     opt.rect = rect.adjusted(b, b, -b, -b);
134     opt.palette = g;
135     opt.state = QStyle::State_Enabled | QStyle::State_Sunken;
136     style()->drawPrimitive(QStyle::PE_Frame, &opt, p, this);
137     b += dfw;
138
139     if ((row == curRow) && (col == curCol)) {
140         if (hasFocus()) {
141             QStyleOptionFocusRect opt;
142             opt.palette = g;
143             opt.rect = rect;
144             opt.state = QStyle::State_None | QStyle::State_KeyboardFocusChange;
145             style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, this);
146         }
147     }
148     paintCellContents(p, row, col, opt.rect.adjusted(dfw, dfw, -dfw, -dfw));
149 }
150
151 /*!
152   Reimplement this function to change the contents of the well array.
153  */
154 void WellArray::paintCellContents(QPainter *p, int row, int col, const QRect &r)
155 {
156     if (d) {
157         p->fillRect(r, d->brush[row*numCols()+col]);
158     } else {
159         p->fillRect(r, Qt::white);
160         p->setPen(Qt::black);
161         p->drawLine(r.topLeft(), r.bottomRight());
162         p->drawLine(r.topRight(), r.bottomLeft());
163     }
164 }
165
166 void WellArray::mousePressEvent(QMouseEvent *event)
167 {
168     // The current cell marker is set to the cell the mouse is pressed in
169     QPoint pos = event->pos();
170     setCurrent(rowAt(pos.y()), columnAt(pos.x()));
171 }
172
173 void WellArray::mouseReleaseEvent(QMouseEvent * /* event */)
174 {
175     // The current cell marker is set to the cell the mouse is clicked in
176     setSelected(curRow, curCol);
177 }
178
179
180 /*
181   Sets the cell currently having the focus. This is not necessarily
182   the same as the currently selected cell.
183 */
184
185 void WellArray::setCurrent(int row, int col)
186 {
187     if ((curRow == row) && (curCol == col))
188         return;
189
190     if (row < 0 || col < 0)
191         row = col = -1;
192
193     int oldRow = curRow;
194     int oldCol = curCol;
195
196     curRow = row;
197     curCol = col;
198
199     updateCell(oldRow, oldCol);
200     updateCell(curRow, curCol);
201 }
202
203 /*
204   Sets the currently selected cell to \a row, \a column. If \a row or
205   \a column are less than zero, the current cell is unselected.
206
207   Does not set the position of the focus indicator.
208 */
209 void WellArray::setSelected(int row, int col)
210 {
211     int oldRow = selRow;
212     int oldCol = selCol;
213
214     if (row < 0 || col < 0)
215         row = col = -1;
216
217     selCol = col;
218     selRow = row;
219
220     updateCell(oldRow, oldCol);
221     updateCell(selRow, selCol);
222     if (row >= 0)
223         selected(row, col);
224 }
225
226 void WellArray::focusInEvent(QFocusEvent*)
227 {
228     updateCell(curRow, curCol);
229 }
230
231 void WellArray::setCellBrush(int row, int col, const QBrush &b)
232 {
233     if (!d) {
234         d = new WellArrayData;
235         int i = numRows()*numCols();
236         d->brush = new QBrush[i];
237     }
238     if (row >= 0 && row < numRows() && col >= 0 && col < numCols())
239         d->brush[row*numCols()+col] = b;
240 }
241
242 /*
243   Returns the brush set for the cell at \a row, \a column. If no brush is
244   set, Qt::NoBrush is returned.
245 */
246
247 QBrush WellArray::cellBrush(int row, int col)
248 {
249     if (d && row >= 0 && row < numRows() && col >= 0 && col < numCols())
250         return d->brush[row*numCols()+col];
251     return Qt::NoBrush;
252 }
253
254
255
256 /*!\reimp
257 */
258
259 void WellArray::focusOutEvent(QFocusEvent*)
260 {
261     updateCell(curRow, curCol);
262 }
263
264 /*\reimp
265 */
266 void WellArray::keyPressEvent(QKeyEvent* event)
267 {
268     switch (event->key()) {                        // Look at the key code
269     case Qt::Key_Left:                                // If 'left arrow'-key,
270         if (curCol > 0)                        // and cr't not in leftmost col
271             setCurrent(curRow, curCol - 1);        // set cr't to next left column
272         break;
273     case Qt::Key_Right:                                // Correspondingly...
274         if (curCol < numCols()-1)
275             setCurrent(curRow, curCol + 1);
276         break;
277     case Qt::Key_Up:
278         if (curRow > 0)
279             setCurrent(curRow - 1, curCol);
280         break;
281     case Qt::Key_Down:
282         if (curRow < numRows()-1)
283             setCurrent(curRow + 1, curCol);
284         break;
285     case Qt::Key_Space:
286         setSelected(curRow, curCol);
287         break;
288     default:                                // If not an interesting key,
289         event->ignore();                        // we don't accept the event
290         return;
291     }
292
293 }
294
295 }  // namespace widgets
296 } // namespace pv