diff options
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/equipmentwindow.cpp | 229 | ||||
-rw-r--r-- | src/gui/equipmentwindow.h | 29 | ||||
-rw-r--r-- | src/gui/itempopup.cpp | 35 | ||||
-rw-r--r-- | src/gui/itempopup.h | 11 | ||||
-rw-r--r-- | src/gui/popupmenu.cpp | 25 | ||||
-rw-r--r-- | src/gui/popupmenu.h | 2 | ||||
-rw-r--r-- | src/gui/quitdialog.cpp | 2 | ||||
-rw-r--r-- | src/gui/quitdialog.h | 6 | ||||
-rw-r--r-- | src/gui/setup_keyboard.cpp | 3 | ||||
-rw-r--r-- | src/gui/specialswindow.h | 3 | ||||
-rw-r--r-- | src/gui/viewport.cpp | 4 | ||||
-rw-r--r-- | src/gui/viewport.h | 2 | ||||
-rw-r--r-- | src/gui/widgets/button.cpp | 74 | ||||
-rw-r--r-- | src/gui/widgets/button.h | 18 | ||||
-rw-r--r-- | src/gui/widgets/tabbedarea.cpp | 8 | ||||
-rw-r--r-- | src/gui/widgets/tabbedarea.h | 2 | ||||
-rw-r--r-- | src/gui/windowmenu.cpp | 108 | ||||
-rw-r--r-- | src/gui/windowmenu.h | 12 |
18 files changed, 398 insertions, 175 deletions
diff --git a/src/gui/equipmentwindow.cpp b/src/gui/equipmentwindow.cpp index c17b5e04..209ecdb0 100644 --- a/src/gui/equipmentwindow.cpp +++ b/src/gui/equipmentwindow.cpp @@ -54,7 +54,8 @@ EquipmentWindow::EquipmentWindow(Equipment *equipment): Window(_("Equipment")), mEquipBox(0), mSelected(-1), - mEquipment(equipment) + mEquipment(equipment), + mBoxesNumber(0) { mItemPopup = new ItemPopup; setupWindow->registerWindowForReset(this); @@ -80,9 +81,28 @@ EquipmentWindow::EquipmentWindow(Equipment *equipment): add(mUnequip); } +void EquipmentWindow::loadEquipBoxes() +{ + if (mEquipBox) + delete[] mEquipBox; + + // Load equipment boxes. + mBoxesNumber = mEquipment->getSlotNumber(); + mEquipBox = new EquipBox[mBoxesNumber]; + + for (int i = 0; i < mBoxesNumber; ++i) + { + Position boxPosition = Net::getInventoryHandler()->getBoxPosition(i); + mEquipBox[i].posX = boxPosition.x + getPadding(); + mEquipBox[i].posY = boxPosition.y + getTitleBarHeight(); + } +} + EquipmentWindow::~EquipmentWindow() { delete mItemPopup; + if (mEquipBox) + delete[] mEquipBox; } void EquipmentWindow::draw(gcn::Graphics *graphics) @@ -91,32 +111,84 @@ void EquipmentWindow::draw(gcn::Graphics *graphics) Window::draw(graphics); Window::drawChildren(graphics); + + // Draw equipment boxes + Graphics *g = static_cast<Graphics*>(graphics); + + for (int i = 0; i < mBoxesNumber; i++) + { + if (i == mSelected) + { + const gcn::Color color = Theme::getThemeColor(Theme::HIGHLIGHT); + + // Set color to the highlight color + g->setColor(gcn::Color(color.r, color.g, color.b, getGuiAlpha())); + g->fillRectangle(gcn::Rectangle(mEquipBox[i].posX, + mEquipBox[i].posY, + BOX_WIDTH, BOX_HEIGHT)); + } + + // Set color black + g->setColor(gcn::Color(0, 0, 0)); + // Draw box border + g->drawRectangle(gcn::Rectangle(mEquipBox[i].posX, mEquipBox[i].posY, + BOX_WIDTH, BOX_HEIGHT)); + + Item *item = mEquipment->getEquipment(i); + if (item) + { + // Draw Item. + Image *image = item->getImage(); + // Ensure the image is drawn with maximum opacity + image->setAlpha(1.0f); + g->drawImage(image, + mEquipBox[i].posX + 2, + mEquipBox[i].posY + 2); + if (i == TmwAthena::EQUIP_PROJECTILE_SLOT) + { + g->setColor(Theme::getThemeColor(Theme::TEXT)); + graphics->drawText(toString(item->getQuantity()), + mEquipBox[i].posX + (BOX_WIDTH / 2), + mEquipBox[i].posY - getFont()->getHeight(), + gcn::Graphics::CENTER); + } + } + } } void EquipmentWindow::action(const gcn::ActionEvent &event) { if (event.getId() == "unequip" && mSelected > -1) { - Item *item = mEquipment->getEquipment(mSelected); - item->doEvent(Event::DoUnequip); + mEquipment->triggerUnequip(mSelected); setSelected(-1); } } Item *EquipmentWindow::getItem(int x, int y) const { - if (Net::getNetworkType() == ServerInfo::TMWATHENA) + for (int i = 0; i < mBoxesNumber; ++i) { - for (int i = 0; i < TmwAthena::EQUIP_VECTOR_END; i++) - { - gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY, - BOX_WIDTH, BOX_HEIGHT); + gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY, + BOX_WIDTH, BOX_HEIGHT); - if (tRect.isPointInRect(x, y)) - return mEquipment->getEquipment(i); - } + if (tRect.isPointInRect(x, y)) + return mEquipment->getEquipment(i); + } + return 0; +} + +const std::string EquipmentWindow::getSlotName(int x, int y) const +{ + for (int i = 0; i < mBoxesNumber; ++i) + { + gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY, + BOX_WIDTH, BOX_HEIGHT); + + if (tRect.isPointInRect(x, y)) + return mEquipment->getSlotName(i); } - return NULL; + return std::string(); } void EquipmentWindow::mousePressed(gcn::MouseEvent& mouseEvent) @@ -125,51 +197,58 @@ void EquipmentWindow::mousePressed(gcn::MouseEvent& mouseEvent) const int x = mouseEvent.getX(); const int y = mouseEvent.getY(); + Item *item = 0; - if (mouseEvent.getButton() == gcn::MouseEvent::LEFT) + // Checks if any of the presses were in the equip boxes. + for (int i = 0; i < mBoxesNumber; ++i) { - // Checks if any of the presses were in the equip boxes. - if (Net::getNetworkType() == ServerInfo::TMWATHENA) - { - for (int i = 0; i < TmwAthena::EQUIP_VECTOR_END; i++) - { - Item *item = mEquipment->getEquipment(i); - gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY, - BOX_WIDTH, BOX_HEIGHT); + item = mEquipment->getEquipment(i); + gcn::Rectangle tRect(mEquipBox[i].posX, mEquipBox[i].posY, + BOX_WIDTH, BOX_HEIGHT); - if (tRect.isPointInRect(x, y) && item) - setSelected(i); - } + if (tRect.isPointInRect(x, y) && item) + { + setSelected(i); + break; } } - else if (mouseEvent.getButton() == gcn::MouseEvent::RIGHT) + + if (mouseEvent.getButton() == gcn::MouseEvent::RIGHT) { - if (Item *item = getItem(x, y)) + if (item) { /* Convert relative to the window coordinates to absolute screen * coordinates. */ const int mx = x + getX(); const int my = y + getY(); - viewport->showPopup(this, mx, my, item, true); + viewport->showPopup(this, mx, my, item, true, false); } } } -// Show ItemTooltip void EquipmentWindow::mouseMoved(gcn::MouseEvent &event) { const int x = event.getX(); const int y = event.getY(); - Item *item = getItem(x, y); + int mouseX, mouseY; + SDL_GetMouseState(&mouseX, &mouseY); - if (item) + // Show ItemTooltip + std::string slotName = getSlotName(x, y); + if (!slotName.empty()) { - int mouseX, mouseY; - SDL_GetMouseState(&mouseX, &mouseY); + mItemPopup->setEquipmentText(slotName); + + Item *item = getItem(x, y); + if (item) + { + mItemPopup->setItem(item->getInfo()); + } + else + mItemPopup->setNoItem(); - mItemPopup->setItem(item->getInfo()); mItemPopup->position(x + getX(), y + getY()); } else @@ -178,7 +257,6 @@ void EquipmentWindow::mouseMoved(gcn::MouseEvent &event) } } -// Hide ItemTooltip void EquipmentWindow::mouseExited(gcn::MouseEvent &event) { mItemPopup->setVisible(false); @@ -189,86 +267,3 @@ void EquipmentWindow::setSelected(int index) mSelected = index; mUnequip->setEnabled(mSelected != -1); } - -namespace TmwAthena { - -TaEquipmentWindow::TaEquipmentWindow(Equipment *equipment): - EquipmentWindow(equipment) -{ - // Positions of the boxes, 2nd dimension is X and Y respectively. - const int boxPosition[][2] = { - { 90, 40 }, // EQUIP_TORSO_SLOT - { 8, 78 }, // EQUIP_GLOVES_SLOT - { 70, 0 }, // EQUIP_HEAD_SLOT - { 50, 208 }, // EQUIP_LEGS_SLOT - { 90, 208 }, // EQUIP_FEET_SLOT - { 8, 168 }, // EQUIP_RING1_SLOT - { 129, 168 }, // EQUIP_RING2_SLOT - { 50, 40 }, // EQUIP_NECK_SLOT - { 8, 123 }, // EQUIP_FIGHT1_SLOT - { 129, 123 }, // EQUIP_FIGHT2_SLOT - { 129, 78 } // EQUIP_PROJECTILE_SLOT - }; - - // Load equipment boxes. - mEquipBox = new EquipBox[TmwAthena::EQUIP_VECTOR_END]; - - for (int i = 0; i < TmwAthena::EQUIP_VECTOR_END; i++) - { - mEquipBox[i].posX = boxPosition[i][0] + getPadding(); - mEquipBox[i].posY = boxPosition[i][1] + getTitleBarHeight(); - } -} - -TaEquipmentWindow::~TaEquipmentWindow() -{ - delete[] mEquipBox; -} - -void TaEquipmentWindow::draw(gcn::Graphics *graphics) -{ - EquipmentWindow::draw(graphics); - - // Draw equipment boxes - Graphics *g = static_cast<Graphics*>(graphics); - - for (int i = 0; i < TmwAthena::EQUIP_VECTOR_END; i++) - { - if (i == mSelected) - { - const gcn::Color color = Theme::getThemeColor(Theme::HIGHLIGHT); - - // Set color to the highlight color - g->setColor(gcn::Color(color.r, color.g, color.b, getGuiAlpha())); - g->fillRectangle(gcn::Rectangle(mEquipBox[i].posX, mEquipBox[i].posY, - BOX_WIDTH, BOX_HEIGHT)); - } - - // Set color black - g->setColor(gcn::Color(0, 0, 0)); - // Draw box border - g->drawRectangle(gcn::Rectangle(mEquipBox[i].posX, mEquipBox[i].posY, - BOX_WIDTH, BOX_HEIGHT)); - - Item *item = mEquipment->getEquipment(i); - if (item) - { - // Draw Item. - Image *image = item->getImage(); - image->setAlpha(1.0f); // Ensure the image is drawn with maximum opacity - g->drawImage(image, - mEquipBox[i].posX + 2, - mEquipBox[i].posY + 2); - if (i == TmwAthena::EQUIP_PROJECTILE_SLOT) - { - g->setColor(Theme::getThemeColor(Theme::TEXT)); - graphics->drawText(toString(item->getQuantity()), - mEquipBox[i].posX + (BOX_WIDTH / 2), - mEquipBox[i].posY - getFont()->getHeight(), - gcn::Graphics::CENTER); - } - } - } -} - -} // namespace TmwAthena diff --git a/src/gui/equipmentwindow.h b/src/gui/equipmentwindow.h index 5ba15ae3..57a13d40 100644 --- a/src/gui/equipmentwindow.h +++ b/src/gui/equipmentwindow.h @@ -53,6 +53,17 @@ class EquipmentWindow : public Window, public gcn::ActionListener void mousePressed(gcn::MouseEvent& mouseEvent); + /** + * Loads the correct amount of displayed equip boxes. + */ + void loadEquipBoxes(); + + /** + * Returns the current selected slot or -1 if none. + */ + int getSelected() + { return mSelected; } + protected: /** * Equipment box. @@ -67,12 +78,14 @@ class EquipmentWindow : public Window, public gcn::ActionListener int mSelected; /**< Index of selected item. */ Equipment *mEquipment; + int mBoxesNumber; /**< Number of equipment boxes to display */ private: void mouseExited(gcn::MouseEvent &event); void mouseMoved(gcn::MouseEvent &event); Item *getItem(int x, int y) const; + const std::string getSlotName(int x, int y) const; void setSelected(int index); @@ -80,22 +93,6 @@ class EquipmentWindow : public Window, public gcn::ActionListener gcn::Button *mUnequip; }; -namespace TmwAthena { - -class TaEquipmentWindow : public EquipmentWindow -{ - public: - TaEquipmentWindow(Equipment *equipment); - ~TaEquipmentWindow(); - - /** - * Draws the equipment window using TmwAthena routine. - */ - void draw(gcn::Graphics *graphics); -}; - -} // namespace TmwAthena - extern EquipmentWindow *equipmentWindow; #endif // EQUIPMENTWINDOW_H diff --git a/src/gui/itempopup.cpp b/src/gui/itempopup.cpp index 60943756..d65764a5 100644 --- a/src/gui/itempopup.cpp +++ b/src/gui/itempopup.cpp @@ -123,6 +123,34 @@ ItemPopup::~ItemPopup() } } +void ItemPopup::setEquipmentText(const std::string& text) +{ + mItemEquipSlot = text; +} + +void ItemPopup::setNoItem() +{ + mIcon->setImage(0); + + std::string caption = _("No item"); + if (!mItemEquipSlot.empty()) + { + caption += " ("; + caption += mItemEquipSlot; + caption += ")"; + } + mItemName->setCaption(caption); + mItemName->adjustSize(); + + mItemName->setForegroundColor(Theme::getThemeColor(Theme::GENERIC)); + mItemName->setPosition(getPadding(), getPadding()); + + mItemDesc->setText(std::string()); + mItemEffect->setText(std::string()); + + setContentSize(mItemName->getWidth() + 2 * getPadding(), 0); +} + void ItemPopup::setItem(const ItemInfo &item, bool showImage) { if (item.getName() == mItemName->getCaption()) @@ -157,7 +185,11 @@ void ItemPopup::setItem(const ItemInfo &item, bool showImage) mItemType = item.getItemType(); - mItemName->setCaption(item.getName()); + std::string caption = item.getName(); + if (!mItemEquipSlot.empty()) + caption += " (" + mItemEquipSlot + ")"; + + mItemName->setCaption(caption); mItemName->adjustSize(); mItemName->setForegroundColor(getColorFromItemType(mItemType)); mItemName->setPosition(getPadding() + space, getPadding()); @@ -226,5 +258,6 @@ void ItemPopup::mouseMoved(gcn::MouseEvent &event) // When the mouse moved on top of the popup, hide it setVisible(false); + mItemEquipSlot.clear(); } diff --git a/src/gui/itempopup.h b/src/gui/itempopup.h index f054ddf5..95adcf45 100644 --- a/src/gui/itempopup.h +++ b/src/gui/itempopup.h @@ -49,6 +49,16 @@ class ItemPopup : public Popup ~ItemPopup(); /** + * Tells the item popup to say: No Item. + */ + void setNoItem(); + + /** + * Tells in which equipment slot the item is equipped. + */ + void setEquipmentText(const std::string& text = std::string()); + + /** * Sets the info to be displayed given a particular item. */ void setItem(const ItemInfo &item, bool showImage = false); @@ -60,6 +70,7 @@ class ItemPopup : public Popup TextBox *mItemDesc; TextBox *mItemEffect; TextBox *mItemWeight; + std::string mItemEquipSlot; ItemType mItemType; Icon *mIcon; }; diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp index 1c2f3b60..fbe3c739 100644 --- a/src/gui/popupmenu.cpp +++ b/src/gui/popupmenu.cpp @@ -32,6 +32,7 @@ #include "playerrelations.h" #include "gui/chat.h" +#include "gui/equipmentwindow.h" #include "gui/inventorywindow.h" #include "gui/itemamount.h" @@ -266,15 +267,20 @@ void PopupMenu::handleLink(const std::string &link) { } - else if (link == "activate") + else if (link == "activate" || link == "equip" || link == "unequip") { assert(mItem); if (mItem->isEquippable()) { if (mItem->isEquipped()) - mItem->doEvent(Event::DoUnequip); + { + PlayerInfo::getEquipment()->triggerUnequip( + equipmentWindow->getSelected()); + } else + { mItem->doEvent(Event::DoEquip); + } } else { @@ -347,7 +353,7 @@ void PopupMenu::handleLink(const std::string &link) } void PopupMenu::showPopup(Window *parent, int x, int y, Item *item, - bool isInventory) + bool isInventory, bool canDrop) { assert(item); mItem = item; @@ -364,17 +370,20 @@ void PopupMenu::showPopup(Window *parent, int x, int y, Item *item, if (item->getInfo().getEquippable()) { if (item->isEquipped()) - mBrowserBox->addRow(strprintf("@@equip|%s@@", _("Unequip"))); + mBrowserBox->addRow(strprintf("@@unequip|%s@@", _("Unequip"))); else mBrowserBox->addRow(strprintf("@@equip|%s@@", _("Equip"))); } if (item->getInfo().getActivatable()) mBrowserBox->addRow(strprintf("@@activate|%s@@", _("Activate"))); - if (item->getQuantity() > 1) - mBrowserBox->addRow(strprintf("@@drop|%s@@", _("Drop..."))); - else - mBrowserBox->addRow(strprintf("@@drop|%s@@", _("Drop"))); + if (canDrop) + { + if (item->getQuantity() > 1) + mBrowserBox->addRow(strprintf("@@drop|%s@@", _("Drop..."))); + else + mBrowserBox->addRow(strprintf("@@drop|%s@@", _("Drop"))); + } if (Net::getInventoryHandler()->canSplit(item)) { diff --git a/src/gui/popupmenu.h b/src/gui/popupmenu.h index 969c5c20..111f94ed 100644 --- a/src/gui/popupmenu.h +++ b/src/gui/popupmenu.h @@ -55,7 +55,7 @@ class PopupMenu : public Popup, public LinkHandler * at the specified mouse coordinates. */ void showPopup(Window *parent, int x, int y, Item *item, - bool isInventory); + bool isInventory, bool canDrop = true); /** * Handles link action. diff --git a/src/gui/quitdialog.cpp b/src/gui/quitdialog.cpp index 6ecc62a6..3da07206 100644 --- a/src/gui/quitdialog.cpp +++ b/src/gui/quitdialog.cpp @@ -44,7 +44,9 @@ QuitDialog::QuitDialog(QuitDialog** pointerToMe): mSwitchAccountServer = new RadioButton(_("Switch server"), "quitdialog"); mSwitchCharacter = new RadioButton(_("Switch character"), "quitdialog"); mOkButton = new Button(_("OK"), "ok", this); + mOkButton->setButtonIcon("button-icon-confirm.png"); mCancelButton = new Button(_("Cancel"), "cancel", this); + mCancelButton->setButtonIcon("button-icon-cancel.png"); addKeyListener(this); diff --git a/src/gui/quitdialog.h b/src/gui/quitdialog.h index 65a325b8..21fe2f8a 100644 --- a/src/gui/quitdialog.h +++ b/src/gui/quitdialog.h @@ -29,6 +29,8 @@ #include <vector> +class Button; + /** * The quit dialog. * @@ -62,8 +64,8 @@ class QuitDialog : public Window, public gcn::ActionListener, gcn::RadioButton *mForceQuit; gcn::RadioButton *mSwitchAccountServer; gcn::RadioButton *mSwitchCharacter; - gcn::Button *mOkButton; - gcn::Button *mCancelButton; + Button *mOkButton; + Button *mCancelButton; QuitDialog **mMyPointer; }; diff --git a/src/gui/setup_keyboard.cpp b/src/gui/setup_keyboard.cpp index d3ee3937..b8ce3e89 100644 --- a/src/gui/setup_keyboard.cpp +++ b/src/gui/setup_keyboard.cpp @@ -22,6 +22,7 @@ #include "gui/setup_keyboard.h" +#include "game.h" #include "keyboardconfig.h" #include "gui/gui.h" @@ -190,6 +191,8 @@ void Setup_Keyboard::refreshAssignedKey(int index) } mKeyListModel->setElementAt(index, caption); + if (Game *game = Game::instance()) + game->updateWindowMenuCaptions(); } void Setup_Keyboard::newKeyCallback(int index) diff --git a/src/gui/specialswindow.h b/src/gui/specialswindow.h index dedeeffc..b440ce13 100644 --- a/src/gui/specialswindow.h +++ b/src/gui/specialswindow.h @@ -51,6 +51,9 @@ class SpecialsWindow : public Window, public gcn::ActionListener { void draw(gcn::Graphics *graphics); + bool hasSpecials() + { return !mEntries.empty(); } + private: // (re)constructs the list of specials void rebuild(const std::map<int, Special> &specialData); diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 5e519879..1fa60808 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -530,9 +530,9 @@ void Viewport::mouseReleased(gcn::MouseEvent &event) } void Viewport::showPopup(Window *parent, int x, int y, Item *item, - bool isInventory) + bool isInventory, bool canDrop) { - mPopupMenu->showPopup(parent, x, y, item, isInventory); + mPopupMenu->showPopup(parent, x, y, item, isInventory, canDrop); } void Viewport::closePopupMenu() diff --git a/src/gui/viewport.h b/src/gui/viewport.h index 5814f08e..e5fb92b0 100644 --- a/src/gui/viewport.h +++ b/src/gui/viewport.h @@ -106,7 +106,7 @@ class Viewport : public WindowContainer, public gcn::MouseListener, * TODO Find some way to get rid of Item here */ void showPopup(Window *parent, int x, int y, Item *item, - bool isInventory = true); + bool isInventory = true, bool canDrop = true); /** * Closes the popup menu. Needed for when the player dies or switching diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp index f072ef61..61ec28a2 100644 --- a/src/gui/widgets/button.cpp +++ b/src/gui/widgets/button.cpp @@ -25,6 +25,7 @@ #include "graphics.h" #include "gui/palette.h" +#include "gui/textpopup.h" #include "resources/image.h" #include "resources/theme.h" @@ -36,7 +37,8 @@ int Button::mInstances = 0; float Button::mAlpha = 1.0; -ImageRect *Button::mButton; +ImageRect* Button::mButton; +TextPopup* Button::mTextPopup = 0; enum{ BUTTON_STANDARD, // 0 @@ -81,23 +83,26 @@ Button::Button(const std::string &caption, const std::string &actionEventId, adjustSize(); } -void Button::setButtonIcon(const std::string& iconFile, int frameHeight, - int frameWidth) +bool Button::setButtonIcon(const std::string& iconFile) { // We clean up possible older references. if (mButtonIcon) removeButtonIcon(); // If nothing relevant was set, we can quit now. - if (iconFile.empty() || !frameWidth || !frameHeight) - return; + if (iconFile.empty()) + return false; // Load the icon frames. Image *btnIcons = Theme::getImageFromTheme(iconFile); if (!btnIcons) - return; + return false; - if (btnIcons->getWidth() > 0 && btnIcons->getHeight() > 0) + // Compute the sub images size. + const int frameWidth = btnIcons->getWidth() / 4; + const int frameHeight = btnIcons->getHeight(); + + if (frameWidth > 0 && frameHeight > 0) { mButtonIcon = new Image*[BUTTON_COUNT]; for (int mode = 0; mode < BUTTON_COUNT; ++mode) @@ -110,6 +115,7 @@ void Button::setButtonIcon(const std::string& iconFile, int frameHeight, } btnIcons->decRef(); + return (mButtonIcon); } void Button::removeButtonIcon() @@ -159,6 +165,10 @@ void Button::init() btn[mode]->decRef(); } updateAlpha(); + + // Load the popup + if (!mTextPopup) + mTextPopup = new TextPopup(); } mInstances++; } @@ -175,6 +185,9 @@ Button::~Button() dtor<Image*>()); } delete[] mButton; + + // Remove the popup + delete mTextPopup; } removeButtonIcon(); } @@ -301,3 +314,50 @@ void Button::setCaption(const std::string& caption) mCaption = caption; adjustSize(); } + +void Button::logic() +{ + gcn::Button::logic(); + mTextPopup->logic(); +} + +void Button::mouseMoved(gcn::MouseEvent &event) +{ + gcn::Button::mouseMoved(event); + mTextPopup->mouseMoved(event); + + int x = event.getX(); + int y = event.getY(); + + if (event.getSource() == this && !mPopupText.empty()) + { + if (mParent) + { + x += mParent->getX(); + y += mParent->getY(); + } + + mTextPopup->show(x + getX(), y + getY(), mPopupText); + } + else + { + mTextPopup->setVisible(false); + } +} + +void Button::mouseExited(gcn::MouseEvent &event) +{ + gcn::Button::mouseExited(event); + mTextPopup->mouseExited(event); + + mTextPopup->setVisible(false); +} + +void Button::setButtonPopupText(const std::string& text) +{ + mPopupText = text; + if (!mPopupText.empty()) + mTextPopup->show(getX(), getY(), mPopupText); + else + mTextPopup->setVisible(false); +} diff --git a/src/gui/widgets/button.h b/src/gui/widgets/button.h index 6d8f773c..7463d2ad 100644 --- a/src/gui/widgets/button.h +++ b/src/gui/widgets/button.h @@ -26,6 +26,7 @@ class ImageRect; class Image; +class TextPopup; /** * Button widget. Same as the Guichan button but with custom look. @@ -71,8 +72,18 @@ class Button : public gcn::Button * Standard, Highlighted, Pressed, and Disabled. * If the image is too short, the missing states won't be loaded. */ - void setButtonIcon(const std::string& iconFile = std::string(), - int frameHeight = 0, int frameWidth = 0); + bool setButtonIcon(const std::string& iconFile = std::string()); + + /** + * Set the button popup text when hovering it for a few seconds. + * + * @note: An empty text will disable the popup. + */ + void setButtonPopupText(const std::string& text = std::string()); + + void logic(); + void mouseMoved(gcn::MouseEvent &event); + void mouseExited(gcn::MouseEvent &event); private: void init(); @@ -84,6 +95,9 @@ class Button : public gcn::Button static float mAlpha; Image** mButtonIcon; /**< Button Icons graphics */ + + static TextPopup* mTextPopup; /**< The buttons popup */ + std::string mPopupText; /**< the current button text */ }; #endif diff --git a/src/gui/widgets/tabbedarea.cpp b/src/gui/widgets/tabbedarea.cpp index 412d3ddc..9b51b311 100644 --- a/src/gui/widgets/tabbedarea.cpp +++ b/src/gui/widgets/tabbedarea.cpp @@ -33,8 +33,12 @@ TabbedArea::TabbedArea() : gcn::TabbedArea(), mWidgetContainer->setOpaque(false); addWidgetListener(this); - mArrowButton[0] = new Button("<", "shift_left", this); - mArrowButton[1] = new Button(">", "shift_right", this); + mArrowButton[0] = new Button("", "shift_left", this); + mArrowButton[1] = new Button("", "shift_right", this); + if (!mArrowButton[0]->setButtonIcon("tab_arrows_left.png")) + mArrowButton[0]->setCaption("<"); + if (!mArrowButton[1]->setButtonIcon("tab_arrows_right.png")) + mArrowButton[1]->setCaption(">"); add(mArrowButton[0]); add(mArrowButton[1]); diff --git a/src/gui/widgets/tabbedarea.h b/src/gui/widgets/tabbedarea.h index d364eac5..cb29a756 100644 --- a/src/gui/widgets/tabbedarea.h +++ b/src/gui/widgets/tabbedarea.h @@ -117,7 +117,7 @@ class TabbedArea : public gcn::TabbedArea, public gcn::WidgetListener typedef std::vector< std::pair<gcn::Tab*, gcn::Widget*> > TabContainer; /** The tab arrows */ - gcn::Button *mArrowButton[2]; + Button *mArrowButton[2]; /** Check whether the arrow should be clickable */ void updateArrowEnableState(); diff --git a/src/gui/windowmenu.cpp b/src/gui/windowmenu.cpp index 542ab4a0..2cac55b5 100644 --- a/src/gui/windowmenu.cpp +++ b/src/gui/windowmenu.cpp @@ -50,20 +50,27 @@ WindowMenu::WindowMenu(): { int x = 0, h = 0; - addButton(":-)", x, h); - addButton(N_("Status"), x, h); - addButton(N_("Equipment"), x, h); - addButton(N_("Inventory"), x, h); + addButton(":-)", x, h, "button-icon-smilies.png"); + addButton(N_("Status"), x, h, "button-icon-status.png", + KeyboardConfig::KEY_WINDOW_STATUS); + addButton(N_("Inventory"), x, h, "button-icon-inventory.png", + KeyboardConfig::KEY_WINDOW_INVENTORY); + addButton(N_("Equipment"), x, h, "button-icon-equipment.png", + KeyboardConfig::KEY_WINDOW_EQUIPMENT); if (skillDialog->hasSkills()) - addButton(N_("Skills"), x, h); + addButton(N_("Skills"), x, h, "button-icon-skills.png", + KeyboardConfig::KEY_WINDOW_SKILL); - // if (specialsWindow->hasSpecials()) - addButton(N_("Specials"), x, h); + if (specialsWindow->hasSpecials()) + addButton(N_("Specials"), x, h, "button-icon-specials.png"); - addButton(N_("Social"), x, h); - addButton(N_("Shortcut"), x, h); - addButton(N_("Setup"), x, h); + addButton(N_("Social"), x, h, "button-icon-social.png", + KeyboardConfig::KEY_WINDOW_SOCIAL); + addButton(N_("Shortcuts"), x, h, "button-icon-shortcut.png", + KeyboardConfig::KEY_WINDOW_SHORTCUT); + addButton(N_("Setup"), x, h, "button-icon-setup.png", + KeyboardConfig::KEY_WINDOW_SETUP); setDimension(gcn::Rectangle(graphics->getWidth() - x - 3, 3, x - 3, h)); @@ -124,7 +131,7 @@ void WindowMenu::action(const gcn::ActionEvent &event) { window = socialWindow; } - else if (event.getId() == "Shortcut") + else if (event.getId() == "Shortcuts") { window = itemShortcutWindow; } @@ -156,11 +163,84 @@ void WindowMenu::valueChanged(const gcn::SelectionEvent &event) } } -void WindowMenu::addButton(const char* text, int &x, int &h) +static std::string createShortcutCaption(const std::string& text, + KeyboardConfig::KeyAction key) { - gcn::Button *btn = new Button(gettext(text), text, this); + std::string caption = gettext(text.c_str()); + if (key != KeyboardConfig::KEY_NO_VALUE) + { + caption += " ("; + caption += SDL_GetKeyName((SDLKey) keyboard.getKeyValue(key)); + caption += ")"; + } + return caption; +} + +void WindowMenu::addButton(const std::string& text, int &x, int &h, + const std::string& iconPath, + KeyboardConfig::KeyAction key) +{ + Button *btn = new Button("", text, this); + if (!iconPath.empty() && btn->setButtonIcon(iconPath)) + { + // When in image button mode, we have room to show + // the keyboard shortcut. + btn->setButtonPopupText(createShortcutCaption(text, key)); + } + else + { + btn->setCaption(gettext(text.c_str())); + } + btn->setPosition(x, 0); add(btn); x += btn->getWidth() + 3; - h = btn->getHeight(); + h = std::max(h, btn->getHeight()); +} + +void WindowMenu::updatePopUpCaptions() +{ + for (WidgetList::iterator it = mWidgets.begin(); it != mWidgets.end(); ++it) + { + Button *button = dynamic_cast<Button*> (*it); + if (button) + { + std::string eventId = button->getActionEventId(); + if (eventId == "Status") + { + button->setButtonPopupText(createShortcutCaption("Status", + KeyboardConfig::KEY_WINDOW_STATUS)); + } + else if (eventId == "Equipment") + { + button->setButtonPopupText(createShortcutCaption("Equipment", + KeyboardConfig::KEY_WINDOW_EQUIPMENT)); + } + else if (eventId == "Inventory") + { + button->setButtonPopupText(createShortcutCaption("Inventory", + KeyboardConfig::KEY_WINDOW_INVENTORY)); + } + else if (eventId == "Skills") + { + button->setButtonPopupText(createShortcutCaption("Skills", + KeyboardConfig::KEY_WINDOW_SKILL)); + } + else if (eventId == "Social") + { + button->setButtonPopupText(createShortcutCaption("Social", + KeyboardConfig::KEY_WINDOW_SOCIAL)); + } + else if (eventId == "Shortcuts") + { + button->setButtonPopupText(createShortcutCaption("Shortcuts", + KeyboardConfig::KEY_WINDOW_SHORTCUT)); + } + else if (eventId == "Setup") + { + button->setButtonPopupText(createShortcutCaption("Setup", + KeyboardConfig::KEY_WINDOW_SETUP)); + } + } + } } diff --git a/src/gui/windowmenu.h b/src/gui/windowmenu.h index 2bb3e764..962abaf5 100644 --- a/src/gui/windowmenu.h +++ b/src/gui/windowmenu.h @@ -22,6 +22,8 @@ #ifndef WINDOWMENU_H #define WINDOWMENU_H +#include "keyboardconfig.h" + #include "gui/widgets/container.h" #include <guichan/actionlistener.hpp> @@ -47,8 +49,16 @@ class WindowMenu : public Container, void valueChanged(const gcn::SelectionEvent &event); + /** + * Update the pop-up captions with new key shortcuts. + */ + void updatePopUpCaptions(); + private: - inline void addButton(const char* text, int &x, int &h); + inline void addButton(const std::string& text, int &x, int &h, + const std::string& iconPath = std::string(), + KeyboardConfig::KeyAction key = + KeyboardConfig::KEY_NO_VALUE); EmotePopup *mEmotePopup; }; |