diff options
Diffstat (limited to 'src/gui/setup_players.cpp')
-rw-r--r-- | src/gui/setup_players.cpp | 342 |
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); +} |