Prepare 1.0 alpha3 release.
[tagua/yd.git] / src / chesstable.cpp
blobede77e91b50d16bf059aee6c18c616aba2bd689c
1 /*
2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@gmail.com>
3 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 */
11 #include <QLayout>
12 #include <QSplitter>
13 #include <QMouseEvent>
14 #include <KDebug>
15 #include "chesstable.h"
16 #include "game.h"
17 #include "gameinfo.h"
18 #include "connection.h"
19 #include "piecepool.h"
20 #include "clock.h"
21 #include "mastersettings.h"
22 #include "movelist_table.h"
23 #include "infodisplay.h"
25 using namespace boost;
27 ChessTable::ChessTable(QWidget* parent)
28 : KGameCanvasWidget(parent)
29 , m_wallpaper(NULL)
30 , m_current(NULL)
31 , m_mousegrab(NULL)
32 , m_need_reload(false) {
34 setMouseTracking(true);
36 // create m_board
37 m_board = new Board(m_anim_settings, this);
38 m_board->show();
40 // create move list
41 m_movelist = new MoveList::Table;
43 // create clocks
44 for(int i=0;i<2;i++) {
45 m_clocks[i] = new Clock(i, this);
46 m_clocks[i]->show();
48 m_clocks[0]->activate(0);
50 // create info display
51 m_info = new InfoDisplay(this);
52 // m_info->show();
54 // create pools
55 for(int i=0;i<2;i++) {
56 m_pools[i] = new PiecePool(i, m_board, m_anim_settings, this);
57 m_pools[i]->show();
60 m_board->raise();
61 settingsChanged();
64 ChessTable::~ChessTable() {
65 for(int i=0;i<2;i++)
66 delete m_clocks[i];
67 delete m_movelist;
68 delete m_board;
69 for(int i=0;i<2;i++)
70 delete m_pools[i];
71 delete m_info;
74 void ChessTable::renderWallpaper() {
75 if (!m_background_pixmap.isNull()) {
76 QPixmap bg = m_background_pixmap;
77 // scale & crop background
78 double ratio_x = (double) width() / m_background_pixmap.width();
79 double ratio_y = (double) height() / m_background_pixmap.height();
80 if (ratio_x > ratio_y)
81 bg = bg.scaledToWidth(width(), Qt::SmoothTransformation);
82 else
83 bg = bg.scaledToHeight(height(), Qt::SmoothTransformation);
84 QSize size(width(), height());
85 QImage res(size, QImage::Format_ARGB32_Premultiplied);
87 QPoint pos(
88 (bg.width() - width()) / 2,
89 (bg.height() - height()) / 2);
90 kDebug() << "img size" << bg.size();
91 kDebug() << "size" << size;
92 kDebug() << "pos" << pos;
93 QPainter p(&res);
94 p.drawPixmap(QPoint(0,0), bg, QRectF(pos, size));
97 bg = QPixmap::fromImage(res);
98 if (m_wallpaper) {
99 m_wallpaper->setPixmap(bg);
101 else {
102 delete m_wallpaper;
103 m_wallpaper = new KGameCanvasPixmap(QPixmap::fromImage(res), this);
104 m_wallpaper->lower();
105 m_wallpaper->show();
108 else {
109 delete m_wallpaper;
110 m_wallpaper = 0;
114 void ChessTable::settingsChanged() {
115 m_anim_settings.reload();
117 m_board->settingsChanged();
118 for(int i=0;i<2;i++)
119 m_clocks[i]->settingsChanged();
120 m_info->settingsChanged();
121 for(int i=0;i<2;i++)
122 m_pools[i]->settingsChanged();
124 m_background_pixmap = m_board->controlsLoader()->getStaticValue<QPixmap>("wallpaper", 0, true);
125 renderWallpaper();
127 /* redo the layout, forcing reload */
128 if(isVisible())
129 layout(true);
130 else
131 m_need_reload = true;
134 ClickableCanvas* ChessTable::eventItemAt(QPoint pos) {
135 if (m_board->boardRect().contains(pos))
136 return m_board;
138 for (int i=0; i<2; i++)
139 if (m_pools[i]->boardRect().contains(pos))
140 return m_pools[i];
142 for (int i=0; i<2; i++)
143 if (m_clocks[i]->rect().contains(pos))
144 return m_clocks[i];
146 return NULL;
149 void ChessTable::setEntity(const boost::shared_ptr<UserEntity>& entity) {
150 m_board->setEntity(entity);
153 void ChessTable::layout(bool force_reload) {
154 force_reload |= m_need_reload;
155 m_need_reload = false;
157 renderWallpaper();
159 ::LuaApi::LuaValueMap params;
160 params["width"] = width();
161 params["height"] = height();
162 params["grid_size"] = QPointF(m_board->gridSize());
164 ::LuaApi::LuaValueMap lvals = m_board->controlsLoader()->getStaticValue< ::LuaApi::LuaValueMap>("layout", &params);
166 #if 0
167 for(::LuaApi::LuaValueMap::iterator it = lvals.begin(); it != lvals.end(); ++it)
168 if(double* val = boost::get<double>(&it.value()))
169 kDebug() << "lvals[" << it.key() << "] = " << *val;
170 else if(QPointF* val = boost::get<QPointF>(&it.value()))
171 kDebug() << "lvals[" << it.key() << "] = Point(" << val->x() << "," << val->y() << ")";
172 else if(QRectF* val = boost::get<QRectF>(&it.value()))
173 kDebug() << "lvals[" << it.key() << "] = Rect(" << val->x() << "," << val->y()
174 << "," << val->width() << "," << val->height() << ")";
175 #endif
177 #define GET_INT(name) \
178 int name = 0; \
179 {::LuaApi::LuaValueMap::iterator it = lvals.find(#name);\
180 if(double* val = (it==lvals.end()) ? 0 : boost::get<double>(&lvals[#name]) ) \
181 name = (int)*val; \
182 else \
183 kError() << "Theme error:" << #name << "should be set to a number in the layout";}
185 #define GET_POINT(name) \
186 QPoint name; \
187 {::LuaApi::LuaValueMap::iterator it = lvals.find(#name);\
188 if(QPointF* val = (it==lvals.end()) ? 0 : boost::get<QPointF>(&lvals[#name]) ) \
189 name = val->toPoint(); \
190 else \
191 kError() << "Theme error:" << #name << "should be set to a point in the layout";}
193 GET_POINT(board_position);
194 GET_INT(square_size);
195 GET_INT(border_size);
196 GET_INT(border_text_near);
197 GET_INT(border_text_far);
198 GET_POINT(clock0_position);
199 GET_POINT(clock1_position);
200 GET_INT(clock_size);
201 GET_POINT(pool0_position);
202 GET_POINT(pool1_position);
203 GET_INT(pool_piece_size);
204 GET_INT(pool_width);
206 m_board->moveTo(board_position.x(), board_position.y());
207 m_board->onResize( square_size, border_size, border_text_near, border_text_far, force_reload);
209 int x = !m_board->flipped();
211 m_clocks[x]->resize(clock_size);
212 m_clocks[x]->moveTo(clock0_position.x(), clock0_position.y());
213 // kDebug() << "moving clock " << x << " to " << clock0_position.y();
215 m_clocks[!x]->resize(clock_size);
216 m_clocks[!x]->moveTo(clock1_position.x(), clock1_position.y());
217 // kDebug() << "moving clock " << !x << " to " << clock1_position.y();
219 m_pools[x]->m_flipped = false;
220 m_pools[x]->onResize(pool_piece_size, force_reload);
221 m_pools[x]->moveTo(pool0_position.x(), pool0_position.y());
222 m_pools[x]->setGridWidth(pool_width);
224 m_pools[!x]->m_flipped = true;
225 m_pools[!x]->onResize(pool_piece_size, force_reload);
226 m_pools[!x]->moveTo(pool1_position.x(), pool1_position.y());
227 m_pools[!x]->setGridWidth(pool_width);
230 void ChessTable::resizeEvent(QResizeEvent* /*e*/) {
231 layout();
234 void ChessTable::mouseReleaseEvent(QMouseEvent* e) {
236 if(m_mousegrab) {
237 m_mousegrab->onMouseRelease(e->pos() - m_mousegrab->pos(), e->button() );
238 if(!e->buttons()) {
239 m_mousegrab = NULL;
241 ClickableCanvas* cb = eventItemAt(e->pos());
242 if(cb != m_current) {
243 if(m_current)
244 m_current->onMouseLeave();
245 if(cb) {
246 cb->onMouseEnter();
247 cb->onMouseMove(e->pos() - cb->pos(), 0);
249 m_current = cb;
252 return;
256 void ChessTable::mousePressEvent(QMouseEvent* e) {
257 if(m_mousegrab) {
258 m_mousegrab->onMousePress(e->pos() - m_mousegrab->pos(), e->button() );
259 return;
262 ClickableCanvas* cb = eventItemAt(e->pos());
263 if(cb != m_current) {
264 if(m_current)
265 m_current->onMouseLeave();
266 if(cb)
267 cb->onMouseEnter();
268 m_current = cb;
270 if(cb) {
271 cb->onMousePress(e->pos() - cb->pos(), e->button() );
272 m_mousegrab = cb;
276 void ChessTable::mouseMoveEvent(QMouseEvent* e) {
277 if(m_mousegrab) {
278 m_mousegrab->onMouseMove(e->pos() - m_mousegrab->pos(), e->button() );
279 return;
282 ClickableCanvas* cb = eventItemAt(e->pos());
283 if(cb != m_current) {
284 if(m_current)
285 m_current->onMouseLeave();
286 if(cb)
287 cb->onMouseEnter();
288 m_current = cb;
290 if(cb)
291 cb->onMouseMove(e->pos() - cb->pos(), e->button() );
294 void ChessTable::enterEvent(QEvent*) { }
296 void ChessTable::leaveEvent(QEvent*) {
297 if(m_current)
298 m_current->onMouseLeave();
299 m_current = NULL;
302 void ChessTable::flip() {
303 m_board->flip();
305 int delta = qAbs(m_pools[0]->pos().y() - m_pools[1]->pos().y());
306 for(int i=0;i<2;i++)
307 m_pools[i]->flipAndMoveBy( QPoint(0, delta) );
309 // flip clocks
310 QPoint pos = m_clocks[0]->pos();
311 m_clocks[0]->moveTo(m_clocks[1]->pos());
312 m_clocks[1]->moveTo(pos);
315 void ChessTable::flip(bool flipped) {
316 if(m_board->flipped() != flipped)
317 flip();
320 void ChessTable::changeClock(int color) {
321 if(m_clocks[0]->running() || m_clocks[1]->running())
322 for(int i=0;i<2;i++) {
323 if ( (i == color) != m_clocks[i]->running() )
324 if( i==color )
325 m_clocks[i]->start();
326 else
327 m_clocks[i]->stop();
331 void ChessTable::updateTurn(int color) {
332 for(int i=0; i<2; i++)
333 m_clocks[i]->activate(color == i);
336 void ChessTable::stopClocks() {
337 for(int i=0; i<2; i++)
338 m_clocks[i]->stop();
341 void ChessTable::updateTime(int white, int black) {
342 m_clocks[0]->setTime(white);
343 m_clocks[1]->setTime(black);
346 void ChessTable::resetClock() {
347 stopClocks();
348 updateTime(0, 0);
349 for(int i=0; i<2; i++)
350 m_clocks[i]->setPlayer(Player());
353 void ChessTable::setPlayers(const Player& white, const Player& black) {
354 m_clocks[0]->setPlayer(white);
355 m_clocks[1]->setPlayer(black);
358 void ChessTable::run() {
359 for(int i=0;i<2;i++)
360 if(m_clocks[i]->active() && !m_clocks[i]->running())
361 m_clocks[i]->start();
364 void ChessTable::displayMessage(const QString& msg) {
365 kDebug() << msg;
366 message(msg);
369 const AnimationSettings& ChessTable::animationSettings() const {
370 return m_anim_settings;