Fixed sprite creation.
[tagua/yd.git] / src / clock.cpp
blobae18e8ee349c0729536d4f9a865e10f509312c3a
1 /*
2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@sns.it>
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 "clock.h"
12 #include "board.h"
13 #include <math.h>
14 #include <iostream>
16 class ConstrainedText : public KGameCanvasItem
18 private:
19 QString m_text;
20 QColor m_color;
21 QFont m_font;
22 QRect m_constr;
23 QRect m_bounding_rect;
24 QRect m_bounding_rect_max;
26 void calcBoundingRect();
28 public:
29 ConstrainedText(const QString& text, const QColor& color,
30 const QFont& font, const QRect& rect,
31 KGameCanvasAbstract* canvas = NULL);
33 ConstrainedText(KGameCanvasAbstract* canvas = NULL);
35 virtual ~ConstrainedText();
37 QRect constrainRect() const { return m_constr; }
38 void setConstrainRect(const QRect& );
39 QString text() const { return m_text; }
40 void setText(const QString& text);
41 QColor color() const { return m_color; }
42 void setColor(const QColor& color);
43 QFont font() const { return m_font; }
44 void setFont(const QFont& font);
46 virtual void paint(QPainter* p);
47 virtual QRect rect() const;
48 virtual bool layered() const { return false; }
53 ConstrainedText::ConstrainedText(const QString& text, const QColor& color,
54 const QFont& font, const QRect& rect,
55 KGameCanvasAbstract* Constrained)
56 : KGameCanvasItem(Constrained)
57 , m_text(text)
58 , m_color(color)
59 , m_font(font)
60 , m_constr(rect) {
61 calcBoundingRect();
64 ConstrainedText::ConstrainedText(KGameCanvasAbstract* Constrained)
65 : KGameCanvasItem(Constrained)
66 //, m_text("")
67 , m_color(Qt::black)
68 , m_font(QApplication::font()) {
72 ConstrainedText::~ConstrainedText() {
76 void ConstrainedText::calcBoundingRect() {
77 QString test;
78 for(int i=0;i<m_text.length();i++)
79 test += 'H';
80 m_bounding_rect_max = QFontMetrics(m_font).boundingRect(test);
82 m_bounding_rect = QFontMetrics(m_font).boundingRect(m_text);
85 void ConstrainedText::setConstrainRect(const QRect& rect) {
86 if(m_constr == rect)
87 return;
89 m_constr = rect;
90 if(visible() && canvas() )
91 changed();
94 void ConstrainedText::setText(const QString& text) {
95 if(m_text == text)
96 return;
97 m_text = text;
98 calcBoundingRect();
100 if(visible() && canvas() )
101 changed();
104 void ConstrainedText::setColor(const QColor& color) {
105 m_color = color;
108 void ConstrainedText::setFont(const QFont& font) {
109 m_font = font;
110 calcBoundingRect();
112 if(visible() && canvas() )
113 changed();
116 void ConstrainedText::paint(QPainter* p) {
117 if(m_bounding_rect_max.width() == 0 || m_bounding_rect_max.height() == 0)
118 return;
120 p->setPen(m_color);
121 p->setFont(m_font);
123 double fact = qMin(double(m_constr.width())/m_bounding_rect_max.width(),
124 double(m_constr.height())/m_bounding_rect_max.height());
125 QMatrix savem = p->matrix();
126 //p->fillRect( m_constr, Qt::blue );
127 p->translate(QRectF(m_constr).center());
128 p->scale(fact, fact);
129 p->translate(-QRectF(m_bounding_rect_max).center());
130 //p->fillRect( m_bounding_rect_max, Qt::red );
131 p->drawText( QPoint((m_bounding_rect_max.width()-m_bounding_rect.width())/2,0), m_text);
132 p->setMatrix(savem);
135 QRect ConstrainedText::rect() const {
136 return m_constr; //suboptimal. oh, well...
142 Clock::Clock(int col, Board* b, KGameCanvasAbstract* canvas)
143 : ClickableCanvas(canvas)
144 , m_color(col)
145 , m_board(b) {
146 m_background = new KGameCanvasPixmap(this);
147 m_caption = new ConstrainedText(this);
148 m_time_label = new ConstrainedText(this);
149 m_player_name = new ConstrainedText(this);
150 m_decs = new ConstrainedText(this);
152 m_background->show();
153 m_caption->show();
154 m_time_label->show();
155 m_player_name->show();
157 setTime(0);
158 setPlayer(Player());
159 m_caption->setText(col == 0 ? "White" : "Black");
160 connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick()));
163 Clock::~Clock() {
164 delete m_background;
165 delete m_caption;
166 delete m_time_label;
167 delete m_player_name;
168 delete m_decs;
171 void Clock::start() {
172 m_running = true;
173 m_time.start();
174 m_timer.start(100);
177 void Clock::stop() {
178 if (m_running) m_total_time -= m_time.elapsed();
179 m_running = false;
180 m_timer.stop();
183 void Clock::activate(bool a) {
184 if(m_active == a)
185 return;
187 m_active = a;
188 m_background->setPixmap(m_active ? m_active_pixmap : m_inactive_pixmap);
190 m_time_label->setColor(m_active ? m_active_text : m_inactive_text);
191 m_player_name->setColor(m_active ? m_active_text : m_inactive_text);
192 m_caption->setColor(m_active ? m_active_text : m_inactive_text);
195 void Clock::tick() {
196 computeTime();
199 void Clock::computeTime() {
200 int time = m_total_time;
201 if (m_running) time -= m_time.elapsed();
202 bool positive;
203 int total_secs;
204 int decs = -1;
206 if (time > 0 && time < 10000) {
207 int total_decs = static_cast<int>(ceil(time / 100.0));
208 positive = total_decs >= 0;
209 if (!positive) total_decs = -total_decs;
210 decs = total_decs % 10;
211 total_secs = total_decs / 10;
213 else {
214 total_secs = static_cast<int>(ceil(time / 1000.0));
215 positive = total_secs >= 0;
216 if (!positive) total_secs = -total_secs;
220 int secs = total_secs % 60;
221 int mins = total_secs / 60;
222 QString timeText;
225 QString secText = QString::number(secs);
226 if (secText.length() < 2) secText = "0" + secText;
228 QString minText = QString::number(mins);
229 if (minText.length() < 2) minText = "0" + minText;
231 timeText = minText + ":" + secText;
232 if (!positive)
233 timeText = "-" + timeText;
235 #if 0
236 if (positive && decs != -1) {
237 int dec = static_cast<int>(ceil(time / 100.0)) % 10;
239 m_decs->moveTo(m_time_label->rect().bottomRight() + QPoint(2, 0));
240 m_decs->setText(":" + QString::number(dec));
241 m_decs->show();
243 else
244 m_decs->hide();
245 #endif
248 m_time_label->setText(timeText);
251 QString Clock::playerString(const Player& player) {
252 QString rating = player.rating != -1 ? QString(" (%1)").arg(player.rating) : QString();
253 return QString("%1").arg(player.name) + rating;
256 void Clock::setPlayer(const Player& player) {
257 m_player_name->setText(playerString(player));
260 void Clock::setTime(int t) {
261 m_total_time = t;
262 tick();
265 void Clock::onMousePress(const QPoint& pos, int button) {
268 void Clock::resize() {
269 m_height = (int)m_board->tagsLoader()->getNumber("clock_height");
271 m_active_pixmap = m_board->tagsLoader()->operator()("clock_active_background");
272 m_inactive_pixmap = m_board->tagsLoader()->operator()("clock_inactive_background");
274 m_active_text = m_board->tagsLoader()->getBrush("clock_active_text").color();
275 m_inactive_text = m_board->tagsLoader()->getBrush("clock_inactive_text").color();
277 m_background->setPixmap(m_active ? m_active_pixmap : m_inactive_pixmap);
278 m_background->moveTo(m_board->tagsLoader()->getPoint("clock_background_offset"));
280 m_time_label->setConstrainRect(m_board->tagsLoader()->getRect("clock_time_rect"));
281 m_time_label->setColor(m_active ? m_active_text : m_inactive_text);
283 m_player_name->setConstrainRect(m_board->tagsLoader()->getRect("clock_player_rect"));
284 m_player_name->setColor(m_active ? m_active_text : m_inactive_text);
286 m_caption->setConstrainRect(m_board->tagsLoader()->getRect("clock_caption_rect"));
287 m_caption->setColor(m_active ? m_active_text : m_inactive_text);
290 #if 1-1
291 #include <math.h>
292 #include <iostream>
293 #include <QResizeEvent>
294 #include "clock.h"
295 #include "global.h"
297 static void setFontSize(int max, int width, const QString& text, QFont& font) {
298 font.setPointSize(max);
299 return; // FIXME
300 while (max >= 8) {
301 QTime tm; tm.start();
302 QFontMetrics metrics(font);
303 int fw = metrics.boundingRect(text).width();
304 std::cout << "font metrics: " << tm.elapsed() << std::endl;
306 if (fw <= width) break;
307 max--;
308 font.setPointSize(max);
312 void Clock::Info::settingsChanged() {
315 void Clock::Info::setup(const Player& player, const QRect& rect, const QString& caption, KGameCanvasAbstract* canvas) {
316 putInCanvas(canvas);
318 m_player = player;
319 m_total_time = 0;
320 m_rect = rect;
322 Settings s_clock = settings.group("clock");
324 QColor framecol(0x60,0x60,0x90);
325 QColor backgroundColor;
326 (s_clock["background"] |= QColor(0xa0,0xf0,0xd0,200)) >> backgroundColor;
327 m_background = new KGameCanvasRectangle(backgroundColor, QSize(m_rect.size()), this);
328 m_frame[0] = new KGameCanvasRectangle(framecol, QSize(m_rect.width()-2,1), this);
329 m_frame[0]->moveTo(1,0);
330 m_frame[1] = new KGameCanvasRectangle(framecol, QSize(m_rect.width()-2,1), this);
331 m_frame[1]->moveTo(0,m_rect.height()-1);
332 m_frame[2] = new KGameCanvasRectangle(framecol, QSize(1,m_rect.height()), this);
333 m_frame[2]->moveTo(0,0);
334 m_frame[3] = new KGameCanvasRectangle(framecol, QSize(1,m_rect.height()), this);
335 m_frame[3]->moveTo(m_rect.width()-1,0);
337 int tempFontSize;
340 QFont captionFont("Bitstream Vera Sans");
341 (s_clock["captionFontSize"] |=
342 static_cast<int>(captionFont.pointSize() * 1.4)) >> tempFontSize;
343 captionFont.setPointSize(tempFontSize);
344 m_caption = new KGameCanvasText(caption, Qt::black, captionFont,
345 KGameCanvasText::HStart, KGameCanvasText::VTop, this);
346 m_caption->show();
350 QFont timeFont("Bitstream Vera Sans");
351 (s_clock["timeFontSize"] |= timeFont.pointSize() * 2) >> tempFontSize;
352 timeFont.setPointSize(tempFontSize);
353 timeFont.setWeight(QFont::Bold);
354 m_time_label = new KGameCanvasText("", Qt::black, timeFont,
355 KGameCanvasText::HStart, KGameCanvasText::VCenter, this);
356 m_time_label->show();
360 QFont decsFont("Bitstream Vera Sans");
361 (s_clock["decsFontSize"] |=
362 static_cast<int>(decsFont.pointSize() * 0.8)) >> tempFontSize;
363 decsFont.setPointSize(tempFontSize);
364 m_decs = new KGameCanvasText("", Qt::black, decsFont,
365 KGameCanvasText::HStart, KGameCanvasText::VBottom, this);
369 QFont playerFont("Bitstream Vera Sans");
370 (s_clock["playerFontSize"] |= playerFont.pointSize()) >> tempFontSize;
371 playerFont.setPointSize(tempFontSize);
372 m_player_name = new KGameCanvasText(playerString(player), Qt::black, playerFont,
373 KGameCanvasText::HStart, KGameCanvasText::VBottom, this);
374 m_player_name->show();
377 computeTime();
378 update();
379 show();
382 void Clock::Info::reload() {
383 Settings s_clock = settings.group("clock");
385 QFont tempFont;
386 QColor backgroundColor;
388 s_clock["background"] >> backgroundColor;
389 m_background->setColor(backgroundColor);
391 tempFont = m_caption->font();
392 tempFont.setPointSize(s_clock["captionFontSize"].value<int>());
393 m_caption->setFont(tempFont);
395 tempFont = m_time_label->font();
396 tempFont.setPointSize(s_clock["timeFontSize"].value<int>());
397 m_time_label->setFont(tempFont);
399 tempFont = m_decs->font();
400 tempFont.setPointSize(s_clock["decsFontSize"].value<int>());
401 m_decs->setFont(tempFont);
403 tempFont = m_player_name->font();
404 tempFont.setPointSize(s_clock["playerFontSize"].value<int>());
405 m_player_name->setFont(tempFont);
408 QString Clock::Info::playerString(const Player& player) const {
409 QString rating = player.rating != -1 ? QString(" (%1)").arg(player.rating) : "";
410 return QString("%1").arg(player.name) + rating;
413 void Clock::Info::setPlayer(const Player& player) {
414 m_player_name->setText(playerString(player));
417 void Clock::Info::setTime(int time) {
418 m_total_time = time;
419 tick();
422 void Clock::Info::resize(const QRect& rect) {
423 m_rect = rect;
424 update();
427 void Clock::Info::update() {
428 m_background->setSize(m_rect.size());
430 m_frame[0]->setSize(QSize(m_rect.width()-2,1));
431 m_frame[0]->moveTo(1,0);
432 m_frame[1]->setSize(QSize(m_rect.width()-2,1));
433 m_frame[1]->moveTo(1,m_rect.height()-1);
434 m_frame[2]->setSize(QSize(1,m_rect.height()));
435 m_frame[2]->moveTo(0,0);
436 m_frame[3]->setSize(QSize(1,m_rect.height()));
437 m_frame[3]->moveTo(m_rect.width()-1,0);
440 /*QFont font = m_caption->font();
441 setFontSize(20, m_rect.width() / 2, m_caption->text(), font);
442 m_caption->setFont(font);*/
443 m_caption->moveTo(QPoint(10, 10));
447 QPoint pos(
448 static_cast<int>(m_rect.width() * 0.5),
449 static_cast<int>(m_rect.height() * 0.5));
450 /*QFont font = m_time_label->font();
451 int width = m_rect.width() - pos.x();
452 setFontSize(22, width,
453 m_time_label->text(), font);
454 m_time_label->setFont(font);*/
455 m_time_label->moveTo(pos);
458 m_player_name->moveTo(QPoint(
459 static_cast<int>(m_rect.width() * 0.05),
460 static_cast<int>(m_rect.height() * 0.8)));
462 moveTo(m_rect.topLeft());
465 void Clock::Info::start() {
466 m_running = true;
467 m_time.start();
470 void Clock::Info::stop() {
471 if (m_running) m_total_time -= m_time.elapsed();
472 m_running = false;
475 void Clock::Info::computeTime() const {
476 int time = m_total_time;
477 if (m_running) time -= m_time.elapsed();
478 bool positive;
479 int total_secs;
480 int decs = -1;
482 if (time > 0 && time < 10000) {
483 int total_decs = static_cast<int>(ceil(time / 100.0));
484 positive = total_decs >= 0;
485 if (!positive) total_decs = -total_decs;
486 decs = total_decs % 10;
487 total_secs = total_decs / 10;
489 else {
490 total_secs = static_cast<int>(ceil(time / 1000.0));
491 positive = total_secs >= 0;
492 if (!positive) total_secs = -total_secs;
496 int secs = total_secs % 60;
497 int mins = total_secs / 60;
498 QString timeText;
501 QString secText = QString::number(secs);
502 if (secText.length() < 2) secText = "0" + secText;
504 QString minText = QString::number(mins);
505 if (minText.length() < 2) minText = "0" + minText;
507 timeText = minText + ":" + secText;
508 if (!positive)
509 timeText = "-" + timeText;
511 if (positive && decs != -1) {
512 int dec = static_cast<int>(ceil(time / 100.0)) % 10;
514 m_decs->moveTo(m_time_label->rect().bottomRight() + QPoint(2, 0));
515 m_decs->setText(":" + QString::number(dec));
516 m_decs->show();
518 else
519 m_decs->hide();
522 m_time_label->setText(timeText);
523 m_time_label->setColor(time <= 0 && m_running ? QColor(200,20,20) : Qt::black);
526 void Clock::Info::tick() {
527 computeTime();
530 void Clock::Info::activate(bool value) {
531 m_background->setVisible(value);
532 for(int i=0;i<4;i++)
533 m_frame[i]->setVisible(value);
535 QColor textcolor = value ? Qt::black : Qt::darkGray;
536 m_caption->setColor(textcolor);
537 m_time_label->setColor(textcolor);
538 m_decs->setColor(textcolor);
539 m_player_name->setColor(textcolor);
542 QRect Clock::Info::eventRect() const {
543 return m_background->rect().translated(pos());
547 Clock::Clock(KGameCanvasAbstract* parent)
548 : ClickableCanvas(parent)
549 , m_running(-1)
550 , m_active(-1) {
551 QTime startup_time; startup_time.start();
552 m_info[0].setup(Player(), QRect(0, 0, 0, 0), "White", this);
553 m_info[1].setup(Player(), QRect(0, 0, 0, 0), "Black", this);
554 connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick()));
557 void Clock::settingsChanged() {
558 for(int i=0;i<2;i++)
559 m_info[i].settingsChanged();
562 void Clock::resize(QSize size) {
563 int baseWidth = (size.width() - 10) / 2;
564 m_info[0].resize(QRect(0, 0, baseWidth, 70));
565 m_info[1].resize(QRect(baseWidth + 10, 0, baseWidth, 70));
568 void Clock::reload() {
569 m_info[0].reload();
570 m_info[1].reload();
573 void Clock::setTime(int index, int value) {
574 Q_ASSERT(index == 0 || index == 1);
576 m_info[index].setTime(value);
579 void Clock::start(int index) {
580 Q_ASSERT(index == 0 || index == 1);
582 m_timer.start(10);
583 m_running = index;
584 m_info[index].start();
585 m_info[1 - index].stop();
588 void Clock::stop() {
589 m_info[0].stop();
590 m_info[1].stop();
591 m_timer.stop();
592 m_running = -1;
595 void Clock::activate(int index) {
596 m_active = index;
597 m_info[0].activate(index == 0);
598 m_info[1].activate(index == 1);
601 void Clock::tick() {
602 if (m_running != -1) {
603 Q_ASSERT(m_running == 0 || m_running == 1);
604 m_info[m_running].tick();
608 void Clock::setPlayers(const Player& white, const Player& black) {
609 m_info[0].setPlayer(white);
610 m_info[1].setPlayer(black);
613 void Clock::onMousePress(const QPoint& pos, int button) {
614 if (button == Qt::LeftButton) {
615 if (m_info[0].eventRect().contains(pos))
616 emit labelClicked(0);
617 else if (m_info[1].eventRect().contains(pos))
618 emit labelClicked(1);
622 #endif