lines-grid-editor/gridpreview.cpp

265 lines
6.5 KiB
C++

#include "gridpreview.h"
GridPreview::GridPreview(QWidget *parent)
: QWidget{parent}
{
colorMap.insert(QString("red"), Qt::red);
colorMap.insert(QString("green"), Qt::green);
colorMap.insert(QString("blue"), Qt::blue);
}
void GridPreview::setSize(int newWidth, int newHeight)
{
width = newWidth;
height = newHeight;
emit updatedContents();
}
void GridPreview::addLine(Line &line)
{
lines.push_back(line);
emit updatedContents();
}
void GridPreview::removeLine(int index)
{
lines.removeAt(index);
emit updatedContents();
}
void GridPreview::setLineColor(int index, QString color)
{
lines[index].setColor(color);
emit updatedContents();
}
void GridPreview::setLineStartPoint(int index, QPoint point)
{
lines[index].setStartPoint(point);
emit updatedContents();
}
void GridPreview::setLineEndPoint(int index, QPoint point)
{
lines[index].setEndPoint(point);
emit updatedContents();
}
int GridPreview::getWidth()
{
return width;
}
int GridPreview::getHeight()
{
return height;
}
const Line &GridPreview::getLine(int index)
{
return lines.at(index);
}
const PointProbe &GridPreview::getCapturedProbe()
{
return capturedProbe;
}
const QString GridPreview::toLuaTable()
{
QString output(tableTemplate.arg(width).arg(height));
QString linesSubTable = "";
for(auto iter = lines.begin(); iter != lines.end(); iter++ )
{
linesSubTable += QString(" %1,\n").arg(iter->toLuaTable());
}
linesSubTable.removeLast(); // \n
linesSubTable.removeLast(); // ,
return output.arg(linesSubTable);
}
void GridPreview::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QPen pen(Qt::black, 2);
painter.setPen(pen);
QBrush brush(Qt::black);
double aspectRatio = (double) rect().width() / rect().height();
double cellAspectRatio = (double) width / height;
bool widthBased = aspectRatio > cellAspectRatio;
int cellSize = widthBased ?
rect().height() / height :
rect().width() / width;
int dotSize = cellSize * 0.5;
int filledDotSize = cellSize * 0.7;
int areaWidth = cellSize * width;
int areaHeight = cellSize * height;
int offsetX = (rect().width() - areaWidth) / 2;
int offsetY = (rect().height() - areaHeight) / 2;
QRect drawArea(offsetX, offsetY, areaWidth, areaHeight);
// Draw main grid
painter.drawRect(drawArea);
QRect cell(0, 0, cellSize, cellSize);
painter.setBrush(brush);
for (int cellX = 0; cellX < width; cellX++)
{
for (int cellY = 0; cellY < height; cellY++)
{
cell.setLeft(offsetX + (cellSize - dotSize) / 2 + cellX * cellSize);
cell.setWidth(dotSize);
cell.setTop(offsetY + (cellSize - dotSize) / 2 + cellY * cellSize);
cell.setHeight(dotSize);
painter.drawEllipse(cell);
}
}
// Draw line points
for (auto iter = lines.begin(); iter < lines.end(); iter++)
{
QColor color(colorFromString(iter->getColor()));
brush.setColor(color);
painter.setBrush(brush);
// Draw start
cell.setLeft(offsetX + (cellSize - filledDotSize) / 2 + (iter->getStart().x() - 1) * cellSize);
cell.setWidth(filledDotSize);
cell.setTop(offsetY + (cellSize - filledDotSize) / 2 + (iter->getStart().y() - 1) * cellSize);
cell.setHeight(filledDotSize);
painter.drawEllipse(cell);
// Draw end
cell.setLeft(offsetX + (cellSize - filledDotSize) / 2 + (iter->getEnd().x() - 1) * cellSize);
cell.setWidth(filledDotSize);
cell.setTop(offsetY + (cellSize - filledDotSize) / 2 + (iter->getEnd().y() - 1) * cellSize);
cell.setHeight(filledDotSize);
painter.drawEllipse(cell);
}
}
const QColor GridPreview::colorFromString(const QString color)
{
if (!colorMap.contains(color))
return colorMap[QString("red")];
return colorMap[color];
}
void GridPreview::mouseMoveEvent(QMouseEvent *event)
{
if (!mouseCaptured)
{
return;
}
QPoint gridPos = localMousePosition(event);
lastProbe = probePoint(gridPos);
if (pointIsFree(lastProbe))
{
if (capturedProbe.isStart)
{
setLineStartPoint(capturedProbe.ownerIndex, gridPos);
}
else
{
setLineEndPoint(capturedProbe.ownerIndex, gridPos);
}
}
}
void GridPreview::mousePressEvent(QMouseEvent *event)
{
mouseCaptured = true;
QPoint gridPos = localMousePosition(event);
std::cout << gridPos.x() << ',' << gridPos.y() << std::endl;
lastProbe = probePoint(gridPos);
capturedProbe = lastProbe;
if (pointIsFree(lastProbe))
{
Line line;
line.setStartPoint(gridPos);
line.setEndPoint(gridPos);
addLine(line);
capturedProbe.ownerIndex = lines.size() - 1;
}
}
void GridPreview::mouseReleaseEvent(QMouseEvent *event)
{
mouseCaptured = false;
}
const QPoint GridPreview::localMousePosition(QMouseEvent *event)
{
QPoint position(event->position().toPoint());
return snapToGrid(position);
}
const QPoint GridPreview::snapToGrid(const QPoint &global)
{
double aspectRatio = (double) rect().width() / rect().height();
double cellAspectRatio = (double) width / height;
bool widthBased = aspectRatio > cellAspectRatio;
int cellSize = widthBased ?
rect().height() / height :
rect().width() / width;
int areaWidth = cellSize * width;
int areaHeight = cellSize * height;
int offsetX = (rect().width() - areaWidth) / 2;
int offsetY = (rect().height() - areaHeight) / 2;
return QPoint(1 + (global.x() - offsetX) / cellSize, 1 + (global.y() - offsetY) / cellSize);
}
bool GridPreview::isPointOccupied(const QPoint &point)
{
for (auto iter = lines.begin(); iter < lines.end(); iter++)
{
if (iter->getStart() == point || iter->getEnd() == point)
{
return true;
}
}
return false;
}
bool GridPreview::pointInBounds(const QPoint &point)
{
return point.x() > 0 && point.y() > 0 && point.x() <= width && point.y() <= height;
}
bool GridPreview::pointIsFree(PointProbe& pp)
{
return pp.ownerIndex == -1 && pp.inBounds;
}
const PointProbe GridPreview::probePoint(const QPoint &point)
{
for (int i = 0; i < lines.size(); i++)
{
if (lines[i].getStart() == point || lines[i].getEnd() == point)
{
return PointProbe(i, lines[i].getStart() == point, pointInBounds(point));
}
}
return PointProbe();
}