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.
16 class ConstrainedText
: public KGameCanvasItem
23 QRect m_bounding_rect
;
24 QRect m_bounding_rect_max
;
26 void calcBoundingRect();
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
)
64 ConstrainedText::ConstrainedText(KGameCanvasAbstract
* Constrained
)
65 : KGameCanvasItem(Constrained
)
68 , m_font(QApplication::font()) {
72 ConstrainedText::~ConstrainedText() {
76 void ConstrainedText::calcBoundingRect() {
78 for(int i
=0;i
<m_text
.length();i
++)
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
) {
90 if(visible() && canvas() )
94 void ConstrainedText::setText(const QString
& text
) {
100 if(visible() && canvas() )
104 void ConstrainedText::setColor(const QColor
& color
) {
108 void ConstrainedText::setFont(const QFont
& font
) {
112 if(visible() && canvas() )
116 void ConstrainedText::paint(QPainter
* p
) {
117 if(m_bounding_rect_max
.width() == 0 || m_bounding_rect_max
.height() == 0)
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
);
135 QRect
ConstrainedText::rect() const {
136 return m_constr
; //suboptimal. oh, well...
142 Clock::Clock(int col
, Board
* b
, KGameCanvasAbstract
* canvas
)
143 : ClickableCanvas(canvas
)
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();
154 m_time_label
->show();
155 m_player_name
->show();
159 m_caption
->setText(col
== 0 ? "White" : "Black");
160 connect(&m_timer
, SIGNAL(timeout()), this, SLOT(tick()));
167 delete m_player_name
;
171 void Clock::start() {
178 if (m_running
) m_total_time
-= m_time
.elapsed();
183 void Clock::activate(bool 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
);
199 void Clock::computeTime() {
200 int time
= m_total_time
;
201 if (m_running
) time
-= m_time
.elapsed();
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;
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;
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
;
233 timeText
= "-" + timeText
;
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
));
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
) {
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
);
293 #include <QResizeEvent>
297 static void setFontSize(int max
, int width
, const QString
& text
, QFont
& font
) {
298 font
.setPointSize(max
);
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;
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
) {
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);
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);
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();
382 void Clock::Info::reload() {
383 Settings s_clock
= settings
.group("clock");
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
) {
422 void Clock::Info::resize(const QRect
& rect
) {
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));
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() {
470 void Clock::Info::stop() {
471 if (m_running
) m_total_time
-= m_time
.elapsed();
475 void Clock::Info::computeTime() const {
476 int time
= m_total_time
;
477 if (m_running
) time
-= m_time
.elapsed();
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;
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;
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
;
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
));
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() {
530 void Clock::Info::activate(bool value
) {
531 m_background
->setVisible(value
);
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
)
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() {
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() {
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);
584 m_info
[index
].start();
585 m_info
[1 - index
].stop();
595 void Clock::activate(int index
) {
597 m_info
[0].activate(index
== 0);
598 m_info
[1].activate(index
== 1);
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);