Skip to content

Commit cd7c03c

Browse files
committed
Import ImageGridWidget from Makou
1 parent c9ec519 commit cd7c03c

File tree

3 files changed

+444
-0
lines changed

3 files changed

+444
-0
lines changed

src/widgets/common/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ set(ff7tkQtWidgets_SRC
88
ColorDisplay.cpp
99
DialogPreview.cpp
1010
DoubleCheckBox.cpp
11+
ImageGridWidget.cpp
1112
HexLineEdit.cpp
1213
ListWidget.cpp
1314
OrientationWidget.cpp
@@ -23,6 +24,7 @@ set(ff7tkQtWidgets_HEADERS
2324
DialogPreview.h
2425
DoubleCheckBox.h
2526
HexLineEdit.h
27+
ImageGridWidget.h
2628
ListWidget.h
2729
OrientationWidget.h
2830
QTaskBarButton.h
Lines changed: 335 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,335 @@
1+
/****************************************************************************/
2+
// Copyright (C) 2009-2022 Arzel Jérôme <myst6re@gmail.com> //
3+
// //
4+
// This file is part of FF7tk //
5+
// //
6+
// FF7tk is free software: you can redistribute it and/or modify //
7+
// it under the terms of the GNU General Public License as published by //
8+
// the Free Software Foundation, either version 3 of the License, or //
9+
// (at your option) any later version. //
10+
// //
11+
// FF7tk is distributed in the hope that it will be useful, //
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
14+
// GNU General Public License for more details. //
15+
/****************************************************************************/
16+
#include <ImageGridWidget.h>
17+
18+
#include <QPainter>
19+
#include <QPen>
20+
#include <QStyleOption>
21+
#include <QMouseEvent>
22+
23+
ImageGridWidget::ImageGridWidget(QWidget *parent)
24+
: QWidget(parent)
25+
, _hoverCell(-1, -1)
26+
, _startMousePress(-1, -1)
27+
, _pixmapPoint(-1, -1)
28+
, _scaledRatio(0.0)
29+
, _selectionMode(SingleSelection)
30+
, _cellSize(0)
31+
, _groupedCellSize(0)
32+
{
33+
setMouseTracking(_selectionMode != NoSelection);
34+
}
35+
36+
void ImageGridWidget::setPixmap(const QPixmap &pixmap)
37+
{
38+
_pixmap = pixmap;
39+
updateGrid();
40+
update();
41+
}
42+
43+
void ImageGridWidget::setPixmap(const QPoint &point, const QPixmap &pixmap)
44+
{
45+
_pixmapPoint = point;
46+
_pixmap = pixmap;
47+
updateGrid();
48+
update();
49+
}
50+
51+
void ImageGridWidget::setPixmapPoint(const QPoint &point)
52+
{
53+
_pixmapPoint = point;
54+
updateGrid();
55+
update();
56+
}
57+
58+
void ImageGridWidget::setCellSize(int size)
59+
{
60+
_cellSize = size;
61+
updateGrid();
62+
update();
63+
}
64+
65+
void ImageGridWidget::setGroupedCellSize(int size)
66+
{
67+
_groupedCellSize = size;
68+
updateGrid();
69+
update();
70+
}
71+
72+
void ImageGridWidget::setCustomLines(const QList<QLine> &lines)
73+
{
74+
_customLines = lines;
75+
update();
76+
}
77+
78+
void ImageGridWidget::setGridSize(const QSize &gridSize)
79+
{
80+
_gridSize = gridSize;
81+
updateGrid();
82+
update();
83+
}
84+
85+
QPixmap ImageGridWidget::cellPixmap(const Cell &point) const
86+
{
87+
if (point == Cell(-1, -1))
88+
return QPixmap();
89+
return _pixmap.copy(QRect(point * _cellSize, QSize(_cellSize, _cellSize)));
90+
}
91+
92+
void ImageGridWidget::setSelectionMode(SelectionMode selectionMode)
93+
{
94+
_selectionMode = selectionMode;
95+
setMouseTracking(_selectionMode != NoSelection);
96+
clearHover();
97+
}
98+
99+
void ImageGridWidget::setSelectedCells(const QList<Cell> &cells)
100+
{
101+
if (_selectedCells != cells) {
102+
_selectedCells = cells;
103+
update();
104+
Q_EMIT currentSelectionChanged(cells);
105+
}
106+
}
107+
108+
void ImageGridWidget::clearHover()
109+
{
110+
Cell newCell(-1, -1);
111+
112+
if (newCell != _hoverCell) {
113+
_hoverCell = newCell;
114+
update();
115+
}
116+
}
117+
118+
Cell ImageGridWidget::getCell(const QPoint &pos) const
119+
{
120+
if (_cellSize == 0 || _scaledRatio == 0.0)
121+
return Cell(-1, -1);
122+
123+
QPointF cell = QPointF(pos - _scaledGridPoint) / (_scaledRatio * _cellSize);
124+
Cell ret(qFloor(cell.x()), qFloor(cell.y()));
125+
return cellIsInRange(ret) ? ret : Cell(-1, -1);
126+
}
127+
128+
bool ImageGridWidget::cellIsInRange(const Cell &point) const
129+
{
130+
return QRect(QPoint(0, 0), gridSize()).contains(point);
131+
}
132+
133+
QList<QLine> ImageGridWidget::createGrid(const QSize &gridS, int cellSize)
134+
{
135+
QList<QLine> ret;
136+
137+
if (cellSize == 0)
138+
return ret;
139+
140+
const int lineCountV = gridS.width() + 1,
141+
lineCountH = gridS.height() + 1;
142+
143+
for (int i = 0; i < lineCountV; ++i)
144+
ret.append(QLine(scaledPoint(QPoint(i * cellSize, 0)), scaledPoint(QPoint(i, gridS.height()) * cellSize)));
145+
146+
for (int i = 0; i < lineCountH; ++i)
147+
ret.append(QLine(scaledPoint(QPoint(0, i * cellSize)), scaledPoint(QPoint(gridS.width(), i) * cellSize)));
148+
149+
return ret;
150+
}
151+
152+
void ImageGridWidget::updateGrid()
153+
{
154+
_gridLines.clear();
155+
_groupedGridLines.clear();
156+
157+
if (_cellSize == 0)
158+
return;
159+
160+
const QSize gridS = gridSize();
161+
162+
_scaledRatio = gridS.width() == 0 ? 0.0 : (gridS * _cellSize).scaled(size(), Qt::KeepAspectRatio).width() / double(gridS.width() * _cellSize);
163+
164+
_gridLines = createGrid(gridS, _cellSize);
165+
166+
_scaledGridPoint = (QPoint(width(), height()) - scaledPoint(QPoint(gridS.width(), gridS.height()) * _cellSize)) / 2;
167+
_scaledPixmapPoint = _pixmapPoint == QPoint(-1, -1) ? _scaledGridPoint : scaledPoint(_pixmapPoint);
168+
169+
if (_groupedCellSize != 0)
170+
_groupedGridLines = createGrid(gridS * _cellSize / _groupedCellSize, _groupedCellSize);
171+
}
172+
173+
void ImageGridWidget::paintEvent(QPaintEvent *event)
174+
{
175+
QPainter p(this);
176+
177+
if (isEnabled()) {
178+
// Background
179+
p.setBrush(Qt::black);
180+
p.drawRect(0, 0, width(), height());
181+
// Grid Background
182+
p.setBrush(palette().color(QPalette::Dark));
183+
p.drawRect(QRect(_scaledGridPoint, gridSizePixel() * _scaledRatio));
184+
// Pixmap
185+
p.drawPixmap(QRect(_scaledPixmapPoint, _pixmap.size() * _scaledRatio), _pixmap);
186+
// Grid
187+
p.setPen(Qt::gray);
188+
p.translate(_scaledGridPoint);
189+
p.drawLines(_gridLines);
190+
p.setPen(QPen(Qt::darkGray, 3, Qt::DashLine));
191+
p.drawLines(_groupedGridLines);
192+
p.drawLines(_customLines);
193+
194+
QColor lightRed(0xff, 0x7f, 0x7f);
195+
196+
p.setPen(hasFocus() ? Qt::red : lightRed);
197+
for (const Cell &cell: _selectedCells) {
198+
drawSelection(p, cell);
199+
}
200+
201+
p.setPen(lightRed);
202+
drawSelection(p, _hoverCell);
203+
} else {
204+
QStyleOption opt;
205+
opt.initFrom(this);
206+
p.drawPixmap(QRect(_scaledPixmapPoint, _pixmap.size() * _scaledRatio), QWidget::style()->generatedIconPixmap(QIcon::Disabled, _pixmap, &opt));
207+
}
208+
209+
QWidget::paintEvent(event);
210+
}
211+
212+
void ImageGridWidget::drawSelection(QPainter &p, QPoint selection)
213+
{
214+
if (selection == Cell(-1, -1)) {
215+
return;
216+
}
217+
218+
selection *= _cellSize;
219+
p.drawLine(QLine(scaledPoint(selection), scaledPoint(selection + QPoint(0, _cellSize))));
220+
p.drawLine(QLine(scaledPoint(selection), scaledPoint(selection + QPoint(_cellSize, 0))));
221+
p.drawLine(QLine(scaledPoint(selection + QPoint(_cellSize, 0)), scaledPoint(selection + QPoint(_cellSize, _cellSize))));
222+
p.drawLine(QLine(scaledPoint(selection + QPoint(0, _cellSize)), scaledPoint(selection + QPoint(_cellSize, _cellSize))));
223+
}
224+
225+
void ImageGridWidget::mouseMoveEvent(QMouseEvent *event)
226+
{
227+
QWidget::mouseMoveEvent(event);
228+
229+
if (_selectionMode == NoSelection) {
230+
return;
231+
}
232+
233+
Cell newCell = getCell(event->pos());
234+
235+
if (_selectionMode == MultiSelection && _startMousePress != Cell(-1, -1) && _startMousePress != newCell) {
236+
QPoint diff = newCell - _startMousePress;
237+
QList<Cell> selectedCells;
238+
for (int yp = 0; yp < std::max(std::abs(diff.y()), 1); ++yp) {
239+
for (int xp = 0; xp < std::max(std::abs(diff.x()), 1); ++xp) {
240+
int x = diff.x() >= 0 ? xp : -xp,
241+
y = diff.y() >= 0 ? yp : -yp;
242+
selectedCells.append(_startMousePress + Cell(x, y));
243+
}
244+
}
245+
246+
setSelectedCells(selectedCells);
247+
} else if (newCell != _hoverCell) {
248+
_hoverCell = newCell;
249+
update();
250+
251+
Q_EMIT highlighted(_hoverCell);
252+
}
253+
}
254+
255+
void ImageGridWidget::leaveEvent(QEvent *event)
256+
{
257+
QWidget::leaveEvent(event);
258+
259+
if (_selectionMode == NoSelection) {
260+
return;
261+
}
262+
263+
clearHover();
264+
}
265+
266+
void ImageGridWidget::mousePressEvent(QMouseEvent *event)
267+
{
268+
Cell cell = getCell(event->pos());
269+
270+
if (_selectionMode != NoSelection) {
271+
setSelectedCell(cell);
272+
setFocus();
273+
if (_selectionMode == MultiSelection) {
274+
_startMousePress = cell;
275+
}
276+
}
277+
278+
Q_EMIT clicked(cell);
279+
280+
QWidget::mousePressEvent(event);
281+
}
282+
283+
void ImageGridWidget::mouseReleaseEvent(QMouseEvent *event)
284+
{
285+
_startMousePress = Cell(-1, -1);
286+
287+
QWidget::mouseReleaseEvent(event);
288+
}
289+
290+
void ImageGridWidget::keyPressEvent(QKeyEvent *event)
291+
{
292+
if (_selectedCells.isEmpty()) {
293+
QWidget::keyPressEvent(event);
294+
return;
295+
}
296+
297+
Cell cell = _selectedCells.last();
298+
299+
switch (event->key()) {
300+
case Qt::Key_Left:
301+
cell.setX(cell.x() - 1);
302+
break;
303+
case Qt::Key_Right:
304+
cell.setX(cell.x() + 1);
305+
break;
306+
case Qt::Key_Up:
307+
cell.setY(cell.y() - 1);
308+
break;
309+
case Qt::Key_Down:
310+
cell.setY(cell.y() + 1);
311+
break;
312+
}
313+
314+
if (cellIsInRange(cell)) {
315+
setSelectedCell(cell);
316+
} else {
317+
QWidget::keyPressEvent(event);
318+
}
319+
}
320+
321+
void ImageGridWidget::resizeEvent(QResizeEvent *event)
322+
{
323+
updateGrid();
324+
QWidget::resizeEvent(event);
325+
}
326+
327+
QSize ImageGridWidget::minimumSizeHint() const
328+
{
329+
return gridSize() * 8;
330+
}
331+
332+
QSize ImageGridWidget::sizeHint() const
333+
{
334+
return minimumSizeHint();
335+
}

0 commit comments

Comments
 (0)