summaryrefslogtreecommitdiff
path: root/src/gui/setup_players.cpp
diff options
context:
space:
mode:
authorBjørn Lindeijer <bjorn@lindeijer.nl>2008-05-14 18:57:32 +0000
committerBjørn Lindeijer <bjorn@lindeijer.nl>2008-05-14 18:57:32 +0000
commit2d648c5dc29a1ceae154194c23c799c7076894b4 (patch)
treef6c31a30260b80713257be211b139263b3291098 /src/gui/setup_players.cpp
parent41906acb990895831e3b2c39102f41c9b580ae10 (diff)
downloadmana-client-2d648c5dc29a1ceae154194c23c799c7076894b4.tar.gz
mana-client-2d648c5dc29a1ceae154194c23c799c7076894b4.tar.bz2
mana-client-2d648c5dc29a1ceae154194c23c799c7076894b4.tar.xz
mana-client-2d648c5dc29a1ceae154194c23c799c7076894b4.zip
Added ability to define friends, players you want to ignore or disregard and
configure whether trading is allowed. Based on new popup code, configuration improvements to store hierarchical data and a table model.
Diffstat (limited to 'src/gui/setup_players.cpp')
-rw-r--r--src/gui/setup_players.cpp342
1 files changed, 342 insertions, 0 deletions
diff --git a/src/gui/setup_players.cpp b/src/gui/setup_players.cpp
new file mode 100644
index 00000000..16c916b4
--- /dev/null
+++ b/src/gui/setup_players.cpp
@@ -0,0 +1,342 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "setup_players.h"
+
+#include <vector>
+#include <guichan/widgets/label.hpp>
+#include "popup_box.h"
+#include "button.h"
+
+#include "checkbox.h"
+#include "ok_dialog.h"
+
+#include "../player_relations.h"
+#include "../configuration.h"
+#include "../log.h"
+#include "../sound.h"
+
+#define COLUMNS_NR 2 // name plus listbox
+#define NAME_COLUMN 0
+#define RELATION_CHOICE_COLUMN 1
+
+#define ROW_HEIGHT 12
+// The following column widths really shouldn't be hardcoded but should scale with the size of the widget... except
+// that, right now, the widget doesn't exactly scale either.
+#define NAME_COLUMN_WIDTH 120
+#define RELATION_CHOICE_COLUMN_WIDTH 80
+
+#define WIDGET_AT(row, column) (((row) * COLUMNS_NR) + column)
+
+static std::string table_titles[COLUMNS_NR] = {"name", "relation"};
+
+static const std::string RELATION_NAMES[PlayerRelation::RELATIONS_NR] = {
+ "neutral", "friend", "disregarded", "ignored"
+};
+
+class PlayerRelationListModel : public gcn::ListModel
+{
+public:
+ virtual ~PlayerRelationListModel(void) { }
+
+ virtual int getNumberOfElements(void)
+ {
+ return PlayerRelation::RELATIONS_NR;
+ }
+
+ virtual std::string getElementAt(int i)
+ {
+ if (i >= getNumberOfElements() || i < 0)
+ return "";
+ return RELATION_NAMES[i];
+ }
+};
+
+class PlayerTableModel : public TableModel
+{
+public:
+ PlayerTableModel(void) :
+ mPlayers(NULL)
+ {
+ playerRelationsUpdated();
+ }
+
+ virtual ~PlayerTableModel(void)
+ {
+ freeWidgets();
+ if (mPlayers)
+ delete mPlayers;
+ }
+
+ virtual int getRows(void)
+ {
+ return mPlayers->size();
+ }
+
+ virtual int getColumns(void)
+ {
+ return COLUMNS_NR;
+ }
+
+ virtual int getRowHeight(void)
+ {
+ return ROW_HEIGHT;
+ }
+
+ virtual int getColumnWidth(int index)
+ {
+ if (index == NAME_COLUMN)
+ return NAME_COLUMN_WIDTH;
+ else
+ return RELATION_CHOICE_COLUMN_WIDTH;
+ }
+
+ virtual void playerRelationsUpdated(void)
+ {
+ signalBeforeUpdate();
+
+ freeWidgets();
+ std::vector<std::string> *player_names = player_relations.getPlayers();
+ if (mPlayers)
+ delete mPlayers;
+ mPlayers = player_names;
+
+ // set up widgets
+ for (unsigned int r = 0; r < player_names->size(); ++r) {
+ std::string name = (*player_names)[r];
+ gcn::Widget *widget = new gcn::Label(name);
+ mWidgets.push_back(widget);
+
+ PopupBox *choicebox = new PopupBox(new PlayerRelationListModel());
+ choicebox->setSelected(player_relations.getRelation(name));
+ mWidgets.push_back(choicebox);
+ }
+
+ signalAfterUpdate();
+ }
+
+ virtual void updateModelInRow(int row)
+ {
+ PopupBox *choicebox = dynamic_cast<PopupBox *>(getElementAt(row, RELATION_CHOICE_COLUMN));
+ player_relations.setRelation(getPlayerAt(row),
+ static_cast<PlayerRelation::relation>(choicebox->getSelected()));
+ }
+
+
+ virtual gcn::Widget *getElementAt(int row, int column)
+ {
+ return mWidgets[WIDGET_AT(row, column)];
+ }
+
+ virtual void freeWidgets(void)
+ {
+ if (mPlayers)
+ delete mPlayers;
+ mPlayers = NULL;
+
+ for (std::vector<gcn::Widget *>::const_iterator it = mWidgets.begin(); it != mWidgets.end(); it++) {
+ delete *it;
+ }
+
+ mWidgets.clear();
+ }
+
+ std::string getPlayerAt(int index)
+ {
+ return (*mPlayers)[index];
+ }
+
+protected:
+ std::vector<std::string> *mPlayers;
+ std::vector<gcn::Widget *> mWidgets;
+};
+
+/**
+ * Class for choosing one of the various `what to do when ignoring a player' options
+ */
+class IgnoreChoicesListModel : public gcn::ListModel
+{
+public:
+ virtual ~IgnoreChoicesListModel(void) { }
+
+ virtual int getNumberOfElements(void)
+ {
+ return player_relations.getPlayerIgnoreStrategies()->size();
+ }
+
+ virtual std::string getElementAt(int i)
+ {
+ if (i >= getNumberOfElements()) {
+ return "???";
+ }
+ return (*player_relations.getPlayerIgnoreStrategies())[i]->mDescription;
+ }
+};
+
+#define ACTION_DELETE "delete"
+#define ACTION_TABLE "table"
+#define ACTION_STRATEGY "strategy"
+
+Setup_Players::Setup_Players():
+ mPlayerTableTitleModel(new StaticTableModel(1, COLUMNS_NR)),
+ mPlayerTableModel(new PlayerTableModel()),
+ mPlayerTable(new GuiTable(mPlayerTableModel)),
+ mPlayerTitleTable(new GuiTable(mPlayerTableTitleModel)),
+ mPlayerScrollArea(new ScrollArea(mPlayerTable)),
+ mPersistIgnores(new CheckBox("save player list", player_relations.getPersistIgnores())),
+ mDefaultTrading(new CheckBox("allow trading", player_relations.getDefault() & PlayerRelation::TRADE)),
+ mDefaultWhisper(new CheckBox("allow whispers", player_relations.getDefault() & PlayerRelation:: WHISPER)),
+ mDeleteButton(new Button("Delete", ACTION_DELETE, this)),
+ mIgnoreActionChoicesBox(new PopupBox(new IgnoreChoicesListModel()))
+{
+ setOpaque(false);
+
+ int table_width = NAME_COLUMN_WIDTH + RELATION_CHOICE_COLUMN_WIDTH;
+ mPlayerTableTitleModel->fixColumnWidth(NAME_COLUMN, NAME_COLUMN_WIDTH);
+ mPlayerTableTitleModel->fixColumnWidth(RELATION_CHOICE_COLUMN, RELATION_CHOICE_COLUMN_WIDTH);
+ mPlayerTitleTable->setDimension(gcn::Rectangle(10, 10, table_width, 10));
+ mPlayerTitleTable->setBackgroundColor(gcn::Color(0xbf, 0xbf, 0xbf));
+ for (int i = 0; i < COLUMNS_NR; i++)
+ mPlayerTableTitleModel->set(0, i, new gcn::Label(table_titles[i]));
+ mPlayerTitleTable->setLinewiseSelection(true);
+
+ mPlayerScrollArea->setDimension(gcn::Rectangle(10, 25, table_width + COLUMNS_NR, 90));
+ mPlayerScrollArea->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
+ mPlayerTable->setActionEventId(ACTION_TABLE);
+ mPlayerTable->setLinewiseSelection(true);
+ mPlayerTable->addActionListener(this);
+
+ mDeleteButton->setPosition(10, 118);
+
+ gcn::Label *ignore_action_label = new gcn::Label("When ignoring:");
+
+ ignore_action_label->setPosition(80, 118);
+ mIgnoreActionChoicesBox->setDimension(gcn::Rectangle(80, 132, 120, 12));
+ mIgnoreActionChoicesBox->setActionEventId(ACTION_STRATEGY);
+ mIgnoreActionChoicesBox->addActionListener(this);
+ int ignore_strategy_index = 0; // safe default
+ if (player_relations.getPlayerIgnoreStrategy()) {
+ ignore_strategy_index = player_relations.getPlayerIgnoreStrategyIndex(
+ player_relations.getPlayerIgnoreStrategy()->mShortName);
+ if (ignore_strategy_index < 0)
+ ignore_strategy_index = 0;
+ }
+ mIgnoreActionChoicesBox->setSelected(ignore_strategy_index);
+ mIgnoreActionChoicesBox->adjustHeight();
+
+ mPersistIgnores->setPosition(80, 148);
+ mDefaultTrading->setPosition(80, 160);
+ mDefaultWhisper->setPosition(80, 172);
+
+ reset();
+
+ add(ignore_action_label);
+ add(mDefaultTrading);
+ add(mDefaultWhisper);
+ add(mIgnoreActionChoicesBox);
+ add(mDeleteButton);
+ add(mPlayerScrollArea);
+ add(mPlayerTitleTable);
+ add(mPersistIgnores);
+
+ player_relations.addListener(this);
+}
+
+Setup_Players::~Setup_Players(void)
+{
+ player_relations.removeListener(this);
+}
+
+
+void
+Setup_Players::reset()
+{
+ // We now have to search through the list of ignore choices to find the current
+ // selection. We could use an index into the table of config options in
+ // player_relations instead of strategies to sidestep this.
+ int selection = 0;
+ for (unsigned int i = 0; i < player_relations.getPlayerIgnoreStrategies()->size(); ++i)
+ if ((*player_relations.getPlayerIgnoreStrategies())[i] ==
+ player_relations.getPlayerIgnoreStrategy()) {
+
+ selection = i;
+ break;
+ }
+
+ mIgnoreActionChoicesBox->setSelected(selection);
+}
+
+void
+Setup_Players::apply()
+{
+ player_relations.setPersistIgnores(mPersistIgnores->isSelected());
+ player_relations.store();
+
+ unsigned int old_default_relations =
+ player_relations.getDefault() & ~(PlayerRelation::TRADE | PlayerRelation::WHISPER);
+ player_relations.setDefault(old_default_relations
+ | (mDefaultTrading->isSelected()? PlayerRelation::TRADE : 0)
+ | (mDefaultWhisper->isSelected()? PlayerRelation::WHISPER : 0));
+}
+
+void
+Setup_Players::cancel()
+{
+}
+
+void
+Setup_Players::action(const gcn::ActionEvent &event)
+{
+ if (event.getId() == ACTION_TABLE) {
+ // temporarily eliminate ourselves: we are fully aware of this change, so there is no
+ // need for asynchronous updates. (In fact, thouse might destroy the widet that
+ // triggered them, which would be rather embarrassing.)
+ player_relations.removeListener(this);
+
+ int row = mPlayerTable->getSelectedRow();
+ if (row >= 0)
+ mPlayerTableModel->updateModelInRow(row);
+
+ player_relations.addListener(this);
+
+ } else if (event.getId() == ACTION_DELETE) {
+ std::string name = mPlayerTableModel->getPlayerAt(mPlayerTable->getSelectedRow());
+
+ player_relations.removePlayer(name);
+
+ } else if (event.getId() == ACTION_STRATEGY) {
+ PlayerIgnoreStrategy *s =
+ (*player_relations.getPlayerIgnoreStrategies())[
+ mIgnoreActionChoicesBox->getSelected()];
+
+ player_relations.setPlayerIgnoreStrategy(s);
+ }
+}
+
+void
+Setup_Players::updatedPlayer(const std::string &name)
+{
+ mPlayerTableModel->playerRelationsUpdated();
+ mDefaultTrading->setSelected(player_relations.getDefault() & PlayerRelation::TRADE);
+ mDefaultWhisper->setSelected(player_relations.getDefault() & PlayerRelation::WHISPER);
+}