diff options
author | Andrei Karas <akaras@inbox.ru> | 2013-09-30 15:01:42 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2013-09-30 15:01:42 +0300 |
commit | 64781090e80fa93a43ce37f0705bbb1cf22ed8bf (patch) | |
tree | 6932ff7f29b4a1e1fe2f3834592587c33d7c4651 /src/gui/popups | |
parent | 25d77892d72d455f8a89372687db45aefbc61cec (diff) | |
download | manaverse-64781090e80fa93a43ce37f0705bbb1cf22ed8bf.tar.gz manaverse-64781090e80fa93a43ce37f0705bbb1cf22ed8bf.tar.bz2 manaverse-64781090e80fa93a43ce37f0705bbb1cf22ed8bf.tar.xz manaverse-64781090e80fa93a43ce37f0705bbb1cf22ed8bf.zip |
move popups into popups directory.
Diffstat (limited to 'src/gui/popups')
-rw-r--r-- | src/gui/popups/beingpopup.cpp | 211 | ||||
-rw-r--r-- | src/gui/popups/beingpopup.h | 65 | ||||
-rw-r--r-- | src/gui/popups/itempopup.cpp | 267 | ||||
-rw-r--r-- | src/gui/popups/itempopup.h | 76 | ||||
-rw-r--r-- | src/gui/popups/popupmenu.cpp | 2914 | ||||
-rw-r--r-- | src/gui/popups/popupmenu.h | 241 | ||||
-rw-r--r-- | src/gui/popups/speechbubble.cpp | 97 | ||||
-rw-r--r-- | src/gui/popups/speechbubble.h | 64 | ||||
-rw-r--r-- | src/gui/popups/spellpopup.cpp | 116 | ||||
-rw-r--r-- | src/gui/popups/spellpopup.h | 69 | ||||
-rw-r--r-- | src/gui/popups/statuspopup.cpp | 169 | ||||
-rw-r--r-- | src/gui/popups/statuspopup.h | 69 | ||||
-rw-r--r-- | src/gui/popups/textpopup.cpp | 105 | ||||
-rw-r--r-- | src/gui/popups/textpopup.h | 79 |
14 files changed, 4542 insertions, 0 deletions
diff --git a/src/gui/popups/beingpopup.cpp b/src/gui/popups/beingpopup.cpp new file mode 100644 index 000000000..ae16d8eb2 --- /dev/null +++ b/src/gui/popups/beingpopup.cpp @@ -0,0 +1,211 @@ +/* + * The ManaPlus Client + * Copyright (C) 2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gui/popups/beingpopup.h" + +#include "being/being.h" +#include "being/playerrelations.h" + +#include "gui/gui.h" +#include "gui/sdlfont.h" + +#include "gui/widgets/label.h" + +#include "utils/gettext.h" +#include "utils/stringutils.h" + +#include <guichan/font.hpp> + +#include "debug.h" + +BeingPopup::BeingPopup() : + Popup("BeingPopup", "beingpopup.xml"), + mBeingName(new Label(this, "A")), + mBeingParty(new Label(this, "A")), + mBeingGuild(new Label(this, "A")), + mBeingRank(new Label(this, "A")), + mBeingComment(new Label(this, "A")) +{ + // Being Name + mBeingName->setFont(boldFont); + mBeingName->setPosition(0, 0); + + const int fontHeight = mBeingName->getHeight(); + + // Being's party + mBeingParty->setPosition(0, fontHeight); + // Being's party + mBeingGuild->setPosition(0, 2 * fontHeight); + mBeingRank->setPosition(0, 3 * fontHeight); + mBeingComment->setPosition(0, 4 * fontHeight); + + mBeingParty->setForegroundColorAll(getThemeColor(Theme::POPUP), + getThemeColor(Theme::POPUP_OUTLINE)); + mBeingGuild->setForegroundColorAll(getThemeColor(Theme::POPUP), + getThemeColor(Theme::POPUP_OUTLINE)); + mBeingRank->setForegroundColorAll(getThemeColor(Theme::POPUP), + getThemeColor(Theme::POPUP_OUTLINE)); + mBeingComment->setForegroundColorAll(getThemeColor(Theme::POPUP), + getThemeColor(Theme::POPUP_OUTLINE)); + + add(mBeingName); + add(mBeingParty); + add(mBeingGuild); + add(mBeingRank); + add(mBeingComment); +} + +BeingPopup::~BeingPopup() +{ +} + +void BeingPopup::show(const int x, const int y, Being *const b) +{ + if (!b) + { + setVisible(false); + return; + } + + Label *label1 = mBeingParty; + Label *label2 = mBeingGuild; + Label *label3 = mBeingRank; + Label *label4 = mBeingComment; + + b->updateComment(); + + if (b->getType() == Being::NPC && b->getComment().empty()) + { + setVisible(false); + return; + } + + mBeingName->setCaption(b->getName() + b->getGenderSignWithSpace()); + if (gui) + { + if (player_relations.isGoodName(b)) + mBeingName->setFont(boldFont); + else + mBeingName->setFont(gui->getSecureFont()); + } + if (b->isAdvanced()) + { + mBeingName->setForegroundColorAll(getThemeColor( + Theme::PLAYER_ADVANCED), getThemeColor( + Theme::PLAYER_ADVANCED_OUTLINE)); + } + else + { + mBeingName->setForegroundColorAll(getThemeColor(Theme::POPUP), + getThemeColor(Theme::POPUP_OUTLINE)); + } + + mBeingName->adjustSize(); + label1->setCaption(""); + label2->setCaption(""); + label3->setCaption(""); + label4->setCaption(""); + + if (!(b->getPartyName().empty())) + { + // TRANSLATORS: being popup label + label1->setCaption(strprintf(_("Party: %s"), + b->getPartyName().c_str())); + label1->adjustSize(); + } + else + { + label4 = label3; + label3 = label2; + label2 = label1; + label1 = nullptr; + } + + if (!(b->getGuildName().empty())) + { + // TRANSLATORS: being popup label + label2->setCaption(strprintf(_("Guild: %s"), + b->getGuildName().c_str())); + label2->adjustSize(); + } + else + { + label4 = label3; + label3 = label2; + label2 = nullptr; + } + + if (b->getPvpRank() > 0) + { + // TRANSLATORS: being popup label + label3->setCaption(strprintf(_("Pvp rank: %u"), b->getPvpRank())); + label3->adjustSize(); + } + else + { + label4 = label3; + label3 = nullptr; + } + + if (!b->getComment().empty()) + { + // TRANSLATORS: being popup label + label4->setCaption(strprintf(_("Comment: %s"), + b->getComment().c_str())); + label4->adjustSize(); + } + else + { + label4 = nullptr; + } + + int minWidth = mBeingName->getWidth(); + if (label1 && label1->getWidth() > minWidth) + minWidth = label1->getWidth(); + if (label2 && label2->getWidth() > minWidth) + minWidth = label2->getWidth(); + if (label3 && label3->getWidth() > minWidth) + minWidth = label3->getWidth(); + if (label4 && label4->getWidth() > minWidth) + minWidth = label4->getWidth(); + + const int height1 = getFont()->getHeight(); + int height = height1; + if (label1) + height += height1; + if (label2) + height += height1; + if (label3) + height += height1; + if (label4) + height += height1; + + setContentSize(minWidth, height); + position(x, y); + return; +} + +#ifdef USE_PROFILER +void BeingPopup::logic() +{ + logicChildren(); +} +#endif diff --git a/src/gui/popups/beingpopup.h b/src/gui/popups/beingpopup.h new file mode 100644 index 000000000..3ac46d30c --- /dev/null +++ b/src/gui/popups/beingpopup.h @@ -0,0 +1,65 @@ +/* + * The ManaPlus Client + * Copyright (C) 2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GUI_BEINGPOPUP_H +#define GUI_BEINGPOPUP_H + +#include "gui/widgets/popup.h" + +class Being; +class Label; + +/** + * A popup that displays information about a being. + */ +class BeingPopup final : public Popup +{ + public: + /** + * Constructor. Initializes the being popup. + */ + BeingPopup(); + + A_DELETE_COPY(BeingPopup) + + /** + * Destructor. Cleans up the being popup on deletion. + */ + ~BeingPopup(); + + /** + * Sets the info to be displayed given a particular player. + */ + void show(const int x, const int y, Being *const b); + +#ifdef USE_PROFILER + void logic(); +#endif + + private: + Label *mBeingName; + Label *mBeingParty; + Label *mBeingGuild; + Label *mBeingRank; + Label *mBeingComment; +}; + +#endif // GUI_BEINGPOPUP_H diff --git a/src/gui/popups/itempopup.cpp b/src/gui/popups/itempopup.cpp new file mode 100644 index 000000000..63fe3628c --- /dev/null +++ b/src/gui/popups/itempopup.cpp @@ -0,0 +1,267 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008 The Legend of Mazzeroth Development Team + * Copyright (C) 2008-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gui/popups/itempopup.h" + +#include "client.h" +#include "configuration.h" +#include "item.h" +#include "units.h" + +#include "gui/gui.h" +#include "gui/sdlfont.h" + +#include "gui/widgets/icon.h" +#include "gui/widgets/label.h" +#include "gui/widgets/textbox.h" + +#include "utils/gettext.h" + +#include "resources/image.h" +#include "resources/resourcemanager.h" + +#include <guichan/font.hpp> + +#include "debug.h" + +ItemPopup::ItemPopup() : + Popup("ItemPopup", "itempopup.xml"), + mItemName(new Label(this)), + mItemDesc(new TextBox(this)), + mItemEffect(new TextBox(this)), + mItemWeight(new TextBox(this)), + mItemType(ITEM_UNUSABLE), + mIcon(new Icon(this, nullptr)), + mLastName(), + mLastColor(1) +{ + // Item Name + mItemName->setFont(boldFont); + mItemName->setPosition(0, 0); + + const int fontHeight = getFont()->getHeight(); + + // Item Description + mItemDesc->setEditable(false); + mItemDesc->setPosition(0, fontHeight); + mItemDesc->setForegroundColorAll(getThemeColor(Theme::POPUP), + getThemeColor(Theme::POPUP_OUTLINE)); + + // Item Effect + mItemEffect->setEditable(false); + mItemEffect->setPosition(0, 2 * fontHeight); + mItemEffect->setForegroundColorAll(getThemeColor(Theme::POPUP), + getThemeColor(Theme::POPUP_OUTLINE)); + + // Item Weight + mItemWeight->setEditable(false); + mItemWeight->setPosition(0, 3 * fontHeight); + mItemWeight->setForegroundColorAll(getThemeColor(Theme::POPUP), + getThemeColor(Theme::POPUP_OUTLINE)); + + add(mItemName); + add(mItemDesc); + add(mItemEffect); + add(mItemWeight); + add(mIcon); + + addMouseListener(this); +} + +ItemPopup::~ItemPopup() +{ + if (mIcon) + { + Image *const image = mIcon->getImage(); + if (image) + image->decRef(); + } +} + +void ItemPopup::setItem(const Item *const item, const bool showImage) +{ + if (!item) + return; + + const ItemInfo &ii = item->getInfo(); + setItem(ii, item->getColor(), showImage, item->getId()); + if (item->getRefine() > 0) + { + mLastName = ii.getName(); + mLastColor = item->getColor(); + if (serverVersion > 0) + { + mItemName->setCaption(strprintf("%s (+%d), %d", ii.getName( + item->getColor()).c_str(), item->getRefine(), ii.getId())); + } + else + { + mItemName->setCaption(strprintf("%s (+%d), %d", + ii.getName().c_str(), item->getRefine(), ii.getId())); + } + mItemName->adjustSize(); + const unsigned minWidth = mItemName->getWidth() + 8; + if (static_cast<unsigned>(getWidth()) < minWidth) + setWidth(minWidth); + } +} + +void ItemPopup::setItem(const ItemInfo &item, const unsigned char color, + const bool showImage, int id) +{ + if (!mIcon || (item.getName() == mLastName && color == mLastColor)) + return; + + if (id == -1) + id = item.getId(); + + int space = 0; + + Image *const oldImage = mIcon->getImage(); + if (oldImage) + oldImage->decRef(); + + if (showImage) + { + ResourceManager *const resman = ResourceManager::getInstance(); + Image *const image = resman->getImage(combineDye2( + paths.getStringValue("itemIcons").append( + item.getDisplay().image), item.getDyeColorsString(color))); + + mIcon->setImage(image); + if (image) + { + mIcon->setPosition(0, 0); + space = mIcon->getWidth(); + } + } + else + { + mIcon->setImage(nullptr); + } + + mItemType = item.getType(); + + mLastName = item.getName(); + mLastColor = color; + + if (serverVersion > 0) + { + mItemName->setCaption(strprintf("%s, %d", + item.getName(color).c_str(), id)); + mItemDesc->setTextWrapped(item.getDescription(color), 196); + } + else + { + mItemName->setCaption(strprintf("%s, %d", + item.getName().c_str(), id)); + mItemDesc->setTextWrapped(item.getDescription(), 196); + } + + mItemName->adjustSize(); + setLabelColor(mItemName, mItemType); + mItemName->setPosition(space, 0); + + mItemEffect->setTextWrapped(item.getEffect(), 196); + // TRANSLATORS: popup label + mItemWeight->setTextWrapped(strprintf(_("Weight: %s"), + Units::formatWeight(item.getWeight()).c_str()), 196); + + int minWidth = mItemName->getWidth() + space; + + if (mItemName->getWidth() + space > minWidth) + minWidth = mItemName->getWidth() + space; + if (mItemDesc->getMinWidth() > minWidth) + minWidth = mItemDesc->getMinWidth(); + if (mItemEffect->getMinWidth() > minWidth) + minWidth = mItemEffect->getMinWidth(); + if (mItemWeight->getMinWidth() > minWidth) + minWidth = mItemWeight->getMinWidth(); + + const int numRowsDesc = mItemDesc->getNumberOfRows(); + const int numRowsEffect = mItemEffect->getNumberOfRows(); + const int numRowsWeight = mItemWeight->getNumberOfRows(); + const int height = getFont()->getHeight(); + + if (item.getEffect().empty()) + { + setContentSize(minWidth, (numRowsDesc + 2 + numRowsWeight) * height); + mItemWeight->setPosition(0, (numRowsDesc + 2) * height); + } + else + { + setContentSize(minWidth, (numRowsDesc + numRowsEffect + 2 + + numRowsWeight) * height); + mItemWeight->setPosition(0, (numRowsDesc + numRowsEffect + 2) + * height); + mItemEffect->setPosition(0, (numRowsDesc + 2) * height); + } + + mItemDesc->setPosition(0, 2 * height); +} + +#define caseSetColor(name1, name2) \ + case name1: \ + { \ + return label->setForegroundColorAll(getThemeColor(name2), \ + getThemeColor(name2##_OUTLINE)); \ + } +void ItemPopup::setLabelColor(Label *label, const ItemType type) const +{ + switch (type) + { + caseSetColor(ITEM_UNUSABLE, Theme::GENERIC) + caseSetColor(ITEM_USABLE, Theme::USABLE) + caseSetColor(ITEM_EQUIPMENT_ONE_HAND_WEAPON, Theme::ONEHAND) + caseSetColor(ITEM_EQUIPMENT_TWO_HANDS_WEAPON, Theme::TWOHAND) + caseSetColor(ITEM_EQUIPMENT_TORSO, Theme::TORSO) + caseSetColor(ITEM_EQUIPMENT_ARMS, Theme::ARMS) + caseSetColor(ITEM_EQUIPMENT_HEAD, Theme::HEAD) + caseSetColor(ITEM_EQUIPMENT_LEGS, Theme::LEGS) + caseSetColor(ITEM_EQUIPMENT_SHIELD, Theme::SHIELD) + caseSetColor(ITEM_EQUIPMENT_RING, Theme::RING) + caseSetColor(ITEM_EQUIPMENT_NECKLACE, Theme::NECKLACE) + caseSetColor(ITEM_EQUIPMENT_FEET, Theme::FEET) + caseSetColor(ITEM_EQUIPMENT_AMMO, Theme::AMMO) + caseSetColor(ITEM_EQUIPMENT_CHARM, Theme::CHARM) + caseSetColor(ITEM_SPRITE_RACE, Theme::UNKNOWN_ITEM) + caseSetColor(ITEM_SPRITE_HAIR, Theme::UNKNOWN_ITEM) + default: + { + return label->setForegroundColorAll(getThemeColor( + Theme::UNKNOWN_ITEM), getThemeColor( + Theme::UNKNOWN_ITEM_OUTLINE)); + } + } +} +#undef caseSetColor + +void ItemPopup::mouseMoved(gcn::MouseEvent &event) +{ + Popup::mouseMoved(event); + + // When the mouse moved on top of the popup, hide it + setVisible(false); + mLastName.clear(); + mLastColor = 1; +} diff --git a/src/gui/popups/itempopup.h b/src/gui/popups/itempopup.h new file mode 100644 index 000000000..d0b313e26 --- /dev/null +++ b/src/gui/popups/itempopup.h @@ -0,0 +1,76 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008 The Legend of Mazzeroth Development Team + * Copyright (C) 2008-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GUI_ITEMPOPUP_H +#define GUI_ITEMPOPUP_H + +#include "gui/widgets/popup.h" + +#include "resources/iteminfo.h" + +class Icon; +class Label; +class TextBox; + +/** + * A popup that displays information about an item. + */ +class ItemPopup final : public Popup +{ + public: + /** + * Constructor. Initializes the item popup. + */ + ItemPopup(); + + A_DELETE_COPY(ItemPopup) + + /** + * Destructor. Cleans up the item popup on deletion. + */ + ~ItemPopup(); + + /** + * Sets the info to be displayed given a particular item. + */ + void setItem(const ItemInfo &item, const unsigned char color, + const bool showImage = false, int id = -1); + + void setItem(const Item *const item, const bool showImage = false); + + void mouseMoved(gcn::MouseEvent &mouseEvent) override; + + private: + Label *mItemName; + TextBox *mItemDesc; + TextBox *mItemEffect; + TextBox *mItemWeight; + ItemType mItemType; + Icon *mIcon; + std::string mLastName; + unsigned char mLastColor; + + void setLabelColor(Label *label, const ItemType type) const; +}; + +#endif // GUI_ITEMPOPUP_H diff --git a/src/gui/popups/popupmenu.cpp b/src/gui/popups/popupmenu.cpp new file mode 100644 index 000000000..6771e7e3e --- /dev/null +++ b/src/gui/popups/popupmenu.cpp @@ -0,0 +1,2914 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gui/popups/popupmenu.h" + +#include "actorspritemanager.h" +#include "commandhandler.h" +#include "configuration.h" +#include "dropshortcut.h" +#include "game.h" +#include "guild.h" +#include "guildmanager.h" +#include "item.h" +#include "maplayer.h" +#include "party.h" +#include "spellmanager.h" + +#include "being/localplayer.h" +#include "being/playerinfo.h" +#include "being/playerrelations.h" + +#include "input/inputmanager.h" + +#include "gui/windows/chatwindow.h" +#include "gui/windows/equipmentwindow.h" +#include "gui/windows/inventorywindow.h" +#include "gui/windows/itemamountwindow.h" +#include "gui/windows/ministatuswindow.h" +#include "gui/windows/npcdialog.h" +#include "gui/windows/outfitwindow.h" +#include "gui/windows/skilldialog.h" +#include "gui/windows/socialwindow.h" +#include "gui/windows/textcommandeditor.h" +#include "gui/windows/textdialog.h" +#include "gui/windows/tradewindow.h" +#include "gui/windowmenu.h" + +#include "gui/viewport.h" + +#include "gui/widgets/browserbox.h" +#include "gui/widgets/chattab.h" +#include "gui/widgets/progressbar.h" +#include "gui/widgets/scrollarea.h" +#include "gui/widgets/textfield.h" +#include "gui/widgets/whispertab.h" + +#include "net/adminhandler.h" +#include "net/beinghandler.h" +#include "net/buysellhandler.h" +#include "net/guildhandler.h" +#include "net/inventoryhandler.h" +#include "net/net.h" +#include "net/npchandler.h" +#include "net/partyhandler.h" +#include "net/tradehandler.h" + +#include "resources/iteminfo.h" + +#include "utils/copynpaste.h" +#include "utils/gettext.h" +#include "utils/process.h" + +#include <guichan/listmodel.hpp> + +#include "debug.h" + +extern int serverVersion; + +std::string tradePartnerName; + +PopupMenu::PopupMenu() : + Popup("PopupMenu", "popupmenu.xml"), + mBrowserBox(new BrowserBox(this)), + mScrollArea(nullptr), + mBeingId(0), + mFloorItemId(0), + mItem(nullptr), + mItemId(0), + mItemColor(1), + mMapItem(nullptr), + mTab(nullptr), + mSpell(nullptr), + mWindow(nullptr), + mRenameListener(), + mPlayerListener(), + mDialog(nullptr), + mButton(nullptr), + mNick(), + mTextField(nullptr), + mType(static_cast<int>(Being::UNKNOWN)), + mX(0), + mY(0) +{ + mBrowserBox->setHighlightMode(BrowserBox::BACKGROUND); + mBrowserBox->setOpaque(false); + mBrowserBox->setLinkHandler(this); + mRenameListener.setMapItem(nullptr); + mRenameListener.setDialog(nullptr); + mPlayerListener.setNick(""); + mPlayerListener.setDialog(nullptr); + mPlayerListener.setType(static_cast<int>(Being::UNKNOWN)); + mScrollArea = new ScrollArea(mBrowserBox, false); + mScrollArea->setVerticalScrollPolicy(ScrollArea::SHOW_AUTO); + add(mScrollArea); +} + +void PopupMenu::showPopup(const int x, const int y, const Being *const being) +{ + if (!being || !player_node || !actorSpriteManager) + return; + + mBeingId = being->getId(); + mNick = being->getName(); + mType = static_cast<int>(being->getType()); + mBrowserBox->clearRows(); + mX = x; + mY = y; + + const std::string &name = mNick; + mBrowserBox->addRow(name + being->getGenderSignWithSpace()); + + switch (being->getType()) + { + case ActorSprite::PLAYER: + { + // TRANSLATORS: popup menu item + // TRANSLATORS: trade with player + mBrowserBox->addRow("trade", _("Trade")); + // TRANSLATORS: popup menu item + // TRANSLATORS: trade attack player + mBrowserBox->addRow("attack", _("Attack")); + // TRANSLATORS: popup menu item + // TRANSLATORS: send whisper to player + mBrowserBox->addRow("whisper", _("Whisper")); + addGmCommands(); + mBrowserBox->addRow("##3---"); + + // TRANSLATORS: popup menu item + // TRANSLATORS: heal player + mBrowserBox->addRow("heal", _("Heal")); + mBrowserBox->addRow("##3---"); + + addPlayerRelation(name); + mBrowserBox->addRow("##3---"); + + addFollow(); + addParty(being->getPartyName()); + + const Guild *const guild1 = being->getGuild(); + const Guild *const guild2 = player_node->getGuild(); + if (guild2) + { + if (guild1) + { + if (guild1->getId() == guild2->getId()) + { + mBrowserBox->addRow("guild-kick", + // TRANSLATORS: popup menu item + // TRANSLATORS: kick player from guild + _("Kick from guild")); + if (guild2->getServerGuild()) + { + mBrowserBox->addRow(strprintf( + "@@guild-pos|%s >@@", + // TRANSLATORS: popup menu item + // TRANSLATORS: change player position in guild + _("Change pos in guild"))); + } + } + } + else if (guild2->getMember(mNick)) + { + mBrowserBox->addRow("guild-kick", + // TRANSLATORS: popup menu item + // TRANSLATORS: kick player from guild + _("Kick from guild")); + if (guild2->getServerGuild()) + { + mBrowserBox->addRow(strprintf( + "@@guild-pos|%s >@@", + // TRANSLATORS: popup menu item + // TRANSLATORS: change player position in guild + _("Change pos in guild"))); + } + } + else + { + if (guild2->getServerGuild() + || (guildManager && guildManager->havePower())) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: invite player to guild + mBrowserBox->addRow("guild", _("Invite to guild")); + } + } + } + + // TRANSLATORS: popup menu item + // TRANSLATORS: set player invisible for self by id + mBrowserBox->addRow("nuke", _("Nuke")); + // TRANSLATORS: popup menu item + // TRANSLATORS: move to player location + mBrowserBox->addRow("move", _("Move")); + addPlayerMisc(); + addBuySell(being); + break; + } + + case ActorSprite::NPC: + // NPCs can be talked to (single option, candidate for removal + // unless more options would be added) + // TRANSLATORS: popup menu item + // TRANSLATORS: talk with npc + mBrowserBox->addRow("talk", _("Talk")); + // TRANSLATORS: popup menu item + // TRANSLATORS: buy from npc + mBrowserBox->addRow("buy", _("Buy")); + // TRANSLATORS: popup menu item + // TRANSLATORS: sell to npc + mBrowserBox->addRow("sell", _("Sell")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: move to npc location + mBrowserBox->addRow("move", _("Move")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add comment to npc + mBrowserBox->addRow("addcomment", _("Add comment")); + break; + + case ActorSprite::MONSTER: + { + // Monsters can be attacked + // TRANSLATORS: popup menu item + // TRANSLATORS: attack monster + mBrowserBox->addRow("attack", _("Attack")); + + if (config.getBoolValue("enableAttackFilter")) + { + mBrowserBox->addRow("##3---"); + if (actorSpriteManager->isInAttackList(name) + || actorSpriteManager->isInIgnoreAttackList(name) + || actorSpriteManager->isInPriorityAttackList(name)) + { + mBrowserBox->addRow("remove attack", + // TRANSLATORS: remove monster from attack list + // TRANSLATORS: popup menu item + _("Remove from attack list")); + } + else + { + mBrowserBox->addRow("add attack priority", + // TRANSLATORS: popup menu item + // TRANSLATORS: add monster to priotiry attack list + _("Add to priority attack list")); + mBrowserBox->addRow("add attack", + // TRANSLATORS: popup menu item + // TRANSLATORS: add monster to attack list + _("Add to attack list")); + mBrowserBox->addRow("add attack ignore", + // TRANSLATORS: popup menu item + // TRANSLATORS: add monster to ignore list + _("Add to ignore list")); + } + } + break; + } + + case ActorSprite::AVATAR: + case ActorSprite::UNKNOWN: + case ActorSprite::FLOOR_ITEM: + case ActorSprite::PORTAL: + case ActorSprite::PET: + default: + /* Other beings aren't interesting... */ + return; + } + // TRANSLATORS: popup menu item + // TRANSLATORS: add being name to chat + mBrowserBox->addRow("name", _("Add name to chat")); + mBrowserBox->addRow("##3---"); + + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showPopup(const int x, const int y, + std::vector<ActorSprite*> &beings) +{ + mX = x; + mY = y; + mBrowserBox->clearRows(); + // TRANSLATORS: popup menu header + mBrowserBox->addRow(_("Players")); + FOR_EACH (std::vector<ActorSprite*>::const_iterator, it, beings) + { + const Being *const being = dynamic_cast<Being*>(*it); + const ActorSprite *const actor = *it; + if (being && !being->getName().empty()) + { + mBrowserBox->addRow(strprintf("@@player_%u|%s >@@", + static_cast<unsigned>(being->getId()), (being->getName() + + being->getGenderSignWithSpace()).c_str())); + } + else if (actor->getType() == ActorSprite::FLOOR_ITEM) + { + const FloorItem *const floorItem + = static_cast<const FloorItem*>(actor); + mBrowserBox->addRow(strprintf("@@flooritem_%u|%s >@@", + static_cast<unsigned>(actor->getId()), + floorItem->getName().c_str())); + } + } + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + showPopup(x, y); +} + +void PopupMenu::showPlayerPopup(const int x, const int y, + const std::string &nick) +{ + if (nick.empty() || !player_node) + return; + + mNick = nick; + mBeingId = 0; + mType = static_cast<int>(Being::PLAYER); + mX = x; + mY = y; + mBrowserBox->clearRows(); + + const std::string &name = mNick; + + mBrowserBox->addRow(name); + + // TRANSLATORS: popup menu item + // TRANSLATORS: send whisper to player + mBrowserBox->addRow("whisper", _("Whisper")); + addGmCommands(); + mBrowserBox->addRow("##3---"); + + addPlayerRelation(name); + mBrowserBox->addRow("##3---"); + + addFollow(); + // TRANSLATORS: popup menu item + // TRANSLATORS: add comment to player + mBrowserBox->addRow("addcomment", _("Add comment")); + + if (player_node->isInParty()) + { + const Party *const party = player_node->getParty(); + if (party) + { + const PartyMember *const member = party->getMember(mNick); + if (member) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: kick player from party + mBrowserBox->addRow("kick party", _("Kick from party")); + mBrowserBox->addRow("##3---"); + const PartyMember *const o = party->getMember( + player_node->getName()); + if (o && member->getMap() == o->getMap()) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: move to player position + mBrowserBox->addRow("move", _("Move")); + } + } + } + } + + const Guild *const guild2 = player_node->getGuild(); + if (guild2) + { + if (guild2->getMember(mNick)) + { + if (guild2->getServerGuild() || (guildManager + && guildManager->havePower())) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: kick player from guild + mBrowserBox->addRow("guild-kick", _("Kick from guild")); + } + if (guild2->getServerGuild()) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: change player position in guild + mBrowserBox->addRow(strprintf( + "@@guild-pos|%s >@@", _("Change pos in guild"))); + } + } + else + { + if (guild2->getServerGuild() || (guildManager + && guildManager->havePower())) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: invite player to guild + mBrowserBox->addRow("guild", _("Invite to guild")); + } + } + } + + addBuySellDefault(); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player name to chat + mBrowserBox->addRow("name", _("Add name to chat")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showPopup(const int x, const int y, + const FloorItem *const floorItem) +{ + if (!floorItem) + return; + + mFloorItemId = floorItem->getId(); + mX = x; + mY = y; + mType = static_cast<int>(Being::FLOOR_ITEM); + mBrowserBox->clearRows(); + const std::string name = floorItem->getName(); + mNick = name; + + mBrowserBox->addRow(name); + + if (config.getBoolValue("enablePickupFilter")) + { + if (actorSpriteManager->isInPickupList(name) + || (actorSpriteManager->isInPickupList("") + && !actorSpriteManager->isInIgnorePickupList(name))) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: pickup item from ground + mBrowserBox->addRow("pickup", _("Pick up")); + mBrowserBox->addRow("##3---"); + } + addPickupFilter(name); + } + else + { + // TRANSLATORS: popup menu item + // TRANSLATORS: pickup item from ground + mBrowserBox->addRow("pickup", _("Pick up")); + } + addProtection(); + // TRANSLATORS: popup menu item + // TRANSLATORS: add item name to chat + mBrowserBox->addRow("chat", _("Add to chat")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showPopup(const int x, const int y, MapItem *const mapItem) +{ + if (!mapItem) + return; + + mMapItem = mapItem; + mX = x; + mY = y; + + mBrowserBox->clearRows(); + + // TRANSLATORS: popup menu header + mBrowserBox->addRow(_("Map Item")); + // TRANSLATORS: popup menu item + // TRANSLATORS: rename map item + mBrowserBox->addRow("rename map", _("Rename")); + // TRANSLATORS: popup menu item + // TRANSLATORS: remove map item + mBrowserBox->addRow("remove map", _("Remove")); + + if (player_node && player_node->isGM()) + { + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: warp to map item + mBrowserBox->addRow("warp map", _("Warp")); + } + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showMapPopup(const int x, const int y, + const int x2, const int y2) +{ + mX = x2; + mY = y2; + + mBrowserBox->clearRows(); + + // TRANSLATORS: popup menu header + mBrowserBox->addRow(_("Map Item")); + + if (player_node && player_node->isGM()) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: warp to map item + mBrowserBox->addRow("warp map", _("Warp")); + } + // TRANSLATORS: popup menu item + // TRANSLATORS: move to map item + mBrowserBox->addRow("move", _("Move")); + // TRANSLATORS: popup menu item + // TRANSLATORS: move camera to map item + mBrowserBox->addRow("movecamera", _("Move camera")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showOutfitsPopup(const int x, const int y) +{ + mX = x; + mY = y; + + mBrowserBox->clearRows(); + + // TRANSLATORS: popup menu header + mBrowserBox->addRow(_("Outfits")); + // TRANSLATORS: popup menu item + // TRANSLATORS: clear selected outfit + mBrowserBox->addRow("clear outfit", _("Clear outfit")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showSpellPopup(const int x, const int y, + TextCommand *const cmd) +{ + if (!cmd) + return; + + mBrowserBox->clearRows(); + + mSpell = cmd; + mX = x; + mY = y; + + // TRANSLATORS: popup menu header + mBrowserBox->addRow(_("Spells")); + // TRANSLATORS: popup menu item + // TRANSLATORS: edit selected spell + mBrowserBox->addRow("edit spell", _("Edit spell")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showChatPopup(const int x, const int y, ChatTab *const tab) +{ + if (!tab || !actorSpriteManager || !player_node) + return; + + mTab = tab; + mX = x; + mY = y; + + mBrowserBox->clearRows(); + + if (tab->getType() == static_cast<int>(ChatTab::TAB_WHISPER)) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: close chat tab + mBrowserBox->addRow("chat close", _("Close")); + } + + // TRANSLATORS: popup menu item + // TRANSLATORS: remove all text from chat tab + mBrowserBox->addRow("chat clear", _("Clear")); + mBrowserBox->addRow("##3---"); + + if (tab->getAllowHighlight()) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: disable chat tab highlight + mBrowserBox->addRow("disable highlight", _("Disable highlight")); + } + else + { + // TRANSLATORS: popup menu item + // TRANSLATORS: enable chat tab highlight + mBrowserBox->addRow("enable highlight", _("Enable highlight")); + } + if (tab->getRemoveNames()) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: do not remove player names from chat tab + mBrowserBox->addRow("dont remove name", _("Don't remove name")); + } + else + { + // TRANSLATORS: popup menu item + // TRANSLATORS: remove player names from chat tab + mBrowserBox->addRow("remove name", _("Remove name")); + } + if (tab->getNoAway()) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: enable away messages in chat tab + mBrowserBox->addRow("enable away", _("Enable away")); + } + else + { + // TRANSLATORS: popup menu item + // TRANSLATORS: disable away messages in chat tab + mBrowserBox->addRow("disable away", _("Disable away")); + } + mBrowserBox->addRow("##3---"); + if (tab->getType() == static_cast<int>(ChatTab::TAB_PARTY)) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: enable away messages in chat tab + mBrowserBox->addRow("leave party", _("Leave")); + mBrowserBox->addRow("##3---"); + } + // TRANSLATORS: popup menu item + // TRANSLATORS: copy selected text to clipboard + mBrowserBox->addRow("chat clipboard", _("Copy to clipboard")); + mBrowserBox->addRow("##3---"); + + if (tab->getType() == static_cast<int>(ChatTab::TAB_WHISPER)) + { + const WhisperTab *const wTab = static_cast<WhisperTab*>(tab); + std::string name = wTab->getNick(); + + const Being* const being = actorSpriteManager->findBeingByName( + name, Being::PLAYER); + + if (being) + { + mBeingId = being->getId(); + mNick = being->getName(); + mType = static_cast<int>(being->getType()); + + // TRANSLATORS: popup menu item + // TRANSLATORS: trade with player + mBrowserBox->addRow("trade", _("Trade")); + // TRANSLATORS: popup menu item + // TRANSLATORS: attack player + mBrowserBox->addRow("attack", _("Attack")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: heal player + mBrowserBox->addRow("heal", _("Heal")); + mBrowserBox->addRow("##3---"); + addPlayerRelation(name); + mBrowserBox->addRow("##3---"); + addFollow(); + // TRANSLATORS: popup menu item + // TRANSLATORS: move to player position + mBrowserBox->addRow("move", _("Move")); + addPlayerMisc(); + addBuySell(being); + mBrowserBox->addRow("##3---"); + + if (player_node->isInParty()) + { + const Party *const party = player_node->getParty(); + if (party) + { + if (!party->isMember(wTab->getNick())) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: invite player to party + mBrowserBox->addRow("party", _("Invite to party")); + } + else + { + // TRANSLATORS: popup menu item + // TRANSLATORS: kick player from party + mBrowserBox->addRow("kick party", + _("Kick from party")); + } + mBrowserBox->addRow("##3---"); + } + } + const Guild *const guild1 = being->getGuild(); + const Guild *const guild2 = player_node->getGuild(); + if (guild2) + { + if (guild1) + { + if (guild1->getId() == guild2->getId()) + { + if (guild2->getServerGuild() || (guildManager + && guildManager->havePower())) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: kick player from guild + mBrowserBox->addRow(strprintf( + "@@guild-kick|%s@@", _("Kick from guild"))); + } + if (guild2->getServerGuild()) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: change player position in guild + mBrowserBox->addRow(strprintf("@@guild-pos|%s >@@", + _("Change pos in guild"))); + } + } + } + else + { + if (guild2->getServerGuild() || (guildManager + && guildManager->havePower())) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: invite player to guild + mBrowserBox->addRow("guild", _("Invite to guild")); + } + } + } + } + else + { + mNick = name; + mType = static_cast<int>(Being::PLAYER); + addPlayerRelation(name); + mBrowserBox->addRow("##3---"); + addFollow(); + + if (player_node->isInParty()) + { + const Party *const party = player_node->getParty(); + if (party) + { + const PartyMember *const m = party->getMember(mNick); + if (m) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: move to player location + mBrowserBox->addRow("move", _("Move")); + } + } + } + addPlayerMisc(); + addBuySellDefault(); + mBrowserBox->addRow("##3---"); + } + } + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showChangePos(const int x, const int y) +{ + mBrowserBox->clearRows(); + // TRANSLATORS: popup menu header + mBrowserBox->addRow(_("Change guild position")); + + if (!player_node) + return; + + mX = x; + mY = y; + const Guild *const guild = player_node->getGuild(); + if (guild) + { + const PositionsMap map = guild->getPositions(); + FOR_EACH (PositionsMap::const_iterator, itr, map) + { + mBrowserBox->addRow(strprintf("@@guild-pos-%u|%s@@", + itr->first, itr->second.c_str())); + } + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); + } + else + { + mBeingId = 0; + mFloorItemId = 0; + mItem = nullptr; + mMapItem = nullptr; + mNick.clear(); + mType = static_cast<int>(Being::UNKNOWN); + mX = 0; + mY = 0; + setVisible(false); + } +} + +void PopupMenu::handleLink(const std::string &link, + gcn::MouseEvent *event A_UNUSED) +{ + Being *being = nullptr; + if (actorSpriteManager) + being = actorSpriteManager->findBeing(mBeingId); + + // Talk To action + if (link == "talk" && being && being->canTalk()) + { + being->talkTo(); + } + // Trade action + else if (link == "trade" && being && + being->getType() == ActorSprite::PLAYER) + { + Net::getTradeHandler()->request(being); + tradePartnerName = being->getName(); + if (tradeWindow) + tradeWindow->clear(); + } + else if (link == "buy" && being && mBeingId != 0) + { + if (being->getType() == Being::NPC) + Net::getNpcHandler()->buy(mBeingId); + else if (being->getType() == Being::PLAYER) + Net::getBuySellHandler()->requestSellList(being->getName()); + } + else if (link == "buy" && !mNick.empty()) + { + Net::getBuySellHandler()->requestSellList(mNick); + } + else if (link == "sell" && being && mBeingId != 0) + { + if (being->getType() == Being::NPC) + Net::getNpcHandler()->sell(mBeingId); + else if (being->getType() == Being::PLAYER) + Net::getBuySellHandler()->requestBuyList(being->getName()); + } + else if (link == "sell" && !mNick.empty()) + { + Net::getBuySellHandler()->requestBuyList(mNick); + } + else if (link == "attack" && being) + { + if (player_node) + player_node->attack(being, true); + } + else if (link == "heal" && being && being->getType() != Being::MONSTER) + { + if (actorSpriteManager) + actorSpriteManager->heal(being); + } + else if (link == "unignore" && being && + being->getType() == ActorSprite::PLAYER) + { + player_relations.setRelation(being->getName(), + PlayerRelation::NEUTRAL); + } + else if (link == "unignore" && !mNick.empty()) + { + player_relations.setRelation(mNick, PlayerRelation::NEUTRAL); + } + else if (link == "ignore" && being && + being->getType() == ActorSprite::PLAYER) + { + player_relations.setRelation(being->getName(), + PlayerRelation::IGNORED); + } + else if (link == "ignore" && !mNick.empty()) + { + player_relations.setRelation(mNick, PlayerRelation::IGNORED); + } + + else if (link == "blacklist" && being && + being->getType() == ActorSprite::PLAYER) + { + player_relations.setRelation(being->getName(), + PlayerRelation::BLACKLISTED); + } + else if (link == "blacklist" && !mNick.empty()) + { + player_relations.setRelation(mNick, PlayerRelation::BLACKLISTED); + } + else if (link == "enemy" && being && + being->getType() == ActorSprite::PLAYER) + { + player_relations.setRelation(being->getName(), + PlayerRelation::ENEMY2); + } + else if (link == "enemy" && !mNick.empty()) + { + player_relations.setRelation(mNick, PlayerRelation::ENEMY2); + } + else if (link == "erase" && being && + being->getType() == ActorSprite::PLAYER) + { + player_relations.setRelation(being->getName(), PlayerRelation::ERASED); + being->updateName(); + } + else if (link == "erase" && !mNick.empty()) + { + player_relations.setRelation(mNick, PlayerRelation::ERASED); + } + else if (link == "disregard" && being && + being->getType() == ActorSprite::PLAYER) + { + player_relations.setRelation(being->getName(), + PlayerRelation::DISREGARDED); + } + else if (link == "disregard" && !mNick.empty()) + { + player_relations.setRelation(mNick, PlayerRelation::DISREGARDED); + } + else if (link == "friend" && being && + being->getType() == ActorSprite::PLAYER) + { + player_relations.setRelation(being->getName(), PlayerRelation::FRIEND); + } + else if (link == "friend" && !mNick.empty()) + { + player_relations.setRelation(mNick, PlayerRelation::FRIEND); + } + // Guild action + else if (link == "guild" && !mNick.empty()) + { + if (player_node) + { + const Guild *const guild = player_node->getGuild(); + if (guild) + { + if (guild->getServerGuild()) + Net::getGuildHandler()->invite(guild->getId(), mNick); + else if (guildManager) + guildManager->invite(mNick); + } + } + } + else if (link == "nuke" && being) + { + if (actorSpriteManager) + { + actorSpriteManager->addBlock(static_cast<uint32_t>( + being->getId())); + actorSpriteManager->destroy(being); + } + } + // Follow Player action + else if (link == "follow" && !mNick.empty()) + { + if (player_node) + player_node->setFollow(mNick); + } + else if (link == "imitation" && !mNick.empty()) + { + if (player_node) + player_node->setImitate(mNick); + } + // Pick Up Floor Item action + else if ((link == "pickup") && mFloorItemId) + { + if (player_node && actorSpriteManager) + { + FloorItem *const item = actorSpriteManager->findItem( + mFloorItemId); + if (item) + player_node->pickUp(item); + } + } + else if (link == "use" && mItemId) + { + if (mItemId < SPELL_MIN_ID) + { + const Inventory *const inv = PlayerInfo::getInventory(); + if (inv) + { + const Item *const item = inv->findItem(mItemId, mItemColor); + if (item) + { + if (item->isEquipment()) + { + if (item->isEquipped()) + Net::getInventoryHandler()->unequipItem(item); + else + Net::getInventoryHandler()->equipItem(item); + } + else + { + if (!PlayerInfo::isItemProtected(item->getId())) + Net::getInventoryHandler()->useItem(item); + } + } + } + } + else if (mItemId < SKILL_MIN_ID && spellManager) + { + spellManager->useItem(mItemId); + } + else if (skillDialog) + { + skillDialog->useItem(mItemId); + } + } + else if (link == "chat") + { + if (chatWindow) + { + if (mItem) + { + if (serverVersion > 0) + { + chatWindow->addItemText(mItem->getInfo().getName( + mItem->getColor())); + } + else + { + chatWindow->addItemText(mItem->getInfo().getName()); + } + } + else if (mFloorItemId && actorSpriteManager) + { + const FloorItem *const item = actorSpriteManager->findItem( + mFloorItemId); + + if (item) + { + if (serverVersion > 0) + { + chatWindow->addItemText(item->getInfo().getName( + item->getColor())); + } + else + { + chatWindow->addItemText(item->getInfo().getName()); + } + } + } + } + } + else if (link == "whisper" && !mNick.empty() && chatWindow) + { + if (chatWindow) + { + if (config.getBoolValue("whispertab")) + { + chatWindow->localChatInput("/q " + mNick); + } + else + { + chatWindow->addInputText(std::string("/w \"").append( + mNick).append("\" ")); + } + } + } + else if (link == "move" && !mNick.empty()) + { + if (player_node) + { + if (being) + { + player_node->navigateTo(being->getTileX(), being->getTileY()); + } + else if (player_node->isInParty()) + { + const Party *const party = player_node->getParty(); + if (party) + { + const PartyMember *const m = party->getMember(mNick); + const PartyMember *const o = party->getMember( + player_node->getName()); + if (m && o && m->getMap() == o->getMap()) + player_node->navigateTo(m->getX(), m->getY()); + } + } + } + } + else if (link == "move" && (mX || mY)) + { + if (player_node) + player_node->navigateTo(mX, mY); + } + else if (link == "movecamera" && (mX || mY)) + { + if (viewport) + viewport->moveCameraToPosition(mX * 32, mY * 32); + } + else if (link == "split" && mItem) + { + ItemAmountWindow::showWindow(ItemAmountWindow::ItemSplit, + inventoryWindow, mItem); + } + else if (link == "drop" && mItem) + { + if (!PlayerInfo::isItemProtected(mItem->getId())) + { + ItemAmountWindow::showWindow(ItemAmountWindow::ItemDrop, + inventoryWindow, mItem); + } + } + else if (link == "drop all" && mItem) + { + if (!PlayerInfo::isItemProtected(mItem->getId())) + Net::getInventoryHandler()->dropItem(mItem, mItem->getQuantity()); + } + else if (link == "store" && mItem) + { + ItemAmountWindow::showWindow(ItemAmountWindow::StoreAdd, + inventoryWindow, mItem); + } + else if (link == "store 10" && mItem) + { + int cnt = 10; + if (cnt > mItem->getQuantity()) + cnt = mItem->getQuantity(); + Net::getInventoryHandler()->moveItem2(Inventory::INVENTORY, + mItem->getInvIndex(), cnt, + Inventory::STORAGE); + } + else if (link == "store half" && mItem) + { + Net::getInventoryHandler()->moveItem2(Inventory::INVENTORY, + mItem->getInvIndex(), mItem->getQuantity() / 2, + Inventory::STORAGE); + } + else if (link == "store all-1" && mItem) + { + Net::getInventoryHandler()->moveItem2(Inventory::INVENTORY, + mItem->getInvIndex(), mItem->getQuantity() - 1, + Inventory::STORAGE); + } + else if (link == "store all" && mItem) + { + Net::getInventoryHandler()->moveItem2(Inventory::INVENTORY, + mItem->getInvIndex(), mItem->getQuantity(), + Inventory::STORAGE); + } + else if (link == "addtrade" && mItem) + { + if (!PlayerInfo::isItemProtected(mItem->getId())) + { + ItemAmountWindow::showWindow(ItemAmountWindow::TradeAdd, + tradeWindow, mItem); + } + } + else if (link == "addtrade 10" && mItem) + { + if (tradeWindow && !PlayerInfo::isItemProtected(mItem->getId())) + { + int cnt = 10; + if (cnt > mItem->getQuantity()) + cnt = mItem->getQuantity(); + tradeWindow->tradeItem(mItem, cnt, true); + } + } + else if (link == "addtrade half" && mItem) + { + if (tradeWindow && !PlayerInfo::isItemProtected(mItem->getId())) + tradeWindow->tradeItem(mItem, mItem->getQuantity() / 2, true); + } + else if (link == "addtrade all-1" && mItem) + { + if (tradeWindow && !PlayerInfo::isItemProtected(mItem->getId())) + tradeWindow->tradeItem(mItem, mItem->getQuantity() - 1, true); + } + else if (link == "addtrade all" && mItem) + { + if (tradeWindow && !PlayerInfo::isItemProtected(mItem->getId())) + tradeWindow->tradeItem(mItem, mItem->getQuantity(), true); + } + else if (link == "retrieve" && mItem) + { + ItemAmountWindow::showWindow(ItemAmountWindow::StoreRemove, + mWindow, mItem); + } + else if (link == "retrieve 10" && mItem) + { + int cnt = 10; + if (cnt > mItem->getQuantity()) + cnt = mItem->getQuantity(); + Net::getInventoryHandler()->moveItem2(Inventory::STORAGE, + mItem->getInvIndex(), cnt, + Inventory::INVENTORY); + } + else if (link == "retrieve half" && mItem) + { + Net::getInventoryHandler()->moveItem2(Inventory::STORAGE, + mItem->getInvIndex(), mItem->getQuantity() / 2, + Inventory::INVENTORY); + } + else if (link == "retrieve all-1" && mItem) + { + Net::getInventoryHandler()->moveItem2(Inventory::STORAGE, + mItem->getInvIndex(), mItem->getQuantity() - 1, + Inventory::INVENTORY); + } + else if (link == "retrieve all" && mItem) + { + Net::getInventoryHandler()->moveItem2(Inventory::STORAGE, + mItem->getInvIndex(), mItem->getQuantity(), + Inventory::INVENTORY); + } + else if (link == "protect item" && mItemId) + { + PlayerInfo::protectItem(mItemId); + } + else if (link == "unprotect item" && mItemId) + { + PlayerInfo::unprotectItem(mItemId); + } + else if (link == "party" && being && + being->getType() == ActorSprite::PLAYER) + { + Net::getPartyHandler()->invite(being); + } + else if (link == "kick party" && being + && being->getType() == Being::PLAYER) + { + Net::getPartyHandler()->kick(being); + } + else if (link == "kick party" && !mNick.empty()) + { + if (player_node && player_node->getParty()) + { + const PartyMember *const member = player_node-> + getParty()->getMember(mNick); + if (member) + Net::getPartyHandler()->kick(mNick); + } + } + else if (link == "name" && !mNick.empty()) + { + const std::string &name = mNick; + if (chatWindow) + chatWindow->addInputText(name); + } + else if (link == "admin-kick" && being && + (being->getType() == ActorSprite::PLAYER || + being->getType() == ActorSprite::MONSTER)) + { + Net::getAdminHandler()->kick(being->getId()); + } + else if (link == "chat close" && mTab) + { + if (commandHandler) + commandHandler->invokeCommand("close", "", mTab); + } + else if (link == "leave party" && mTab) + { + Net::getPartyHandler()->leave(); + } + else if (link == "chat clear" && mTab) + { + if (chatWindow) + chatWindow->clearTab(); + } + else if (link == "warp map" && mMapItem) + { + if (Game::instance()) + { + Net::getAdminHandler()->warp(Game::instance()->getCurrentMapName(), + mMapItem->getX(), mMapItem->getY()); + } + } + else if (link == "warp map" && (mX || mY)) + { + if (Game::instance()) + { + Net::getAdminHandler()->warp(Game::instance()->getCurrentMapName(), + mX, mY); + } + } + else if (link == "remove map" && mMapItem) + { + if (viewport) + { + const Map *const map = viewport->getMap(); + if (map) + { + SpecialLayer *const specialLayer = map->getSpecialLayer(); + if (specialLayer) + { + const bool isHome = (mMapItem->getType() + == static_cast<int>(MapItem::HOME)); + const int x = static_cast<const int>(mMapItem->getX()); + const int y = static_cast<const int>(mMapItem->getY()); + specialLayer->setTile(x, y, + static_cast<int>(MapItem::EMPTY)); + if (socialWindow) + socialWindow->removePortal(x, y); + if (isHome && player_node) + { + player_node->removeHome(); + player_node->saveHomes(); + } + } + } + } + } + else if (link == "rename map" && mMapItem) + { + mRenameListener.setMapItem(mMapItem); + // TRANSLATORS: number of chars in string should be near original + mDialog = new TextDialog(_("Rename map sign "), + // TRANSLATORS: number of chars in string should be near original + _("Name: ")); + mRenameListener.setDialog(mDialog); + mDialog->setText(mMapItem->getComment()); + mDialog->setActionEventId("ok"); + mDialog->addActionListener(&mRenameListener); + } + else if (link == "clear drops") + { + if (dropShortcut) + dropShortcut->clear(); + } + else if (link == "edit spell" && mSpell) + { + new TextCommandEditor(mSpell); + } + else if (link == "undress" && being) + { + Net::getBeingHandler()->undress(being); + } + else if (link == "addcomment" && !mNick.empty()) + { + // TRANSLATORS: number of chars in string should be near original + TextDialog *const dialog = new TextDialog( + _("Player comment "), + // TRANSLATORS: number of chars in string should be near original + _("Comment: ")); + mPlayerListener.setDialog(dialog); + mPlayerListener.setNick(mNick); + mPlayerListener.setType(mType); + + if (being) + { + being->updateComment(); + dialog->setText(being->getComment()); + } + else + { + dialog->setText(Being::loadComment(mNick, mType)); + } + dialog->setActionEventId("ok"); + dialog->addActionListener(&mPlayerListener); + } + else if (link == "guild-kick" && !mNick.empty()) + { + if (player_node) + { + const Guild *const guild = player_node->getGuild(); + if (guild) + { + if (guild->getServerGuild()) + Net::getGuildHandler()->kick(guild->getMember(mNick), ""); + else if (guildManager) + guildManager->kick(mNick); + } + } + } + else if (link == "enable highlight" && mTab) + { + if (commandHandler) + commandHandler->invokeCommand(COMMAND_ENABLEHIGHLIGHT, mTab); + } + else if (link == "disable highlight" && mTab) + { + if (commandHandler) + commandHandler->invokeCommand(COMMAND_DISABLEHIGHLIGHT, mTab); + } + else if (link == "dont remove name" && mTab) + { + if (commandHandler) + commandHandler->invokeCommand(COMMAND_DONTREMOVENAME, mTab); + } + else if (link == "remove name" && mTab) + { + if (commandHandler) + commandHandler->invokeCommand(COMMAND_REMOVENAME, mTab); + } + else if (link == "disable away" && mTab) + { + if (commandHandler) + commandHandler->invokeCommand(COMMAND_DISABLEAWAY, mTab); + } + else if (link == "enable away" && mTab) + { + if (commandHandler) + commandHandler->invokeCommand(COMMAND_ENABLEAWAY, mTab); + } + else if (link == "chat clipboard" && mTab) + { + if (chatWindow) + chatWindow->copyToClipboard(mX, mY); + } + else if (link == "npc clipboard" && mBeingId) + { + NpcDialog::copyToClipboard(mBeingId, mX, mY); + } + else if (link == "remove attack" && being) + { + if (actorSpriteManager && being->getType() == Being::MONSTER) + { + actorSpriteManager->removeAttackMob(being->getName()); + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } + else if (link == "add attack" && being) + { + if (actorSpriteManager && being->getType() == Being::MONSTER) + { + actorSpriteManager->addAttackMob(being->getName()); + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } + else if (link == "add attack priority" && being) + { + if (actorSpriteManager && being->getType() == Being::MONSTER) + { + actorSpriteManager->addPriorityAttackMob(being->getName()); + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } + else if (link == "add attack ignore" && being) + { + if (actorSpriteManager && being->getType() == Being::MONSTER) + { + actorSpriteManager->addIgnoreAttackMob(being->getName()); + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } + else if (link == "remove pickup" && !mNick.empty()) + { + if (actorSpriteManager) + { + actorSpriteManager->removePickupItem(mNick); + if (socialWindow) + socialWindow->updatePickupFilter(); + } + } + else if (link == "add pickup" && !mNick.empty()) + { + if (actorSpriteManager) + { + actorSpriteManager->addPickupItem(mNick); + if (socialWindow) + socialWindow->updatePickupFilter(); + } + } + else if (link == "add pickup ignore" && !mNick.empty()) + { + if (actorSpriteManager) + { + actorSpriteManager->addIgnorePickupItem(mNick); + if (socialWindow) + socialWindow->updatePickupFilter(); + } + } + else if (link == "attack moveup") + { + if (actorSpriteManager) + { + const int idx = actorSpriteManager->getAttackMobIndex(mNick); + if (idx > 0) + { + std::list<std::string> mobs + = actorSpriteManager->getAttackMobs(); + std::list<std::string>::iterator it = mobs.begin(); + std::list<std::string>::iterator it2 = mobs.begin(); + while (it != mobs.end()) + { + if (*it == mNick) + { + -- it2; + mobs.splice(it2, mobs, it); + actorSpriteManager->setAttackMobs(mobs); + actorSpriteManager->rebuildAttackMobs(); + break; + } + ++ it; + ++ it2; + } + + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } + } + else if (link == "priority moveup") + { + if (actorSpriteManager) + { + const int idx = actorSpriteManager-> + getPriorityAttackMobIndex(mNick); + if (idx > 0) + { + std::list<std::string> mobs + = actorSpriteManager->getPriorityAttackMobs(); + std::list<std::string>::iterator it = mobs.begin(); + std::list<std::string>::iterator it2 = mobs.begin(); + while (it != mobs.end()) + { + if (*it == mNick) + { + -- it2; + mobs.splice(it2, mobs, it); + actorSpriteManager->setPriorityAttackMobs(mobs); + actorSpriteManager->rebuildPriorityAttackMobs(); + break; + } + ++ it; + ++ it2; + } + + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } + } + else if (link == "attack movedown") + { + if (actorSpriteManager) + { + const int idx = actorSpriteManager->getAttackMobIndex(mNick); + const int size = actorSpriteManager->getAttackMobsSize(); + if (idx + 1 < size) + { + std::list<std::string> mobs + = actorSpriteManager->getAttackMobs(); + std::list<std::string>::iterator it = mobs.begin(); + std::list<std::string>::iterator it2 = mobs.begin(); + while (it != mobs.end()) + { + if (*it == mNick) + { + ++ it2; + if (it2 == mobs.end()) + break; + + mobs.splice(it, mobs, it2); + actorSpriteManager->setAttackMobs(mobs); + actorSpriteManager->rebuildAttackMobs(); + break; + } + ++ it; + ++ it2; + } + + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } + } + else if (link == "priority movedown") + { + if (player_node) + { + const int idx = actorSpriteManager + ->getPriorityAttackMobIndex(mNick); + const int size = actorSpriteManager->getPriorityAttackMobsSize(); + if (idx + 1 < size) + { + std::list<std::string> mobs + = actorSpriteManager->getPriorityAttackMobs(); + std::list<std::string>::iterator it = mobs.begin(); + std::list<std::string>::iterator it2 = mobs.begin(); + while (it != mobs.end()) + { + if (*it == mNick) + { + ++ it2; + if (it2 == mobs.end()) + break; + + mobs.splice(it, mobs, it2); + actorSpriteManager->setPriorityAttackMobs(mobs); + actorSpriteManager->rebuildPriorityAttackMobs(); + break; + } + ++ it; + ++ it2; + } + + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } + } + else if (link == "attack remove") + { + if (actorSpriteManager) + { + if (mNick.empty()) + { + if (actorSpriteManager->isInAttackList(mNick)) + { + actorSpriteManager->removeAttackMob(mNick); + actorSpriteManager->addIgnoreAttackMob(mNick); + } + else + { + actorSpriteManager->removeAttackMob(mNick); + actorSpriteManager->addAttackMob(mNick); + } + } + else + { + actorSpriteManager->removeAttackMob(mNick); + } + if (socialWindow) + socialWindow->updateAttackFilter(); + } + } + else if (link == "pickup remove") + { + if (actorSpriteManager) + { + if (mNick.empty()) + { + if (actorSpriteManager->isInPickupList(mNick)) + { + actorSpriteManager->removePickupItem(mNick); + actorSpriteManager->addIgnorePickupItem(mNick); + } + else + { + actorSpriteManager->removePickupItem(mNick); + actorSpriteManager->addPickupItem(mNick); + } + } + else + { + actorSpriteManager->removePickupItem(mNick); + } + if (socialWindow) + socialWindow->updatePickupFilter(); + } + } + else if (link == "reset yellow") + { + if (player_node) + player_node->resetYellowBar(); + } + else if (link == "bar to chat" && !mNick.empty()) + { + if (chatWindow) + chatWindow->addInputText(mNick); + } + else if (link == "items" && being) + { + if (being == player_node) + { + if (equipmentWindow && !equipmentWindow->isWindowVisible()) + equipmentWindow->setVisible(true); + } + else + { + if (beingEquipmentWindow) + { + beingEquipmentWindow->setBeing(being); + beingEquipmentWindow->setVisible(true); + } + } + } + else if (link == "undress item" && being && mItemId) + { + being->undressItemById(mItemId); + } + else if (link == "guild-pos" && !mNick.empty()) + { + showChangePos(getX(), getY()); + return; + } + else if (link == "clear outfit") + { + if (outfitWindow) + outfitWindow->clearCurrentOutfit(); + } + else if (link == "clipboard copy") + { + if (mTextField) + mTextField->handleCopy(); + } + else if (link == "clipboard paste") + { + if (mTextField) + mTextField->handlePaste(); + } + else if (link == "open link" && !mNick.empty()) + { + openBrowser(mNick); + } + else if (link == "clipboard link" && !mNick.empty()) + { + sendBuffer(mNick); + } + else if (link == "goto" && !mNick.empty()) + { + Net::getAdminHandler()->gotoName(mNick); + } + else if (link == "recall" && !mNick.empty()) + { + Net::getAdminHandler()->recallName(mNick); + } + else if (link == "revive" && !mNick.empty()) + { + Net::getAdminHandler()->reviveName(mNick); + } + else if (link == "ipcheck" && !mNick.empty()) + { + Net::getAdminHandler()->ipcheckName(mNick); + } + else if (link == "gm" && !mNick.empty()) + { + showGMPopup(); + return; + } + else if (!link.compare(0, 10, "guild-pos-")) + { + if (player_node) + { + const int num = atoi(link.substr(10).c_str()); + const Guild *const guild = player_node->getGuild(); + if (guild) + { + Net::getGuildHandler()->changeMemberPostion( + guild->getMember(mNick), num); + } + } + } + else if (!link.compare(0, 7, "player_")) + { + if (actorSpriteManager) + { + mBeingId = atoi(link.substr(7).c_str()); + being = actorSpriteManager->findBeing(mBeingId); + if (being) + { + showPopup(getX(), getY(), being); + return; + } + } + } + else if (!link.compare(0, 10, "flooritem_")) + { + if (actorSpriteManager) + { + const int id = atoi(link.substr(10).c_str()); + if (id) + { + const FloorItem *const item = actorSpriteManager->findItem(id); + if (item) + { + mFloorItemId = item->getId(); + showPopup(getX(), getY(), item); + return; + } + } + } + } + else if (!link.compare(0, 12, "hide button_")) + { + if (windowMenu) + windowMenu->showButton(link.substr(12), false); + } + else if (!link.compare(0, 12, "show button_")) + { + if (windowMenu) + windowMenu->showButton(link.substr(12), true); + } + else if (!link.compare(0, 9, "hide bar_")) + { + if (miniStatusWindow) + miniStatusWindow->showBar(link.substr(9), false); + } + else if (!link.compare(0, 9, "show bar_")) + { + if (miniStatusWindow) + miniStatusWindow->showBar(link.substr(9), true); + } + else if (!link.compare(0, 12, "show window_")) + { + const int id = atoi(link.substr(12).c_str()); + if (id >= 0) + inputManager.executeAction(id); + } + // Unknown actions + else if (link != "cancel") + { + logger->log("PopupMenu: Warning, unknown action '%s'", link.c_str()); + } + + setVisible(false); + + mBeingId = 0; + mFloorItemId = 0; + mItem = nullptr; + mItemId = 0; + mItemColor = 1; + mMapItem = nullptr; + mTab = nullptr; + mSpell = nullptr; + mWindow = nullptr; + mDialog = nullptr; + mButton = nullptr; + mNick.clear(); + mTextField = nullptr; + mType = static_cast<int>(Being::UNKNOWN); + mX = 0; + mY = 0; +} + +void PopupMenu::showPopup(Window *const parent, const int x, const int y, + Item *const item, const bool isInventory) +{ + if (!item) + return; + + mItem = item; + mItemId = item->getId(); + mItemColor = item->getColor(); + mWindow = parent; + mX = x; + mY = y; + mNick.clear(); + mBrowserBox->clearRows(); + + const int cnt = item->getQuantity(); + const bool isProtected = PlayerInfo::isItemProtected(mItemId); + + if (isInventory) + { + if (tradeWindow && tradeWindow->isWindowVisible() && !isProtected) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: add item to trade + mBrowserBox->addRow("addtrade", _("Add to trade")); + if (cnt > 1) + { + if (cnt > 10) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: add 10 item amount to trade + mBrowserBox->addRow("addtrade 10", _("Add to trade 10")); + } + // TRANSLATORS: popup menu item + // TRANSLATORS: add half item amount to trade + mBrowserBox->addRow("addtrade half", _("Add to trade half")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add all amount except one item to trade + mBrowserBox->addRow("addtrade all-1", _("Add to trade all-1")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add all amount item to trade + mBrowserBox->addRow("addtrade all", _("Add to trade all")); + } + mBrowserBox->addRow("##3---"); + } + if (InventoryWindow::isStorageActive()) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: add item to storage + mBrowserBox->addRow("store", _("Store")); + if (cnt > 1) + { + if (cnt > 10) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: add 10 item amount to storage + mBrowserBox->addRow("store 10", _("Store 10")); + } + // TRANSLATORS: popup menu item + // TRANSLATORS: add half item amount to storage + mBrowserBox->addRow("store half", _("Store half")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add all except one item amount to storage + mBrowserBox->addRow("store all-1", _("Store all-1")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add all item amount to storage + mBrowserBox->addRow("store all", _("Store all")); + } + mBrowserBox->addRow("##3---"); + } + + addUseDrop(item, isProtected); + } + // Assume in storage for now + else + { + // TRANSLATORS: popup menu item + // TRANSLATORS: get item from storage + mBrowserBox->addRow("retrieve", _("Retrieve")); + if (cnt > 1) + { + if (cnt > 10) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: get 10 item amount from storage + mBrowserBox->addRow("retrieve 10", _("Retrieve 10")); + } + // TRANSLATORS: popup menu item + // TRANSLATORS: get half item amount from storage + mBrowserBox->addRow("retrieve half", _("Retrieve half")); + // TRANSLATORS: popup menu item + // TRANSLATORS: get all except one item amount from storage + mBrowserBox->addRow("retrieve all-1", _("Retrieve all-1")); + // TRANSLATORS: popup menu item + // TRANSLATORS: get all item amount from storage + mBrowserBox->addRow("retrieve all", _("Retrieve all")); + } + } + addProtection(); + if (config.getBoolValue("enablePickupFilter")) + { + mNick = item->getName(); + mBrowserBox->addRow("##3---"); + addPickupFilter(mNick); + } + // TRANSLATORS: popup menu item + // TRANSLATORS: add item name to chat + mBrowserBox->addRow("chat", _("Add to chat")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showItemPopup(const int x, const int y, const int itemId, + const unsigned char color) +{ + const Inventory *const inv = PlayerInfo::getInventory(); + if (!inv) + return; + + Item *const item = inv->findItem(itemId, color); + if (item) + { + showItemPopup(x, y, item); + } + else + { + mItem = nullptr; + mItemId = itemId; + mItemColor = color; + mX = x; + mY = y; + mBrowserBox->clearRows(); + + if (!PlayerInfo::isItemProtected(mItemId)) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: use item + mBrowserBox->addRow("use", _("Use")); + } + addProtection(); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); + } +} + +void PopupMenu::showItemPopup(const int x, const int y, Item *const item) +{ + mItem = item; + mX = x; + mY = y; + if (item) + { + mItemId = item->getId(); + mItemColor = item->getColor(); + } + else + { + mItemId = 0; + mItemColor = 1; + } + mNick.clear(); + mBrowserBox->clearRows(); + + if (item) + { + const bool isProtected = PlayerInfo::isItemProtected(mItemId); + addUseDrop(item, isProtected); + if (InventoryWindow::isStorageActive()) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: add item to storage + mBrowserBox->addRow("store", _("Store")); + } + // TRANSLATORS: popup menu item + // TRANSLATORS: add item name to chat + mBrowserBox->addRow("chat", _("Add to chat")); + + if (config.getBoolValue("enablePickupFilter")) + { + mNick = item->getName(); + + mBrowserBox->addRow("##3---"); + addPickupFilter(mNick); + } + } + addProtection(); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showDropPopup(const int x, const int y, Item *const item) +{ + mItem = item; + mX = x; + mY = y; + mNick.clear(); + mBrowserBox->clearRows(); + + if (item) + { + mItemId = item->getId(); + mItemColor = item->getColor(); + const bool isProtected = PlayerInfo::isItemProtected(mItemId); + addUseDrop(item, isProtected); + if (InventoryWindow::isStorageActive()) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: add item to storage + mBrowserBox->addRow("store", _("Store")); + } + addProtection(); + // TRANSLATORS: popup menu item + // TRANSLATORS: add item name to chat + mBrowserBox->addRow("chat", _("Add to chat")); + if (config.getBoolValue("enablePickupFilter")) + { + mNick = item->getName(); + mBrowserBox->addRow("##3---"); + addPickupFilter(mNick); + } + } + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + mBrowserBox->addRow("clear drops", _("Clear drop window")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showPopup(const int x, const int y, Button *const button) +{ + if (!button || !windowMenu) + return; + + mButton = button; + mX = x; + mY = y; + + mBrowserBox->clearRows(); + std::vector<Button *> names = windowMenu->getButtons(); + for (std::vector<Button *>::const_iterator it = names.begin(), + it_end = names.end(); it != it_end; ++ it) + { + const Button *const btn = dynamic_cast<Button*>(*it); + if (!btn || btn->getActionEventId() == "SET") + continue; + + if (btn->isVisible()) + { + mBrowserBox->addRow(strprintf("@@hide button_%s|%s %s (%s)@@", + // TRANSLATORS: popup menu item + btn->getActionEventId().c_str(), _("Hide"), + btn->getDescription().c_str(), btn->getCaption().c_str())); + } + else + { + mBrowserBox->addRow(strprintf("@@show button_%s|%s %s (%s)@@", + // TRANSLATORS: popup menu item + btn->getActionEventId().c_str(), _("Show"), + btn->getDescription().c_str(), btn->getCaption().c_str())); + } + } + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showPopup(const int x, const int y, const ProgressBar *const b) +{ + if (!b || !miniStatusWindow) + return; + + mNick = b->text(); + mX = x; + mY = y; + + mBrowserBox->clearRows(); + std::vector <ProgressBar*> bars = miniStatusWindow->getBars(); + ProgressBar *onlyBar = nullptr; + int cnt = 0; + + // search for alone visible bar + for (std::vector <ProgressBar*>::const_iterator it = bars.begin(), + it_end = bars.end(); it != it_end; ++it) + { + ProgressBar *const bar = *it; + if (!bar) + continue; + + if (bar->isVisible()) + { + cnt ++; + onlyBar = bar; + } + } + if (cnt > 1) + onlyBar = nullptr; + + for (std::vector <ProgressBar*>::const_iterator it = bars.begin(), + it_end = bars.end(); it != it_end; ++it) + { + ProgressBar *const bar = *it; + if (!bar || bar == onlyBar) + continue; + + if (bar->isVisible()) + { + mBrowserBox->addRow(strprintf("@@hide bar_%s|%s %s@@", + // TRANSLATORS: popup menu item + bar->getActionEventId().c_str(), _("Hide"), + bar->getId().c_str())); + } + else + { + mBrowserBox->addRow(strprintf("@@show bar_%s|%s %s@@", + // TRANSLATORS: popup menu item + bar->getActionEventId().c_str(), _("Show"), + bar->getId().c_str())); + } + } + + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + mBrowserBox->addRow("reset yellow", _("Reset yellow bar")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: copy status to chat + mBrowserBox->addRow("bar to chat", _("Copy to chat")); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showAttackMonsterPopup(const int x, const int y, + const std::string &name, const int type) +{ + if (!player_node || !actorSpriteManager) + return; + + mNick = name; + mType = static_cast<int>(Being::MONSTER); + mX = x; + mY = y; + + mBrowserBox->clearRows(); + + if (name.empty()) + { + // TRANSLATORS: popup menu header + mBrowserBox->addRow(_("(default)")); + } + else + { + mBrowserBox->addRow(name); + } + switch (type) + { + case MapItem::ATTACK: + { + const int idx = actorSpriteManager->getAttackMobIndex(name); + const int size = actorSpriteManager->getAttackMobsSize(); + if (idx > 0) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: move attack target up + mBrowserBox->addRow("attack moveup", _("Move up")); + } + if (idx + 1 < size) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: move attack target down + mBrowserBox->addRow("attack movedown", _("Move down")); + } + break; + } + case MapItem::PRIORITY: + { + const int idx = actorSpriteManager-> + getPriorityAttackMobIndex(name); + const int size = actorSpriteManager->getPriorityAttackMobsSize(); + if (idx > 0) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: move attack target up + mBrowserBox->addRow("priority moveup", _("Move up")); + } + if (idx + 1 < size) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: move attack target down + mBrowserBox->addRow("priority movedown", _("Move down")); + } + break; + } + case MapItem::IGNORE_: + break; + default: + break; + } + + // TRANSLATORS: popup menu item + // TRANSLATORS: remove attack target + mBrowserBox->addRow("attack remove", _("Remove")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showPickupItemPopup(const int x, const int y, std::string name) +{ + if (!player_node || !actorSpriteManager) + return; + + mNick = name; + mType = static_cast<int>(Being::FLOOR_ITEM); + mX = x; + mY = y; + + mBrowserBox->clearRows(); + + if (name.empty()) + { + // TRANSLATORS: popup menu header + mBrowserBox->addRow(_("(default)")); + } + else + { + mBrowserBox->addRow(name); + } + + // TRANSLATORS: popup menu item + // TRANSLATORS: remove item from pickup filter + mBrowserBox->addRow("pickup remove", _("Remove")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showUndressPopup(const int x, const int y, + const Being *const being, Item *const item) +{ + if (!being || !item) + return; + + mBeingId = being->getId(); + mItem = item; + mItemId = item->getId(); + mItemColor = item->getColor(); + mX = x; + mY = y; + + mBrowserBox->clearRows(); + + // TRANSLATORS: popup menu item + // TRANSLATORS: undress item from player + mBrowserBox->addRow("undress item", _("Undress")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showTextFieldPopup(int x, int y, TextField *const input) +{ + mX = x; + mY = y; + mTextField = input; + + mBrowserBox->clearRows(); + + // TRANSLATORS: popup menu item + // TRANSLATORS: copy text to clipboard + mBrowserBox->addRow("clipboard copy", _("Copy")); + // TRANSLATORS: popup menu item + // TRANSLATORS: paste text from clipboard + mBrowserBox->addRow("clipboard paste", _("Paste")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showLinkPopup(const int x, const int y, + const std::string &link) +{ + mX = x; + mY = y; + mNick = link; + + mBrowserBox->clearRows(); + + // TRANSLATORS: popup menu item + // TRANSLATORS: open link in browser + mBrowserBox->addRow("open link", _("Open link")); + // TRANSLATORS: popup menu item + // TRANSLATORS: copy link to clipboard + mBrowserBox->addRow("clipboard link", _("Copy to clipboard")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showWindowsPopup(const int x, const int y) +{ + mX = x; + mY = y; + + mBrowserBox->clearRows(); + const std::vector<ButtonText*> &names = windowMenu->getButtonTexts(); + // TRANSLATORS: popup menu header + mBrowserBox->addRow(_("Show window")); + + FOR_EACH (std::vector<ButtonText*>::const_iterator, it, names) + { + const ButtonText *const btn = *it; + if (!btn) + continue; + + mBrowserBox->addRow(strprintf("show window_%d", btn->key), + btn->text.c_str()); + } + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showNpcDialogPopup(const int npcId, const int x, const int y) +{ + mBeingId = npcId; + mX = x; + mY = y; + mBrowserBox->clearRows(); + // TRANSLATORS: popup menu item + // TRANSLATORS: copy npc text to clipboard + mBrowserBox->addRow("npc clipboard", _("Copy to clipboard")); + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(x, y); +} + +void PopupMenu::showPopup(int x, int y) +{ + const int pad2 = 2 * mPadding; + const int bPad2 = 2 * mBrowserBox->getPadding(); + mBrowserBox->setPosition(mPadding, mPadding); + mScrollArea->setPosition(mPadding, mPadding); + // add padding to initial size before draw browserbox + int height = mBrowserBox->getHeight(); + if (height + pad2 >= mainGraphics->getHeight()) + { + height = mainGraphics->getHeight() - bPad2 - pad2; + mBrowserBox->setWidth(mBrowserBox->getWidth() + bPad2 + 5); + mScrollArea->setWidth(mBrowserBox->getWidth() + pad2 + 10); + setContentSize(mBrowserBox->getWidth() + pad2 + 20, + height + pad2); + } + else + { + mBrowserBox->setWidth(mBrowserBox->getWidth() + bPad2); + mScrollArea->setWidth(mBrowserBox->getWidth() + pad2); + setContentSize(mBrowserBox->getWidth() + pad2, + height + pad2); + } + if (mainGraphics->mWidth < (x + getWidth() + 5)) + x = mainGraphics->mWidth - getWidth(); + if (mainGraphics->mHeight < (y + getHeight() + 5)) + y = mainGraphics->mHeight - getHeight(); + mScrollArea->setHeight(height); + setPosition(x, y); + setVisible(true); + requestMoveToTop(); +} + +void PopupMenu::addPlayerRelation(const std::string &name) +{ + switch (player_relations.getRelation(name)) + { + case PlayerRelation::NEUTRAL: + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to friends list + mBrowserBox->addRow("friend", _("Be friend")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to disregarded list + mBrowserBox->addRow("disregard", _("Disregard")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to ignore list + mBrowserBox->addRow("ignore", _("Ignore")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to black list + mBrowserBox->addRow("blacklist", _("Black list")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to enemy list + mBrowserBox->addRow("enemy", _("Set as enemy")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to erased list + mBrowserBox->addRow("erase", _("Erase")); + break; + + case PlayerRelation::FRIEND: + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to disregarded list + mBrowserBox->addRow("disregard", _("Disregard")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to ignore list + mBrowserBox->addRow("ignore", _("Ignore")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to black list + mBrowserBox->addRow("blacklist", _("Black list")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to enemy list + mBrowserBox->addRow("enemy", _("Set as enemy")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to erased list + mBrowserBox->addRow("erase", _("Erase")); + break; + + case PlayerRelation::BLACKLISTED: + // TRANSLATORS: popup menu item + // TRANSLATORS: remove player from ignore list + mBrowserBox->addRow("unignore", _("Unignore")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to disregarded list + mBrowserBox->addRow("disregard", _("Disregard")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to ignore list + mBrowserBox->addRow("ignore", _("Ignore")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to enemy list + mBrowserBox->addRow("enemy", _("Set as enemy")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to erased list + mBrowserBox->addRow("erase", _("Erase")); + break; + + case PlayerRelation::DISREGARDED: + // TRANSLATORS: popup menu item + // TRANSLATORS: remove player from ignore list + mBrowserBox->addRow("unignore", _("Unignore")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to completle ignore list + mBrowserBox->addRow("ignore", _("Completely ignore")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to erased list + mBrowserBox->addRow("erase", _("Erase")); + break; + + case PlayerRelation::IGNORED: + // TRANSLATORS: popup menu item + // TRANSLATORS: remove player from ignore list + mBrowserBox->addRow("unignore", _("Unignore")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to erased list + mBrowserBox->addRow("erase", _("Erase")); + break; + + case PlayerRelation::ENEMY2: + // TRANSLATORS: popup menu item + // TRANSLATORS: remove player from ignore list + mBrowserBox->addRow("unignore", _("Unignore")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to disregarded list + mBrowserBox->addRow("disregard", _("Disregard")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to ignore list + mBrowserBox->addRow("ignore", _("Ignore")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to black list + mBrowserBox->addRow("blacklist", _("Black list")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to erased list + mBrowserBox->addRow("erase", _("Erase")); + break; + + case PlayerRelation::ERASED: + // TRANSLATORS: popup menu item + // TRANSLATORS: remove player from ignore list + mBrowserBox->addRow("unignore", _("Unignore")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to disregarded list + mBrowserBox->addRow("disregard", _("Disregard")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add player to ignore list + mBrowserBox->addRow("ignore", _("Completely ignore")); + break; + + default: + break; + } +} + +void PopupMenu::addFollow() +{ + // TRANSLATORS: popup menu item + mBrowserBox->addRow("follow", _("Follow")); + // TRANSLATORS: popup menu item + // TRANSLATORS: imitate player + mBrowserBox->addRow("imitation", _("Imitation")); +} + +void PopupMenu::addBuySell(const Being *const being) +{ + if (player_relations.getDefault() & PlayerRelation::TRADE) + { + mBrowserBox->addRow("##3---"); + if (being->isAdvanced()) + { + if (being->isShopEnabled()) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: buy item + mBrowserBox->addRow("buy", _("Buy")); + // TRANSLATORS: popup menu item + // TRANSLATORS: sell item + mBrowserBox->addRow("sell", _("Sell")); + } + } + else + { + // TRANSLATORS: popup menu item + // TRANSLATORS: buy item + mBrowserBox->addRow("buy", _("Buy (?)")); + // TRANSLATORS: popup menu item + // TRANSLATORS: sell item + mBrowserBox->addRow("sell", _("Sell (?)")); + } + } +} + +void PopupMenu::addBuySellDefault() +{ + if (player_relations.getDefault() & PlayerRelation::TRADE) + { + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: buy item + mBrowserBox->addRow("buy", _("Buy (?)")); + // TRANSLATORS: popup menu item + // TRANSLATORS: sell item + mBrowserBox->addRow("sell", _("Sell (?)")); + } +} + +void PopupMenu::addParty(const std::string &partyName) +{ + if (player_node->isInParty()) + { + if (player_node->getParty()) + { + if (player_node->getParty()->getName() != partyName) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: invite player to party + mBrowserBox->addRow("party", _("Invite to party")); + } + else + { + // TRANSLATORS: popup menu item + // TRANSLATORS: kick player from party + mBrowserBox->addRow("kick party", _("Kick from party")); + } + mBrowserBox->addRow("##3---"); + } + } +} + +void PopupMenu::addPlayerMisc() +{ + // TRANSLATORS: popup menu item + mBrowserBox->addRow("items", _("Show Items")); + // TRANSLATORS: popup menu item + // TRANSLATORS: undress player + mBrowserBox->addRow("undress", _("Undress")); + // TRANSLATORS: popup menu item + // TRANSLATORS: add comment to player + mBrowserBox->addRow("addcomment", _("Add comment")); +} + +void PopupMenu::addPickupFilter(const std::string &name) +{ + if (actorSpriteManager->isInPickupList(name) + || actorSpriteManager->isInIgnorePickupList(name)) + { + mBrowserBox->addRow("remove pickup", + // TRANSLATORS: popup menu item + // TRANSLATORS: remove item from pickup list + _("Remove from pickup list")); + } + else + { + // TRANSLATORS: popup menu item + mBrowserBox->addRow("add pickup", _("Add to pickup list")); + mBrowserBox->addRow("add pickup ignore", + // TRANSLATORS: popup menu item + // TRANSLATORS: add item to pickup list + _("Add to ignore list")); + } +} + +void PopupMenu::showPopup(const int x, const int y, + gcn::ListModel *const model) +{ + if (!model) + return; + + mBrowserBox->clearRows(); + for (int f = 0, sz = model->getNumberOfElements(); f < sz; f ++) + { + mBrowserBox->addRow(strprintf("dropdown_%d", f), + model->getElementAt(f).c_str()); + } + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + showPopup(x, y); +} + +void PopupMenu::clear() +{ + if (mDialog) + { + mDialog->close(); + mDialog = nullptr; + } + mItem = nullptr; + mMapItem = nullptr; + mTab = nullptr; + mSpell = nullptr; + mWindow = nullptr; + mButton = nullptr; + mTextField = nullptr; +} + +void PopupMenu::addProtection() +{ + if (PlayerInfo::isItemProtected(mItemId)) + { + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: remove protection from item + mBrowserBox->addRow("unprotect item", _("Unprotect item")); + } + else + { + if (mItemId < SPELL_MIN_ID) + { + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: add protection to item + mBrowserBox->addRow("protect item", _("Protect item")); + } + } +} + +void PopupMenu::addUseDrop(const Item *const item, const bool isProtected) +{ + if (item->isEquipment()) + { + if (item->isEquipped()) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: unequip item + mBrowserBox->addRow("use", _("Unequip")); + } + else + { + // TRANSLATORS: popup menu item + // TRANSLATORS: use item + mBrowserBox->addRow("use", _("Equip")); + } + } + else + { + if (!isProtected) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: use item + mBrowserBox->addRow("use", _("Use")); + } + } + + if (!isProtected) + { + mBrowserBox->addRow("##3---"); + if (item->getQuantity() > 1) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: drop item + mBrowserBox->addRow("drop", _("Drop...")); + // TRANSLATORS: popup menu item + // TRANSLATORS: drop all item amount + mBrowserBox->addRow("drop all", _("Drop all")); + } + else + { + // TRANSLATORS: popup menu item + // TRANSLATORS: drop item + mBrowserBox->addRow("drop", _("Drop")); + } + } + + if (Net::getInventoryHandler()->canSplit(item)) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: split items + mBrowserBox->addRow("split", _("Split")); + } +} + +void PopupMenu::addGmCommands() +{ + if (player_node->isGM()) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: gm commands + mBrowserBox->addRow("gm", _("GM...")); + } +} + +void PopupMenu::showGMPopup() +{ + mBrowserBox->clearRows(); + // TRANSLATORS: popup menu header + mBrowserBox->addRow(_("GM commands")); + if (player_node->isGM()) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: check player ip + mBrowserBox->addRow("ipcheck", _("Check ip")); + // TRANSLATORS: popup menu item + // TRANSLATORS: go to player position + mBrowserBox->addRow("goto", _("Goto")); + // TRANSLATORS: popup menu item + // TRANSLATORS: recall player to current position + mBrowserBox->addRow("recall", _("Recall")); + // TRANSLATORS: popup menu item + // TRANSLATORS: revive player + mBrowserBox->addRow("revive", _("Revive")); + if (mBeingId) + { + // TRANSLATORS: popup menu item + // TRANSLATORS: kick player + mBrowserBox->addRow("admin-kick", _("Kick")); + } + } + + mBrowserBox->addRow("##3---"); + // TRANSLATORS: popup menu item + // TRANSLATORS: close menu + mBrowserBox->addRow("cancel", _("Cancel")); + + showPopup(getX(), getY()); +} + +RenameListener::RenameListener() : + gcn::ActionListener(), + mMapItemX(0), + mMapItemY(0), + mDialog(nullptr) +{ +} + +void RenameListener::setMapItem(MapItem *const mapItem) +{ + if (mapItem) + { + mMapItemX = mapItem->getX(); + mMapItemY = mapItem->getY(); + } + else + { + mMapItemX = 0; + mMapItemY = 0; + } +} + +void RenameListener::action(const gcn::ActionEvent &event) +{ + if (event.getId() == "ok" && viewport && mDialog) + { + Map *const map = viewport->getMap(); + if (!map) + return; + + SpecialLayer *const sl = map->getSpecialLayer(); + MapItem *item = nullptr; + if (sl) + { + item = sl->getTile(mMapItemX, mMapItemY); + if (item) + item->setComment(mDialog->getText()); + } + item = map->findPortalXY(mMapItemX, mMapItemY); + if (item) + item->setComment(mDialog->getText()); + + if (socialWindow) + socialWindow->updatePortalNames(); + } + mDialog = nullptr; +} + +PlayerListener::PlayerListener() : + ActionListener(), + mNick(), + mDialog(nullptr), + mType(static_cast<int>(Being::UNKNOWN)) +{ +} + +void PlayerListener::action(const gcn::ActionEvent &event) +{ + if (event.getId() == "ok" && !mNick.empty() && mDialog) + { + std::string comment = mDialog->getText(); + Being *const being = actorSpriteManager->findBeingByName( + mNick, static_cast<ActorSprite::Type>(mType)); + if (being) + being->setComment(comment); + Being::saveComment(mNick, comment, mType); + } + mDialog = nullptr; +} diff --git a/src/gui/popups/popupmenu.h b/src/gui/popups/popupmenu.h new file mode 100644 index 000000000..3865c2bd3 --- /dev/null +++ b/src/gui/popups/popupmenu.h @@ -0,0 +1,241 @@ +/* + * The ManaPlus Client + * Copyright (C) 2004-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GUI_POPUPMENU_H +#define GUI_POPUPMENU_H + +#include "gui/widgets/linkhandler.h" +#include "gui/widgets/popup.h" + +#include "being/actorsprite.h" + +#include <guichan/actionlistener.hpp> +#include <guichan/listmodel.hpp> + +#include "localconsts.h" + +class Being; +class BrowserBox; +class Button; +class ChatTab; +class FloorItem; +class Item; +class MapItem; +class ScrollArea; +class TextCommand; +class TextDialog; +class TextField; +class ProgressBar; +class Window; + +class RenameListener final : public gcn::ActionListener +{ + public: + RenameListener(); + + A_DELETE_COPY(RenameListener) + + void action(const gcn::ActionEvent &event) override; + + void setMapItem(MapItem *const mapItem); + + void setDialog(TextDialog *dialog) + { mDialog = dialog; } + + private: + int mMapItemX; + int mMapItemY; + TextDialog *mDialog; +}; + +class PlayerListener : public gcn::ActionListener +{ + public: + PlayerListener(); + + A_DELETE_COPY(PlayerListener) + + void action(const gcn::ActionEvent &event) override; + + void setNick(std::string name) + { mNick = name; } + + void setDialog(TextDialog *dialog) + { mDialog = dialog; } + + void setType(int type) + { mType = type; } + + private: + std::string mNick; + TextDialog *mDialog; + int mType; +}; + +/** + * Window showing popup menu. + */ +class PopupMenu final : public Popup, public LinkHandler +{ + public: + /** + * Constructor. + */ + PopupMenu(); + + A_DELETE_COPY(PopupMenu) + + /** + * Shows the being related popup menu at the specified mouse coords. + */ + void showPopup(const int x, const int y, const Being *const being); + + /** + * Shows the beings related popup menu at the specified mouse coords. + */ + void showPopup(const int x, const int y, + std::vector<ActorSprite*> &beings); + + void showPlayerPopup(const int x, const int y, + const std::string &nick); + + /** + * Shows the floor item related popup menu at the specified + * mouse coords. + */ + void showPopup(const int x, const int y, + const FloorItem *const floorItem); + + /** + * Shows the related popup menu when right click on the inventory + * at the specified mouse coordinates. + */ + void showPopup(Window *const parent, const int x, const int y, + Item *const item, const bool isInventory); + + void showPopup(const int x, const int y, Button *const button); + + void showPopup(const int x, const int y, const ProgressBar *const bar); + + void showPopup(const int x, const int y, MapItem *const mapItem); + + void showItemPopup(const int x, const int y, Item *const item); + + void showItemPopup(const int x, const int y, const int itemId, + const unsigned char color); + + void showDropPopup(const int x, const int y, Item *const item); + + void showOutfitsPopup(const int x, const int y); + + void showSpellPopup(const int x, const int y, TextCommand *const cmd); + + void showAttackMonsterPopup(int x, int y, const std::string &name, + int type); + + void showPickupItemPopup(int x, int y, std::string name); + + void showUndressPopup(const int x, const int y, + const Being *const being, + Item *const item); + + void showMapPopup(const int x, const int y, + const int x2, const int y2); + + /** + * Shows the related popup menu when right click on the chat + * at the specified mouse coordinates. + */ + void showChatPopup(const int x, const int y, ChatTab *const tab); + + void showChangePos(const int x, const int y); + + void showPopup(const int x, const int y, gcn::ListModel *const model); + + void showTextFieldPopup(int x, int y, TextField *const input); + + void showLinkPopup(const int x, const int y, const std::string &link); + + void showWindowsPopup(const int x, const int y); + + void showNpcDialogPopup(const int npcId, const int x, const int y); + + /** + * Handles link action. + */ + void handleLink(const std::string &link, + gcn::MouseEvent *event A_UNUSED) override; + + void clear(); + + private: + void addPlayerRelation(const std::string &name); + + void addFollow(); + + void addBuySell(const Being *const being); + + void addParty(const std::string &partyName); + + void addBuySellDefault(); + + void addPlayerMisc(); + + void addPickupFilter(const std::string &name); + + void addProtection(); + + void addUseDrop(const Item *const item, const bool isProtected); + + void addGmCommands(); + + void showGMPopup(); + + BrowserBox *mBrowserBox; + ScrollArea *mScrollArea; + + int mBeingId; + int mFloorItemId; + Item *mItem; + int mItemId; + unsigned char mItemColor; + MapItem *mMapItem; + ChatTab *mTab; + TextCommand *mSpell; + Window *mWindow; + RenameListener mRenameListener; + PlayerListener mPlayerListener; + TextDialog *mDialog; + Button *mButton; + std::string mNick; + TextField *mTextField; + int mType; + int mX; + int mY; + + /** + * Shared code for the various showPopup functions. + */ + void showPopup(int x, int y); +}; + +#endif // GUI_POPUPMENU_H diff --git a/src/gui/popups/speechbubble.cpp b/src/gui/popups/speechbubble.cpp new file mode 100644 index 000000000..510bb9eae --- /dev/null +++ b/src/gui/popups/speechbubble.cpp @@ -0,0 +1,97 @@ +/* + * Speech bubbles + * Copyright (C) 2008 The Legend of Mazzeroth Development Team + * Copyright (C) 2008-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gui/popups/speechbubble.h" + +#include "gui/gui.h" +#include "gui/sdlfont.h" + +#include "gui/widgets/label.h" +#include "gui/widgets/textbox.h" + +#include <guichan/font.hpp> + +#include "debug.h" + +SpeechBubble::SpeechBubble() : + Popup("Speech", "speechbubble.xml"), + mText(), + mCaption(new Label(this)), + mSpeechBox(new TextBox(this)) +{ + setContentSize(140, 46); + setMinWidth(29); + setMinHeight(29); + + mCaption->setFont(boldFont); + mSpeechBox->setEditable(false); + mSpeechBox->setOpaque(false); + mSpeechBox->setForegroundColorAll(getThemeColor(Theme::BUBBLE_TEXT), + getThemeColor(Theme::BUBBLE_TEXT_OUTLINE)); + + add(mCaption); + add(mSpeechBox); +} + +void SpeechBubble::setCaption(const std::string &name, + const gcn::Color *const color1, + const gcn::Color *const color2) +{ + mCaption->setCaption(name); + mCaption->adjustSize(); + mCaption->setForegroundColorAll(*color1, *color2); +} + +void SpeechBubble::setText(const std::string &text, const bool showName) +{ + if (text == mText && (mCaption->getWidth() <= mSpeechBox->getMinWidth())) + return; + + mSpeechBox->setForegroundColorAll(getThemeColor(Theme::BUBBLE_TEXT), + getThemeColor(Theme::BUBBLE_TEXT_OUTLINE)); + + const int pad = mPadding; + const int pad2 = 2 * pad; + int width = mCaption->getWidth() + pad2; + mSpeechBox->setTextWrapped(text, 130 > width ? 130 : width); + const int speechWidth = mSpeechBox->getMinWidth() + pad2; + + const int fontHeight = getFont()->getHeight(); + const int nameHeight = showName ? mCaption->getHeight() + pad / 2 : 0; + const int numRows = mSpeechBox->getNumberOfRows(); + const int height = (numRows * fontHeight) + nameHeight + pad; + + if (width < speechWidth) + width = speechWidth; + + width += pad2; + + setContentSize(width, height); + + const gcn::Rectangle &rect = mDimension; + const int xPos = ((rect.width - width) / 2); + const int yPos = ((rect.height - height) / 2) + nameHeight; + + mCaption->setPosition(xPos, pad); + mSpeechBox->setPosition(xPos, yPos); +} diff --git a/src/gui/popups/speechbubble.h b/src/gui/popups/speechbubble.h new file mode 100644 index 000000000..ca3c9668b --- /dev/null +++ b/src/gui/popups/speechbubble.h @@ -0,0 +1,64 @@ +/* + * Speech bubbles + * Copyright (C) 2008 The Legend of Mazzeroth Development Team + * Copyright (C) 2008-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GUI_SPEECHBUBBLE_H +#define GUI_SPEECHBUBBLE_H + +#include "gui/theme.h" + +#include "gui/widgets/popup.h" + +class Label; +class TextBox; + +class SpeechBubble final : public Popup +{ + public: + /** + * Constructor. Initializes the speech bubble. + */ + SpeechBubble(); + + A_DELETE_COPY(SpeechBubble) + + /** + * Sets the name displayed for the speech bubble, and in what color. + */ + void setCaption(const std::string &name, + const gcn::Color *const color1 = + &Theme::getThemeColor(Theme::BUBBLE_NAME), + const gcn::Color *const color2 = + &Theme::getThemeColor(Theme::BUBBLE_NAME_OUTLINE)); + + /** + * Sets the text to be displayed. + */ + void setText(const std::string &text, const bool showName = true); + + private: + std::string mText; + Label *mCaption; + TextBox *mSpeechBox; +}; + +#endif // GUI_SPEECHBUBBLE_H diff --git a/src/gui/popups/spellpopup.cpp b/src/gui/popups/spellpopup.cpp new file mode 100644 index 000000000..4e06b3d87 --- /dev/null +++ b/src/gui/popups/spellpopup.cpp @@ -0,0 +1,116 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008 The Legend of Mazzeroth Development Team + * Copyright (C) 2009 The Mana World Development Team + * Copyright (C) 2009-2010 Andrei Karas + * Copyright (C) 2011-2013 The ManaPlus developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gui/popups/spellpopup.h" + +#include "gui/gui.h" +#include "gui/sdlfont.h" + +#include "gui/widgets/label.h" + +#include "debug.h" + +SpellPopup::SpellPopup(): + Popup("SpellPopup", "spellpopup.xml"), + mItemName(new Label(this)), + mItemComment(new Label(this)) +{ + mItemName->setFont(boldFont); + mItemName->setForegroundColorAll(getThemeColor(Theme::POPUP), + getThemeColor(Theme::POPUP_OUTLINE)); + mItemComment->setForegroundColorAll(getThemeColor(Theme::POPUP), + getThemeColor(Theme::POPUP_OUTLINE)); + + add(mItemName); + add(mItemComment); + + addMouseListener(this); +} + +SpellPopup::~SpellPopup() +{ +} + +void SpellPopup::setItem(const TextCommand *const spell) +{ + if (spell) + { + mItemName->setCaption(spell->getName()); + mItemComment->setCaption(spell->getComment()); + } + else + { + mItemName->setCaption("?"); + mItemComment->setCaption(""); + } + + mItemName->adjustSize(); + mItemComment->adjustSize(); + int minWidth = mItemName->getWidth(); + if (mItemComment->getWidth() > minWidth) + minWidth = mItemComment->getWidth(); + + mItemName->setPosition(0, 0); + const int fontHeight = mItemName->getHeight(); + mItemComment->setPosition(0, fontHeight); + if (!mItemComment->getCaption().empty()) + setContentSize(minWidth, 2 * fontHeight); + else + setContentSize(minWidth, fontHeight); +} + +void SpellPopup::view(const int x, const int y) +{ + const int distance = 20; + + int posX = std::max(0, x - getWidth() / 2); + int posY = y + distance; + + const gcn::Rectangle &rect = mDimension; + const int w = rect.width; + const int h = rect.height; + if (posX + w > mainGraphics->mWidth) + { + if (mainGraphics->mWidth > w) + posX = mainGraphics->mWidth - w; + else + posX = 0; + } + if (posY + h > mainGraphics->mHeight) + { + if (y > h + distance) + posY = y - h - distance; + } + + setPosition(posX, posY); + setVisible(true); + requestMoveToTop(); +} + +void SpellPopup::mouseMoved(gcn::MouseEvent &event) +{ + Popup::mouseMoved(event); + + // When the mouse moved on top of the popup, hide it + setVisible(false); +} diff --git a/src/gui/popups/spellpopup.h b/src/gui/popups/spellpopup.h new file mode 100644 index 000000000..b7a1f83b3 --- /dev/null +++ b/src/gui/popups/spellpopup.h @@ -0,0 +1,69 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008 The Legend of Mazzeroth Development Team + * Copyright (C) 2009 The Mana World Development Team + * Copyright (C) 2009-2010 Andrei Karas + * Copyright (C) 2011-2013 The ManaPlus developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GUI_SPELLPOPUP_H +#define GUI_SPELLPOPUP_H + +#include "gui/widgets/popup.h" + +#include "textcommand.h" + +class Label; + +/** + * A popup that displays information about an item. + */ +class SpellPopup final : public Popup +{ + public: + /** + * Constructor. Initializes the item popup. + */ + SpellPopup(); + + A_DELETE_COPY(SpellPopup) + + /** + * Destructor. Cleans up the item popup on deletion. + */ + ~SpellPopup(); + + /** + * Sets the info to be displayed given a particular item. + */ + void setItem(const TextCommand *const spell); + + /** + * Sets the location to display the item popup. + */ + void view(const int x, const int y); + + void mouseMoved(gcn::MouseEvent &mouseEvent) override; + + private: + Label *mItemName; + + Label *mItemComment; +}; + +#endif // GUI_SPELLPOPUP_H diff --git a/src/gui/popups/statuspopup.cpp b/src/gui/popups/statuspopup.cpp new file mode 100644 index 000000000..fb2b161c2 --- /dev/null +++ b/src/gui/popups/statuspopup.cpp @@ -0,0 +1,169 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008 The Legend of Mazzeroth Development Team + * Copyright (C) 2009 The Mana World Development Team + * Copyright (C) 2009-2010 Andrei Karas + * Copyright (C) 2011-2013 The ManaPlus developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gui/viewport.h" + +#include "gui/popups/statuspopup.h" + +#include "gui/widgets/label.h" + +#include "being/localplayer.h" + +#include "input/inputmanager.h" + +#include "utils/stringutils.h" + +#include <guichan/font.hpp> + +#include "debug.h" + +#define addLabel(num) \ + { \ + Label *const label = mLabels[num]; \ + label->setPosition(0, y); \ + label->setForegroundColorAll(getThemeColor(Theme::POPUP), \ + getThemeColor(Theme::POPUP_OUTLINE)); \ + add(label); \ + y += fontHeight; \ + } + +StatusPopup::StatusPopup() : + Popup("StatusPopup", "statuspopup.xml") +{ + const int fontHeight = getFont()->getHeight(); + + for (int f = 0; f < STATUSPOPUP_NUM_LABELS; f ++) + mLabels[f] = new Label(this); + int y = 0; + + addLabel(0); + addLabel(1); + addLabel(2); + addLabel(3); + y += 4; + addLabel(4); + addLabel(5); + addLabel(9); + addLabel(10); + y += 4; + addLabel(6); + addLabel(7); + y += 4; + addLabel(8); + y += 4; + addLabel(12); + addLabel(13); + addLabel(14); + y += 4; + addLabel(11); +} + +StatusPopup::~StatusPopup() +{ +} + +void StatusPopup::update() +{ + updateLabels(); + + int maxWidth = mLabels[0]->getWidth(); + + for (int f = 0; f < STATUSPOPUP_NUM_LABELS; f ++) + { + const int width = mLabels[f]->getWidth(); + if (width > maxWidth) + maxWidth = width; + } + + const int pad2 = 2 * mPadding; + maxWidth += pad2; + setWidth(maxWidth); + setHeight(mLabels[11]->getY() + + mLabels[11]->getHeight() + pad2); +} + +void StatusPopup::view(const int x, const int y) +{ + const int distance = 20; + + int posX = std::max(0, x - getWidth() / 2); + int posY = y + distance; + + if (posX + getWidth() > mainGraphics->mWidth) + posX = mainGraphics->mWidth - getWidth(); + if (posY + getHeight() > mainGraphics->mHeight) + posY = y - getHeight() - distance; + + update(); + + setPosition(posX, posY); + setVisible(true); + requestMoveToTop(); +} + +void StatusPopup::setLabelText(const int num, + const std::string &text, + const Input::KeyAction key) const +{ + Label *const label = mLabels[num]; + label->setCaption(strprintf("%s %s", text.c_str(), + inputManager.getKeyValueString(static_cast<int>(key)).c_str())); + label->adjustSize(); +} + +void StatusPopup::updateLabels() const +{ + if (!player_node || !viewport) + return; + + setLabelText(0, player_node->getInvertDirectionString(), + Input::KEY_INVERT_DIRECTION); + setLabelText(1, player_node->getCrazyMoveTypeString(), + Input::KEY_CHANGE_CRAZY_MOVES_TYPE); + setLabelText(2, player_node->getMoveToTargetTypeString(), + Input::KEY_CHANGE_MOVE_TO_TARGET); + setLabelText(3, player_node->getFollowModeString(), + Input::KEY_CHANGE_FOLLOW_MODE); + setLabelText(4, player_node->getAttackWeaponTypeString(), + Input::KEY_CHANGE_ATTACK_WEAPON_TYPE); + setLabelText(5, player_node->getAttackTypeString(), + Input::KEY_CHANGE_ATTACK_TYPE); + setLabelText(6, player_node->getQuickDropCounterString(), + Input::KEY_SWITCH_QUICK_DROP); + setLabelText(7, player_node->getPickUpTypeString(), + Input::KEY_CHANGE_PICKUP_TYPE); + setLabelText(8, player_node->getDebugPathString(), + Input::KEY_PATHFIND); + setLabelText(9, player_node->getMagicAttackString(), + Input::KEY_SWITCH_MAGIC_ATTACK); + setLabelText(10, player_node->getPvpAttackString(), + Input::KEY_SWITCH_PVP_ATTACK); + setLabelText(11, player_node->getGameModifiersString(), + Input::KEY_DISABLE_GAME_MODIFIERS); + setLabelText(12, player_node->getImitationModeString(), + Input::KEY_CHANGE_IMITATION_MODE); + setLabelText(13, player_node->getAwayModeString(), + Input::KEY_AWAY); + setLabelText(14, player_node->getCameraModeString(), + Input::KEY_CAMERA); +} diff --git a/src/gui/popups/statuspopup.h b/src/gui/popups/statuspopup.h new file mode 100644 index 000000000..f7964741b --- /dev/null +++ b/src/gui/popups/statuspopup.h @@ -0,0 +1,69 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008 The Legend of Mazzeroth Development Team + * Copyright (C) 2009 The Mana World Development Team + * Copyright (C) 2009-2010 Andrei Karas + * Copyright (C) 2011-2013 The ManaPlus developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GUI_STATUSPOPUP_H +#define GUI_STATUSPOPUP_H + +#include "input/keydata.h" + +#include "gui/widgets/popup.h" + +class Label; + +const int STATUSPOPUP_NUM_LABELS = 15; + +/** + * A popup that displays information about an item. + */ +class StatusPopup final : public Popup +{ + public: + /** + * Constructor. Initializes the item popup. + */ + StatusPopup(); + + A_DELETE_COPY(StatusPopup) + + /** + * Destructor. Cleans up the item popup on deletion. + */ + ~StatusPopup(); + + /** + * Sets the location to display the item popup. + */ + void view(const int x, const int y); + + void update(); + + private: + void updateLabels() const; + + void setLabelText(const int num, const std::string &text, + const Input::KeyAction key) const; + + Label *mLabels[STATUSPOPUP_NUM_LABELS]; +}; + +#endif // GUI_STATUSPOPUP_H diff --git a/src/gui/popups/textpopup.cpp b/src/gui/popups/textpopup.cpp new file mode 100644 index 000000000..2b89e388b --- /dev/null +++ b/src/gui/popups/textpopup.cpp @@ -0,0 +1,105 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008 The Legend of Mazzeroth Development Team + * Copyright (C) 2008-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "gui/popups/textpopup.h" + +#include "gui/widgets/label.h" + +#include <guichan/font.hpp> + +#include "debug.h" + +TextPopup::TextPopup(): + Popup("TextPopup", "textpopup.xml"), + mText() +{ + const int fontHeight = getFont()->getHeight(); + int y = 0; + for (int f = 0; f < TEXTPOPUPCOUNT; f ++) + { + Label *const label = new Label(this); + mText[f] = label; + label->setPosition(0, y); + label->setForegroundColorAll(getThemeColor(Theme::POPUP), + getThemeColor(Theme::POPUP_OUTLINE)); + add(label); + y += fontHeight; + } + addMouseListener(this); +} + +TextPopup::~TextPopup() +{ +} + +void TextPopup::show(const int x, const int y, const std::string &str1, + const std::string &str2, const std::string &str3) +{ + mText[0]->setCaption(str1); + mText[1]->setCaption(str2); + mText[2]->setCaption(str3); + + int minWidth = 0; + for (int f = 0; f < TEXTPOPUPCOUNT; f ++) + { + Label *const label = mText[f]; + label->adjustSize(); + const int width = label->getWidth(); + if (width > minWidth) + minWidth = width; + } + + const int pad2 = 2 * mPadding; + minWidth += pad2; + setWidth(minWidth); + + int cnt = 1; + if (!str2.empty()) + cnt ++; + if (!str3.empty()) + cnt ++; + + setHeight(pad2 + mText[0]->getFont()->getHeight() * cnt); + const int distance = 20; + + const gcn::Rectangle &rect = mDimension; + int posX = std::max(0, x - rect.width / 2); + int posY = y + distance; + + if (posX + rect.width > mainGraphics->mWidth) + posX = mainGraphics->mWidth - rect.width; + if (posY + rect.height > mainGraphics->mHeight) + posY = y - rect.height - distance; + + setPosition(posX, posY); + setVisible(true); + requestMoveToTop(); +} + +void TextPopup::mouseMoved(gcn::MouseEvent &event) +{ + Popup::mouseMoved(event); + + // When the mouse moved on top of the popup, hide it + setVisible(false); +} diff --git a/src/gui/popups/textpopup.h b/src/gui/popups/textpopup.h new file mode 100644 index 000000000..b165c2f25 --- /dev/null +++ b/src/gui/popups/textpopup.h @@ -0,0 +1,79 @@ +/* + * The ManaPlus Client + * Copyright (C) 2008 The Legend of Mazzeroth Development Team + * Copyright (C) 2008-2009 The Mana World Development Team + * Copyright (C) 2009-2010 The Mana Developers + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program 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. + * + * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GUI_TEXTPOPUP_H +#define GUI_TEXTPOPUP_H + +#include "gui/widgets/popup.h" + +class Label; + +const int TEXTPOPUPCOUNT = 3; + +/** + * A popup that displays information about an item. + */ +class TextPopup final : public Popup +{ + public: + /** + * Constructor. Initializes the item popup. + */ + TextPopup(); + + A_DELETE_COPY(TextPopup) + + /** + * Destructor. Cleans up the item popup on deletion. + */ + ~TextPopup(); + + /** + * Sets the text to be displayed. + */ + void show(const int x, const int y, const std::string &str1) + { + show(x, y, str1, static_cast<const char*>(""), + static_cast<const char*>("")); + } + + /** + * Sets the text to be displayed. + */ + void show(const int x, const int y, const std::string &str1, + const std::string &str2) + { show(x, y, str1, str2, static_cast<const char*>("")); } + + /** + * Sets the text to be displayed. + */ + void show(const int x, const int y, const std::string &str1, + const std::string &str2, const std::string &str3); + + void mouseMoved(gcn::MouseEvent &mouseEvent) override; + + private: + Label *mText[TEXTPOPUPCOUNT]; +}; + +#endif // GUI_TEXTPOPUP_H |