157 lines
5.5 KiB
C++
157 lines
5.5 KiB
C++
/***************************************************************************
|
|
* Copyright (C) 2009 by Stefan Bühler *
|
|
* stbuehler@web.de *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
***************************************************************************/
|
|
#include "field2d.h"
|
|
|
|
#include <math.h>
|
|
|
|
#include <QResizeEvent>
|
|
#include <QMouseEvent>
|
|
#include <QWheelEvent>
|
|
#include <QPainter>
|
|
|
|
namespace toruschess {
|
|
|
|
Field2D::Field2D(Game *game, QWidget *parent)
|
|
: QWidget(parent), m_lib(new PieceLibrary(this)), m_game(game), m_fieldWidth(360), m_fieldHeight(360), m_originX(23), m_originY(23), m_fieldBuffer(0) {
|
|
for (int x = 0; x < 8; x++) for (int y = 0; y < 8; y++) m_marked[x][y] = false;
|
|
m_lib->setSize(m_fieldWidth / 8, m_fieldHeight / 8);
|
|
checkSizes();
|
|
connect(game, SIGNAL(updated()), this, SLOT(fieldUpdated()));
|
|
}
|
|
|
|
Field2D::~Field2D() {
|
|
if (m_fieldBuffer) delete m_fieldBuffer;
|
|
}
|
|
|
|
void Field2D::markMoves(const QList<Move> &moves) {
|
|
foreach(Move m, m_markedMoves) m_marked[m.to().x()][m.to().y()] = false;
|
|
m_markedMoves = moves;
|
|
foreach(Move m, m_markedMoves) m_marked[m.to().x()][m.to().y()] = true;
|
|
updateFieldBuffer();
|
|
update();
|
|
}
|
|
|
|
QSize Field2D::sizeHint() const {
|
|
return QSize(17*m_fieldWidth/8, 17*m_fieldHeight/8);
|
|
}
|
|
|
|
void Field2D::paintEvent(QPaintEvent *) {
|
|
QPainter pt(this);
|
|
|
|
int winWidth = width(), winHeight = height();
|
|
|
|
for (int px = m_originX - m_fieldWidth; px < winWidth; px += m_fieldWidth)
|
|
for (int py = m_originY - m_fieldHeight; py < winHeight; py += m_fieldHeight) {
|
|
pt.drawImage(QRect(px, py, m_fieldWidth, m_fieldHeight), *m_fieldBuffer);
|
|
}
|
|
}
|
|
|
|
void Field2D::mousePressEvent(QMouseEvent *event) {
|
|
if (event->button() == Qt::LeftButton) {
|
|
QList<Move> moves;
|
|
Pos p = findPos(event->x(), event->y());
|
|
moves = m_game->field()->validMoves(p);
|
|
markMoves(moves);
|
|
}
|
|
m_mouseLastX = event->x();
|
|
m_mouseLastY = event->y();
|
|
}
|
|
|
|
void Field2D::mouseMoveEvent(QMouseEvent *event) {
|
|
if (event->buttons() & Qt::RightButton) {
|
|
m_originX += event->x() - m_mouseLastX;
|
|
m_originY += event->y() - m_mouseLastY;
|
|
checkSizes();
|
|
update();
|
|
}
|
|
m_mouseLastX = event->x();
|
|
m_mouseLastY = event->y();
|
|
}
|
|
|
|
void Field2D::mouseReleaseEvent(QMouseEvent *event) {
|
|
m_mouseLastX = event->x();
|
|
m_mouseLastY = event->y();
|
|
if (event->button() == Qt::LeftButton) {
|
|
if (m_markedMoves.size() == 0) return;
|
|
Pos from = m_markedMoves[0].from();
|
|
QList<Move> moves;
|
|
markMoves(QList<Move>());
|
|
Pos p = findPos(event->x(), event->y());
|
|
Move m(m_game->field(), from, p);
|
|
m_game->move(m);
|
|
}
|
|
}
|
|
|
|
void Field2D::wheelEvent(QWheelEvent *event) {
|
|
double zoom = pow(1.2, event->delta() / 120);
|
|
int max = qMin(width(), height());
|
|
m_fieldWidth = qMax(120, qMin(max, (int) (m_fieldWidth * zoom))) & ~(0x7);
|
|
m_fieldHeight = qMax(120, qMin(max, (int) (m_fieldHeight * zoom))) & ~(0x7);
|
|
m_lib->setSize(m_fieldWidth / 8, m_fieldHeight / 8);
|
|
checkSizes();
|
|
update();
|
|
}
|
|
|
|
void Field2D::checkSizes() {
|
|
m_originX = m_originX % m_fieldWidth;
|
|
m_originY = m_originY % m_fieldHeight;
|
|
if (m_originX < 0) m_originX += m_fieldWidth;
|
|
if (m_originY < 0) m_originY += m_fieldHeight;
|
|
if (!m_fieldBuffer || m_fieldBuffer->width() != m_fieldWidth || m_fieldBuffer->height() != m_fieldHeight) {
|
|
if (m_fieldBuffer) delete m_fieldBuffer;
|
|
m_fieldBuffer = new QImage(QSize(m_fieldWidth, m_fieldHeight), QImage::Format_ARGB32_Premultiplied);
|
|
m_fieldBuffer->fill(Qt::black);
|
|
updateFieldBuffer();
|
|
}
|
|
}
|
|
|
|
void Field2D::updateFieldBuffer() {
|
|
QPainter pt(m_fieldBuffer);
|
|
|
|
int pieceWidth = m_fieldWidth / 8;
|
|
int pieceHeight = m_fieldHeight / 8;
|
|
for (int x = 0; x < 8; x++)
|
|
for (int y = 0; y < 8; y++) {
|
|
bool marked = m_marked[x][y];
|
|
int place = m_game->field()->place(Pos(x, y));
|
|
|
|
QRect prect(x * pieceWidth, y * pieceHeight, pieceWidth - 1, pieceHeight - 1);
|
|
m_lib->paint_board(pt, (x+y) % 2 == 1, prect);
|
|
m_lib->paint(pt, place, prect);
|
|
if (marked) {
|
|
int r = qMax(1, (pieceWidth + pieceHeight) / 36);
|
|
pt.setBrush(place != 0 ? Qt::green : Qt::white);
|
|
pt.setPen(Qt::red);
|
|
pt.drawEllipse(QPoint(prect.x() + pieceWidth / 2, prect.y() + pieceHeight / 2), r, r);
|
|
}
|
|
}
|
|
update();
|
|
}
|
|
|
|
Pos Field2D::findPos(int x, int y) {
|
|
return Pos(8 * ((x - m_originX) % m_fieldWidth) / m_fieldWidth, 8 * ((y - m_originY) % m_fieldHeight) / m_fieldHeight);
|
|
}
|
|
|
|
void Field2D::fieldUpdated() {
|
|
markMoves(QList<Move>());
|
|
}
|
|
|
|
}
|