From 78e5068e39e7dd728e1e81de50e34bc88d449a08 Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Sat, 12 Feb 2011 21:09:33 +0100 Subject: [PATCH] converted phases toolbar to graphics item --- cockatrice/cockatrice.qrc | 24 +- .../{ => phases}/icon_phase_cleanup.svg | 0 .../icon_phase_combat_attackers.svg | 0 .../icon_phase_combat_blockers.svg | 0 .../{ => phases}/icon_phase_combat_damage.svg | 0 .../{ => phases}/icon_phase_combat_end.svg | 0 .../{ => phases}/icon_phase_combat_start.svg | 0 .../{ => phases}/icon_phase_draw.svg | 0 .../{ => phases}/icon_phase_main1.svg | 0 .../{ => phases}/icon_phase_main2.svg | 0 .../icon_phase_nextturn.svg} | 0 .../{ => phases}/icon_phase_untap.svg | 0 .../{ => phases}/icon_phase_upkeep.svg | 0 cockatrice/src/abstractcarditem.cpp | 31 ++- cockatrice/src/abstractcarditem.h | 1 + cockatrice/src/gamescene.cpp | 32 ++- cockatrice/src/gamescene.h | 4 +- cockatrice/src/gameview.cpp | 1 - cockatrice/src/phasestoolbar.cpp | 228 ++++++++++-------- cockatrice/src/phasestoolbar.h | 39 ++- cockatrice/src/pixmapgenerator.cpp | 18 ++ cockatrice/src/pixmapgenerator.h | 8 + cockatrice/src/tab_game.cpp | 42 +++- cockatrice/src/tab_game.h | 5 +- 24 files changed, 274 insertions(+), 159 deletions(-) rename cockatrice/resources/{ => phases}/icon_phase_cleanup.svg (100%) rename cockatrice/resources/{ => phases}/icon_phase_combat_attackers.svg (100%) rename cockatrice/resources/{ => phases}/icon_phase_combat_blockers.svg (100%) rename cockatrice/resources/{ => phases}/icon_phase_combat_damage.svg (100%) rename cockatrice/resources/{ => phases}/icon_phase_combat_end.svg (100%) rename cockatrice/resources/{ => phases}/icon_phase_combat_start.svg (100%) rename cockatrice/resources/{ => phases}/icon_phase_draw.svg (100%) rename cockatrice/resources/{ => phases}/icon_phase_main1.svg (100%) rename cockatrice/resources/{ => phases}/icon_phase_main2.svg (100%) rename cockatrice/resources/{icon_nextturn.svg => phases/icon_phase_nextturn.svg} (100%) rename cockatrice/resources/{ => phases}/icon_phase_untap.svg (100%) rename cockatrice/resources/{ => phases}/icon_phase_upkeep.svg (100%) diff --git a/cockatrice/cockatrice.qrc b/cockatrice/cockatrice.qrc index 3e9a550c..a71ed41e 100644 --- a/cockatrice/cockatrice.qrc +++ b/cockatrice/cockatrice.qrc @@ -7,18 +7,18 @@ resources/icon_config_appearance.svg resources/icon_config_interface.svg resources/icon_config_messages.svg - resources/icon_phase_untap.svg - resources/icon_phase_upkeep.svg - resources/icon_phase_draw.svg - resources/icon_phase_main1.svg - resources/icon_phase_combat_start.svg - resources/icon_phase_combat_attackers.svg - resources/icon_phase_combat_blockers.svg - resources/icon_phase_combat_damage.svg - resources/icon_phase_combat_end.svg - resources/icon_phase_main2.svg - resources/icon_phase_cleanup.svg - resources/icon_nextturn.svg + resources/phases/icon_phase_untap.svg + resources/phases/icon_phase_upkeep.svg + resources/phases/icon_phase_draw.svg + resources/phases/icon_phase_main1.svg + resources/phases/icon_phase_combat_start.svg + resources/phases/icon_phase_combat_attackers.svg + resources/phases/icon_phase_combat_blockers.svg + resources/phases/icon_phase_combat_damage.svg + resources/phases/icon_phase_combat_end.svg + resources/phases/icon_phase_main2.svg + resources/phases/icon_phase_cleanup.svg + resources/phases/icon_phase_nextturn.svg resources/hand.svg resources/pencil.svg resources/icon_search.svg diff --git a/cockatrice/resources/icon_phase_cleanup.svg b/cockatrice/resources/phases/icon_phase_cleanup.svg similarity index 100% rename from cockatrice/resources/icon_phase_cleanup.svg rename to cockatrice/resources/phases/icon_phase_cleanup.svg diff --git a/cockatrice/resources/icon_phase_combat_attackers.svg b/cockatrice/resources/phases/icon_phase_combat_attackers.svg similarity index 100% rename from cockatrice/resources/icon_phase_combat_attackers.svg rename to cockatrice/resources/phases/icon_phase_combat_attackers.svg diff --git a/cockatrice/resources/icon_phase_combat_blockers.svg b/cockatrice/resources/phases/icon_phase_combat_blockers.svg similarity index 100% rename from cockatrice/resources/icon_phase_combat_blockers.svg rename to cockatrice/resources/phases/icon_phase_combat_blockers.svg diff --git a/cockatrice/resources/icon_phase_combat_damage.svg b/cockatrice/resources/phases/icon_phase_combat_damage.svg similarity index 100% rename from cockatrice/resources/icon_phase_combat_damage.svg rename to cockatrice/resources/phases/icon_phase_combat_damage.svg diff --git a/cockatrice/resources/icon_phase_combat_end.svg b/cockatrice/resources/phases/icon_phase_combat_end.svg similarity index 100% rename from cockatrice/resources/icon_phase_combat_end.svg rename to cockatrice/resources/phases/icon_phase_combat_end.svg diff --git a/cockatrice/resources/icon_phase_combat_start.svg b/cockatrice/resources/phases/icon_phase_combat_start.svg similarity index 100% rename from cockatrice/resources/icon_phase_combat_start.svg rename to cockatrice/resources/phases/icon_phase_combat_start.svg diff --git a/cockatrice/resources/icon_phase_draw.svg b/cockatrice/resources/phases/icon_phase_draw.svg similarity index 100% rename from cockatrice/resources/icon_phase_draw.svg rename to cockatrice/resources/phases/icon_phase_draw.svg diff --git a/cockatrice/resources/icon_phase_main1.svg b/cockatrice/resources/phases/icon_phase_main1.svg similarity index 100% rename from cockatrice/resources/icon_phase_main1.svg rename to cockatrice/resources/phases/icon_phase_main1.svg diff --git a/cockatrice/resources/icon_phase_main2.svg b/cockatrice/resources/phases/icon_phase_main2.svg similarity index 100% rename from cockatrice/resources/icon_phase_main2.svg rename to cockatrice/resources/phases/icon_phase_main2.svg diff --git a/cockatrice/resources/icon_nextturn.svg b/cockatrice/resources/phases/icon_phase_nextturn.svg similarity index 100% rename from cockatrice/resources/icon_nextturn.svg rename to cockatrice/resources/phases/icon_phase_nextturn.svg diff --git a/cockatrice/resources/icon_phase_untap.svg b/cockatrice/resources/phases/icon_phase_untap.svg similarity index 100% rename from cockatrice/resources/icon_phase_untap.svg rename to cockatrice/resources/phases/icon_phase_untap.svg diff --git a/cockatrice/resources/icon_phase_upkeep.svg b/cockatrice/resources/phases/icon_phase_upkeep.svg similarity index 100% rename from cockatrice/resources/icon_phase_upkeep.svg rename to cockatrice/resources/phases/icon_phase_upkeep.svg diff --git a/cockatrice/src/abstractcarditem.cpp b/cockatrice/src/abstractcarditem.cpp index 366eb031..12ad3a8b 100644 --- a/cockatrice/src/abstractcarditem.cpp +++ b/cockatrice/src/abstractcarditem.cpp @@ -20,7 +20,7 @@ AbstractCardItem::AbstractCardItem(const QString &_name, Player *_owner, QGraphi setCacheMode(DeviceCoordinateCache); connect(info, SIGNAL(pixmapUpdated()), this, SLOT(pixmapUpdated())); - connect(settingsCache, SIGNAL(displayCardNamesChanged()), this, SLOT(update())); + connect(settingsCache, SIGNAL(displayCardNamesChanged()), this, SLOT(callUpdate())); animationTimer = new QTimer(this); animationTimer->setSingleShot(false); @@ -86,9 +86,12 @@ void AbstractCardItem::paintPicture(QPainter *painter, int angle) QPixmap *translatedPixmap = info->getPixmap(translatedSize.toSize()); painter->save(); + QColor bgColor = Qt::transparent; if (translatedPixmap) { + painter->save(); transformPainter(painter, translatedSize, angle); painter->drawPixmap(QPointF(0, 0), *translatedPixmap); + painter->restore(); } else { QString colorStr; if (!color.isEmpty()) @@ -98,33 +101,26 @@ void AbstractCardItem::paintPicture(QPainter *painter, int angle) else if (!info->getColors().isEmpty()) colorStr = info->getColors().first().toLower(); - QColor bgColor; - QColor textColor = Qt::white; if (colorStr == "b") bgColor = QColor(0, 0, 0); else if (colorStr == "u") bgColor = QColor(0, 140, 180); - else if (colorStr == "w") { + else if (colorStr == "w") bgColor = QColor(255, 250, 140); - textColor = Qt::black; - } else if (colorStr == "r") + else if (colorStr == "r") bgColor = QColor(230, 0, 0); else if (colorStr == "g") bgColor = QColor(0, 160, 0); - else if (colorStr == "m") { + else if (colorStr == "m") bgColor = QColor(250, 190, 30); - textColor = Qt::black; - } else { + else bgColor = QColor(230, 230, 230); - textColor = Qt::black; - } - painter->setBrush(bgColor); - QPen pen(Qt::black); - pen.setWidth(2); - painter->setPen(pen); - painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 2)); } - painter->restore(); + painter->setBrush(bgColor); + QPen pen(Qt::black); + pen.setWidth(2); + painter->setPen(pen); + painter->drawRect(QRectF(1, 1, CARD_WIDTH - 2, CARD_HEIGHT - 2)); if (!translatedPixmap || settingsCache->getDisplayCardNames()) { painter->save(); @@ -133,6 +129,7 @@ void AbstractCardItem::paintPicture(QPainter *painter, int angle) painter->setBackground(Qt::black); painter->setBackgroundMode(Qt::OpaqueMode); painter->drawText(QRectF(3 * scaleFactor, 3 * scaleFactor, translatedSize.width() - 6 * scaleFactor, translatedSize.height() - 6 * scaleFactor), Qt::AlignTop | Qt::AlignLeft | Qt::TextWrapAnywhere, name); + painter->restore(); } painter->restore(); diff --git a/cockatrice/src/abstractcarditem.h b/cockatrice/src/abstractcarditem.h index c07b78a0..caf13407 100644 --- a/cockatrice/src/abstractcarditem.h +++ b/cockatrice/src/abstractcarditem.h @@ -27,6 +27,7 @@ private: private slots: void animationEvent(); void pixmapUpdated(); + void callUpdate() { update(); } signals: void hovered(AbstractCardItem *card); void showCardInfoPopup(QPoint pos, QString cardName); diff --git a/cockatrice/src/gamescene.cpp b/cockatrice/src/gamescene.cpp index 330ebef5..6266b011 100644 --- a/cockatrice/src/gamescene.cpp +++ b/cockatrice/src/gamescene.cpp @@ -2,13 +2,15 @@ #include "player.h" #include "zoneviewwidget.h" #include "zoneviewzone.h" +#include "phasestoolbar.h" #include #include #include -GameScene::GameScene(QObject *parent) - : QGraphicsScene(parent) +GameScene::GameScene(PhasesToolbar *_phasesToolbar, QObject *parent) + : QGraphicsScene(parent), phasesToolbar(_phasesToolbar) { + addItem(phasesToolbar); } void GameScene::retranslateUi() @@ -37,34 +39,37 @@ void GameScene::removePlayer(Player *player) void GameScene::rearrange() { struct PlayerProcessor { - static void processPlayer(Player *p, qreal &w, qreal &h, QPointF &b, bool singlePlayer) + static void processPlayer(Player *p, qreal &w, QPointF &b, bool singlePlayer) { const QRectF br = p->boundingRect(); if (br.width() > w) w = br.width(); - if (h) - h += playerAreaSpacing; - h += br.height(); p->setPos(b); p->setMirrored((b.y() < playerAreaSpacing) && !singlePlayer); b += QPointF(0, br.height() + playerAreaSpacing); } }; - - QPointF base; - qreal sceneWidth = 0; - qreal sceneHeight = 0; + + qreal sceneHeight = -playerAreaSpacing; + for (int i = 0; i < players.size(); ++i) + sceneHeight += players[i]->boundingRect().height() + playerAreaSpacing; + phasesToolbar->setHeight(sceneHeight); + qreal phasesWidth = phasesToolbar->getWidth(); + + QPointF base(phasesWidth, 0); + qreal sceneWidth; QList localPlayers; for (int i = 0; i < players.size(); ++i) if (!players[i]->getLocal()) - PlayerProcessor::processPlayer(players[i], sceneWidth, sceneHeight, base, players.size() == 1); + PlayerProcessor::processPlayer(players[i], sceneWidth, base, players.size() == 1); else localPlayers.append(players[i]); for (int i = 0; i < localPlayers.size(); ++i) - PlayerProcessor::processPlayer(localPlayers[i], sceneWidth, sceneHeight, base, players.size() == 1); + PlayerProcessor::processPlayer(localPlayers[i], sceneWidth, base, players.size() == 1); + sceneWidth += phasesWidth; playersRect = QRectF(0, 0, sceneWidth, sceneHeight); setSceneRect(sceneRect().x(), sceneRect().y(), sceneWidth, sceneHeight); @@ -127,6 +132,7 @@ void GameScene::processViewSizeChange(const QSize &newSize) if (w > minWidth) minWidth = w; } + minWidth += phasesToolbar->getWidth(); qreal minRatio = minWidth / sceneRect().height(); if (minRatio > newRatio) { @@ -138,7 +144,7 @@ void GameScene::processViewSizeChange(const QSize &newSize) } for (int i = 0; i < players.size(); ++i) - players[i]->processSceneSizeChange(sceneRect().size()); + players[i]->processSceneSizeChange(sceneRect().size() - QSizeF(phasesToolbar->getWidth(), 0)); } bool GameScene::event(QEvent *event) diff --git a/cockatrice/src/gamescene.h b/cockatrice/src/gamescene.h index 67031fc2..bdc07757 100644 --- a/cockatrice/src/gamescene.h +++ b/cockatrice/src/gamescene.h @@ -8,18 +8,20 @@ class Player; class ZoneViewWidget; class CardZone; class ServerInfo_Card; +class PhasesToolbar; class GameScene : public QGraphicsScene { Q_OBJECT private: static const int playerAreaSpacing = 5; + PhasesToolbar *phasesToolbar; QList players; QRectF playersRect; QList views; QSize viewSize; public: - GameScene(QObject *parent = 0); + GameScene(PhasesToolbar *_phasesToolbar, QObject *parent = 0); void retranslateUi(); const QRectF &getPlayersRect() const { return playersRect; } void processViewSizeChange(const QSize &newSize); diff --git a/cockatrice/src/gameview.cpp b/cockatrice/src/gameview.cpp index 8c32f755..8a7f89fb 100644 --- a/cockatrice/src/gameview.cpp +++ b/cockatrice/src/gameview.cpp @@ -37,7 +37,6 @@ void GameView::resizeEvent(QResizeEvent *event) void GameView::updateSceneRect(const QRectF &rect) { - qDebug(QString("updateSceneRect = %1,%2").arg(rect.width()).arg(rect.height()).toLatin1()); fitInView(rect, Qt::KeepAspectRatio); } diff --git a/cockatrice/src/phasestoolbar.cpp b/cockatrice/src/phasestoolbar.cpp index 2078113f..c510cb9b 100644 --- a/cockatrice/src/phasestoolbar.cpp +++ b/cockatrice/src/phasestoolbar.cpp @@ -1,54 +1,60 @@ #include -#include #include #include #include +#include +#include #include "phasestoolbar.h" #include "protocol_items.h" +#include "pixmapgenerator.h" -PhaseButton::PhaseButton(const QIcon &icon, QAction *_doubleClickAction) - : QPushButton(icon, QString()), active(false), activeAnimationCounter(0), doubleClickAction(_doubleClickAction), pixmap(50, 50) +PhaseButton::PhaseButton(const QString &_name, QGraphicsItem *parent, QAction *_doubleClickAction, bool _highlightable) + : QObject(), QGraphicsItem(parent), name(_name), active(false), highlightable(_highlightable), activeAnimationCounter(0), doubleClickAction(_doubleClickAction), width(50) { - setFocusPolicy(Qt::NoFocus); - setFixedSize(50, 50); + if (highlightable) { + activeAnimationTimer = new QTimer(this); + connect(activeAnimationTimer, SIGNAL(timeout()), this, SLOT(updateAnimation())); + activeAnimationTimer->setSingleShot(false); + } else + activeAnimationCounter = 9.0; - activeAnimationTimer = new QTimer(this); - connect(activeAnimationTimer, SIGNAL(timeout()), this, SLOT(updateAnimation())); - activeAnimationTimer->setSingleShot(false); - - updatePixmap(pixmap); + setCacheMode(DeviceCoordinateCache); } -void PhaseButton::updatePixmap(QPixmap &pixmap) +QRectF PhaseButton::boundingRect() const { - pixmap.fill(Qt::transparent); - - QPainter painter(&pixmap); - int height = pixmap.height(); - int width = pixmap.width(); - - icon().paint(&painter, 5, 5, width - 10, height - 10); + return QRectF(0, 0, width, width); } -void PhaseButton::paintEvent(QPaintEvent */*event*/) +void PhaseButton::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) { - QPainter painter(this); - - painter.setBrush(QColor(220 * (activeAnimationCounter / 10.0), 220 * (activeAnimationCounter / 10.0), 220 * (activeAnimationCounter / 10.0))); - painter.setPen(Qt::gray); - painter.drawRect(1, 1, pixmap.width() - 2, pixmap.height() - 2); - - painter.drawPixmap(0, 0, size().width(), size().height(), pixmap); + QRectF iconRect = boundingRect().adjusted(3, 3, -3, -3); + QRectF translatedIconRect = painter->combinedTransform().mapRect(iconRect); + qreal scaleFactor = translatedIconRect.width() / iconRect.width(); + QPixmap iconPixmap = PhasePixmapGenerator::generatePixmap(round(translatedIconRect.height()), name); -// painter.setBrush(QColor(220 * (activeAnimationCounter / 10.0), 220 * (activeAnimationCounter / 10.0), 220 * (activeAnimationCounter / 10.0), 255 * ((10 - activeAnimationCounter) / 15.0))); - painter.setBrush(QColor(0, 0, 0, 255 * ((10 - activeAnimationCounter) / 15.0))); - painter.setPen(Qt::gray); - painter.drawRect(1, 1, pixmap.width() - 2, pixmap.height() - 2); + painter->setBrush(QColor(220 * (activeAnimationCounter / 10.0), 220 * (activeAnimationCounter / 10.0), 220 * (activeAnimationCounter / 10.0))); + painter->setPen(Qt::gray); + painter->drawRect(0.5, 0.5, width - 1, width - 1); + painter->save(); + painter->resetTransform(); + painter->drawPixmap(iconPixmap.rect().translated(round(3 * scaleFactor), round(3 * scaleFactor)), iconPixmap, iconPixmap.rect()); + painter->restore(); + + painter->setBrush(QColor(0, 0, 0, 255 * ((10 - activeAnimationCounter) / 15.0))); + painter->setPen(Qt::gray); + painter->drawRect(0.5, 0.5, width - 1, width - 1); +} + +void PhaseButton::setWidth(double _width) +{ + prepareGeometryChange(); + width = _width; } void PhaseButton::setActive(bool _active) { - if (active == _active) + if ((active == _active) || !highlightable) return; active = _active; @@ -57,6 +63,9 @@ void PhaseButton::setActive(bool _active) void PhaseButton::updateAnimation() { + if (!highlightable) + return; + if (active) { if (++activeAnimationCounter >= 10) activeAnimationTimer->stop(); @@ -67,13 +76,12 @@ void PhaseButton::updateAnimation() update(); } -void PhaseButton::setPhaseText(const QString &_phaseText) +void PhaseButton::mousePressEvent(QGraphicsSceneMouseEvent * /*event*/) { - phaseText = _phaseText; - setToolTip(phaseText); + emit clicked(); } -void PhaseButton::mouseDoubleClickEvent(QMouseEvent */*event*/) +void PhaseButton::mouseDoubleClickEvent(QGraphicsSceneMouseEvent */*event*/) { triggerDoubleClickAction(); } @@ -84,34 +92,31 @@ void PhaseButton::triggerDoubleClickAction() doubleClickAction->trigger(); } -PhasesToolbar::PhasesToolbar(QWidget *parent) - : QFrame(parent) +PhasesToolbar::PhasesToolbar(QGraphicsItem *parent) + : QGraphicsItem(parent), width(100), height(100) { - setBackgroundRole(QPalette::Shadow); - setAutoFillBackground(true); - QAction *aUntapAll = new QAction(this); connect(aUntapAll, SIGNAL(triggered()), this, SLOT(actUntapAll())); QAction *aDrawCard = new QAction(this); connect(aDrawCard, SIGNAL(triggered()), this, SLOT(actDrawCard())); - PhaseButton *untapButton = new PhaseButton(QIcon(":/resources/icon_phase_untap.svg"), aUntapAll); - untapButton->setShortcut(QKeySequence("F5")); - PhaseButton *upkeepButton = new PhaseButton(QIcon(":/resources/icon_phase_upkeep.svg")); - PhaseButton *drawButton = new PhaseButton(QIcon(":/resources/icon_phase_draw.svg"), aDrawCard); - drawButton->setShortcut(QKeySequence("F6")); - PhaseButton *main1Button = new PhaseButton(QIcon(":/resources/icon_phase_main1.svg")); - main1Button->setShortcut(QKeySequence("F7")); - PhaseButton *combatStartButton = new PhaseButton(QIcon(":/resources/icon_phase_combat_start.svg")); - combatStartButton->setShortcut(QKeySequence("F8")); - PhaseButton *combatAttackersButton = new PhaseButton(QIcon(":/resources/icon_phase_combat_attackers.svg")); - PhaseButton *combatBlockersButton = new PhaseButton(QIcon(":/resources/icon_phase_combat_blockers.svg")); - PhaseButton *combatDamageButton = new PhaseButton(QIcon(":/resources/icon_phase_combat_damage.svg")); - PhaseButton *combatEndButton = new PhaseButton(QIcon(":/resources/icon_phase_combat_end.svg")); - PhaseButton *main2Button = new PhaseButton(QIcon(":/resources/icon_phase_main2.svg")); - main2Button->setShortcut(QKeySequence("F9")); - PhaseButton *cleanupButton = new PhaseButton(QIcon(":/resources/icon_phase_cleanup.svg")); - cleanupButton->setShortcut(QKeySequence("F10")); + PhaseButton *untapButton = new PhaseButton("untap", this, aUntapAll); +// untapButton->setShortcut(QKeySequence("F5")); + PhaseButton *upkeepButton = new PhaseButton("upkeep", this); + PhaseButton *drawButton = new PhaseButton("draw", this, aDrawCard); +// drawButton->setShortcut(QKeySequence("F6")); + PhaseButton *main1Button = new PhaseButton("main1", this); +// main1Button->setShortcut(QKeySequence("F7")); + PhaseButton *combatStartButton = new PhaseButton("combat_start", this); +// combatStartButton->setShortcut(QKeySequence("F8")); + PhaseButton *combatAttackersButton = new PhaseButton("combat_attackers", this); + PhaseButton *combatBlockersButton = new PhaseButton("combat_blockers", this); + PhaseButton *combatDamageButton = new PhaseButton("combat_damage", this); + PhaseButton *combatEndButton = new PhaseButton("combat_end", this); + PhaseButton *main2Button = new PhaseButton("main2", this); +// main2Button->setShortcut(QKeySequence("F9")); + PhaseButton *cleanupButton = new PhaseButton("cleanup", this); +// cleanupButton->setShortcut(QKeySequence("F10")); buttonList << untapButton << upkeepButton << drawButton << main1Button << combatStartButton << combatAttackersButton << combatBlockersButton << combatDamageButton << combatEndButton @@ -120,52 +125,85 @@ PhasesToolbar::PhasesToolbar(QWidget *parent) for (int i = 0; i < buttonList.size(); ++i) connect(buttonList[i], SIGNAL(clicked()), this, SLOT(phaseButtonClicked())); - QPushButton *nextTurnButton = new QPushButton(QIcon(":/resources/icon_nextturn.svg"), QString()); - nextTurnButton->setFocusPolicy(Qt::NoFocus); - nextTurnButton->setIconSize(QSize(40, 40)); - nextTurnButton->setFixedSize(50, 50); + nextTurnButton = new PhaseButton("nextturn", this, 0, false); connect(nextTurnButton, SIGNAL(clicked()), this, SLOT(actNextTurn())); - - QVBoxLayout *layout = new QVBoxLayout; - layout->setSpacing(0); - layout->addStretch(1); - layout->addWidget(untapButton); - layout->addWidget(upkeepButton); - layout->addWidget(drawButton); - layout->addSpacing(10); - layout->addWidget(main1Button); - layout->addSpacing(10); - layout->addWidget(combatStartButton); - layout->addWidget(combatAttackersButton); - layout->addWidget(combatBlockersButton); - layout->addWidget(combatDamageButton); - layout->addWidget(combatEndButton); - layout->addSpacing(10); - layout->addWidget(main2Button); - layout->addSpacing(10); - layout->addWidget(cleanupButton); - layout->addSpacing(20); - layout->addWidget(nextTurnButton); - layout->addStretch(1); + rearrangeButtons(); retranslateUi(); - setLayout(layout); +} + +QRectF PhasesToolbar::boundingRect() const +{ + return QRectF(0, 0, width, height); } void PhasesToolbar::retranslateUi() { - buttonList[0]->setPhaseText(tr("Untap step")); - buttonList[1]->setPhaseText(tr("Upkeep step")); - buttonList[2]->setPhaseText(tr("Draw step")); - buttonList[3]->setPhaseText(tr("First main phase")); - buttonList[4]->setPhaseText(tr("Beginning of combat step")); - buttonList[5]->setPhaseText(tr("Declare attackers step")); - buttonList[6]->setPhaseText(tr("Declare blockers step")); - buttonList[7]->setPhaseText(tr("Combat damage step")); - buttonList[8]->setPhaseText(tr("End of combat step")); - buttonList[9]->setPhaseText(tr("Second main phase")); - buttonList[10]->setPhaseText(tr("End of turn step")); + for (int i = 0; i < buttonList.size(); ++i) + buttonList[i]->setToolTip(getLongPhaseName(i)); +} + +QString PhasesToolbar::getLongPhaseName(int phase) const +{ + switch (phase) { + case 0: return tr("Untap step"); + case 1: return tr("Upkeep step"); + case 2: return tr("Draw step"); + case 3: return tr("First main phase"); + case 4: return tr("Beginning of combat step"); + case 5: return tr("Declare attackers step"); + case 6: return tr("Declare blockers step"); + case 7: return tr("Combat damage step"); + case 8: return tr("End of combat step"); + case 9: return tr("Second main phase"); + case 10: return tr("End of turn step"); + default: return QString(); + } +} + +void PhasesToolbar::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) +{ + painter->fillRect(boundingRect(), QColor(50, 50, 50)); +} + +void PhasesToolbar::rearrangeButtons() +{ + for (int i = 0; i < buttonList.size(); ++i) + buttonList[i]->setWidth(symbolSize); + nextTurnButton->setWidth(symbolSize); + + double y = margin; + buttonList[0]->setPos(margin, y); + buttonList[1]->setPos(margin, y += symbolSize); + buttonList[2]->setPos(margin, y += symbolSize); + y += ySpacing; + buttonList[3]->setPos(margin, y += symbolSize); + y += ySpacing; + buttonList[4]->setPos(margin, y += symbolSize); + buttonList[5]->setPos(margin, y += symbolSize); + buttonList[6]->setPos(margin, y += symbolSize); + buttonList[7]->setPos(margin, y += symbolSize); + buttonList[8]->setPos(margin, y += symbolSize); + y += ySpacing; + buttonList[9]->setPos(margin, y += symbolSize); + y += ySpacing; + buttonList[10]->setPos(margin, y += symbolSize); + y += ySpacing; + y += ySpacing; + nextTurnButton->setPos(margin, y += symbolSize); +} + +void PhasesToolbar::setHeight(double _height) +{ + prepareGeometryChange(); + + height = _height; + ySpacing = (height - 2 * margin) / (buttonCount * 5 + spaceCount); + symbolSize = ySpacing * 5; + width = symbolSize + 2 * margin; + + rearrangeButtons(); } void PhasesToolbar::setActivePhase(int phase) diff --git a/cockatrice/src/phasestoolbar.h b/cockatrice/src/phasestoolbar.h index c685d50b..a6e6cffb 100644 --- a/cockatrice/src/phasestoolbar.h +++ b/cockatrice/src/phasestoolbar.h @@ -3,44 +3,57 @@ #include #include -#include +#include class Player; class GameCommand; -class PhaseButton : public QPushButton { +class PhaseButton : public QObject, public QGraphicsItem { Q_OBJECT private: - QString phaseText; - bool active; + QString name; + bool active, highlightable; int activeAnimationCounter; QTimer *activeAnimationTimer; QAction *doubleClickAction; - QPixmap pixmap; + double width; void updatePixmap(QPixmap &pixmap); private slots: void updateAnimation(); public: - PhaseButton(const QIcon &icon, QAction *_doubleClickAction = 0); - void setPhaseText(const QString &_phaseText); - QString getPhaseText() const { return phaseText; } + PhaseButton(const QString &_name, QGraphicsItem *parent = 0, QAction *_doubleClickAction = 0, bool _highlightable = true); + QRectF boundingRect() const; + void setWidth(double _width); void setActive(bool _active); bool getActive() const { return active; } void triggerDoubleClickAction(); +signals: + void clicked(); protected: - void paintEvent(QPaintEvent *event); - void mouseDoubleClickEvent(QMouseEvent *event); + void paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/); + void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); }; -class PhasesToolbar : public QFrame { +class PhasesToolbar : public QObject, public QGraphicsItem { Q_OBJECT private: QList buttonList; + PhaseButton *nextTurnButton; + double width, height, ySpacing, symbolSize; + static const int buttonCount = 12; + static const int spaceCount = 6; + static const double margin = 3; + void rearrangeButtons(); public: - PhasesToolbar(QWidget *parent = 0); + PhasesToolbar(QGraphicsItem *parent = 0); + QRectF boundingRect() const; void retranslateUi(); + void setHeight(double _height); + double getWidth() const { return width; } int phaseCount() const { return buttonList.size(); } + QString getLongPhaseName(int phase) const; public slots: void setActivePhase(int phase); private slots: @@ -50,6 +63,8 @@ private slots: void actDrawCard(); signals: void sendGameCommand(GameCommand *command, int playerId); +protected: + void paint(QPainter *painter, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/); }; #endif diff --git a/cockatrice/src/pixmapgenerator.cpp b/cockatrice/src/pixmapgenerator.cpp index e3325d42..a27b081d 100644 --- a/cockatrice/src/pixmapgenerator.cpp +++ b/cockatrice/src/pixmapgenerator.cpp @@ -5,6 +5,24 @@ #include #include +QMap PhasePixmapGenerator::pmCache; + +QPixmap PhasePixmapGenerator::generatePixmap(int height, QString name) +{ + QString key = name + QString::number(height); + if (pmCache.contains(key)) + return pmCache.value(key); + + QSvgRenderer svg(QString(":/resources/phases/icon_phase_" + name + ".svg")); + + QPixmap pixmap(height, height); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + svg.render(&painter, QRectF(0, 0, height, height)); + pmCache.insert(key, pixmap); + return pixmap; +} + QMap CounterPixmapGenerator::pmCache; QPixmap CounterPixmapGenerator::generatePixmap(int height, QString name, bool highlight) diff --git a/cockatrice/src/pixmapgenerator.h b/cockatrice/src/pixmapgenerator.h index d988b679..7f69c26d 100644 --- a/cockatrice/src/pixmapgenerator.h +++ b/cockatrice/src/pixmapgenerator.h @@ -4,6 +4,14 @@ #include #include +class PhasePixmapGenerator { +private: + static QMap pmCache; +public: + static QPixmap generatePixmap(int size, QString name); + static void clear() { pmCache.clear(); } +}; + class CounterPixmapGenerator { private: static QMap pmCache; diff --git a/cockatrice/src/tab_game.cpp b/cockatrice/src/tab_game.cpp index 7f0e9e95..600e958b 100644 --- a/cockatrice/src/tab_game.cpp +++ b/cockatrice/src/tab_game.cpp @@ -162,7 +162,11 @@ void DeckViewContainer::setDeck(DeckList *deck) TabGame::TabGame(QList &_clients, int _gameId, const QString &_gameDescription, int _localPlayerId, bool _spectator, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, bool _resuming) : Tab(), clients(_clients), gameId(_gameId), gameDescription(_gameDescription), localPlayerId(_localPlayerId), spectator(_spectator), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), started(false), resuming(_resuming), currentPhase(-1), infoPopup(0) { - scene = new GameScene(this); + phasesToolbar = new PhasesToolbar; + phasesToolbar->hide(); + connect(phasesToolbar, SIGNAL(sendGameCommand(GameCommand *, int)), this, SLOT(sendGameCommand(GameCommand *, int))); + + scene = new GameScene(phasesToolbar, this); gameView = new GameView(scene); gameView->hide(); @@ -185,10 +189,6 @@ TabGame::TabGame(QList &_clients, int _gameId, const QString & deckViewContainerLayout = new QVBoxLayout; - phasesToolbar = new PhasesToolbar; - phasesToolbar->hide(); - connect(phasesToolbar, SIGNAL(sendGameCommand(GameCommand *, int)), this, SLOT(sendGameCommand(GameCommand *, int))); - QVBoxLayout *verticalLayout = new QVBoxLayout; verticalLayout->addWidget(cardInfo); verticalLayout->addWidget(playerListWidget, 1); @@ -197,7 +197,6 @@ TabGame::TabGame(QList &_clients, int _gameId, const QString & verticalLayout->addLayout(hLayout); mainLayout = new QHBoxLayout; - mainLayout->addWidget(phasesToolbar); mainLayout->addWidget(gameView, 10); mainLayout->addLayout(deckViewContainerLayout, 10); mainLayout->addLayout(verticalLayout); @@ -221,9 +220,28 @@ TabGame::TabGame(QList &_clients, int _gameId, const QString & aLeaveGame = new QAction(this); connect(aLeaveGame, SIGNAL(triggered()), this, SLOT(actLeaveGame())); + phasesMenu = new QMenu(this); + for (int i = 0; i < phasesToolbar->phaseCount(); ++i) { + QAction *temp = new QAction(QString(), this); + connect(temp, SIGNAL(triggered()), this, SLOT(actPhaseAction())); + switch (i) { + case 0: temp->setShortcut(tr("F5")); break; + case 2: temp->setShortcut(tr("F6")); break; + case 3: temp->setShortcut(tr("F7")); break; + case 4: temp->setShortcut(tr("F8")); break; + case 9: temp->setShortcut(tr("F9")); break; + case 10: temp->setShortcut(tr("F10")); break; + default: ; + } + phasesMenu->addAction(temp); + phaseActions.append(temp); + } + phasesMenu->addSeparator(); + phasesMenu->addAction(aNextPhase); + tabMenu = new QMenu(this); playersSeparator = tabMenu->addSeparator(); - tabMenu->addAction(aNextPhase); + tabMenu->addMenu(phasesMenu); tabMenu->addAction(aNextTurn); tabMenu->addSeparator(); tabMenu->addAction(aRemoveLocalArrows); @@ -251,6 +269,10 @@ TabGame::~TabGame() void TabGame::retranslateUi() { + for (int i = 0; i < phaseActions.size(); ++i) + phaseActions[i]->setText(phasesToolbar->getLongPhaseName(i)); + phasesMenu->setTitle(tr("&Phases")); + tabMenu->setTitle(tr("&Game")); aNextPhase->setText(tr("Next &phase")); aNextPhase->setShortcut(tr("Ctrl+Space")); @@ -300,6 +322,12 @@ void TabGame::actSay() } } +void TabGame::actPhaseAction() +{ + int phase = phaseActions.indexOf(static_cast(sender())); + emit sendGameCommand(new Command_SetActivePhase(-1, phase), -1); +} + void TabGame::actNextPhase() { int phase = currentPhase; diff --git a/cockatrice/src/tab_game.h b/cockatrice/src/tab_game.h index 0a022adf..3e34471a 100644 --- a/cockatrice/src/tab_game.h +++ b/cockatrice/src/tab_game.h @@ -93,6 +93,7 @@ private: QMap spectators; bool started; bool resuming; + QStringList phasesList; int currentPhase; int activePlayer; @@ -111,8 +112,9 @@ private: QHBoxLayout *mainLayout; ZoneViewLayout *zoneLayout; QAction *playersSeparator; - QMenu *playersMenu; + QMenu *phasesMenu; QAction *aConcede, *aLeaveGame, *aNextPhase, *aNextTurn, *aRemoveLocalArrows; + QList phaseActions; Player *addPlayer(int playerId, ServerInfo_User *info); @@ -145,6 +147,7 @@ private slots: void actLeaveGame(); void actRemoveLocalArrows(); void actSay(); + void actPhaseAction(); void actNextPhase(); void actNextTurn(); public: