summaryrefslogtreecommitdiffstats
path: root/atlantik/libatlantikui
diff options
context:
space:
mode:
Diffstat (limited to 'atlantik/libatlantikui')
-rw-r--r--atlantik/libatlantikui/Makefile.am15
-rw-r--r--atlantik/libatlantikui/auction_widget.cpp141
-rw-r--r--atlantik/libatlantikui/auction_widget.h65
-rw-r--r--atlantik/libatlantikui/board.cpp601
-rw-r--r--atlantik/libatlantikui/board.h102
-rw-r--r--atlantik/libatlantikui/estatedetails.cpp327
-rw-r--r--atlantik/libatlantikui/estatedetails.h77
-rw-r--r--atlantik/libatlantikui/estateview.cpp558
-rw-r--r--atlantik/libatlantikui/estateview.h80
-rw-r--r--atlantik/libatlantikui/kwrappedlistviewitem.cpp116
-rw-r--r--atlantik/libatlantikui/kwrappedlistviewitem.h54
-rw-r--r--atlantik/libatlantikui/libatlantikui_export.h25
-rw-r--r--atlantik/libatlantikui/portfolioestate.cpp94
-rw-r--r--atlantik/libatlantikui/portfolioestate.h55
-rw-r--r--atlantik/libatlantikui/portfolioview.cpp295
-rw-r--r--atlantik/libatlantikui/portfolioview.h73
-rw-r--r--atlantik/libatlantikui/token.cpp157
-rw-r--r--atlantik/libatlantikui/token.h62
-rw-r--r--atlantik/libatlantikui/trade_widget.cpp374
-rw-r--r--atlantik/libatlantikui/trade_widget.h98
20 files changed, 3369 insertions, 0 deletions
diff --git a/atlantik/libatlantikui/Makefile.am b/atlantik/libatlantikui/Makefile.am
new file mode 100644
index 00000000..2e3bbbed
--- /dev/null
+++ b/atlantik/libatlantikui/Makefile.am
@@ -0,0 +1,15 @@
+INCLUDES = -I$(top_srcdir)/atlantik/libatlantic $(all_includes)
+lib_LTLIBRARIES = libatlantikui.la
+libatlantikui_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -no-undefined -version-info 3:0:2
+libatlantikui_la_LIBADD = ../libatlantic/libatlantic.la $(LIB_KIO)
+
+libatlantikui_la_SOURCES = auction_widget.cpp board.cpp estatedetails.cpp \
+ estateview.cpp kwrappedlistviewitem.cpp portfolioestate.cpp \
+ portfolioview.cpp token.cpp trade_widget.cpp
+
+libatlantikuiincludedir = $(includedir)/atlantik/ui
+libatlantikuiinclude_HEADERS = auction_widget.h board.h estatedetails.h \
+ estateview.h kwrappedlistviewitem.h portfolioestate.h \
+ portfolioview.h token.h trade_widget.h libatlantikui_export.h
+
+METASOURCES = AUTO
diff --git a/atlantik/libatlantikui/auction_widget.cpp b/atlantik/libatlantikui/auction_widget.cpp
new file mode 100644
index 00000000..e7dc7fd8
--- /dev/null
+++ b/atlantik/libatlantikui/auction_widget.cpp
@@ -0,0 +1,141 @@
+// Copyright (c) 2002 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#include <qvgroupbox.h>
+#include <qhbox.h>
+#include <qspinbox.h>
+#include <qlabel.h>
+
+#include <kdebug.h>
+
+#include <kdialog.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kpushbutton.h>
+
+#include <atlantic_core.h>
+#include <player.h>
+#include <estate.h>
+#include <auction.h>
+
+#include "auction_widget.moc"
+
+AuctionWidget::AuctionWidget(AtlanticCore *atlanticCore, Auction *auction, QWidget *parent, const char *name) : QWidget(parent, name)
+{
+ m_atlanticCore = atlanticCore;
+
+ m_auction = auction;
+ connect(m_auction, SIGNAL(changed()), this, SLOT(auctionChanged()));
+ connect(m_auction, SIGNAL(updateBid(Player *, int)), this, SLOT(updateBid(Player *, int)));
+ connect(this, SIGNAL(bid(Auction *, int)), m_auction, SIGNAL(bid(Auction *, int)));
+
+ m_mainLayout = new QVBoxLayout(this, KDialog::marginHint());
+ Q_CHECK_PTR(m_mainLayout);
+
+ // Player list
+ Estate *estate = auction->estate();
+ m_playerGroupBox = new QVGroupBox(estate ? i18n("Auction: %1").arg(estate->name()) : i18n("Auction"), this, "groupBox");
+ m_mainLayout->addWidget(m_playerGroupBox);
+
+ m_playerList = new KListView(m_playerGroupBox);
+ m_playerList->addColumn(i18n("Player"));
+ m_playerList->addColumn(i18n("Bid"));
+ m_playerList->setSorting(1, false);
+
+ KListViewItem *item;
+ Player *player, *pSelf = m_atlanticCore->playerSelf();
+
+ QPtrList<Player> playerList = m_atlanticCore->players();
+ for (QPtrListIterator<Player> it(playerList); *it; ++it)
+ {
+ if ( (player = *it) && player->game() == pSelf->game() )
+ {
+ item = new KListViewItem(m_playerList, player->name(), QString("0"));
+ item->setPixmap(0, QPixmap(SmallIcon("personal")));
+ m_playerItems[player] = item;
+
+ connect(player, SIGNAL(changed(Player *)), this, SLOT(playerChanged(Player *)));
+ }
+ }
+
+ // Bid spinbox and button
+ QHBox *bidBox = new QHBox(this);
+ m_mainLayout->addWidget(bidBox);
+
+ m_bidSpinBox = new QSpinBox(1, 10000, 1, bidBox);
+
+ KPushButton *bidButton = new KPushButton(i18n("Make Bid"), bidBox, "bidButton");
+ connect(bidButton, SIGNAL(clicked()), this, SLOT(slotBidButtonClicked()));
+
+ // Status label
+ m_statusLabel = new QLabel(this, "statusLabel");
+ m_mainLayout->addWidget(m_statusLabel);
+}
+
+void AuctionWidget::auctionChanged()
+{
+ QString status;
+ switch (m_auction->status())
+ {
+ case 1:
+ status = i18n("Going once...");
+ break;
+
+ case 2:
+ status = i18n("Going twice...");
+ break;
+
+ case 3:
+ status = i18n("Sold!");
+ break;
+
+ default:
+ status = QString::null;
+ }
+ m_statusLabel->setText(status);
+}
+
+void AuctionWidget::playerChanged(Player *player)
+{
+ if (!player)
+ return;
+
+ QListViewItem *item;
+ if (!(item = m_playerItems[player]))
+ return;
+
+ item->setText(0, player->name());
+ m_playerList->triggerUpdate();
+}
+
+void AuctionWidget::updateBid(Player *player, int amount)
+{
+ if (!player)
+ return;
+
+ QListViewItem *item;
+ if (!(item = m_playerItems[player]))
+ return;
+
+ item->setText(1, QString::number(amount));
+ m_bidSpinBox->setMinValue(amount+1);
+ m_playerList->triggerUpdate();
+}
+
+void AuctionWidget::slotBidButtonClicked()
+{
+ emit bid(m_auction, m_bidSpinBox->value());
+}
diff --git a/atlantik/libatlantikui/auction_widget.h b/atlantik/libatlantikui/auction_widget.h
new file mode 100644
index 00000000..a87b8fc4
--- /dev/null
+++ b/atlantik/libatlantikui/auction_widget.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2002 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#ifndef ATLANTIK_AUCTION_WIDGET_H
+#define ATLANTIK_AUCTION_WIDGET_H
+
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qmap.h>
+
+#include <klistview.h>
+
+class QVGroupBox;
+class QSpinBox;
+class QLabel;
+
+class KListViewItem;
+
+class AtlanticCore;
+class Player;
+class Auction;
+
+class AuctionWidget : public QWidget
+{
+Q_OBJECT
+
+public:
+ AuctionWidget(AtlanticCore *atlanticCore, Auction *auction, QWidget *parent, const char *name=0);
+
+private slots:
+ void auctionChanged();
+ void playerChanged(Player *player);
+ void updateBid(Player *player, int amount);
+ void slotBidButtonClicked();
+
+signals:
+ void bid(Auction *auction, int amount);
+
+private:
+ QVBoxLayout *m_mainLayout;
+ QVGroupBox *m_playerGroupBox;
+ QSpinBox *m_bidSpinBox;
+ QMap<Player *, KListViewItem *> m_playerItems;
+ QLabel *m_statusLabel;
+
+ KListView *m_playerList;
+
+ AtlanticCore *m_atlanticCore;
+ Auction *m_auction;
+};
+
+#endif
diff --git a/atlantik/libatlantikui/board.cpp b/atlantik/libatlantikui/board.cpp
new file mode 100644
index 00000000..a4fdf3ce
--- /dev/null
+++ b/atlantik/libatlantikui/board.cpp
@@ -0,0 +1,601 @@
+// Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#include <iostream>
+
+#include <qpainter.h>
+#include <qstring.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <atlantic_core.h>
+#include <player.h>
+#include <estate.h>
+#include <auction.h>
+
+#include "auction_widget.h"
+#include "estatedetails.h"
+#include "estateview.h"
+#include "token.h"
+
+#include "board.h"
+#include "board.moc"
+
+AtlantikBoard::AtlantikBoard(AtlanticCore *atlanticCore, int maxEstates, DisplayMode mode, QWidget *parent, const char *name) : QWidget(parent, name)
+{
+ m_atlanticCore = atlanticCore;
+ m_maxEstates = maxEstates;
+ m_mode = mode;
+ m_animateTokens = false;
+ m_lastServerDisplay = 0;
+
+ setMinimumSize(QSize(500, 500));
+
+ int sideLen = maxEstates/4;
+
+ // Animated token movement
+ m_movingToken = 0;
+ m_timer = new QTimer(this);
+ connect(m_timer, SIGNAL(timeout()), this, SLOT(slotMoveToken()));
+ m_resumeTimer = false;
+
+ m_gridLayout = new QGridLayout(this, sideLen+1, sideLen+1);
+ for(int i=0;i<=sideLen;i++)
+ {
+ if (i==0 || i==sideLen)
+ {
+ m_gridLayout->setRowStretch(i, 3);
+ m_gridLayout->setColStretch(i, 3);
+ }
+ else
+ {
+ m_gridLayout->setRowStretch(i, 2);
+ m_gridLayout->setColStretch(i, 2);
+ }
+ }
+
+// spacer = new QWidget(this);
+// m_gridLayout->addWidget(spacer, sideLen, sideLen); // SE
+
+ m_displayQueue.setAutoDelete(true);
+ m_estateViews.setAutoDelete(true);
+ m_tokens.setAutoDelete(true);
+
+ displayDefault();
+}
+
+AtlantikBoard::~AtlantikBoard()
+{
+ reset();
+}
+
+void AtlantikBoard::reset()
+{
+ kdDebug() << "AtlantikBoard::reset" << endl;
+
+ m_tokens.clear();
+ m_estateViews.clear();
+ m_displayQueue.clear();
+ m_lastServerDisplay = 0;
+ m_movingToken = 0;
+}
+
+void AtlantikBoard::setViewProperties(bool indicateUnowned, bool highliteUnowned, bool darkenMortgaged, bool quartzEffects, bool animateTokens)
+{
+ if (m_animateTokens != animateTokens)
+ m_animateTokens = animateTokens;
+
+ // Update EstateViews
+ EstateView *estateView;
+ for (QPtrListIterator<EstateView> it(m_estateViews); *it; ++it)
+ if ((estateView = dynamic_cast<EstateView*>(*it)))
+ estateView->setViewProperties(indicateUnowned, highliteUnowned, darkenMortgaged, quartzEffects);
+}
+
+int AtlantikBoard::heightForWidth(int width)
+{
+ return width;
+}
+
+EstateView *AtlantikBoard::findEstateView(Estate *estate)
+{
+ EstateView *estateView;
+ for (QPtrListIterator<EstateView> i(m_estateViews); *i; ++i)
+ {
+ estateView = dynamic_cast<EstateView*>(*i);
+ if (estateView && estateView->estate() == estate)
+ return estateView;
+ }
+ return 0;
+}
+
+void AtlantikBoard::addEstateView(Estate *estate, bool indicateUnowned, bool highliteUnowned, bool darkenMortgaged, bool quartzEffects)
+{
+ QString icon = QString();
+ int estateId = estate->id();
+ EstateOrientation orientation = North;
+ int sideLen = m_gridLayout->numRows() - 1;
+
+ if (estateId < sideLen)
+ orientation = North;
+ else if (estateId < 2*sideLen)
+ orientation = East;
+ else if (estateId < 3*sideLen)
+ orientation = South;
+ else //if (estateId < 4*sideLen)
+ orientation = West;
+
+ EstateView *estateView = new EstateView(estate, orientation, icon, indicateUnowned, highliteUnowned, darkenMortgaged, quartzEffects, this, "estateview");
+ m_estateViews.append(estateView);
+
+ connect(estate, SIGNAL(changed()), estateView, SLOT(estateChanged()));
+ connect(estateView, SIGNAL(estateToggleMortgage(Estate *)), estate, SIGNAL(estateToggleMortgage(Estate *)));
+ connect(estateView, SIGNAL(LMBClicked(Estate *)), estate, SIGNAL(LMBClicked(Estate *)));
+ connect(estateView, SIGNAL(estateHouseBuy(Estate *)), estate, SIGNAL(estateHouseBuy(Estate *)));
+ connect(estateView, SIGNAL(estateHouseSell(Estate *)), estate, SIGNAL(estateHouseSell(Estate *)));
+ connect(estateView, SIGNAL(newTrade(Player *)), estate, SIGNAL(newTrade(Player *)));
+
+ // Designer has its own LMBClicked slot
+ if (m_mode == Play)
+ connect(estateView, SIGNAL(LMBClicked(Estate *)), this, SLOT(prependEstateDetails(Estate *)));
+
+ if (estateId<sideLen)
+ m_gridLayout->addWidget(estateView, sideLen, sideLen-estateId);
+ else if (estateId<2*sideLen)
+ m_gridLayout->addWidget(estateView, 2*sideLen-estateId, 0);
+ else if (estateId<3*sideLen)
+ m_gridLayout->addWidget(estateView, 0, estateId-2*sideLen);
+ else
+ m_gridLayout->addWidget(estateView, estateId-3*sideLen, sideLen);
+
+ estateView->show();
+
+ if (m_atlanticCore)
+ {
+ Player *player = 0;
+ QPtrList<Player> playerList = m_atlanticCore->players();
+ for (QPtrListIterator<Player> it(playerList); (player = *it) ; ++it)
+ if (player->location() == estate)
+ addToken(player);
+ }
+}
+
+void AtlantikBoard::addAuctionWidget(Auction *auction)
+{
+ AuctionWidget *auctionW = new AuctionWidget(m_atlanticCore, auction, this);
+ m_lastServerDisplay = auctionW;
+ m_displayQueue.prepend(auctionW);
+ updateCenter();
+
+ connect(auction, SIGNAL(completed()), this, SLOT(displayDefault()));
+}
+
+Token *AtlantikBoard::findToken(Player *player)
+{
+ Token *token = 0;
+ for (QPtrListIterator<Token> it(m_tokens); (token = *it) ; ++it)
+ if (token->player() == player)
+ return token;
+ return 0;
+}
+
+void AtlantikBoard::addToken(Player *player)
+{
+ if (!player->location())
+ {
+ kdDebug() << "addToken ignored - estateView null" << endl;
+ return;
+ }
+
+ Player *playerSelf = 0;
+ if (m_atlanticCore)
+ playerSelf = m_atlanticCore->playerSelf();
+
+ if (playerSelf && playerSelf->game() != player->game() )
+ {
+ kdDebug() << "addToken ignored - not in same game as playerSelf" << endl;
+ return;
+ }
+
+ kdDebug() << "addToken" << endl;
+
+ Token *token = new Token(player, this, "token");
+ m_tokens.append(token);
+ connect(player, SIGNAL(changed(Player *)), token, SLOT(playerChanged()));
+
+ jumpToken(token);
+
+ // Timer to reinit the gameboard _after_ event loop
+ QTimer::singleShot(100, this, SLOT(slotResizeAftermath()));
+}
+
+void AtlantikBoard::playerChanged(Player *player)
+{
+ kdDebug() << "playerChanged: playerLoc " << (player->location() ? player->location()->name() : "none") << endl;
+
+ Player *playerSelf = 0;
+ if (m_atlanticCore)
+ playerSelf = m_atlanticCore->playerSelf();
+
+ // Update token
+ Token *token = findToken(player);
+ if (token)
+ {
+ kdDebug() << "playerChanged: tokenLoc " << (token->location() ? token->location()->name() : "none") << endl;
+ if (player->isBankrupt() || (playerSelf && playerSelf->game() != player->game()) )
+ token->hide();
+ if (player->hasTurn())
+ token->raise();
+
+ bool jump = false, move = false;
+
+ if (token->inJail() != player->inJail())
+ {
+ token->setInJail(player->inJail());
+
+ // If any status such as jail is ever allowed to
+ // change in the future, during movement, this needs
+ // to be addressed in moveToken and subsequent steps.
+ if (token != m_movingToken)
+ jump = true;
+ }
+
+ if (token->location() != player->location())
+ {
+ token->setLocation(player->location());
+ jump = true;
+ }
+
+ if (player->destination() && token->destination() != player->destination())
+ {
+ if (m_animateTokens)
+ {
+ token->setDestination(player->destination());
+ move = true;
+ }
+ else
+ {
+ token->setLocation(player->destination());
+ jump = true;
+ }
+ }
+
+ if (move)
+ moveToken(token);
+ else if (jump)
+ jumpToken(token);
+ }
+ else
+ addToken(player);
+}
+
+void AtlantikBoard::removeToken(Player *player)
+{
+ Token *token = findToken(player);
+ if (!token)
+ return;
+
+ if (token == m_movingToken)
+ {
+ m_timer->stop();
+ m_movingToken = 0;
+ }
+
+ m_tokens.remove(token);
+}
+
+void AtlantikBoard::jumpToken(Token *token)
+{
+ if (!token || !token->location())
+ return;
+
+ kdDebug() << "jumpToken to " << token->location()->name() << endl;
+
+ QPoint tGeom = calculateTokenDestination(token);
+ token->setGeometry(tGeom.x(), tGeom.y(), token->width(), token->height());
+
+ Player *player = token->player();
+ if (player)
+ {
+ player->setLocation(token->location());
+ player->setDestination(0);
+
+ if (token->isHidden() && !player->isBankrupt())
+ token->show();
+ }
+
+ if (token == m_movingToken)
+ {
+ m_timer->stop();
+
+ if (!m_resumeTimer)
+ m_movingToken = 0;
+ }
+
+ emit tokenConfirmation(token->location());
+}
+
+void AtlantikBoard::moveToken(Token *token)
+{
+ kdDebug() << "moveToken to " << token->destination()->name() << endl;
+
+ m_movingToken = token;
+
+ // Start timer
+ m_timer->start(15);
+}
+
+QPoint AtlantikBoard::calculateTokenDestination(Token *token, Estate *eDest)
+{
+ if (!eDest)
+ eDest = token->location();
+
+ EstateView *evDest = findEstateView(eDest);
+ if (!evDest)
+ return QPoint(0, 0);
+
+ int x = 0, y = 0;
+ if (token->player()->inJail())
+ {
+ x = evDest->geometry().right() - token->width() - 2;
+ y = evDest->geometry().top();
+ }
+ else
+ {
+ x = evDest->geometry().center().x() - (token->width()/2);
+ y = evDest->geometry().center().y() - (token->height()/2);
+
+/*
+ // Re-center because of EstateView headers
+ switch(evDest->orientation())
+ {
+ case North:
+ y += evDest->height()/8; break;
+ case East:
+ x -= evDest->width()/8; break;
+ case South:
+ y -= evDest->height()/8; break;
+ case West:
+ x += evDest->width()/8; break;
+ }
+*/
+ }
+ return QPoint(x, y);
+}
+
+void AtlantikBoard::slotMoveToken()
+{
+ // Requires a core with estates to operate on
+ if (!m_atlanticCore)
+ {
+ kdDebug() << "slotMoveToken ignored - no atlanticCore" << endl;
+ return;
+ }
+
+ // Do we actually have a token to move?
+ if (!m_movingToken)
+ {
+ m_timer->stop();
+ return;
+ }
+
+ // Where are we?
+ int xCurrent = m_movingToken->geometry().x();
+ int yCurrent = m_movingToken->geometry().y();
+
+ // Where do we want to go today?
+ Estate *eDest = m_atlanticCore->estateAfter(m_movingToken->location());
+ QPoint tGeom = calculateTokenDestination(m_movingToken, eDest);
+
+ int xDest = tGeom.x();
+ int yDest = tGeom.y();
+
+ if (xDest - xCurrent > 1)
+ xDest = xCurrent + 2;
+ else if (xCurrent - xDest > 1)
+ xDest = xCurrent - 2;
+ else
+ xDest = xCurrent;
+
+ if (yDest - yCurrent > 1)
+ yDest = yCurrent + 2;
+ else if (yCurrent - yDest > 1)
+ yDest = yCurrent - 2;
+ else
+ yDest = yCurrent;
+
+// kdDebug() << "TOKEN: at " << xCurrent << "," << yCurrent << " and going to " << xDest << "," << yDest << endl;
+
+ if (xCurrent != xDest || yCurrent != yDest)
+ {
+ m_movingToken->setGeometry(xDest, yDest, m_movingToken->width(), m_movingToken->height());
+ return;
+ }
+
+ // We have arrived at our destination!
+ m_movingToken->setLocation(eDest);
+ m_movingToken->player()->setLocation(eDest);
+ emit tokenConfirmation(eDest);
+
+ // We have arrived at our _final_ destination!
+ if (eDest == m_movingToken->destination())
+ {
+ m_movingToken->setDestination(0);
+ m_movingToken->player()->setDestination(0);
+
+ m_timer->stop();
+ m_movingToken = 0;
+ }
+}
+
+void AtlantikBoard::resizeEvent(QResizeEvent *)
+{
+ // Stop moving tokens, slotResizeAftermath will re-enable this
+ if (m_timer!=0 && m_timer->isActive())
+ {
+ m_timer->stop();
+ m_resumeTimer=true;
+ }
+
+/*
+ // Adjust spacer to make sure board stays a square
+ int q = e->size().width() - e->size().height();
+ if (q > 0)
+ {
+ QSize s(q, 0);
+ spacer->setFixedSize(s);
+ }
+ else
+ {
+ QSize s(0, -q);
+ spacer->setFixedSize(s);
+ }
+*/
+ // Timer to reinit the gameboard _after_ resizeEvent
+ QTimer::singleShot(0, this, SLOT(slotResizeAftermath()));
+}
+
+void AtlantikBoard::slotResizeAftermath()
+{
+ kdDebug() << "AtlantikBoard::slotResizeAftermath" << endl;
+ // Move tokens back to their last known location (this has to be done
+ // _after_ resizeEvent has returned to make sure we have the correct
+ // adjusted estate geometries.
+
+ Token *token = 0;
+ for (QPtrListIterator<Token> it(m_tokens); (token = *it) ; ++it)
+ jumpToken(token);
+
+ // Restart the timer that was stopped in resizeEvent
+ if (m_resumeTimer && m_timer!=0 && !m_timer->isActive())
+ {
+ m_timer->start(15);
+ m_resumeTimer=false;
+ }
+}
+
+void AtlantikBoard::displayDefault()
+{
+ switch(m_displayQueue.count())
+ {
+ case 0:
+ m_displayQueue.prepend(new QWidget(this));
+ break;
+ case 1:
+ if (EstateDetails *display = dynamic_cast<EstateDetails*>(m_lastServerDisplay))
+ display->setEstate(0);
+ break;
+ default:
+ if (m_displayQueue.getFirst() == m_lastServerDisplay)
+ m_lastServerDisplay = 0;
+ m_displayQueue.removeFirst();
+ break;
+ }
+ updateCenter();
+}
+
+void AtlantikBoard::displayButton(QString command, QString caption, bool enabled)
+{
+ if (EstateDetails *display = dynamic_cast<EstateDetails*>(m_lastServerDisplay))
+ display->addButton(command, caption, enabled);
+}
+
+void AtlantikBoard::addCloseButton()
+{
+ EstateDetails *eDetails = 0;
+ if ((eDetails = dynamic_cast<EstateDetails*>(m_lastServerDisplay)) && eDetails != m_displayQueue.getLast())
+ eDetails->addCloseButton();
+}
+
+void AtlantikBoard::insertDetails(QString text, bool clearText, bool clearButtons, Estate *estate)
+{
+ EstateDetails *eDetails = 0;
+
+ if ((eDetails = dynamic_cast<EstateDetails*>(m_lastServerDisplay)))
+ {
+ if (clearText)
+ eDetails->setText(text);
+ else
+ eDetails->appendText(text);
+
+ if (clearButtons)
+ eDetails->clearButtons();
+
+ eDetails->setEstate(estate);
+ return;
+ }
+
+ if (m_displayQueue.getFirst() != m_lastServerDisplay)
+ m_displayQueue.removeFirst();
+
+ eDetails = new EstateDetails(estate, text, this);
+ m_lastServerDisplay = eDetails;
+ connect(eDetails, SIGNAL(buttonCommand(QString)), this, SIGNAL(buttonCommand(QString)));
+ connect(eDetails, SIGNAL(buttonClose()), this, SLOT(displayDefault()));
+
+ m_displayQueue.insert(0, eDetails);
+ updateCenter();
+}
+
+void AtlantikBoard::prependEstateDetails(Estate *estate)
+{
+ if (!estate)
+ return;
+
+ EstateDetails *eDetails = 0;
+
+ if (m_displayQueue.getFirst() == m_lastServerDisplay)
+ {
+ eDetails = new EstateDetails(estate, QString::null, this);
+ m_displayQueue.prepend(eDetails);
+
+ connect(eDetails, SIGNAL(buttonCommand(QString)), this, SIGNAL(buttonCommand(QString)));
+ connect(eDetails, SIGNAL(buttonClose()), this, SLOT(displayDefault()));
+ }
+ else
+ {
+ eDetails = dynamic_cast<EstateDetails*> ( m_displayQueue.getFirst() );
+ if (eDetails)
+ {
+ eDetails->setEstate(estate);
+ eDetails->setText( QString::null );
+ // eDetails->clearButtons();
+ }
+ else
+ {
+ kdDebug() << "manual estatedetails with first in queue neither server nor details" << endl;
+ return;
+ }
+ }
+
+ eDetails->addDetails();
+ eDetails->addCloseButton();
+
+ updateCenter();
+}
+
+void AtlantikBoard::updateCenter()
+{
+ QWidget *center = m_displayQueue.getFirst();
+ m_gridLayout->addMultiCellWidget(center, 1, m_gridLayout->numRows()-2, 1, m_gridLayout->numCols()-2);
+ center->show();
+}
+
+QWidget *AtlantikBoard::centerWidget()
+{
+ return m_displayQueue.getFirst();
+}
diff --git a/atlantik/libatlantikui/board.h b/atlantik/libatlantikui/board.h
new file mode 100644
index 00000000..deedb3d6
--- /dev/null
+++ b/atlantik/libatlantikui/board.h
@@ -0,0 +1,102 @@
+// Copyright (c) 2002-2003 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#ifndef ATLANTIK_BOARD_H
+#define ATLANTIK_BOARD_H
+
+#include <qwidget.h>
+#include <qtimer.h>
+#include <qlayout.h>
+#include <qptrlist.h>
+#include "libatlantikui_export.h"
+class QPoint;
+
+class AtlanticCore;
+class Auction;
+class Estate;
+class Player;
+class Token;
+
+class EstateView;
+
+class LIBATLANTIKUI_EXPORT AtlantikBoard : public QWidget
+{
+Q_OBJECT
+
+public:
+ enum DisplayMode { Play, Edit };
+
+ AtlantikBoard(AtlanticCore *atlanticCore, int maxEstates, DisplayMode mode, QWidget *parent, const char *name=0);
+ ~AtlantikBoard();
+ void reset();
+
+ void setViewProperties(bool indicateUnowned, bool highliteUnowned, bool darkenMortgaged, bool quartzEffects, bool animateTokens);
+ int heightForWidth(int);
+ void addEstateView(Estate *estate, bool indicateUnowned = false, bool highliteUnowned = false, bool darkenMortgaged = false, bool quartzEffects = false);
+ void addAuctionWidget(Auction *auction);
+
+ void addToken(Player *player);
+ void removeToken(Player *player);
+
+ void indicateUnownedChanged();
+ EstateView *findEstateView(Estate *estate);
+ QWidget *centerWidget();
+
+public slots:
+ void slotMoveToken();
+ void slotResizeAftermath();
+ void displayDefault();
+
+private slots:
+ void playerChanged(Player *player);
+ void displayButton(QString command, QString caption, bool enabled);
+ void prependEstateDetails(Estate *);
+ void insertDetails(QString text, bool clearText, bool clearButtons, Estate *estate = 0);
+ void addCloseButton();
+
+signals:
+ void tokenConfirmation(Estate *estate);
+ void buttonCommand(QString command);
+
+protected:
+ void resizeEvent(QResizeEvent *);
+
+private:
+ Token *findToken(Player *player);
+ void jumpToken(Token *token);
+ void moveToken(Token *token);
+ QPoint calculateTokenDestination(Token *token, Estate *estate = 0);
+
+ void updateCenter();
+
+ AtlanticCore *m_atlanticCore;
+ DisplayMode m_mode;
+
+ QWidget *spacer, *m_lastServerDisplay;
+ QGridLayout *m_gridLayout;
+ Token *m_movingToken;
+ QTimer *m_timer;
+ bool m_resumeTimer;
+
+ bool m_animateTokens;
+ int m_maxEstates;
+
+ QPtrList<EstateView> m_estateViews;
+ QPtrList<Token> m_tokens;
+ QPtrList<QWidget> m_displayQueue;
+};
+
+#endif
diff --git a/atlantik/libatlantikui/estatedetails.cpp b/atlantik/libatlantikui/estatedetails.cpp
new file mode 100644
index 00000000..d143033c
--- /dev/null
+++ b/atlantik/libatlantikui/estatedetails.cpp
@@ -0,0 +1,327 @@
+// Copyright (c) 2002-2004 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qlayout.h>
+#include <qptrlist.h>
+#include <qregexp.h>
+#include <qvgroupbox.h>
+
+#include <kdialog.h>
+#include <kglobalsettings.h>
+#include <kiconloader.h>
+#include <klistview.h>
+#include <klocale.h>
+#include <kpixmap.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+
+#include <kdebug.h>
+
+#include <estate.h>
+#include <estategroup.h>
+#include <player.h>
+
+#include "estatedetails.h"
+#include "kwrappedlistviewitem.h"
+
+EstateDetails::EstateDetails(Estate *estate, QString text, QWidget *parent, const char *name) : QWidget(parent, name)
+{
+ m_pixmap = 0;
+ m_quartzBlocks = 0;
+ b_recreate = true;
+ m_recreateQuartz = true;
+
+ m_estate = 0;
+
+ m_closeButton = 0;
+ m_buttons.setAutoDelete(true);
+
+ m_mainLayout = new QVBoxLayout(this, KDialog::marginHint(), KDialog::spacingHint());
+ Q_CHECK_PTR(m_mainLayout);
+
+ m_mainLayout->addItem(new QSpacerItem(KDialog::spacingHint(), KDialog::spacingHint()+50, QSizePolicy::Fixed, QSizePolicy::Minimum));
+
+ m_infoListView = new KListView(this, "infoListView");
+ m_infoListView->addColumn(m_estate ? m_estate->name() : QString("") );
+ m_infoListView->setSorting(-1);
+ m_mainLayout->addWidget(m_infoListView);
+
+ appendText(text);
+
+ m_buttonBox = new QHBoxLayout(m_mainLayout, KDialog::spacingHint());
+ m_buttonBox->setMargin(0);
+
+ m_buttonBox->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
+
+ setEstate(estate);
+}
+
+EstateDetails::~EstateDetails()
+{
+ delete m_pixmap;
+ delete m_quartzBlocks;
+ delete m_infoListView;
+}
+
+void EstateDetails::paintEvent(QPaintEvent *)
+{
+ if (m_recreateQuartz)
+ {
+/*
+ if (m_quartzBlocks)
+ {
+ delete m_quartzBlocks;
+ m_quartzBlocks = 0;
+ }
+
+ if (m_estate->color().isValid())
+ {
+ m_quartzBlocks = new KPixmap();
+
+ if (m_orientation == North || m_orientation == South)
+ m_quartzBlocks->resize(25, m_titleHeight-2);
+ else
+ m_quartzBlocks->resize(25, m_titleWidth-2);
+
+ drawQuartzBlocks(m_quartzBlocks, *m_quartzBlocks, m_estate->color().light(60), m_estate->color());
+ m_quartzBlocks = rotatePixmap(m_quartzBlocks);
+ }
+*/
+ m_recreateQuartz = false;
+ b_recreate = true;
+ }
+
+ if (b_recreate)
+ {
+ delete m_pixmap;
+ m_pixmap = new QPixmap(width(), height());
+
+ QColor greenHouse(0, 255, 0);
+ QColor redHotel(255, 51, 51);
+ QPainter painter;
+ painter.begin(m_pixmap, this);
+
+ painter.setPen(Qt::black);
+
+ painter.setBrush(m_estate ? m_estate->bgColor() : Qt::white);
+ painter.drawRect(rect());
+
+/*
+ // Paint icon only when it exists and fits
+ if (icon!=0 && width() > icon->width() && height() > icon->height())
+ painter.drawPixmap( (width() - icon->width())/2, (height() - icon->height())/2, *icon);
+*/
+
+ if (m_estate)
+ {
+ int titleHeight = 50;
+ QColor titleColor = (m_estate->color().isValid() ? m_estate->color() : m_estate->bgColor().light(80));
+
+ KPixmap* quartzBuffer = new KPixmap;
+ quartzBuffer->resize(25, (height()/4)-2);
+
+ QPainter quartzPainter;
+ quartzPainter.begin(quartzBuffer, this);
+
+ painter.setBrush(titleColor);
+ painter.drawRect(0, 0, width(), titleHeight);
+
+ if (m_quartzBlocks)
+ {
+ quartzPainter.drawPixmap(0, 0, *m_quartzBlocks);
+ painter.drawPixmap(1, 1, *quartzBuffer);
+ }
+
+ if (m_estate->houses() > 0)
+ {
+ int titleWidth = width() / 5;
+
+ if (m_estate->houses() == 5)
+ {
+ // Hotel
+ painter.setBrush(redHotel);
+ painter.drawRect(2, 2, titleWidth-4, titleHeight-4);
+ }
+ else
+ {
+ // Houses
+ painter.setBrush(greenHouse);
+ int h = titleHeight-4, w = titleWidth-4;
+ for ( unsigned int i=0 ; i < m_estate->houses() ; i++ )
+ painter.drawRect(2+(i*(w+2)), 2, w, h);
+ }
+ }
+
+ quartzPainter.end();
+ delete quartzBuffer;
+
+ // TODO: steal blur code from kicker/taskbar/taskcontainer.cpp
+
+ // Estate name
+ painter.setPen(Qt::white);
+ int fontSize = KGlobalSettings::generalFont().pointSize();
+ if (fontSize == -1)
+ fontSize = KGlobalSettings::generalFont().pixelSize();
+
+ painter.setFont(QFont(KGlobalSettings::generalFont().family(), fontSize * 2, QFont::Bold));
+ painter.drawText(KDialog::marginHint(), KDialog::marginHint(), width()-KDialog::marginHint(), titleHeight, Qt::AlignJustify, m_estate->name());
+
+ painter.setPen(Qt::black);
+
+ int xText = 0;
+
+ // Estate group
+ if (m_estate->estateGroup())
+ {
+ xText = titleHeight - fontSize - KDialog::marginHint();
+ painter.setFont(QFont(KGlobalSettings::generalFont().family(), fontSize, QFont::Bold));
+ painter.drawText(5, xText, width()-10, titleHeight, Qt::AlignRight, m_estate->estateGroup()->name().upper());
+ }
+
+ xText = titleHeight + fontSize + 5;
+ painter.setFont(QFont(KGlobalSettings::generalFont().family(), fontSize, QFont::Normal));
+ }
+ b_recreate = false;
+
+ }
+ bitBlt(this, 0, 0, m_pixmap);
+}
+
+void EstateDetails::resizeEvent(QResizeEvent *)
+{
+ m_recreateQuartz = true;
+ b_recreate = true;
+}
+
+void EstateDetails::addDetails()
+{
+ if (m_estate)
+ {
+ QListViewItem *infoText = 0;
+
+ // Price
+ if (m_estate->price())
+ {
+ infoText = new QListViewItem(m_infoListView, m_infoListView->lastItem(), i18n("Price: %1").arg(m_estate->price()));
+ infoText->setPixmap(0, QPixmap(SmallIcon("info")));
+ }
+
+ // Owner, houses, isMortgaged
+ if (m_estate && m_estate->canBeOwned())
+ {
+ infoText = new QListViewItem(m_infoListView, m_infoListView->lastItem(), i18n("Owner: %1").arg(m_estate->owner() ? m_estate->owner()->name() : i18n("unowned")));
+ infoText->setPixmap(0, QPixmap(SmallIcon("info")));
+
+ if (m_estate->isOwned())
+ {
+ infoText = new QListViewItem(m_infoListView, m_infoListView->lastItem(), i18n("Houses: %1").arg(m_estate->houses()));
+ infoText->setPixmap(0, QPixmap(SmallIcon("info")));
+
+ infoText = new QListViewItem(m_infoListView, m_infoListView->lastItem(), i18n("Mortgaged: %1").arg(m_estate->isMortgaged() ? i18n("Yes") : i18n("No")));
+ infoText->setPixmap(0, QPixmap(SmallIcon("info")));
+ }
+ }
+ }
+}
+
+void EstateDetails::addButton(QString command, QString caption, bool enabled)
+{
+ KPushButton *button = new KPushButton(caption, this);
+ m_buttons.append(button);
+ m_buttonCommandMap[(QObject *)button] = command;
+ m_buttonBox->addWidget(button);
+
+ if (m_estate)
+ {
+ QColor bgColor, fgColor;
+ bgColor = m_estate->bgColor().light(110);
+ fgColor = ( bgColor.red() + bgColor.green() + bgColor.blue() < 255 ) ? Qt::white : Qt::black;
+
+ button->setPaletteForegroundColor( fgColor );
+ button->setPaletteBackgroundColor( bgColor );
+ }
+ button->setEnabled(enabled);
+ button->show();
+
+ connect(button, SIGNAL(pressed()), this, SLOT(buttonPressed()));
+}
+
+void EstateDetails::addCloseButton()
+{
+ if (!m_closeButton)
+ {
+ m_closeButton = new KPushButton(KStdGuiItem::close(), this);
+ m_buttonBox->addWidget(m_closeButton);
+ m_closeButton->show();
+ connect(m_closeButton, SIGNAL(pressed()), this, SIGNAL(buttonClose()));
+ }
+}
+
+void EstateDetails::setEstate(Estate *estate)
+{
+ if (m_estate != estate)
+ {
+ m_estate = estate;
+
+ m_infoListView->setColumnText( 0, m_estate ? m_estate->name() : QString("") );
+
+ b_recreate = true;
+ update();
+ }
+}
+
+void EstateDetails::setText(QString text)
+{
+ m_infoListView->clear();
+ appendText(text);
+}
+
+void EstateDetails::appendText(QString text)
+{
+ if ( text.isEmpty() )
+ return;
+
+ KWrappedListViewItem *infoText = new KWrappedListViewItem(m_infoListView, m_infoListView->lastItem(), text);
+
+ if ( text.find( QRegExp("rolls") ) != -1 )
+ infoText->setPixmap(0, QPixmap(SmallIcon("roll")));
+ else
+ infoText->setPixmap(0, QPixmap(SmallIcon("atlantik")));
+
+ m_infoListView->ensureItemVisible( infoText );
+}
+
+void EstateDetails::clearButtons()
+{
+ if (m_closeButton)
+ {
+ delete m_closeButton;
+ m_closeButton = 0;
+ }
+
+ // Delete buttons
+ m_buttons.clear();
+ m_buttonCommandMap.clear();
+}
+
+void EstateDetails::buttonPressed()
+{
+ emit buttonCommand(QString(m_buttonCommandMap[(QObject *)QObject::sender()]));
+}
+
+#include "estatedetails.moc"
diff --git a/atlantik/libatlantikui/estatedetails.h b/atlantik/libatlantikui/estatedetails.h
new file mode 100644
index 00000000..b8264a51
--- /dev/null
+++ b/atlantik/libatlantikui/estatedetails.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2002 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#ifndef ATLANTIK_ESTATEDETAILS_H
+#define ATLANTIK_ESTATEDETAILS_H
+
+#include <qwidget.h>
+
+class QPixmap;
+class QString;
+class QHBoxLayout;
+class QVBoxLayout;
+class QVGroupBox;
+
+class KListView;
+class KPixmap;
+class KPushButton;
+
+class Player;
+class Estate;
+
+class EstateDetails : public QWidget
+{
+Q_OBJECT
+
+public:
+ EstateDetails(Estate *estate, QString text, QWidget *parent, const char *name = 0);
+ ~EstateDetails();
+ Estate *estate() { return m_estate; }
+
+ void addDetails();
+ void addButton(const QString command, const QString caption, bool enabled);
+ void addCloseButton();
+ void setEstate(Estate *estate);
+ void setText(QString text);
+ void appendText(QString text);
+ void clearButtons();
+
+protected:
+ void paintEvent(QPaintEvent *);
+ void resizeEvent(QResizeEvent *);
+
+private slots:
+ void buttonPressed();
+
+signals:
+ void buttonCommand(QString);
+ void buttonClose();
+
+private:
+ Estate *m_estate;
+ QPixmap *m_pixmap;
+ KPixmap *m_quartzBlocks;
+ KListView *m_infoListView;
+ KPushButton *m_closeButton;
+ bool b_recreate, m_recreateQuartz;
+ QVBoxLayout *m_mainLayout;
+ QHBoxLayout *m_buttonBox;
+ QVGroupBox *m_textGroupBox;
+ QMap <QObject *, QString> m_buttonCommandMap;
+ QPtrList<KPushButton> m_buttons;
+};
+
+#endif
diff --git a/atlantik/libatlantikui/estateview.cpp b/atlantik/libatlantikui/estateview.cpp
new file mode 100644
index 00000000..b8c3f38c
--- /dev/null
+++ b/atlantik/libatlantikui/estateview.cpp
@@ -0,0 +1,558 @@
+// Copyright (c) 2002-2003 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#include <qtooltip.h>
+#include <qpainter.h>
+#include <qtimer.h>
+#include <qwmatrix.h>
+#include <qcursor.h>
+
+#include <kdebug.h>
+#include <kdeversion.h>
+#include <kdialogbase.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kpixmapeffect.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+#include <kstringhandler.h>
+
+#include <player.h>
+#include <estate.h>
+
+#include "estateview.moc"
+#include "config.h"
+
+EstateView::EstateView(Estate *estate, EstateOrientation orientation, const QString &_icon, bool indicateUnowned, bool highliteUnowned, bool darkenMortgaged, bool quartzEffects, QWidget *parent, const char *name) : QWidget(parent, name, WResizeNoErase)
+{
+ m_estate = estate;
+ m_orientation = orientation;
+
+ m_indicateUnowned = indicateUnowned;
+ m_highliteUnowned = highliteUnowned;
+ m_darkenMortgaged = darkenMortgaged;
+ m_quartzEffects = quartzEffects;
+
+ setBackgroundMode(NoBackground); // avoid flickering
+
+ qpixmap = 0;
+ b_recreate = true;
+
+ m_quartzBlocks = 0;
+ m_recreateQuartz = true;
+
+ pe = 0;
+ updatePE();
+
+ icon = new QPixmap(locate("data", "atlantik/pics/" + _icon));
+ icon = rotatePixmap(icon);
+
+ updateToolTip();
+}
+
+void EstateView::updateToolTip()
+{
+ QToolTip::remove(this);
+
+ if ( m_estate )
+ {
+ QString toolTip = m_estate->name();
+ if ( m_estate->isOwned() )
+ {
+ toolTip.append( "\n" + i18n("Owner: %1").arg( m_estate->owner()->name() ) );
+ if ( m_estate->isMortgaged() )
+ toolTip.append( "\n" + i18n("Unmortgage Price: %1").arg( m_estate->unmortgagePrice() ) );
+ else
+ toolTip.append( "\n" + i18n("Mortgage Value: %1").arg( m_estate->mortgagePrice() ) );
+ if ( m_estate->canSellHouses() )
+ toolTip.append( "\n" + i18n("House Value: %1").arg( m_estate->houseSellPrice() ) );
+ if ( m_estate->canBuyHouses() )
+ toolTip.append( "\n" + i18n("House Price: %1").arg( m_estate->housePrice() ) );
+ }
+ else if ( m_estate->canBeOwned() )
+ toolTip.append( "\n" + i18n("Price: %1").arg( m_estate->price() ) );
+ else if ( m_estate->money() )
+ toolTip.append( "\n" + i18n("Money: %1").arg( m_estate->money() ) );
+
+ QToolTip::add( this, toolTip );
+ }
+}
+
+void EstateView::setViewProperties(bool indicateUnowned, bool highliteUnowned, bool darkenMortgaged, bool quartzEffects)
+{
+ if (m_indicateUnowned != indicateUnowned)
+ {
+ m_indicateUnowned = indicateUnowned;
+ b_recreate = true;
+ updatePE();
+ }
+
+ if (m_highliteUnowned != highliteUnowned)
+ {
+ m_highliteUnowned = highliteUnowned;
+ b_recreate = true;
+ }
+
+ if (m_darkenMortgaged != darkenMortgaged)
+ {
+ m_darkenMortgaged = darkenMortgaged;
+ b_recreate = true;
+ }
+
+ if (m_quartzEffects != quartzEffects)
+ {
+ m_quartzEffects = quartzEffects;
+ b_recreate = true;
+// m_recreateQuartz = true;
+ }
+
+ if (b_recreate || m_recreateQuartz)
+ update();
+}
+
+QPixmap *EstateView::rotatePixmap(QPixmap *p)
+{
+ if (p==0 || p->isNull())
+ return 0;
+
+ QWMatrix m;
+
+ switch(m_orientation)
+ {
+ case East:
+ m.rotate(90);
+ break;
+ case West:
+ m.rotate(-90);
+ break;
+ case South:
+ m.rotate(180);
+ break;
+ default:;
+ }
+ *p = p->xForm(m);
+ return p;
+}
+
+KPixmap *EstateView::rotatePixmap(KPixmap *p)
+{
+ if (p==0 || p->isNull())
+ return 0;
+
+ QWMatrix m;
+
+ switch(m_orientation)
+ {
+ case East:
+ m.rotate(90);
+ break;
+ case West:
+ m.rotate(-90);
+ break;
+ case South:
+ m.rotate(180);
+ break;
+ default:;
+ }
+ *p = p->xForm(m);
+ return p;
+}
+
+void EstateView::updatePE()
+{
+ // Don't show a when a property is not unowned, cannot be owned at all
+ // or when the user has configured Atlantik not to show them.
+ if (m_estate->isOwned() || !m_estate->canBeOwned() || m_indicateUnowned==false)
+ {
+ delete pe;
+ pe = 0;
+ }
+ else
+ {
+ if (pe==0)
+ {
+ // Display a coloured portfolioestate to indicate property is
+ // for sale
+ pe = new PortfolioEstate(m_estate, 0, true, this, "board-portfolioestate");
+ repositionPortfolioEstate();
+
+ pe->show();
+ }
+ else if (!pe->isVisible())
+ pe->show();
+ }
+}
+
+void EstateView::estateChanged()
+{
+ updateToolTip();
+
+ b_recreate = true;
+ m_recreateQuartz = true;
+
+ update();
+ updatePE();
+}
+
+void EstateView::repositionPortfolioEstate()
+{
+ if (pe!=0)
+ {
+ int x = (m_orientation == West ? (width()-2 - pe->width()) : 2);
+ int y = (m_orientation == North ? (height()-2 - pe->height()) : 2);
+ pe->setGeometry(x, y, pe->width(), pe->height());
+ }
+}
+
+void EstateView::paintEvent(QPaintEvent *)
+{
+ m_titleHeight = height()/4;
+ m_titleWidth = width()/4;
+
+ if (m_recreateQuartz)
+ {
+ if (m_quartzBlocks)
+ {
+ delete m_quartzBlocks;
+ m_quartzBlocks = 0;
+ }
+
+ if (m_estate->color().isValid())
+ {
+ m_quartzBlocks = new KPixmap();
+
+ if (m_orientation == North || m_orientation == South)
+ m_quartzBlocks->resize(25, m_titleHeight-2);
+ else
+ m_quartzBlocks->resize(25, m_titleWidth-2);
+
+ drawQuartzBlocks(m_quartzBlocks, *m_quartzBlocks, m_estate->color().light(60), m_estate->color());
+ m_quartzBlocks = rotatePixmap(m_quartzBlocks);
+ }
+
+ m_recreateQuartz = false;
+ b_recreate = true;
+ }
+
+ if (b_recreate)
+ {
+ delete qpixmap;
+ qpixmap = new QPixmap(width(), height());
+
+ QColor greenHouse(0, 255, 0);
+ QColor redHotel(255, 51, 51);
+ QPainter painter;
+ painter.begin(qpixmap, this);
+
+ painter.setPen(Qt::black);
+
+ if (m_darkenMortgaged==true && m_estate->isMortgaged())
+ painter.setBrush(m_estate->bgColor().light(10));
+ else if (m_highliteUnowned==true && m_estate->canBeOwned() && !m_estate->isOwned())
+ painter.setBrush(m_estate->bgColor().light(190));
+ else
+ painter.setBrush(m_estate->bgColor());
+
+ painter.drawRect(rect());
+
+ // Paint icon only when it exists and fits
+ if (icon!=0 && width() > icon->width() && height() > icon->height())
+ painter.drawPixmap( (width() - icon->width())/2, (height() - icon->height())/2, *icon);
+
+ if (m_estate->color().isValid())
+ {
+ KPixmap* quartzBuffer = new KPixmap;
+ if (m_orientation == North || m_orientation == South)
+ quartzBuffer->resize(25, m_titleHeight-2);
+ else
+ quartzBuffer->resize(m_titleWidth-2, 25);
+
+ QPainter quartzPainter;
+ quartzPainter.begin(quartzBuffer, this);
+
+ painter.setBrush(m_estate->color());
+ switch(m_orientation)
+ {
+ case North:
+ painter.drawRect(0, 0, width(), m_titleHeight);
+
+ if (m_quartzEffects && m_quartzBlocks)
+ {
+ quartzPainter.drawPixmap(0, 0, *m_quartzBlocks);
+ painter.drawPixmap(1, 1, *quartzBuffer);
+ }
+
+ if (m_estate->houses() > 0)
+ {
+ if (m_estate->houses() == 5)
+ {
+ // Hotel
+ painter.setBrush(redHotel);
+ painter.drawRect(2, 2, (width()/2)-4, (m_titleHeight)-4);
+ }
+ else
+ {
+ // Houses
+ painter.setBrush(greenHouse);
+ int h = (m_titleHeight)-4, w = (m_titleWidth)-4;
+ for( unsigned int i=0 ; i < m_estate->houses() ; i++ )
+ painter.drawRect(2+(i*(w+2)), 2, w, h);
+ }
+ }
+ break;
+ case South:
+ painter.drawRect(0, height()-(m_titleHeight), width(), m_titleHeight);
+
+ if (m_quartzEffects && m_quartzBlocks)
+ {
+ quartzPainter.drawPixmap(0, 0, *m_quartzBlocks);
+ painter.drawPixmap(width()-quartzBuffer->width()-1, height()-m_titleHeight+1, *quartzBuffer);
+ }
+
+ if (m_estate->houses() > 0)
+ {
+ if (m_estate->houses() == 5)
+ {
+ // Hotel
+ painter.setBrush(redHotel);
+ painter.drawRect(2, (3*(m_titleHeight))+2, (width()/2)-4, (m_titleHeight)-4);
+ }
+ else
+ {
+ // Houses
+ painter.setBrush(greenHouse);
+ int h = (m_titleHeight)-4, w = (m_titleWidth)-4;
+ for( unsigned int i=0 ; i < m_estate->houses() ; i++ )
+ painter.drawRect(2+(i*(w+2)), (3*(m_titleHeight))+2, w, h);
+ }
+ }
+ break;
+ case West:
+ painter.drawRect(0, 0, m_titleWidth, height());
+
+ if (m_quartzEffects && m_quartzBlocks)
+ {
+ quartzPainter.drawPixmap(0, 0, *m_quartzBlocks);
+ painter.drawPixmap(1, height()-quartzBuffer->height()-1, *quartzBuffer);
+ }
+
+ if (m_estate->houses() > 0)
+ {
+ if (m_estate->houses() == 5)
+ {
+ // Hotel
+ painter.setBrush(redHotel);
+ painter.drawRect(2, 2, (m_titleWidth)-4, (height()/2)-4);
+ }
+ else
+ {
+ // Houses
+ painter.setBrush(greenHouse);
+ int h = (m_titleHeight)-4, w = (m_titleWidth)-4;
+ for( unsigned int i=0 ; i < m_estate->houses() ; i++ )
+ painter.drawRect(2, 2+(i*(h+2)), w, h);
+ }
+ }
+ break;
+ case East:
+ painter.drawRect(width()-(m_titleWidth), 0, m_titleWidth, height());
+
+ if (m_quartzEffects && m_quartzBlocks)
+ {
+ quartzPainter.drawPixmap(0, 0, *m_quartzBlocks);
+ painter.drawPixmap(width()-quartzBuffer->width()-1, 1, *quartzBuffer);
+ }
+
+ if (m_estate->houses() > 0)
+ {
+ if (m_estate->houses() == 5)
+ {
+ // Hotel
+ painter.setBrush(redHotel);
+ painter.drawRect((3*(m_titleWidth))+2, 2, (m_titleWidth)-4, (height()/2)-4);
+ }
+ else
+ {
+ // Houses
+ painter.setBrush(greenHouse);
+ int h = (m_titleHeight)-4, w = (m_titleWidth)-4;
+ for( unsigned int i=0 ; i < m_estate->houses() ; i++ )
+ painter.drawRect((3*(m_titleWidth))+2, 2+(i*(h+2)), w, h);
+ }
+ }
+ break;
+ }
+
+
+ quartzPainter.end();
+ delete quartzBuffer;
+ }
+
+ QFont font = QFont( KGlobalSettings::generalFont().family(), KGlobalSettings::generalFont().pointSize(), QFont::Normal );
+ painter.setFont(font);
+ QString estateName = m_estate->name();
+#if defined(KDE_MAKE_VERSION)
+#if KDE_VERSION >= KDE_MAKE_VERSION(3,2,0)
+ if ( m_estate->color().isValid() && ( m_orientation == West || m_orientation == East ) )
+ estateName = KStringHandler::rPixelSqueeze( m_estate->name(), QFontMetrics( font ), 3*width()/4 );
+ else
+ estateName = KStringHandler::rPixelSqueeze( m_estate->name(), QFontMetrics( font ), width() );
+#endif
+#endif
+ if (m_estate->color().isValid() && m_orientation == West)
+ painter.drawText( width()/4 + 2, height()/2, estateName );
+ else
+ painter.drawText(2, height()/2, estateName );
+
+ b_recreate = false;
+ }
+ bitBlt(this, 0, 0, qpixmap);
+}
+
+void EstateView::resizeEvent(QResizeEvent *)
+{
+ m_recreateQuartz = true;
+ b_recreate = true;
+
+ QTimer::singleShot(0, this, SLOT(slotResizeAftermath()));
+}
+
+void EstateView::mousePressEvent(QMouseEvent *e)
+{
+ if (e->button()==RightButton && m_estate->isOwned())
+ {
+ KPopupMenu *rmbMenu = new KPopupMenu(this);
+ rmbMenu->insertTitle(m_estate->name());
+
+ if (m_estate->isOwnedBySelf())
+ {
+ Player *player = m_estate->owner();
+
+ // Mortgage toggle
+ if (m_estate->isMortgaged())
+ {
+ rmbMenu->insertItem(i18n("Unmortgage"), 0);
+ if (!m_estate->canToggleMortgage() || player->hasDebt())
+ rmbMenu->setItemEnabled(0, false);
+ }
+ else
+ {
+ rmbMenu->insertItem(i18n("Mortgage"), 0);
+ if (!m_estate->canToggleMortgage())
+ rmbMenu->setItemEnabled(0, false);
+ }
+
+ // Estate construction
+ if (m_estate->houses()>=4)
+ rmbMenu->insertItem(i18n("Build Hotel"), 1);
+ else
+ rmbMenu->insertItem(i18n("Build House"), 1);
+
+ if (!m_estate->canBuyHouses() || player->hasDebt())
+ rmbMenu->setItemEnabled(1, false);
+
+ // Estate destruction
+ if (m_estate->houses()==5)
+ rmbMenu->insertItem(i18n("Sell Hotel"), 2);
+ else
+ rmbMenu->insertItem(i18n("Sell House"), 2);
+
+ if (!(m_estate->canSellHouses()))
+ rmbMenu->setItemEnabled(2, false);
+ }
+ else
+ {
+ // Request trade
+ if (Player *player = m_estate->owner())
+ rmbMenu->insertItem(i18n("Request Trade with %1").arg(player->name()), 3);
+ }
+
+ KPopupMenu *pm = dynamic_cast<KPopupMenu *>(rmbMenu);
+ if (pm) {
+ connect(pm, SIGNAL(activated(int)), this, SLOT(slotMenuAction(int)));
+ }
+ QPoint g = QCursor::pos();
+ rmbMenu->exec(g);
+ delete rmbMenu;
+ }
+ else if (e->button()==LeftButton)
+ emit LMBClicked(m_estate);
+}
+
+void EstateView::slotResizeAftermath()
+{
+ repositionPortfolioEstate();
+}
+
+void EstateView::slotMenuAction(int item)
+{
+ switch (item)
+ {
+ case 0:
+ emit estateToggleMortgage(m_estate);
+ break;
+
+ case 1:
+ emit estateHouseBuy(m_estate);
+ break;
+
+ case 2:
+ emit estateHouseSell(m_estate);
+ break;
+
+ case 3:
+ emit newTrade(m_estate->owner());
+ break;
+ }
+}
+
+// Kudos to Gallium <gallium@kde.org> for writing the Quartz KWin style and
+// letting me use the ultra slick algorithm!
+void EstateView::drawQuartzBlocks(KPixmap *pi, KPixmap &p, const QColor &c1, const QColor &c2)
+{
+ QPainter px;
+
+ if (pi==0 || pi->isNull())
+ return;
+
+ px.begin(pi);
+
+ KPixmapEffect::gradient(p, c1, c2, KPixmapEffect::HorizontalGradient);
+
+ px.fillRect( 2, 1, 3, 3, c1.light(120) );
+ px.fillRect( 2, 5, 3, 3, c1 );
+ px.fillRect( 2, 9, 3, 3, c1.light(110) );
+ px.fillRect( 2, 13, 3, 3, c1 );
+
+ px.fillRect( 6, 1, 3, 3, c1.light(110) );
+ px.fillRect( 6, 5, 3, 3, c2.light(110) );
+ px.fillRect( 6, 9, 3, 3, c1.light(120) );
+ px.fillRect( 6, 13, 3, 3, c2.light(130) );
+
+ px.fillRect( 10, 5, 3, 3, c1.light(110) );
+ px.fillRect( 10, 9, 3, 3, c2.light(120) );
+ px.fillRect( 10, 13, 3, 3, c2.light(150) );
+
+ px.fillRect( 14, 1, 3, 3, c1.dark(110) );
+ px.fillRect( 14, 9, 3, 3, c2.light(120) );
+ px.fillRect( 14, 13, 3, 3, c1.dark(120) );
+
+ px.fillRect( 18, 5, 3, 3, c1.light(110) );
+ px.fillRect( 18, 13, 3, 3, c1.dark(110) );
+
+ px.fillRect( 22, 9, 3, 3, c2.light(120));
+ px.fillRect( 22, 13, 3, 3, c2.light(110) );
+}
diff --git a/atlantik/libatlantikui/estateview.h b/atlantik/libatlantikui/estateview.h
new file mode 100644
index 00000000..864c8983
--- /dev/null
+++ b/atlantik/libatlantikui/estateview.h
@@ -0,0 +1,80 @@
+// Copyright (c) 2002-2003 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#ifndef ATLANTIK_ESTATEVIEW_H
+#define ATLANTIK_ESTATEVIEW_H
+
+#include <qwidget.h>
+#include <qpixmap.h>
+
+#include <kpixmap.h>
+
+#include "portfolioestate.h"
+
+enum EstateOrientation { North=0, East=1, South=2, West=3 };
+
+class Player;
+class Estate;
+
+class EstateView : public QWidget
+{
+Q_OBJECT
+
+ public:
+ EstateView(Estate *estate, EstateOrientation orientation, const QString &, bool indicateUnowned, bool highliteUnowned, bool darkenMortgaged, bool quartzEffects, QWidget *parent, const char *name = 0);
+ void setViewProperties(bool indicateUnowned, bool highliteUnowned, bool darkenMortgaged, bool quartzEffects);
+ Estate *estate() { return m_estate; }
+ void updatePE();
+ EstateOrientation orientation() { return m_orientation; }
+
+ public slots:
+ void slotResizeAftermath();
+
+ signals:
+ void estateToggleMortgage(Estate *estate);
+ void estateHouseBuy(Estate *estate);
+ void estateHouseSell(Estate *estate);
+ void newTrade(Player *player);
+ void LMBClicked(Estate *estate);
+
+ protected:
+ void paintEvent(QPaintEvent *);
+ void resizeEvent(QResizeEvent *);
+ void mousePressEvent(QMouseEvent *);
+
+private:
+ void updateToolTip();
+
+ QPixmap *rotatePixmap(QPixmap *);
+ KPixmap *rotatePixmap(KPixmap *);
+ void drawQuartzBlocks(KPixmap *pi, KPixmap &p, const QColor &c1, const QColor &c2);
+ void repositionPortfolioEstate();
+
+ Estate *m_estate;
+ QPixmap *qpixmap, *icon;
+ KPixmap *m_quartzBlocks;
+ bool m_indicateUnowned, m_highliteUnowned, m_darkenMortgaged, m_quartzEffects;
+ bool b_recreate, m_recreateQuartz;
+ int m_titleWidth, m_titleHeight;
+ EstateOrientation m_orientation;
+ PortfolioEstate *pe;
+
+ private slots:
+ void slotMenuAction(int);
+ void estateChanged();
+};
+
+#endif
diff --git a/atlantik/libatlantikui/kwrappedlistviewitem.cpp b/atlantik/libatlantikui/kwrappedlistviewitem.cpp
new file mode 100644
index 00000000..7bd9e2cf
--- /dev/null
+++ b/atlantik/libatlantikui/kwrappedlistviewitem.cpp
@@ -0,0 +1,116 @@
+// Copyright (c) 2004 Rob Kaper <rob@unixcode.org>. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+
+#include <qheader.h>
+#include <qstring.h>
+
+#include <kglobalsettings.h>
+#include <klistview.h>
+#include <kwordwrap.h>
+
+#include "kwrappedlistviewitem.h"
+
+KWrappedListViewItem::KWrappedListViewItem( QListView *parent, QString text, QString t2 )
+: QObject(), KListViewItem( parent )
+{
+ init( parent, text, t2 );
+}
+
+KWrappedListViewItem::KWrappedListViewItem( QListView *parent, QListViewItem *after, QString text, QString t2 )
+: QObject(), KListViewItem( parent, after )
+{
+ init( parent, text, t2 );
+}
+
+void KWrappedListViewItem::setup()
+{
+ widthChanged();
+}
+
+/*
+int KWrappedListViewItem::width( const QFontMetrics&, const QListView*, int ) const
+{
+ return m_wrap->boundingRect().width();
+}
+*/
+
+void KWrappedListViewItem::wrapColumn( int c )
+{
+ if ( c != m_wrapColumn )
+ return;
+
+ QListView *lv = listView();
+ if ( !lv )
+ return;
+
+ QFont font = QFont( KGlobalSettings::generalFont().family(), KGlobalSettings::generalFont().pointSize(), QFont::Normal );
+ QFontMetrics fm = QFontMetrics( font );
+
+ int wrapWidth = lv->width();
+ for ( int i = 0 ; i < m_wrapColumn ; i++ )
+ wrapWidth -= ( width(fm, lv, i) + lv->itemMargin() );
+
+ if ( pixmap(c) )
+ wrapWidth -= ( pixmap( c )->width() + lv->itemMargin() );
+
+ QScrollBar *scrollBar = lv->verticalScrollBar();
+ if ( !scrollBar->isHidden() )
+ wrapWidth -= scrollBar->width();
+
+ QRect rect = QRect( 0, 0, wrapWidth - 20, -1 );
+
+ KWordWrap *wrap = KWordWrap::formatText( fm, rect, 0, m_origText );
+ setText( c, wrap->wrappedString() );
+
+ int lc = text(c).contains( QChar( '\n' ) ) + 1;
+ setHeight( wrap->boundingRect().height() + lc*lv->itemMargin() );
+
+ widthChanged( c );
+
+ delete wrap;
+}
+
+void KWrappedListViewItem::init( QListView *parent, QString text, QString t2 )
+{
+ m_wrapColumn = 0;
+ setMultiLinesEnabled( true );
+ parent->setResizeMode( QListView::LastColumn );
+
+ m_origText = text;
+
+ if ( !t2.isNull() )
+ {
+ setText( 0, text );
+ m_origText = t2;
+ m_wrapColumn = 1;
+ }
+ else
+ m_origText = text;
+
+ wrapColumn( m_wrapColumn );
+
+ connect( parent->header(), SIGNAL(sizeChange(int, int, int)), this, SLOT(wrapColumn(int)));
+}
+
+#include "kwrappedlistviewitem.moc"
diff --git a/atlantik/libatlantikui/kwrappedlistviewitem.h b/atlantik/libatlantikui/kwrappedlistviewitem.h
new file mode 100644
index 00000000..056cef6d
--- /dev/null
+++ b/atlantik/libatlantikui/kwrappedlistviewitem.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2004 Rob Kaper <rob@unixcode.org>. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS'' AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+// SUCH DAMAGE.
+
+#ifndef KWRAPPEDLISTVIEWITEM_H
+#define KWRAPPEDLISTVIEWITEM_H
+
+#include <qobject.h>
+#include <qstring.h>
+
+#include <klistview.h>
+
+class KWordWrap;
+
+class KWrappedListViewItem : public QObject, public KListViewItem
+{
+Q_OBJECT
+
+public:
+ KWrappedListViewItem( QListView *parent, QString text, QString=QString::null );
+ KWrappedListViewItem( QListView *parent, QListViewItem *after, QString text, QString=QString::null );
+ void setup();
+// int width(const QFontMetrics& fm, const QListView* lv, int c) const;
+
+private slots:
+ void wrapColumn( int c );
+
+private:
+ void init( QListView *parent, QString text, QString=QString::null );
+ QString m_origText;
+ int m_wrapColumn;
+};
+
+#endif
diff --git a/atlantik/libatlantikui/libatlantikui_export.h b/atlantik/libatlantikui/libatlantikui_export.h
new file mode 100644
index 00000000..9ea1695f
--- /dev/null
+++ b/atlantik/libatlantikui/libatlantikui_export.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2004 Dirk Mueller <mueller@kde.org>
+
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#ifndef LIBATLANTIKUI_EXPORT_H
+#define LIBATLANTIKUI_EXPORT_H
+
+#include <kdemacros.h>
+
+#define LIBATLANTIKUI_EXPORT KDE_EXPORT
+
+#endif
diff --git a/atlantik/libatlantikui/portfolioestate.cpp b/atlantik/libatlantikui/portfolioestate.cpp
new file mode 100644
index 00000000..625fb055
--- /dev/null
+++ b/atlantik/libatlantikui/portfolioestate.cpp
@@ -0,0 +1,94 @@
+// Copyright (c) 2002 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#include <qcolor.h>
+#include <qpainter.h>
+#include <qrect.h>
+
+#include "portfolioestate.moc"
+#include "estate.h"
+
+PortfolioEstate::PortfolioEstate(Estate *estate, Player *player, bool alwaysOwned, QWidget *parent, const char *name) : QWidget(parent, name)
+{
+ m_estate = estate;
+ m_player = player;
+ m_alwaysOwned = alwaysOwned;
+
+ QSize s(PE_WIDTH, PE_HEIGHT);
+ setFixedSize(s);
+
+ b_recreate = true;
+}
+
+void PortfolioEstate::estateChanged()
+{
+ b_recreate = true;
+ update();
+}
+
+QPixmap PortfolioEstate::drawPixmap(Estate *estate, Player *player, bool alwaysOwned)
+{
+ QColor lightGray(204, 204, 204), darkGray(153, 153, 153);
+ QPixmap qpixmap(PE_WIDTH, PE_HEIGHT);
+ QPainter painter;
+ painter.begin(&qpixmap);
+
+ painter.setPen(lightGray);
+ painter.setBrush(white);
+ painter.drawRect(QRect(0, 0, PE_WIDTH, PE_HEIGHT));
+ if (alwaysOwned || (estate && estate->isOwned() && player == estate->owner()))
+ {
+ painter.setPen(darkGray);
+ for (int y=5;y<=13;y+=2)
+ painter.drawLine(2, y, 10, y);
+
+ painter.setPen(Qt::white);
+ painter.drawPoint(8, 5);
+ painter.drawPoint(8, 7);
+ painter.drawPoint(8, 9);
+ painter.drawPoint(5, 11);
+ painter.drawPoint(9, 11);
+ painter.drawPoint(3, 13);
+ painter.drawPoint(10, 13);
+
+ painter.setPen(estate->color());
+ painter.setBrush(estate->color());
+ }
+ else
+ {
+ painter.setPen(lightGray);
+ painter.setBrush(lightGray);
+ }
+ painter.drawRect(0, 0, PE_WIDTH, 3);
+
+ return qpixmap;
+}
+
+void PortfolioEstate::paintEvent(QPaintEvent *)
+{
+ if (b_recreate)
+ {
+ m_pixmap = drawPixmap(m_estate, m_player, m_alwaysOwned);
+ b_recreate = false;
+ }
+ bitBlt(this, 0, 0, &m_pixmap);
+}
+
+void PortfolioEstate::mousePressEvent(QMouseEvent *e)
+{
+ if (e->button()==LeftButton)
+ emit estateClicked(m_estate);
+}
diff --git a/atlantik/libatlantikui/portfolioestate.h b/atlantik/libatlantikui/portfolioestate.h
new file mode 100644
index 00000000..65bd5db3
--- /dev/null
+++ b/atlantik/libatlantikui/portfolioestate.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2002 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#ifndef ATLANTIK_PORTFOLIOESTATE_H
+#define ATLANTIK_PORTFOLIOESTATE_H
+
+#include <qpixmap.h>
+#include <qwidget.h>
+
+#define PE_WIDTH 13
+#define PE_HEIGHT 16
+
+class Estate;
+class Player;
+
+class PortfolioEstate : public QWidget
+{
+Q_OBJECT
+
+public:
+ PortfolioEstate(Estate *estate, Player *player, bool alwaysOwned, QWidget *parent, const char *name = 0);
+ Estate *estate() { return m_estate; }
+ static QPixmap drawPixmap(Estate *estate, Player *player = 0, bool alwaysOwned = true);
+
+protected:
+ void paintEvent(QPaintEvent *);
+ void mousePressEvent(QMouseEvent *);
+
+private slots:
+ void estateChanged();
+
+signals:
+ void estateClicked(Estate *estate);
+
+private:
+ Estate *m_estate;
+ Player *m_player;
+ QPixmap m_pixmap;
+ bool b_recreate, m_alwaysOwned;
+};
+
+#endif
diff --git a/atlantik/libatlantikui/portfolioview.cpp b/atlantik/libatlantikui/portfolioview.cpp
new file mode 100644
index 00000000..c07d426b
--- /dev/null
+++ b/atlantik/libatlantikui/portfolioview.cpp
@@ -0,0 +1,295 @@
+// Copyright (c) 2002-2003 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#include <qpainter.h>
+#include <qcursor.h>
+
+#include <kdebug.h>
+#include <kdialogbase.h>
+#include <kiconeffect.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kpopupmenu.h>
+#include <kstandarddirs.h>
+
+#include <atlantic_core.h>
+#include <config.h>
+#include <player.h>
+#include <estate.h>
+#include <estategroup.h>
+
+#include "portfolioview.moc"
+
+#define PE_DISTW 4
+#define PE_DISTH 4
+#define PE_SPACE 2
+#define PE_MARGINW 5
+#define PE_MARGINH 2
+#define ICONSIZE 48
+
+PortfolioView::PortfolioView(AtlanticCore *core, Player *player, QColor activeColor, QColor inactiveColor, QWidget *parent, const char *name) : QWidget(parent, name)
+{
+ m_atlanticCore = core;
+ m_player = player;
+ m_activeColor = activeColor;
+ m_inactiveColor = inactiveColor;
+ m_lastPE = 0;
+
+ qpixmap = 0;
+ b_recreate = true;
+
+ m_portfolioEstates.setAutoDelete(true);
+ setBackgroundColor(Qt::white);
+ setMinimumHeight(ICONSIZE);
+
+ // Init icon
+ m_image = 0;
+ m_imageName = "hamburger.png";
+ loadIcon();
+}
+
+PortfolioView::~PortfolioView()
+{
+ clearPortfolio();
+ delete m_image;
+ delete qpixmap;
+}
+
+Player *PortfolioView::player()
+{
+ return m_player;
+}
+
+void PortfolioView::buildPortfolio()
+{
+ if ( m_portfolioEstates.count() )
+ clearPortfolio();
+
+ // Loop through estate groups in order
+ QPtrList<EstateGroup> estateGroups = m_atlanticCore->estateGroups();
+ PortfolioEstate *lastPE = 0, *firstPEprevGroup = 0;
+
+ int x = 100, y = 25, marginHint = 5, bottom;
+ bottom = ICONSIZE - PE_HEIGHT - marginHint;
+
+ EstateGroup *estateGroup;
+ for (QPtrListIterator<EstateGroup> it(estateGroups); *it; ++it)
+ {
+ if ((estateGroup = *it))
+ {
+ // New group
+ lastPE = 0;
+
+ // Loop through estates
+ QPtrList<Estate> estates = m_atlanticCore->estates();
+ Estate *estate;
+ for (QPtrListIterator<Estate> it(estates); *it; ++it)
+ {
+ if ((estate = *it) && estate->estateGroup() == estateGroup)
+ {
+ // Create PE
+ PortfolioEstate *portfolioEstate = new PortfolioEstate(estate, m_player, false, this, "portfolioestate");
+ m_portfolioEstates.append(portfolioEstate);
+
+ connect(portfolioEstate, SIGNAL(estateClicked(Estate *)), this, SIGNAL(estateClicked(Estate *)));
+ if (lastPE)
+ {
+ x = lastPE->x() + 2;
+ y = lastPE->y() + 4;
+ if (y > bottom)
+ bottom = y;
+ }
+ else if (firstPEprevGroup)
+ {
+ x = firstPEprevGroup->x() + PE_WIDTH + 8;
+ y = 20 + marginHint;
+ firstPEprevGroup = portfolioEstate;
+ }
+ else
+ {
+ x = ICONSIZE + marginHint;
+ y = 20 + marginHint;
+ if (y > bottom)
+ bottom = y;
+ firstPEprevGroup = portfolioEstate;
+ }
+
+ portfolioEstate->setGeometry(x, y, portfolioEstate->width(), portfolioEstate->height());
+ portfolioEstate->show();
+
+ connect(estate, SIGNAL(changed()), portfolioEstate, SLOT(estateChanged()));
+
+ lastPE = portfolioEstate;
+ }
+ }
+ }
+ }
+ setMinimumWidth(x + PE_WIDTH + marginHint);
+ int minHeight = bottom + PE_HEIGHT + marginHint;
+ if (minHeight > minimumHeight())
+ setMinimumHeight(minHeight);
+}
+
+void PortfolioView::clearPortfolio()
+{
+ m_portfolioEstates.clear();
+}
+
+void PortfolioView::loadIcon()
+{
+ if (m_imageName == m_player->image())
+ return;
+ m_imageName = m_player->image();
+
+ delete m_image;
+ m_image = 0;
+
+ if (!m_imageName.isEmpty())
+ {
+ QString filename = locate("data", "atlantik/themes/default/tokens/" + m_imageName);
+ if (KStandardDirs::exists(filename))
+ m_image = new QPixmap(filename);
+ }
+
+ if (!m_image)
+ {
+ return;
+
+/*
+ m_imageName = "hamburger.png";
+
+ QString filename = locate("data", "atlantik/themes/default/tokens/" + m_imageName);
+ if (KStandardDirs::exists(filename))
+ m_image = new QPixmap(filename);
+*/
+ }
+ else if (ICONSIZE > minimumHeight())
+ setMinimumHeight(ICONSIZE);
+
+ QWMatrix m;
+ m.scale(double(ICONSIZE) / m_image->width(), double(ICONSIZE) / m_image->height());
+ QPixmap *scaledPixmap = new QPixmap(ICONSIZE, ICONSIZE);
+ *scaledPixmap = m_image->xForm(m);
+
+ delete m_image;
+ m_image = scaledPixmap;
+}
+
+void PortfolioView::paintEvent(QPaintEvent *)
+{
+ if (b_recreate)
+ {
+ delete qpixmap;
+ qpixmap = new QPixmap(width(), height());
+
+ QPainter painter;
+ painter.begin(qpixmap, this);
+
+ painter.setPen(Qt::white);
+ painter.setBrush(Qt::white);
+ painter.drawRect(rect());
+
+ painter.setPen(m_player->hasTurn() ? m_activeColor : Qt::black);
+ painter.setBrush(m_player->hasTurn() ? m_activeColor : Qt::black);
+ painter.drawRect(0, 0, width(), 20);
+
+ if (m_image)
+ {
+ painter.setPen(Qt::black);
+ painter.setBrush(Qt::white);
+ painter.drawRect(0, 0, ICONSIZE, ICONSIZE);
+
+ painter.drawPixmap(0, 0, *m_image);
+ }
+
+ painter.setPen(Qt::white);
+ painter.setFont(QFont(KGlobalSettings::generalFont().family(), KGlobalSettings::generalFont().pointSize(), QFont::Bold));
+ painter.drawText(ICONSIZE + KDialog::marginHint(), 15, m_player->name());
+
+ if ( m_portfolioEstates.count() )
+ painter.drawText(width() - 50, 15, QString::number(m_player->money()));
+ else
+ {
+ painter.setPen(Qt::black);
+ painter.setBrush(Qt::white);
+
+ painter.setFont(QFont(KGlobalSettings::generalFont().family(), KGlobalSettings::generalFont().pointSize(), QFont::Normal));
+ painter.drawText(ICONSIZE + KDialog::marginHint(), 30, m_player->host());
+ }
+
+ b_recreate = false;
+ }
+ bitBlt(this, 0, 0, qpixmap);
+}
+
+void PortfolioView::resizeEvent(QResizeEvent *)
+{
+ b_recreate = true;
+}
+
+void PortfolioView::playerChanged()
+{
+ loadIcon();
+
+ b_recreate = true;
+ update();
+}
+
+void PortfolioView::mousePressEvent(QMouseEvent *e)
+{
+ Player *playerSelf = m_atlanticCore->playerSelf();
+
+ if ( e->button()==RightButton && (m_player != playerSelf) )
+ {
+ KPopupMenu *rmbMenu = new KPopupMenu(this);
+ rmbMenu->insertTitle(m_player->name());
+
+ if ( m_portfolioEstates.count() )
+ {
+ // Start trade
+ rmbMenu->insertItem(i18n("Request Trade with %1").arg(m_player->name()), 0);
+ }
+ else
+ {
+ // Kick player
+ rmbMenu->insertItem(i18n("Boot Player %1 to Lounge").arg(m_player->name()), 0);
+ rmbMenu->setItemEnabled( 0, m_atlanticCore->selfIsMaster() );
+ }
+
+ connect(rmbMenu, SIGNAL(activated(int)), this, SLOT(slotMenuAction(int)));
+ QPoint g = QCursor::pos();
+ rmbMenu->exec(g);
+ }
+}
+
+void PortfolioView::slotMenuAction(int item)
+{
+ switch (item)
+ {
+ case 0:
+ if ( m_portfolioEstates.count() )
+ emit newTrade(m_player);
+ else
+ emit kickPlayer(m_player);
+ break;
+ }
+}
+#undef PE_DISTW
+#undef PE_DISTH
+#undef PE_SPACE
+#undef PE_MARGINW
+#undef PE_MARGINH
+#undef ICONSIZE
diff --git a/atlantik/libatlantikui/portfolioview.h b/atlantik/libatlantikui/portfolioview.h
new file mode 100644
index 00000000..26317e2b
--- /dev/null
+++ b/atlantik/libatlantikui/portfolioview.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2002-2003 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#ifndef ATLANTIK_PORTFOLIOVIEW_H
+#define ATLANTIK_PORTFOLIOVIEW_H
+
+#include <qwidget.h>
+#include <qpixmap.h>
+#include <qptrlist.h>
+
+#include "portfolioestate.h"
+#include "libatlantikui_export.h"
+class QColor;
+class QString;
+
+class AtlanticCore;
+class Player;
+class Estate;
+
+class LIBATLANTIKUI_EXPORT PortfolioView : public QWidget
+{
+Q_OBJECT
+
+public:
+ PortfolioView(AtlanticCore *core, Player *_player, QColor activeColor, QColor inactiveColor, QWidget *parent, const char *name = 0);
+ ~PortfolioView();
+
+ void buildPortfolio();
+ void clearPortfolio();
+
+ Player *player();
+
+protected:
+ void paintEvent(QPaintEvent *);
+ void resizeEvent(QResizeEvent *);
+ void mousePressEvent(QMouseEvent *);
+
+signals:
+ void newTrade(Player *player);
+ void kickPlayer(Player *player);
+ void estateClicked(Estate *);
+
+private slots:
+ void playerChanged();
+ void slotMenuAction(int item);
+
+private:
+ void loadIcon();
+
+ AtlanticCore *m_atlanticCore;
+ Player *m_player;
+ PortfolioEstate *m_lastPE;
+ QColor m_activeColor, m_inactiveColor;
+ QPixmap *qpixmap, *m_image;
+ QString m_imageName;
+ bool b_recreate;
+ QPtrList<PortfolioEstate> m_portfolioEstates;
+};
+
+#endif
diff --git a/atlantik/libatlantikui/token.cpp b/atlantik/libatlantikui/token.cpp
new file mode 100644
index 00000000..6f13333f
--- /dev/null
+++ b/atlantik/libatlantikui/token.cpp
@@ -0,0 +1,157 @@
+// Copyright (c) 2002-2003 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#include <iostream>
+
+#include <qpainter.h>
+#include <qpixmap.h>
+#include <qfont.h>
+
+#include <kdebug.h>
+
+#include <kstandarddirs.h>
+#include <kglobalsettings.h>
+
+#include "board.h"
+#include "estate.h"
+#include "player.h"
+
+#include "token.moc"
+
+#define TOKEN_ICONSIZE 32
+
+Token::Token(Player *player, AtlantikBoard *parent, const char *name) : QWidget(parent, name)
+{
+ setBackgroundMode(NoBackground); // avoid flickering
+
+ m_parentBoard = parent;
+
+ m_player = player;
+ connect(m_player, SIGNAL(changed(Player *)), this, SLOT(playerChanged()));
+
+ m_inJail = m_player->inJail();
+ m_location = m_player->location();
+ m_destination = 0;
+
+ qpixmap = 0;
+ b_recreate = true;
+
+ // Init icon
+ m_image = 0;
+ loadIcon();
+
+ setFixedSize(QSize(TOKEN_ICONSIZE, TOKEN_ICONSIZE + KGlobalSettings::generalFont().pointSize()));
+}
+
+Token::~Token()
+{
+ delete m_image;
+}
+
+Player *Token::player()
+{
+ return m_player;
+}
+
+void Token::setLocation(Estate *location)
+{
+ if (m_location != location)
+ m_location = location;
+}
+
+void Token::setDestination(Estate *estateView)
+{
+ if (m_destination != estateView)
+ m_destination = estateView;
+}
+
+void Token::playerChanged()
+{
+ if (m_imageName != m_player->image())
+ loadIcon();
+
+ b_recreate = true;
+ update();
+}
+
+void Token::loadIcon()
+{
+ m_imageName = m_player->image();
+
+ delete m_image;
+ m_image = 0;
+
+ if (!m_imageName.isEmpty())
+ {
+ QString filename = locate("data", "atlantik/themes/default/tokens/" + m_imageName);
+ if (KStandardDirs::exists(filename))
+ m_image = new QPixmap(filename);
+ }
+
+ if (!m_image)
+ {
+ m_imageName = "hamburger.png";
+
+ QString filename = locate("data", "atlantik/themes/default/tokens/" + m_imageName);
+ if (KStandardDirs::exists(filename))
+ m_image = new QPixmap(filename);
+ }
+
+ QWMatrix m;
+ m.scale(double(TOKEN_ICONSIZE) / m_image->width(), double(TOKEN_ICONSIZE) / m_image->height());
+ QPixmap *scaledPixmap = new QPixmap(TOKEN_ICONSIZE, TOKEN_ICONSIZE);
+ *scaledPixmap = m_image->xForm(m);
+
+ delete m_image;
+ m_image = scaledPixmap;
+}
+
+void Token::paintEvent(QPaintEvent *)
+{
+ if (b_recreate)
+ {
+ delete qpixmap;
+ qpixmap = new QPixmap(width(), height());
+
+ QPainter painter;
+ painter.begin(qpixmap, this);
+
+ if (m_image)
+ {
+ painter.setPen(Qt::black);
+ painter.setBrush(Qt::white);
+ painter.drawRect(0, 0, TOKEN_ICONSIZE, TOKEN_ICONSIZE);
+
+ painter.drawPixmap(0, 0, *m_image);
+ }
+
+ painter.setPen(Qt::black);
+ painter.setBrush(Qt::black);
+ painter.drawRect(0, TOKEN_ICONSIZE, width(), KGlobalSettings::generalFont().pointSize());
+
+ painter.setPen(Qt::white);
+ painter.setFont(QFont(KGlobalSettings::generalFont().family(), KGlobalSettings::generalFont().pointSize(), QFont::DemiBold));
+ painter.drawText(1, height()-1, (m_player ? m_player->name() : QString::null));
+
+ b_recreate = false;
+ }
+ bitBlt(this, 0, 0, qpixmap);
+}
+
+void Token::resizeEvent(QResizeEvent *)
+{
+ b_recreate = true;
+}
diff --git a/atlantik/libatlantikui/token.h b/atlantik/libatlantikui/token.h
new file mode 100644
index 00000000..f0e52f2b
--- /dev/null
+++ b/atlantik/libatlantikui/token.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2002-2003 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#ifndef ATLANTIK_TOKEN_H
+#define ATLANTIK_TOKEN_H
+
+#include <qwidget.h>
+
+class QPixmap;
+
+class Player;
+class Estate;
+class AtlantikBoard;
+
+class Token : public QWidget
+{
+Q_OBJECT
+
+ public:
+ Token (Player *player, AtlantikBoard *parent, const char *name = 0);
+ ~Token();
+ Player *player();
+ void setLocation(Estate *estate);
+ Estate *location() { return m_location; }
+ void setDestination(Estate *estate);
+ Estate *destination() { return m_destination; }
+ void setInJail (bool inJail) { m_inJail = inJail; }
+ bool inJail() { return m_inJail; }
+
+ private slots:
+ void playerChanged();
+
+ protected:
+ void paintEvent(QPaintEvent *);
+ void resizeEvent(QResizeEvent *);
+
+private:
+ void loadIcon();
+
+ Player *m_player;
+ Estate *m_location, *m_destination;
+ bool m_inJail;
+ AtlantikBoard *m_parentBoard;
+ bool b_recreate;
+ QPixmap *qpixmap, *m_image;
+ QString m_imageName;
+};
+
+#endif
diff --git a/atlantik/libatlantikui/trade_widget.cpp b/atlantik/libatlantikui/trade_widget.cpp
new file mode 100644
index 00000000..b2658abb
--- /dev/null
+++ b/atlantik/libatlantikui/trade_widget.cpp
@@ -0,0 +1,374 @@
+// Copyright (c) 2002-2003 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#include <iostream>
+
+#include <qlayout.h>
+#include <qhgroupbox.h>
+#include <qheader.h>
+#include <qpopupmenu.h>
+#include <qcursor.h>
+#include <qvalidator.h>
+#include <qmap.h>
+#include <qlabel.h>
+#include <qspinbox.h>
+
+#include <klocale.h>
+#include <klistview.h>
+#include <kdebug.h>
+#include <kdialogbase.h>
+#include <klineedit.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+#include <kcombobox.h>
+#include <kpopupmenu.h>
+
+#include <atlantic_core.h>
+#include <player.h>
+#include <estate.h>
+#include <trade.h>
+#include <portfolioestate.h>
+
+#include "trade_widget.moc"
+
+TradeDisplay::TradeDisplay(Trade *trade, AtlanticCore *atlanticCore, QWidget *parent, const char *name)
+ : QWidget(parent, name,
+ WType_Dialog | WStyle_Customize | WStyle_DialogBorder | WStyle_Title |
+ WStyle_Minimize | WStyle_ContextHelp )
+{
+ m_trade = trade;
+ m_atlanticCore = atlanticCore;
+
+ setCaption(i18n("Trade %1").arg(trade->tradeId()));
+
+ QVBoxLayout *listCompBox = new QVBoxLayout(this, KDialog::marginHint());
+
+ m_updateComponentBox = new QHGroupBox(i18n("Add Component"), this);
+ listCompBox->addWidget(m_updateComponentBox);
+
+ m_editTypeCombo = new KComboBox(m_updateComponentBox);
+ m_editTypeCombo->insertItem(i18n("Estate"));
+ m_editTypeCombo->insertItem(i18n("Money"));
+
+ connect(m_editTypeCombo, SIGNAL(activated(int)), this, SLOT(setTypeCombo(int)));
+
+ m_estateCombo = new KComboBox(m_updateComponentBox);
+ QPtrList<Estate> estateList = m_atlanticCore->estates();
+ Estate *estate;
+ for (QPtrListIterator<Estate> it(estateList); *it; ++it)
+ {
+ if ((estate = *it) && estate->isOwned())
+ {
+ m_estateCombo->insertItem( PortfolioEstate::drawPixmap(estate), estate->name() );
+ m_estateMap[m_estateCombo->count() - 1] = estate;
+ m_estateRevMap[estate] = m_estateCombo->count() - 1;
+ }
+ }
+
+ connect(m_estateCombo, SIGNAL(activated(int)), this, SLOT(setEstateCombo(int)));
+
+ m_moneyBox = new QSpinBox(0, 10000, 1, m_updateComponentBox);
+
+ QPtrList<Player> playerList = m_atlanticCore->players();
+ Player *player, *pSelf = m_atlanticCore->playerSelf();
+
+ m_fromLabel = new QLabel(m_updateComponentBox);
+ m_fromLabel->setText(i18n("From"));
+ m_playerFromCombo = new KComboBox(m_updateComponentBox);
+
+ m_toLabel = new QLabel(m_updateComponentBox);
+ m_toLabel->setText(i18n("To"));
+ m_playerTargetCombo = new KComboBox(m_updateComponentBox);
+
+ for (QPtrListIterator<Player> it(playerList); *it; ++it)
+ {
+ if ((player = *it) && player->game() == pSelf->game())
+ {
+ m_playerFromCombo->insertItem(player->name());
+ m_playerFromMap[m_playerFromCombo->count() - 1] = player;
+ m_playerFromRevMap[player] = m_playerFromCombo->count() - 1;
+
+ m_playerTargetCombo->insertItem(player->name());
+ m_playerTargetMap[m_playerTargetCombo->count() - 1] = player;
+ m_playerTargetRevMap[player] = m_playerTargetCombo->count() - 1;
+
+ connect(player, SIGNAL(changed(Player *)), this, SLOT(playerChanged(Player *)));
+ }
+ }
+
+ m_updateButton = new KPushButton(i18n("Update"), m_updateComponentBox);
+ m_updateButton->setEnabled(false);
+
+ connect(m_updateButton, SIGNAL(clicked()), this, SLOT(updateComponent()));
+
+ m_componentList = new KListView(this, "componentList");
+ listCompBox->addWidget(m_componentList);
+
+ m_componentList->addColumn(i18n("Player"));
+ m_componentList->addColumn(i18n("Gives"));
+ m_componentList->addColumn(i18n("Player"));
+ m_componentList->addColumn(i18n("Item"));
+
+ connect(m_componentList, SIGNAL(contextMenu(KListView*, QListViewItem *, const QPoint&)), SLOT(contextMenu(KListView *, QListViewItem *, const QPoint&)));
+ connect(m_componentList, SIGNAL(clicked(QListViewItem *)), this, SLOT(setCombos(QListViewItem *)));
+
+ QHBoxLayout *actionBox = new QHBoxLayout(this, 0, KDialog::spacingHint());
+ listCompBox->addItem(actionBox);
+
+ actionBox->addItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum));
+
+ m_rejectButton = new KPushButton(BarIcon("cancel", KIcon::SizeSmall), i18n("Reject"), this);
+ actionBox->addWidget(m_rejectButton);
+
+ connect(m_rejectButton, SIGNAL(clicked()), this, SLOT(reject()));
+
+ m_acceptButton = new KPushButton(BarIcon("ok", KIcon::SizeSmall), i18n("Accept"), this);
+// m_acceptButton->setEnabled(false);
+ actionBox->addWidget(m_acceptButton);
+
+ connect(m_acceptButton, SIGNAL(clicked()), this, SLOT(accept()));
+
+ m_status = new QLabel(this);
+ listCompBox->addWidget(m_status);
+ m_status->setText( i18n( "%1 out of %2 players accept current trade proposal." ).arg( m_trade->count( true ) ).arg( m_trade->count( false ) ) );
+
+// mPlayerList->header()->hide();
+// mPlayerList->setRootIsDecorated(true);
+// mPlayerList->setResizeMode(KListView::AllColumns);
+
+ connect(m_trade, SIGNAL(itemAdded(TradeItem *)), this, SLOT(tradeItemAdded(TradeItem *)));
+ connect(m_trade, SIGNAL(itemRemoved(TradeItem *)), this, SLOT(tradeItemRemoved(TradeItem *)));
+ connect(m_trade, SIGNAL(changed(Trade *)), this, SLOT(tradeChanged()));
+ connect(m_trade, SIGNAL(rejected(Player *)), this, SLOT(tradeRejected(Player *)));
+ connect(this, SIGNAL(updateEstate(Trade *, Estate *, Player *)), m_trade, SIGNAL(updateEstate(Trade *, Estate *, Player *)));
+ connect(this, SIGNAL(updateMoney(Trade *, unsigned int, Player *, Player *)), m_trade, SIGNAL(updateMoney(Trade *, unsigned int, Player *, Player *)));
+ connect(this, SIGNAL(reject(Trade *)), m_trade, SIGNAL(reject(Trade *)));
+ connect(this, SIGNAL(accept(Trade *)), m_trade, SIGNAL(accept(Trade *)));
+
+ setTypeCombo(m_editTypeCombo->currentItem());
+ setEstateCombo(m_estateCombo->currentItem());
+
+ m_contextTradeItem = 0;
+}
+
+void TradeDisplay::closeEvent(QCloseEvent *e)
+{
+ // Don't send network event when trade is already rejected
+ if (m_trade->isRejected())
+ m_atlanticCore->removeTrade(m_trade);
+ else
+ emit reject(m_trade);
+
+ e->accept();
+}
+
+void TradeDisplay::tradeItemAdded(TradeItem *tradeItem)
+{
+ KListViewItem *item = new KListViewItem(m_componentList, (tradeItem->from() ? tradeItem->from()->name() : QString("?")), i18n("gives is transitive ;)", "gives"), (tradeItem->to() ? tradeItem->to()->name() : QString("?")), tradeItem->text());
+ connect(tradeItem, SIGNAL(changed(TradeItem *)), this, SLOT(tradeItemChanged(TradeItem *)));
+
+ item->setPixmap(0, QPixmap(SmallIcon("personal")));
+ item->setPixmap(2, QPixmap(SmallIcon("personal")));
+
+ if (TradeEstate *tradeEstate = dynamic_cast<TradeEstate*>(tradeItem))
+ item->setPixmap(3, PortfolioEstate::drawPixmap(tradeEstate->estate()));
+// else if (TradeMoney *tradeMoney = dynamic_cast<TradeMoney*>(tradeItem))
+// item->setPixmap(3, PortfolioEstate::pixMap(tradeEstate->estate()));
+
+ m_componentMap[tradeItem] = item;
+ m_componentRevMap[item] = tradeItem;
+}
+
+void TradeDisplay::tradeItemRemoved(TradeItem *t)
+{
+ KListViewItem *item = m_componentMap[t];
+ delete item;
+ m_componentMap[t] = 0;
+}
+
+void TradeDisplay::tradeItemChanged(TradeItem *t)
+{
+ KListViewItem *item = m_componentMap[t];
+ if (item)
+ {
+ item->setText(0, t->from() ? t->from()->name() : QString("?"));
+ item->setPixmap(0, QPixmap(SmallIcon("personal")));
+ item->setText(2, t->to() ? t->to()->name() : QString("?"));
+ item->setPixmap(2, QPixmap(SmallIcon("personal")));
+ item->setText(3, t->text());
+ }
+}
+
+void TradeDisplay::tradeChanged()
+{
+ // TODO: add notification whether playerSelf has accepted or not and
+ // enable/disable accept button based on that
+ m_status->setText( i18n( "%1 out of %2 players accept current trade proposal." ).arg( m_trade->count( true ) ).arg( m_trade->count( false ) ) );
+}
+
+void TradeDisplay::playerChanged(Player *player)
+{
+ m_playerFromCombo->changeItem(player->name(), m_playerFromRevMap[player]);
+ m_playerTargetCombo->changeItem(player->name(), m_playerTargetRevMap[player]);
+
+ TradeItem *item = 0;
+ for (QMap<KListViewItem *, TradeItem *>::Iterator it=m_componentRevMap.begin() ; it != m_componentRevMap.end() && (item = *it) ; ++it)
+ tradeItemChanged(item);
+}
+
+void TradeDisplay::tradeRejected(Player *player)
+{
+ if (player)
+ m_status->setText(i18n("Trade proposal was rejected by %1.").arg(player->name()));
+ else
+ m_status->setText(i18n("Trade proposal was rejected."));
+
+ // Disable GUI elements
+ m_updateButton->setEnabled(false);
+ m_componentList->setEnabled(false);
+ m_rejectButton->setEnabled(false);
+ m_acceptButton->setEnabled(false);
+
+ // TODO: add/enable close button
+}
+
+void TradeDisplay::setTypeCombo(int index)
+{
+ switch (index)
+ {
+ case 0:
+ // Editing estate component
+
+ m_estateCombo->show();
+ m_estateCombo->setMaximumWidth(9999);
+
+ m_moneyBox->hide();
+ m_moneyBox->setMaximumWidth(0);
+
+ setEstateCombo(m_estateCombo->currentItem()); // also updates playerfromCombo
+ m_playerFromCombo->setEnabled(false);
+
+ m_updateButton->setEnabled( m_estateCombo->count() > 0 );
+
+ break;
+
+ case 1:
+ // Editing money component
+
+ m_estateCombo->hide();
+ m_estateCombo->setMaximumWidth(0);
+
+ m_moneyBox->show();
+ m_moneyBox->setMaximumWidth(9999);
+
+ m_playerFromCombo->setEnabled(true);
+
+ m_updateButton->setEnabled(true);
+
+ break;
+ }
+}
+
+void TradeDisplay::setEstateCombo(int index)
+{
+ if (m_estateCombo->currentItem() != index)
+ m_estateCombo->setCurrentItem(index);
+
+ if (Estate *estate = m_estateMap[index])
+ m_playerFromCombo->setCurrentItem( m_playerFromRevMap[estate->owner()] );
+}
+
+void TradeDisplay::setCombos(QListViewItem *i)
+{
+ TradeItem *item = m_componentRevMap[(KListViewItem *)(i)];
+ if (TradeEstate *tradeEstate = dynamic_cast<TradeEstate*>(item))
+ {
+ setTypeCombo(0);
+ setEstateCombo( m_estateRevMap[tradeEstate->estate()] ); // also updates playerFromCombo
+ m_playerTargetCombo->setCurrentItem( m_playerTargetRevMap[tradeEstate->to()] );
+ }
+ else if (TradeMoney *tradeMoney = dynamic_cast<TradeMoney*>(item))
+ {
+ setTypeCombo(1);
+ m_moneyBox->setValue( tradeMoney->money() );
+ m_playerFromCombo->setCurrentItem( m_playerFromRevMap[tradeMoney->from()] );
+ m_playerTargetCombo->setCurrentItem( m_playerTargetRevMap[tradeMoney->to()] );
+ }
+}
+
+void TradeDisplay::updateComponent()
+{
+ Estate *estate;
+ Player *pFrom, *pTarget;
+
+ switch (m_editTypeCombo->currentItem())
+ {
+ case 0:
+ // Updating estate component
+ estate = m_estateMap[m_estateCombo->currentItem()];
+ pTarget = m_playerTargetMap[m_playerTargetCombo->currentItem()];
+
+ if (estate && pTarget)
+ emit updateEstate(m_trade, estate, pTarget);
+
+ break;
+
+ case 1:
+ // Updating money component
+ pFrom = m_playerFromMap[m_playerFromCombo->currentItem()];
+ pTarget = m_playerTargetMap[m_playerTargetCombo->currentItem()];
+
+ if (pFrom && pTarget)
+ emit updateMoney(m_trade, m_moneyBox->value(), pFrom, pTarget);
+
+ break;
+ }
+}
+
+void TradeDisplay::reject()
+{
+ emit reject(m_trade);
+}
+
+void TradeDisplay::accept()
+{
+ emit accept(m_trade);
+}
+
+void TradeDisplay::contextMenu(KListView *, QListViewItem *i, const QPoint& p)
+{
+ m_contextTradeItem = m_componentRevMap[(KListViewItem *)(i)];
+
+ KPopupMenu *rmbMenu = new KPopupMenu(this);
+// rmbMenu->insertTitle( ... );
+ rmbMenu->insertItem(i18n("Remove From Trade"), 0);
+
+ connect(rmbMenu, SIGNAL(activated(int)), this, SLOT(contextMenuClicked(int)));
+ rmbMenu->exec(p);
+}
+
+void TradeDisplay::contextMenuClicked(int)
+{
+ if (!m_contextTradeItem)
+ return;
+
+ if (TradeEstate *tradeEstate = dynamic_cast<TradeEstate*>(m_contextTradeItem))
+ emit updateEstate(m_trade, tradeEstate->estate(), 0);
+ else if (TradeMoney *tradeMoney = dynamic_cast<TradeMoney*>(m_contextTradeItem))
+ emit updateMoney(m_trade, 0, tradeMoney->from(), tradeMoney->to());
+
+ m_contextTradeItem = 0;
+}
diff --git a/atlantik/libatlantikui/trade_widget.h b/atlantik/libatlantikui/trade_widget.h
new file mode 100644
index 00000000..642cc919
--- /dev/null
+++ b/atlantik/libatlantikui/trade_widget.h
@@ -0,0 +1,98 @@
+// Copyright (c) 2002 Rob Kaper <cap@capsi.com>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License version 2.1 as published by the Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; see the file COPYING.LIB. If not, write to
+// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+#ifndef TRADEWIDGET_H
+#define TRADEWIDGET_H
+
+#include <qwidget.h>
+#include <qmap.h>
+#include "libatlantikui_export.h"
+
+class QHGroupBox;
+class QLabel;
+class QListViewItem;
+class QSpinBox;
+
+class KListView;
+class KListViewItem;
+class KComboBox;
+class KPushButton;
+
+class AtlanticCore;
+class Player;
+class Trade;
+class TradeItem;
+
+class LIBATLANTIKUI_EXPORT TradeDisplay : public QWidget
+{
+Q_OBJECT
+
+public:
+ TradeDisplay(Trade *trade, AtlanticCore *atlanticCore, QWidget *parent=0, const char *name = 0);
+
+ Trade *trade() { return mTrade; }
+
+protected:
+ void closeEvent(QCloseEvent *e);
+
+private slots:
+ void tradeItemAdded(TradeItem *);
+ void tradeItemRemoved(TradeItem *);
+ void tradeItemChanged(TradeItem *);
+ void tradeChanged();
+ void playerChanged(Player *player);
+ void tradeRejected(Player *);
+
+ void setTypeCombo(int);
+ void setEstateCombo(int);
+ void setCombos(QListViewItem *i);
+
+ void updateComponent();
+ void reject();
+ void accept();
+
+ void contextMenu(KListView *l, QListViewItem *i, const QPoint& p);
+ void contextMenuClicked(int item);
+
+signals:
+ void updateEstate(Trade *trade, Estate *estate, Player *to);
+ void updateMoney(Trade *trade, unsigned int money, Player *from, Player *to);
+ void reject(Trade *trade);
+ void accept(Trade *trade);
+
+private:
+ QHGroupBox *m_updateComponentBox;
+ QLabel *m_status, *m_fromLabel, *m_toLabel;
+ QSpinBox *m_moneyBox;
+
+ KComboBox *m_editTypeCombo, *m_playerFromCombo, *m_playerTargetCombo, *m_estateCombo;
+ KListView *m_componentList;
+ KPushButton *m_updateButton, *m_rejectButton, *m_acceptButton;
+
+ AtlanticCore *m_atlanticCore;
+ Trade *mTrade, *m_trade;
+ TradeItem *m_contextTradeItem;
+
+ // TODO: Wouldn't QPair make more sense here?
+ QMap<TradeItem *, KListViewItem *> m_componentMap;
+ QMap<KListViewItem *, TradeItem *> m_componentRevMap;
+ QMap<int, Estate *> m_estateMap;
+ QMap<Estate *, int> m_estateRevMap;
+ QMap<int, Player *> m_playerFromMap, m_playerTargetMap;
+ QMap<Player *, int> m_playerFromRevMap, m_playerTargetRevMap;
+};
+
+#endif