Tentative Randomless-Entropy variant.
[tagua/yd.git] / src / chesstable.cpp
blobc8620dd9fc20d42c4b83c5ccb78df986c9c1f272
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 <core/color.h>
16 #include "chesstable.h"
17 #include "game.h"
18 #include "gameinfo.h"
19 #include "connection.h"
20 #include "piecepool.h"
21 #include "clock.h"
22 #include "mastersettings.h"
23 #include "movelist_table.h"
24 #include "infodisplay.h"
26 using namespace boost;
28 ChessTable::ChessTable(Variant* variant, QWidget* parent)
29 : KGameCanvasWidget(parent)
30 , m_wallpaper(NULL)
31 , m_current(NULL)
32 , m_mousegrab(NULL)
33 , m_need_reload(false)
34 , m_components(variant) {
36 setMouseTracking(true);
38 // create m_board
39 m_board = new ChessBoard(&m_components, &m_anim_manager, this);
40 m_board->show();
42 // create move list
43 m_movelist = new MoveList::Table;
45 // create clocks
46 for(int i=0;i<2;i++) {
47 m_clocks[i] = new Clock(i, this);
48 m_clocks[i]->show();
50 m_clocks[0]->activate(0);
52 // create info display
53 m_info = new InfoDisplay(this);
54 // m_info->show();
56 // create pools
57 // FIXME what to do for more than 2 players?
58 for (int i = 0; i < 2; i++) {
59 const IColor* color = m_components.player(i);
60 if (color) {
61 m_pools[i] = new PiecePool(color, m_board, &m_anim_manager, this);
62 m_pools[i]->show();
66 m_board->raise();
67 settingsChanged();
70 ChessTable::~ChessTable() {
71 for(int i=0;i<2;i++)
72 delete m_clocks[i];
73 delete m_movelist;
74 delete m_board;
75 for(int i=0;i<2;i++)
76 delete m_pools[i];
77 delete m_info;
80 void ChessTable::renderWallpaper() {
81 if (!m_background_pixmap.isNull()) {
82 QPixmap bg = m_background_pixmap;
83 // scale & crop background
84 double ratio_x = (double) width() / m_background_pixmap.width();
85 double ratio_y = (double) height() / m_background_pixmap.height();
86 if (ratio_x > ratio_y)
87 bg = bg.scaledToWidth(width(), Qt::SmoothTransformation);
88 else
89 bg = bg.scaledToHeight(height(), Qt::SmoothTransformation);
90 QSize size(width(), height());
91 QImage res(size, QImage::Format_ARGB32_Premultiplied);
93 QPoint pos(
94 (bg.width() - width()) / 2,
95 (bg.height() - height()) / 2);
96 kDebug() << "img size" << bg.size();
97 kDebug() << "size" << size;
98 kDebug() << "pos" << pos;
99 QPainter p(&res);
100 p.drawPixmap(QPoint(0,0), bg, QRectF(pos, size));
103 bg = QPixmap::fromImage(res);
104 if (m_wallpaper) {
105 m_wallpaper->setPixmap(bg);
107 else {
108 delete m_wallpaper;
109 m_wallpaper = new KGameCanvasPixmap(QPixmap::fromImage(res), this); // FIXME[vg]: leaked
110 m_wallpaper->lower();
111 m_wallpaper->show();
114 else {
115 delete m_wallpaper;
116 m_wallpaper = 0;
120 void ChessTable::settingsChanged() {
121 m_anim_manager.reload();
123 m_board->settingsChanged();
124 for(int i=0;i<2;i++)
125 m_clocks[i]->settingsChanged();
126 m_info->settingsChanged();
127 for(int i=0;i<2;i++)
128 m_pools[i]->settingsChanged();
130 m_background_pixmap = m_board->controlsLoader()->getStaticValue<QPixmap>("wallpaper", 0, true);
131 renderWallpaper();
133 /* redo the layout, forcing reload */
134 if(isVisible())
135 layout(true);
136 else
137 m_need_reload = true;
140 ClickableCanvas* ChessTable::eventItemAt(QPoint pos) {
141 if (m_board->boardRect().contains(pos))
142 return m_board;
144 for (int i=0; i<2; i++)
145 if (m_pools[i]->boardRect().contains(pos))
146 return m_pools[i];
148 for (int i=0; i<2; i++)
149 if (m_clocks[i]->rect().contains(pos))
150 return m_clocks[i];
152 return NULL;
155 void ChessTable::setEntity(const boost::shared_ptr<UserEntity>& entity) {
156 m_board->setEntity(entity);
159 void ChessTable::layout(bool force_reload) {
160 force_reload |= m_need_reload;
161 m_need_reload = false;
163 renderWallpaper();
165 ::LuaApi::LuaValueMap params;
166 params["width"] = width();
167 params["height"] = height();
168 params["grid_size"] = QPointF(m_board->gridSize());
170 ::LuaApi::LuaValueMap lvals = m_board->controlsLoader()->getStaticValue< ::LuaApi::LuaValueMap>("layout", &params);
172 #if 0
173 for(::LuaApi::LuaValueMap::iterator it = lvals.begin(); it != lvals.end(); ++it)
174 if(double* val = boost::get<double>(&it.value()))
175 kDebug() << "lvals[" << it.key() << "] = " << *val;
176 else if(QPointF* val = boost::get<QPointF>(&it.value()))
177 kDebug() << "lvals[" << it.key() << "] = Point(" << val->x() << "," << val->y() << ")";
178 else if(QRectF* val = boost::get<QRectF>(&it.value()))
179 kDebug() << "lvals[" << it.key() << "] = Rect(" << val->x() << "," << val->y()
180 << "," << val->width() << "," << val->height() << ")";
181 #endif
183 #define GET_INT(name) \
184 int name = 0; \
185 {::LuaApi::LuaValueMap::iterator it = lvals.find(#name);\
186 if(double* val = (it==lvals.end()) ? 0 : boost::get<double>(&lvals[#name]) ) \
187 name = (int)*val; \
188 else \
189 kError() << "Theme error:" << #name << "should be set to a number in the layout";}
191 #define GET_POINT(name) \
192 QPoint name; \
193 {::LuaApi::LuaValueMap::iterator it = lvals.find(#name);\
194 if(QPointF* val = (it==lvals.end()) ? 0 : boost::get<QPointF>(&lvals[#name]) ) \
195 name = val->toPoint(); \
196 else \
197 kError() << "Theme error:" << #name << "should be set to a point in the layout";}
199 GET_POINT(board_position);
200 GET_INT(square_size);
201 GET_INT(border_size);
202 GET_INT(border_text_near);
203 GET_INT(border_text_far);
204 GET_POINT(clock0_position);
205 GET_POINT(clock1_position);
206 GET_INT(clock_size);
207 GET_POINT(pool0_position);
208 GET_POINT(pool1_position);
209 GET_INT(pool_piece_size);
210 GET_INT(pool_width);
212 m_board->moveTo(board_position.x(), board_position.y());
213 m_board->onResize( square_size, border_size, border_text_near, border_text_far, force_reload);
215 int x = !m_board->flipped();
217 m_clocks[x]->resize(clock_size);
218 m_clocks[x]->moveTo(clock0_position.x(), clock0_position.y());
219 // kDebug() << "moving clock " << x << " to " << clock0_position.y();
221 m_clocks[!x]->resize(clock_size);
222 m_clocks[!x]->moveTo(clock1_position.x(), clock1_position.y());
223 // kDebug() << "moving clock " << !x << " to " << clock1_position.y();
225 m_pools[x]->m_flipped = false;
226 m_pools[x]->onResize(pool_piece_size, force_reload);
227 m_pools[x]->moveTo(pool0_position.x(), pool0_position.y());
228 m_pools[x]->setGridWidth(pool_width);
230 m_pools[!x]->m_flipped = true;
231 m_pools[!x]->onResize(pool_piece_size, force_reload);
232 m_pools[!x]->moveTo(pool1_position.x(), pool1_position.y());
233 m_pools[!x]->setGridWidth(pool_width);
236 void ChessTable::resizeEvent(QResizeEvent* /*e*/) {
237 layout();
240 void ChessTable::mouseReleaseEvent(QMouseEvent* e) {
242 if(m_mousegrab) {
243 m_mousegrab->onMouseRelease(e->pos() - m_mousegrab->pos(), e->button() );
244 if(!e->buttons()) {
245 m_mousegrab = NULL;
247 ClickableCanvas* cb = eventItemAt(e->pos());
248 if(cb != m_current) {
249 if(m_current)
250 m_current->onMouseLeave();
251 if(cb) {
252 cb->onMouseEnter();
253 cb->onMouseMove(e->pos() - cb->pos(), 0);
255 m_current = cb;
258 return;
262 void ChessTable::mousePressEvent(QMouseEvent* e) {
263 if(m_mousegrab) {
264 m_mousegrab->onMousePress(e->pos() - m_mousegrab->pos(), e->button() );
265 return;
268 ClickableCanvas* cb = eventItemAt(e->pos());
269 if(cb != m_current) {
270 if(m_current)
271 m_current->onMouseLeave();
272 if(cb)
273 cb->onMouseEnter();
274 m_current = cb;
276 if(cb) {
277 cb->onMousePress(e->pos() - cb->pos(), e->button() );
278 m_mousegrab = cb;
282 void ChessTable::mouseMoveEvent(QMouseEvent* e) {
283 if(m_mousegrab) {
284 m_mousegrab->onMouseMove(e->pos() - m_mousegrab->pos(), e->button() );
285 return;
288 ClickableCanvas* cb = eventItemAt(e->pos());
289 if(cb != m_current) {
290 if(m_current)
291 m_current->onMouseLeave();
292 if(cb)
293 cb->onMouseEnter();
294 m_current = cb;
296 if(cb)
297 cb->onMouseMove(e->pos() - cb->pos(), e->button() );
300 void ChessTable::enterEvent(QEvent*) { }
302 void ChessTable::leaveEvent(QEvent*) {
303 if(m_current)
304 m_current->onMouseLeave();
305 m_current = NULL;
308 void ChessTable::flip() {
309 m_board->flip();
311 int delta = qAbs(m_pools[0]->pos().y() - m_pools[1]->pos().y());
312 for(int i=0;i<2;i++)
313 m_pools[i]->flipAndMoveBy( QPoint(0, delta) );
315 // flip clocks
316 QPoint pos = m_clocks[0]->pos();
317 m_clocks[0]->moveTo(m_clocks[1]->pos());
318 m_clocks[1]->moveTo(pos);
321 void ChessTable::flip(bool flipped) {
322 if(m_board->flipped() != flipped)
323 flip();
326 void ChessTable::changeClock(int color) {
327 if(m_clocks[0]->running() || m_clocks[1]->running())
328 for(int i=0;i<2;i++) {
329 if ( (i == color) != m_clocks[i]->running() )
330 if( i==color )
331 m_clocks[i]->start();
332 else
333 m_clocks[i]->stop();
337 void ChessTable::updateTurn(int color) {
338 for(int i=0; i<2; i++)
339 m_clocks[i]->activate(color == i);
342 void ChessTable::stopClocks() {
343 for(int i=0; i<2; i++)
344 m_clocks[i]->stop();
347 void ChessTable::updateTime(int white, int black) {
348 m_clocks[0]->setTime(white);
349 m_clocks[1]->setTime(black);
352 void ChessTable::resetClock() {
353 stopClocks();
354 updateTime(0, 0);
355 for(int i=0; i<2; i++)
356 m_clocks[i]->setPlayer(Player());
359 void ChessTable::setPlayers(const Player& white, const Player& black) {
360 m_clocks[0]->setPlayer(white);
361 m_clocks[1]->setPlayer(black);
364 void ChessTable::run() {
365 for(int i=0;i<2;i++)
366 if(m_clocks[i]->active() && !m_clocks[i]->running())
367 m_clocks[i]->start();
370 void ChessTable::displayMessage(const QString& msg) {
371 kDebug() << msg;
372 message(msg);
375 AnimationManager* ChessTable::animationManager() { return &m_anim_manager; }
376 const AnimationManager* ChessTable::animationManager() const { return &m_anim_manager; }
378 void ChessTable::setVariant(Variant* variant) {
379 m_components.setVariant(variant);
382 Components* ChessTable::components() { return &m_components; }