/*************************************************************************** * 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 #include #include #include #include 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 &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 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 moves; markMoves(QList()); 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()); } }