diff options
author | Jared Adams <jaxad0127@gmail.com> | 2010-01-11 02:12:47 +0000 |
---|---|---|
committer | Jared Adams <jaxad0127@gmail.com> | 2010-01-11 02:12:47 +0000 |
commit | 440150cba3cd8441283d9914fc444358dee64495 (patch) | |
tree | 89ff0bb6b5229748861ba5364268e3c465a3b3a0 /src/gui/widgets | |
parent | ada99b0ff2395e4d0853016306564f471bfc1bc8 (diff) | |
download | mana-440150cba3cd8441283d9914fc444358dee64495.tar.gz mana-440150cba3cd8441283d9914fc444358dee64495.tar.bz2 mana-440150cba3cd8441283d9914fc444358dee64495.tar.xz mana-440150cba3cd8441283d9914fc444358dee64495.zip |
Cleanup GUI classes
Moved remaining widgets into widgets folder, standardized include order, moved TextRenderer out.
Diffstat (limited to 'src/gui/widgets')
42 files changed, 3578 insertions, 43 deletions
diff --git a/src/gui/widgets/avatar.cpp b/src/gui/widgets/avatar.cpp index 5d8aea01..7bec47a2 100644 --- a/src/gui/widgets/avatar.cpp +++ b/src/gui/widgets/avatar.cpp @@ -24,6 +24,7 @@ #include "localplayer.h" #include "gui/gui.h" + #include "gui/widgets/icon.h" #include "gui/widgets/label.h" diff --git a/src/gui/widgets/browserbox.cpp b/src/gui/widgets/browserbox.cpp index d189947d..610bc153 100644 --- a/src/gui/widgets/browserbox.cpp +++ b/src/gui/widgets/browserbox.cpp @@ -21,9 +21,10 @@ #include "gui/widgets/browserbox.h" -#include "gui/linkhandler.h" #include "gui/palette.h" +#include "gui/widgets/linkhandler.h" + #include <guichan/graphics.hpp> #include <guichan/font.hpp> diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp index 9f44cdfc..3fd5fdf6 100644 --- a/src/gui/widgets/button.cpp +++ b/src/gui/widgets/button.cpp @@ -21,14 +21,14 @@ #include "gui/widgets/button.h" -#include "gui/palette.h" - #include "configuration.h" #include "graphics.h" +#include "gui/palette.h" +#include "gui/skin.h" + #include "resources/image.h" #include "resources/resourcemanager.h" -#include "gui/skin.h" #include "utils/dtor.h" diff --git a/src/gui/widgets/chattab.cpp b/src/gui/widgets/chattab.cpp index 443fab3d..6a915e5b 100644 --- a/src/gui/widgets/chattab.cpp +++ b/src/gui/widgets/chattab.cpp @@ -25,11 +25,11 @@ #include "configuration.h" #include "localplayer.h" +#include "gui/recorder.h" + #include "gui/widgets/browserbox.h" #include "gui/widgets/scrollarea.h" - -#include "gui/itemlinkhandler.h" -#include "gui/recorder.h" +#include "gui/widgets/itemlinkhandler.h" #include "net/chathandler.h" #include "net/net.h" diff --git a/src/gui/widgets/checkbox.cpp b/src/gui/widgets/checkbox.cpp index 9b4ab2f4..bff8d4d8 100644 --- a/src/gui/widgets/checkbox.cpp +++ b/src/gui/widgets/checkbox.cpp @@ -21,14 +21,14 @@ #include "gui/widgets/checkbox.h" -#include "gui/palette.h" - #include "configuration.h" #include "graphics.h" +#include "gui/palette.h" +#include "gui/skin.h" + #include "resources/image.h" #include "resources/resourcemanager.h" -#include "gui/skin.h" int CheckBox::instances = 0; float CheckBox::mAlpha = 1.0; diff --git a/src/gui/widgets/desktop.cpp b/src/gui/widgets/desktop.cpp index 13ac866a..fb807f38 100644 --- a/src/gui/widgets/desktop.cpp +++ b/src/gui/widgets/desktop.cpp @@ -22,6 +22,7 @@ #include "gui/widgets/desktop.h" #include "gui/palette.h" + #include "gui/widgets/label.h" #include "resources/image.h" diff --git a/src/gui/widgets/dropdown.cpp b/src/gui/widgets/dropdown.cpp index d5b324a6..9088bad9 100644 --- a/src/gui/widgets/dropdown.cpp +++ b/src/gui/widgets/dropdown.cpp @@ -21,18 +21,18 @@ #include "gui/widgets/dropdown.h" -#include "gui/widgets/listbox.h" -#include "gui/widgets/scrollarea.h" +#include "configuration.h" +#include "graphics.h" #include "gui/palette.h" #include "gui/sdlinput.h" +#include "gui/skin.h" -#include "configuration.h" -#include "graphics.h" +#include "gui/widgets/listbox.h" +#include "gui/widgets/scrollarea.h" #include "resources/image.h" #include "resources/resourcemanager.h" -#include "gui/skin.h" #include "utils/dtor.h" diff --git a/src/gui/widgets/emoteshortcutcontainer.cpp b/src/gui/widgets/emoteshortcutcontainer.cpp new file mode 100644 index 00000000..5327caab --- /dev/null +++ b/src/gui/widgets/emoteshortcutcontainer.cpp @@ -0,0 +1,197 @@ +/* + * Extended support for activating emotes + * Copyright (C) 2009 Aethyra Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gui/widgets/emoteshortcutcontainer.h" + +#include "animatedsprite.h" +#include "configuration.h" +#include "emoteshortcut.h" +#include "graphics.h" +#include "inventory.h" +#include "item.h" +#include "itemshortcut.h" +#include "keyboardconfig.h" +#include "localplayer.h" +#include "log.h" + +#include "gui/palette.h" + +#include "resources/emotedb.h" +#include "resources/image.h" +#include "resources/resourcemanager.h" + +#include "utils/dtor.h" + +static const int MAX_ITEMS = 12; + +EmoteShortcutContainer::EmoteShortcutContainer(): + ShortcutContainer(), + mEmoteClicked(false), + mEmoteMoved(0) +{ + addMouseListener(this); + addWidgetListener(this); + + ResourceManager *resman = ResourceManager::getInstance(); + + mBackgroundImg = resman->getImage("graphics/gui/item_shortcut_bgr.png"); + + mBackgroundImg->setAlpha(config.getValue("guialpha", 0.8)); + + // Setup emote sprites + for (int i = 0; i <= EmoteDB::getLast(); i++) + { + mEmoteImg.push_back(EmoteDB::getAnimation(i)); + } + + mMaxItems = EmoteDB::getLast() < MAX_ITEMS ? EmoteDB::getLast() : MAX_ITEMS; + + mBoxHeight = mBackgroundImg->getHeight(); + mBoxWidth = mBackgroundImg->getWidth(); +} + +EmoteShortcutContainer::~EmoteShortcutContainer() +{ + mBackgroundImg->decRef(); +} + +void EmoteShortcutContainer::draw(gcn::Graphics *graphics) +{ + if (config.getValue("guialpha", 0.8) != mAlpha) + { + mAlpha = config.getValue("guialpha", 0.8); + mBackgroundImg->setAlpha(mAlpha); + } + + Graphics *g = static_cast<Graphics*>(graphics); + + graphics->setFont(getFont()); + + for (int i = 0; i < mMaxItems; i++) + { + const int emoteX = (i % mGridWidth) * mBoxWidth; + const int emoteY = (i / mGridWidth) * mBoxHeight; + + g->drawImage(mBackgroundImg, emoteX, emoteY); + + // Draw emote keyboard shortcut. + const char *key = SDL_GetKeyName( + (SDLKey) keyboard.getKeyValue(keyboard.KEY_EMOTE_1 + i)); + graphics->setColor(guiPalette->getColor(Palette::TEXT)); + g->drawText(key, emoteX + 2, emoteY + 2, gcn::Graphics::LEFT); + + if (emoteShortcut->getEmote(i)) + { + mEmoteImg[emoteShortcut->getEmote(i) - 1]->draw(g, emoteX + 2, + emoteY + 10); + } + + } + + if (mEmoteMoved) + { + // Draw the emote image being dragged by the cursor. + const AnimatedSprite* sprite = mEmoteImg[mEmoteMoved - 1]; + if (sprite) + { + const int tPosX = mCursorPosX - (sprite->getWidth() / 2); + const int tPosY = mCursorPosY - (sprite->getHeight() / 2); + + sprite->draw(g, tPosX, tPosY); + } + } +} + +void EmoteShortcutContainer::mouseDragged(gcn::MouseEvent &event) +{ + if (event.getButton() == gcn::MouseEvent::LEFT) + { + if (!mEmoteMoved && mEmoteClicked) + { + const int index = getIndexFromGrid(event.getX(), event.getY()); + const int emoteId = emoteShortcut->getEmote(index); + + if (index == -1) + return; + + if (emoteId) + { + mEmoteMoved = emoteId; + emoteShortcut->removeEmote(index); + } + } + if (mEmoteMoved) + { + mCursorPosX = event.getX(); + mCursorPosY = event.getY(); + } + } +} + +void EmoteShortcutContainer::mousePressed(gcn::MouseEvent &event) +{ + const int index = getIndexFromGrid(event.getX(), event.getY()); + + if (index == -1) + return; + + // Stores the selected emote if there is one. + if (emoteShortcut->isEmoteSelected()) + { + emoteShortcut->setEmote(index); + emoteShortcut->setEmoteSelected(0); + } + else if (emoteShortcut->getEmote(index)) + { + mEmoteClicked = true; + } +} + +void EmoteShortcutContainer::mouseReleased(gcn::MouseEvent &event) +{ + if (event.getButton() == gcn::MouseEvent::LEFT) + { + const int index = getIndexFromGrid(event.getX(), event.getY()); + + if (emoteShortcut->isEmoteSelected()) + emoteShortcut->setEmoteSelected(0); + + if (index == -1) + { + mEmoteMoved = 0; + return; + } + + if (mEmoteMoved) + { + emoteShortcut->setEmotes(index, mEmoteMoved); + mEmoteMoved = 0; + } + else if (emoteShortcut->getEmote(index) && mEmoteClicked) + { + emoteShortcut->useEmote(index + 1); + } + + if (mEmoteClicked) + mEmoteClicked = false; + } +} + diff --git a/src/gui/widgets/emoteshortcutcontainer.h b/src/gui/widgets/emoteshortcutcontainer.h new file mode 100644 index 00000000..8860927e --- /dev/null +++ b/src/gui/widgets/emoteshortcutcontainer.h @@ -0,0 +1,77 @@ +/* + * Extended support for activating emotes + * Copyright (C) 2009 Aethyra Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef EMOTESHORTCUTCONTAINER_H +#define EMOTESHORTCUTCONTAINER_H + +#include <vector> + +#include "gui/widgets/shortcutcontainer.h" + +class AnimatedSprite; +class Image; + +/** + * An emote shortcut container. Used to quickly use emoticons. + * + * \ingroup GUI + */ +class EmoteShortcutContainer : public ShortcutContainer +{ + public: + /** + * Constructor. Initializes the graphic. + */ + EmoteShortcutContainer(); + + /** + * Destructor. + */ + virtual ~EmoteShortcutContainer(); + + /** + * Draws the items. + */ + void draw(gcn::Graphics *graphics); + + /** + * Handles mouse when dragged. + */ + void mouseDragged(gcn::MouseEvent &event); + + /** + * Handles mouse when pressed. + */ + void mousePressed(gcn::MouseEvent &event); + + /** + * Handles mouse release. + */ + void mouseReleased(gcn::MouseEvent &event); + + private: + std::vector<const AnimatedSprite*> mEmoteImg; + + bool mEmoteClicked; + int mEmoteMoved; +}; + +#endif diff --git a/src/gui/widgets/guildlistbox.cpp b/src/gui/widgets/guildlistbox.cpp new file mode 100644 index 00000000..14a8f77f --- /dev/null +++ b/src/gui/widgets/guildlistbox.cpp @@ -0,0 +1,131 @@ +/* + * The Mana World + * Copyright (C) 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gui/widgets/guildlistbox.h" + +#include "graphics.h" + +#include "resources/image.h" +#include "resources/resourcemanager.h" + +#include <guichan/font.hpp> + +GuildListBox::GuildListBox(): + ListBox(NULL) +{ + onlineIcon = ResourceManager::getInstance()->getImage("graphics/gui/circle-green.png"); + offlineIcon = ResourceManager::getInstance()->getImage("graphics/gui/circle-gray.png"); +} + +void GuildListBox::draw(gcn::Graphics *gcnGraphics) +{ + if (!mListModel) + return; + + Graphics *graphics = static_cast<Graphics*>(gcnGraphics); + + graphics->setColor(gcn::Color(110, 160, 255)); + graphics->setFont(getFont()); + + int fontHeight = getFont()->getHeight(); + + // Draw rectangle below the selected list element + if (mSelected >= 0) + { + graphics->fillRectangle(gcn::Rectangle(0, fontHeight * mSelected, + getWidth(), fontHeight)); + } + + // Draw the list elements + for (int i = 0, y = 0; + i < mListModel->getNumberOfElements(); + ++i, y += fontHeight) + { + // Draw online status + bool online = false; + UserMap::iterator itr = mUsers.find(mListModel->getElementAt(i)); + if (itr != mUsers.end()) + { + online = itr->second; + } + Image *icon = online ? onlineIcon : offlineIcon; + if (icon) + graphics->drawImage(icon, 1, y); + // Draw Name + graphics->setColor(gcn::Color(0, 0, 0)); + graphics->drawText(mListModel->getElementAt(i), 33, y); + } +} +/* +void GuildListBox::setSelected(int selected) +{ + if (!mListModel) + { + mSelected = -1; + } + else + { + // Update mSelected with bounds checking + mSelected = std::min(mListModel->getNumberOfElements() - 1, + std::max(-1, selected)); + + gcn::Widget *parent; + parent = (gcn::Widget*)getParent(); + if (parent) + { + gcn::Rectangle scroll; + scroll.y = (mSelected < 0) ? 0 : getFont()->getHeight() * mSelected; + scroll.height = getFont()->getHeight(); + parent->showWidgetPart(this, scroll); + } + } + + distributeValueChangedEvent(); +} +*/ +void GuildListBox::mousePressed(gcn::MouseEvent &event) +{ + if (event.getButton() == gcn::MouseEvent::LEFT) + { + int y = event.getY(); + setSelected(y / getFont()->getHeight()); + distributeActionEvent(); + } + // TODO: Add guild functions, ie private messaging + if (event.getButton() == gcn::MouseEvent::RIGHT) + { + // Show context menu + } +} + +void GuildListBox::setOnlineStatus(const std::string &user, bool online) +{ + UserMap::iterator itr = mUsers.find(user); + if (itr == mUsers.end()) + { + mUsers.insert(std::pair<std::string, bool>(user, online)); + } + else + { + itr->second = online; + } + adjustSize(); +} diff --git a/src/gui/widgets/guildlistbox.h b/src/gui/widgets/guildlistbox.h new file mode 100644 index 00000000..d266fe46 --- /dev/null +++ b/src/gui/widgets/guildlistbox.h @@ -0,0 +1,65 @@ +/* + * The Mana World + * Copyright (C) 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef GUI_GUILDLISTBOX_H +#define GUI_GUILDLISTBOX_H + +#include <map> +#include <string> +#include <vector> + +#include "gui/widgets/listbox.h" + +class Image; + +class GuildListBox : public ListBox +{ +public: + /** + * Constructor + */ + GuildListBox(); + + /** + * Draws the list box. + */ + void draw(gcn::Graphics *gcnGraphics); + + void mousePressed(gcn::MouseEvent &event); + + /** + * Sets the index of the selected element. + */ +// void setSelected(int selected); + + /** + * Set whether a member is online or offline + */ + void setOnlineStatus(const std::string &user, bool online); + +private: + Image *onlineIcon; + Image *offlineIcon; + typedef std::map<std::string, bool> UserMap; + UserMap mUsers; +}; + +#endif diff --git a/src/gui/widgets/itemcontainer.cpp b/src/gui/widgets/itemcontainer.cpp new file mode 100644 index 00000000..67561e89 --- /dev/null +++ b/src/gui/widgets/itemcontainer.cpp @@ -0,0 +1,436 @@ +/* + * The Mana World + * Copyright (C) 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gui/widgets/itemcontainer.h" + +#include "graphics.h" +#include "inventory.h" +#include "item.h" +#include "itemshortcut.h" +#include "log.h" + +#include "gui/chat.h" +#include "gui/itempopup.h" +#include "gui/outfitwindow.h" +#include "gui/palette.h" +#include "gui/sdlinput.h" +#include "gui/viewport.h" + +#include "net/net.h" +#include "net/inventoryhandler.h" + +#include "resources/image.h" +#include "resources/iteminfo.h" +#include "resources/resourcemanager.h" + +#include "utils/stringutils.h" + +#include <guichan/mouseinput.hpp> +#include <guichan/selectionlistener.hpp> + +// TODO: Add support for adding items to the item shortcut window (global +// itemShortcut). + +static const int BOX_WIDTH = 35; +static const int BOX_HEIGHT = 43; + +ItemContainer::ItemContainer(Inventory *inventory, bool forceQuantity): + mInventory(inventory), + mGridColumns(1), + mGridRows(1), + mSelectedIndex(-1), + mHighlightedIndex(-1), + mLastUsedSlot(-1), + mSelectionStatus(SEL_NONE), + mForceQuantity(forceQuantity), + mSwapItems(false), + mDescItems(false) +{ + mItemPopup = new ItemPopup; + setFocusable(true); + + ResourceManager *resman = ResourceManager::getInstance(); + + mSelImg = resman->getImage("graphics/gui/selection.png"); + if (!mSelImg) + logger->error("Unable to load selection.png"); + + addKeyListener(this); + addMouseListener(this); + addWidgetListener(this); +} + +ItemContainer::~ItemContainer() +{ + mSelImg->decRef(); + delete mItemPopup; +} + +void ItemContainer::logic() +{ + gcn::Widget::logic(); + + const int lastUsedSlot = mInventory->getLastUsedSlot(); + + if (lastUsedSlot != mLastUsedSlot) + { + mLastUsedSlot = lastUsedSlot; + adjustHeight(); + } +} + +void ItemContainer::draw(gcn::Graphics *graphics) +{ + Graphics *g = static_cast<Graphics*>(graphics); + + g->setFont(getFont()); + + for (int i = 0; i < mGridColumns; i++) + { + for (int j = 0; j < mGridRows; j++) + { + int itemX = i * BOX_WIDTH; + int itemY = j * BOX_HEIGHT; + int itemIndex = (j * mGridColumns) + i; + Item *item = mInventory->getItem(itemIndex); + + if (!item || item->getId() == 0) + continue; + + Image *image = item->getImage(); + if (image) + { + if (itemIndex == mSelectedIndex) + { + if (mSelectionStatus == SEL_DRAGGING) + { + // Reposition the coords to that of the cursor. + itemX = mDragPosX - (BOX_WIDTH / 2); + itemY = mDragPosY - (BOX_HEIGHT / 2); + } + else + { + // Draw selection border image. + g->drawImage(mSelImg, itemX, itemY); + } + } + image->setAlpha(1.0f); // ensure the image if fully drawn... + g->drawImage(image, itemX, itemY); + } + // Draw item caption + std::string caption; + if (item->getQuantity() > 1 || mForceQuantity) + caption = toString(item->getQuantity()); + else if (item->isEquipped()) + caption = "Eq."; + + if (item->isEquipped()) + g->setColor(guiPalette->getColor(Palette::ITEM_EQUIPPED)); + else + g->setColor(gcn::Color(0, 0, 0)); + + g->drawText(caption, itemX + BOX_WIDTH / 2, + itemY + BOX_HEIGHT - 14, gcn::Graphics::CENTER); + } + } + + // Draw an orange box around the selected item + if (isFocused() && mHighlightedIndex != -1) + { + const int itemX = (mHighlightedIndex % mGridColumns) * BOX_WIDTH; + const int itemY = (mHighlightedIndex / mGridColumns) * BOX_HEIGHT; + g->setColor(gcn::Color(255, 128, 0)); + g->drawRectangle(gcn::Rectangle(itemX, itemY, BOX_WIDTH, BOX_HEIGHT)); + } +} + +void ItemContainer::selectNone() +{ + setSelectedIndex(-1); + mSelectionStatus = SEL_NONE; + outfitWindow->setItemSelected(-1); +} + +void ItemContainer::setSelectedIndex(int newIndex) +{ + if (mSelectedIndex != newIndex) + { + mSelectedIndex = newIndex; + distributeValueChangedEvent(); + } +} + +Item *ItemContainer::getSelectedItem() const +{ + return mInventory->getItem(mSelectedIndex); +} + +void ItemContainer::distributeValueChangedEvent() +{ + SelectionListenerIterator i, i_end; + + for (i = mSelectionListeners.begin(), i_end = mSelectionListeners.end(); + i != i_end; ++i) + { + gcn::SelectionEvent event(this); + (*i)->valueChanged(event); + } +} + +void ItemContainer::keyPressed(gcn::KeyEvent &event) +{ + /*switch (event.getKey().getValue()) + { + case Key::LEFT: + moveHighlight(Left); + break; + case Key::RIGHT: + moveHighlight(Right); + break; + case Key::UP: + moveHighlight(Up); + break; + case Key::DOWN: + moveHighlight(Down); + break; + case Key::SPACE: + keyAction(); + break; + case Key::LEFT_ALT: + case Key::RIGHT_ALT: + mSwapItems = true; + break; + case Key::RIGHT_CONTROL: + mDescItems = true; + break; + }*/ +} + +void ItemContainer::keyReleased(gcn::KeyEvent &event) +{ + /*switch (event.getKey().getValue()) + { + case Key::LEFT_ALT: + case Key::RIGHT_ALT: + mSwapItems = false; + break; + case Key::RIGHT_CONTROL: + mDescItems = false; + break; + }*/ +} + +void ItemContainer::mousePressed(gcn::MouseEvent &event) +{ + const int button = event.getButton(); + if (button == gcn::MouseEvent::LEFT || button == gcn::MouseEvent::RIGHT) + { + const int index = getSlotIndex(event.getX(), event.getY()); + if (index == Inventory::NO_SLOT_INDEX) + return; + + Item *item = mInventory->getItem(index); + + // put item name into chat window + if (mDescItems) + { + chatWindow->addItemText(item->getInfo().getName()); + } + + if (mSelectedIndex == index) + { + mSelectionStatus = SEL_DESELECTING; + } + else if (item && item->getId()) + { + setSelectedIndex(index); + mSelectionStatus = SEL_SELECTING; + + itemShortcut->setItemSelected(item->getId()); + if (item->isEquipment()) + outfitWindow->setItemSelected(item->getId()); + } + else + { + selectNone(); + } + } +} + +void ItemContainer::mouseDragged(gcn::MouseEvent &event) +{ + if (mSelectionStatus != SEL_NONE) + { + mSelectionStatus = SEL_DRAGGING; + mDragPosX = event.getX(); + mDragPosY = event.getY(); + } +} + +void ItemContainer::mouseReleased(gcn::MouseEvent &event) +{ + switch (mSelectionStatus) + { + case SEL_SELECTING: + mSelectionStatus = SEL_SELECTED; + return; + case SEL_DESELECTING: + selectNone(); + return; + case SEL_DRAGGING: + mSelectionStatus = SEL_SELECTED; + break; + default: + return; + }; + + int index = getSlotIndex(event.getX(), event.getY()); + if (index == Inventory::NO_SLOT_INDEX) + return; + if (index == mSelectedIndex || mSelectedIndex == -1) + return; + Net::getInventoryHandler()->moveItem(mSelectedIndex, index); + selectNone(); +} + + +// Show ItemTooltip +void ItemContainer::mouseMoved(gcn::MouseEvent &event) +{ + Item *item = mInventory->getItem(getSlotIndex(event.getX(), event.getY())); + + if (item) + { + mItemPopup->setItem(item->getInfo()); + mItemPopup->view(viewport->getMouseX(), viewport->getMouseY()); + } + else + { + mItemPopup->setVisible(false); + } +} + +// Hide ItemTooltip +void ItemContainer::mouseExited(gcn::MouseEvent &event) +{ + mItemPopup->setVisible(false); +} + +void ItemContainer::widgetResized(const gcn::Event &event) +{ + mGridColumns = std::max(1, getWidth() / BOX_WIDTH); + adjustHeight(); +} + +void ItemContainer::adjustHeight() +{ + mGridRows = (mLastUsedSlot + 1) / mGridColumns; + if (mGridRows == 0 || (mLastUsedSlot + 1) % mGridColumns > 0) + ++mGridRows; + + setHeight(mGridRows * BOX_HEIGHT); +} + +int ItemContainer::getSlotIndex(int x, int y) const +{ + if (x < getWidth() && y < getHeight()) + { + return (y / BOX_HEIGHT) * mGridColumns + (x / BOX_WIDTH); + } + return Inventory::NO_SLOT_INDEX; +} + +void ItemContainer::keyAction() +{ + // If there is no highlight then return. + if (mHighlightedIndex == -1) + return; + + // If the highlight is on the selected item, then deselect it. + if (mHighlightedIndex == mSelectedIndex) + { + selectNone(); + } + // Check and swap items if necessary. + else if (mSwapItems && + mSelectedIndex != -1 && + mHighlightedIndex != -1) + { + Net::getInventoryHandler()->moveItem( + mSelectedIndex, mHighlightedIndex); + setSelectedIndex(mHighlightedIndex); + } + // If the highlight is on an item then select it. + else if (mHighlightedIndex != -1) + { + setSelectedIndex(mHighlightedIndex); + mSelectionStatus = SEL_SELECTED; + } + // If the highlight is on a blank space then move it. + else if (mSelectedIndex != -1) + { + Net::getInventoryHandler()->moveItem( + mSelectedIndex, mHighlightedIndex); + selectNone(); + } +} + +void ItemContainer::moveHighlight(Direction direction) +{ + if (mHighlightedIndex == -1) + { + if (mSelectedIndex != -1) + mHighlightedIndex = mSelectedIndex; + else + mHighlightedIndex = 0; + return; + } + + switch (direction) + { + case Left: + if (mHighlightedIndex % mGridColumns == 0) + mHighlightedIndex += mGridColumns; + mHighlightedIndex--; + break; + case Right: + if ((mHighlightedIndex % mGridColumns) == + (mGridColumns - 1)) + { + mHighlightedIndex -= mGridColumns; + } + mHighlightedIndex++; + break; + case Up: + if (mHighlightedIndex / mGridColumns == 0) + mHighlightedIndex += (mGridColumns * mGridRows); + mHighlightedIndex -= mGridColumns; + break; + case Down: + if ((mHighlightedIndex / mGridColumns) == + (mGridRows - 1)) + { + mHighlightedIndex -= (mGridColumns * mGridRows); + } + mHighlightedIndex += mGridColumns; + break; + } +} diff --git a/src/gui/widgets/itemcontainer.h b/src/gui/widgets/itemcontainer.h new file mode 100644 index 00000000..2cfd06b2 --- /dev/null +++ b/src/gui/widgets/itemcontainer.h @@ -0,0 +1,192 @@ +/* + * The Mana World + * Copyright (C) 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ITEMCONTAINER_H +#define ITEMCONTAINER_H + +#include <guichan/keylistener.hpp> +#include <guichan/mouselistener.hpp> +#include <guichan/widget.hpp> +#include <guichan/widgetlistener.hpp> + +#include <list> + +class Image; +class Inventory; +class Item; +class ItemPopup; + +namespace gcn { + class SelectionListener; +} + +/** + * An item container. Used to show items in inventory and trade dialog. + * + * \ingroup GUI + */ +class ItemContainer : public gcn::Widget, + public gcn::KeyListener, + public gcn::MouseListener, + public gcn::WidgetListener +{ + public: + /** + * Constructor. Initializes the graphic. + * + * @param inventory + * @param gridColumns Amount of columns in grid. + * @param gridRows Amount of rows in grid. + * @param offset Index offset + */ + ItemContainer(Inventory *inventory, bool forceQuantity = false); + + /** + * Destructor. + */ + virtual ~ItemContainer(); + + /** + * Necessary for checking how full the inventory is. + */ + void logic(); + + /** + * Draws the items. + */ + void draw(gcn::Graphics *graphics); + + // KeyListener + void keyPressed(gcn::KeyEvent &event); + void keyReleased(gcn::KeyEvent &event); + + // MouseListener + void mousePressed(gcn::MouseEvent &event); + void mouseDragged(gcn::MouseEvent &event); + void mouseReleased(gcn::MouseEvent &event); + void mouseMoved(gcn::MouseEvent &event); + void mouseExited(gcn::MouseEvent &event); + + // WidgetListener + void widgetResized(const gcn::Event &event); + + /** + * Returns the selected item. + */ + Item *getSelectedItem() const; + + /** + * Sets selected item to NULL. + */ + void selectNone(); + + /** + * Adds a listener to the list that's notified each time a change to + * the selection occurs. + */ + void addSelectionListener(gcn::SelectionListener *listener) + { + mSelectionListeners.push_back(listener); + } + + /** + * Removes a listener from the list that's notified each time a change + * to the selection occurs. + */ + void removeSelectionListener(gcn::SelectionListener *listener) + { + mSelectionListeners.remove(listener); + } + + private: + enum Direction + { + Left, + Right, + Up, + Down + }; + + enum SelectionState + { + SEL_NONE = 0, + SEL_SELECTED, + SEL_SELECTING, + SEL_DESELECTING, + SEL_DRAGGING + }; + + /** + * Execute all the functionality associated with the action key. + */ + void keyAction(); + + /** + * Moves the highlight in the direction specified. + * + * @param direction The move direction of the highlighter. + */ + void moveHighlight(Direction direction); + + /** + * Sets the currently selected item. + */ + void setSelectedIndex(int index); + + /** + * Determine and set the height of the container. + */ + void adjustHeight(); + + /** + * Sends out selection events to the list of selection listeners. + */ + void distributeValueChangedEvent(); + + /** + * Gets the slot index based on the cursor position. + * + * @param x The X coordinate position. + * @param y The Y coordinate position. + * @return The slot index on success, -1 on failure. + */ + int getSlotIndex(int x, int y) const; + + Inventory *mInventory; + int mGridColumns, mGridRows; + Image *mSelImg; + int mSelectedIndex, mHighlightedIndex; + int mLastUsedSlot; + SelectionState mSelectionStatus; + bool mForceQuantity; + bool mSwapItems; + bool mDescItems; + int mDragPosX, mDragPosY; + + ItemPopup *mItemPopup; + + typedef std::list<gcn::SelectionListener*> SelectionListenerList; + typedef SelectionListenerList::iterator SelectionListenerIterator; + + SelectionListenerList mSelectionListeners; +}; + +#endif diff --git a/src/gui/widgets/itemlinkhandler.cpp b/src/gui/widgets/itemlinkhandler.cpp new file mode 100644 index 00000000..1a7011ab --- /dev/null +++ b/src/gui/widgets/itemlinkhandler.cpp @@ -0,0 +1,60 @@ +/* + * The Mana World + * Copyright (C) 2009 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <sstream> +#include <string> + +#include "gui/widgets/itemlinkhandler.h" +#include "gui/itempopup.h" +#include "gui/viewport.h" + +#include "resources/iteminfo.h" +#include "resources/itemdb.h" + +ItemLinkHandler::ItemLinkHandler() +{ + mItemPopup = new ItemPopup; +} + +ItemLinkHandler::~ItemLinkHandler() +{ + delete mItemPopup; +} + +void ItemLinkHandler::handleLink(const std::string &link) +{ + int id = 0; + std::stringstream stream; + stream << link; + stream >> id; + + if (id > 0) + { + const ItemInfo &iteminfo = ItemDB::get(id); + + mItemPopup->setItem(iteminfo); + + if (mItemPopup->isVisible()) + mItemPopup->setVisible(false); + else + mItemPopup->view(viewport->getMouseX(), viewport->getMouseY()); + } +} diff --git a/src/gui/widgets/itemlinkhandler.h b/src/gui/widgets/itemlinkhandler.h new file mode 100644 index 00000000..af20b9ce --- /dev/null +++ b/src/gui/widgets/itemlinkhandler.h @@ -0,0 +1,40 @@ +/* + * The Mana World + * Copyright (C) 2009 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ITEM_LINK_HANDLER_H +#define ITEM_LINK_HANDLER_H + +#include "gui/widgets/linkhandler.h" + +class ItemPopup; + +class ItemLinkHandler : public LinkHandler +{ + public: + ItemLinkHandler(); + ~ItemLinkHandler(); + void handleLink(const std::string &link); + + private: + ItemPopup *mItemPopup; +}; + +#endif diff --git a/src/gui/widgets/itemshortcutcontainer.cpp b/src/gui/widgets/itemshortcutcontainer.cpp new file mode 100644 index 00000000..489a85be --- /dev/null +++ b/src/gui/widgets/itemshortcutcontainer.cpp @@ -0,0 +1,254 @@ +/* + * The Mana World + * Copyright (C) 2007 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gui/widgets/itemshortcutcontainer.h" + +#include "configuration.h" +#include "graphics.h" +#include "inventory.h" +#include "item.h" +#include "itemshortcut.h" +#include "keyboardconfig.h" +#include "localplayer.h" + +#include "gui/inventorywindow.h" +#include "gui/itempopup.h" +#include "gui/palette.h" +#include "gui/viewport.h" + +#include "resources/image.h" +#include "resources/iteminfo.h" +#include "resources/resourcemanager.h" + +#include "utils/stringutils.h" + +ItemShortcutContainer::ItemShortcutContainer(): + ShortcutContainer(), + mItemClicked(false), + mItemMoved(NULL) +{ + addMouseListener(this); + addWidgetListener(this); + + mItemPopup = new ItemPopup; + + ResourceManager *resman = ResourceManager::getInstance(); + + mBackgroundImg = resman->getImage("graphics/gui/item_shortcut_bgr.png"); + mMaxItems = itemShortcut->getItemCount(); + + mBackgroundImg->setAlpha(config.getValue("guialpha", 0.8)); + + mBoxHeight = mBackgroundImg->getHeight(); + mBoxWidth = mBackgroundImg->getWidth(); +} + +ItemShortcutContainer::~ItemShortcutContainer() +{ + mBackgroundImg->decRef(); + delete mItemPopup; +} + +void ItemShortcutContainer::draw(gcn::Graphics *graphics) +{ + if (config.getValue("guialpha", 0.8) != mAlpha) + { + mAlpha = config.getValue("guialpha", 0.8); + mBackgroundImg->setAlpha(mAlpha); + } + + Graphics *g = static_cast<Graphics*>(graphics); + + graphics->setFont(getFont()); + + for (int i = 0; i < mMaxItems; i++) + { + const int itemX = (i % mGridWidth) * mBoxWidth; + const int itemY = (i / mGridWidth) * mBoxHeight; + + g->drawImage(mBackgroundImg, itemX, itemY); + + // Draw item keyboard shortcut. + const char *key = SDL_GetKeyName( + (SDLKey) keyboard.getKeyValue(keyboard.KEY_SHORTCUT_1 + i)); + graphics->setColor(guiPalette->getColor(Palette::TEXT)); + g->drawText(key, itemX + 2, itemY + 2, gcn::Graphics::LEFT); + + if (itemShortcut->getItem(i) < 0) + continue; + + Item *item = + player_node->getInventory()->findItem(itemShortcut->getItem(i)); + + if (item) + { + // Draw item icon. + Image* image = item->getImage(); + + if (image) + { + std::string caption; + if (item->getQuantity() > 1) + caption = toString(item->getQuantity()); + else if (item->isEquipped()) + caption = "Eq."; + + g->drawImage(image, itemX, itemY); + if (item->isEquipped()) + g->setColor(guiPalette->getColor(Palette::ITEM_EQUIPPED)); + g->drawText(caption, itemX + mBoxWidth / 2, + itemY + mBoxHeight - 14, gcn::Graphics::CENTER); + } + } + } + + if (mItemMoved) + { + // Draw the item image being dragged by the cursor. + Image* image = mItemMoved->getImage(); + if (image) + { + const int tPosX = mCursorPosX - (image->getWidth() / 2); + const int tPosY = mCursorPosY - (image->getHeight() / 2); + + g->drawImage(image, tPosX, tPosY); + g->drawText(toString(mItemMoved->getQuantity()), + tPosX + mBoxWidth / 2, tPosY + mBoxHeight - 14, + gcn::Graphics::CENTER); + } + } +} + +void ItemShortcutContainer::mouseDragged(gcn::MouseEvent &event) +{ + if (event.getButton() == gcn::MouseEvent::LEFT) + { + if (!mItemMoved && mItemClicked) + { + const int index = getIndexFromGrid(event.getX(), event.getY()); + const int itemId = itemShortcut->getItem(index); + + if (index == -1 || itemId < 0) + return; + + Item *item = player_node->getInventory()->findItem(itemId); + + if (item) + { + mItemMoved = item; + itemShortcut->removeItem(index); + } + } + if (mItemMoved) + { + mCursorPosX = event.getX(); + mCursorPosY = event.getY(); + } + } +} + +void ItemShortcutContainer::mousePressed(gcn::MouseEvent &event) +{ + const int index = getIndexFromGrid(event.getX(), event.getY()); + + if (index == -1) + return; + + if (event.getButton() == gcn::MouseEvent::LEFT) + { + // Stores the selected item if theirs one. + if (itemShortcut->isItemSelected() && inventoryWindow->isVisible()) + { + itemShortcut->setItem(index); + itemShortcut->setItemSelected(-1); + } + else if (itemShortcut->getItem(index)) + mItemClicked = true; + } + else if (event.getButton() == gcn::MouseEvent::RIGHT) + { + Item *item = player_node->getInventory()-> + findItem(itemShortcut->getItem(index)); + + if (!item) + return; + + // Convert relative to the window coordinates to absolute screen + // coordinates. + viewport->showPopup(viewport->getMouseX(), viewport->getMouseY(), item); + } +} + +void ItemShortcutContainer::mouseReleased(gcn::MouseEvent &event) +{ + if (event.getButton() == gcn::MouseEvent::LEFT) + { + if (itemShortcut->isItemSelected()) + itemShortcut->setItemSelected(-1); + + const int index = getIndexFromGrid(event.getX(), event.getY()); + if (index == -1) + { + mItemMoved = NULL; + return; + } + if (mItemMoved) + { + itemShortcut->setItems(index, mItemMoved->getId()); + mItemMoved = NULL; + } + else if (itemShortcut->getItem(index) && mItemClicked) + { + itemShortcut->useItem(index); + } + + if (mItemClicked) + mItemClicked = false; + } +} + +// Show ItemTooltip +void ItemShortcutContainer::mouseMoved(gcn::MouseEvent &event) +{ + const int index = getIndexFromGrid(event.getX(), event.getY()); + const int itemId = itemShortcut->getItem(index); + + if (index == -1 || itemId < 0) + return; + + Item *item = player_node->getInventory()->findItem(itemId); + + if (item) + { + mItemPopup->setItem(item->getInfo()); + mItemPopup->view(viewport->getMouseX(), viewport->getMouseY()); + } + else + { + mItemPopup->setVisible(false); + } +} + +// Hide ItemTooltip +void ItemShortcutContainer::mouseExited(gcn::MouseEvent &event) +{ + mItemPopup->setVisible(false); +} diff --git a/src/gui/widgets/itemshortcutcontainer.h b/src/gui/widgets/itemshortcutcontainer.h new file mode 100644 index 00000000..03d57b8d --- /dev/null +++ b/src/gui/widgets/itemshortcutcontainer.h @@ -0,0 +1,81 @@ +/* + * The Mana World + * Copyright (C) 2007 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef ITEMSHORTCUTCONTAINER_H +#define ITEMSHORTCUTCONTAINER_H + +#include <guichan/mouselistener.hpp> + +#include "gui/widgets/shortcutcontainer.h" + +class Image; +class Item; +class ItemPopup; + +/** + * An item shortcut container. Used to quickly use items. + * + * \ingroup GUI + */ +class ItemShortcutContainer : public ShortcutContainer +{ + public: + /** + * Constructor. Initializes the graphic. + */ + ItemShortcutContainer(); + + /** + * Destructor. + */ + virtual ~ItemShortcutContainer(); + + /** + * Draws the items. + */ + void draw(gcn::Graphics *graphics); + + /** + * Handles mouse when dragged. + */ + void mouseDragged(gcn::MouseEvent &event); + + /** + * Handles mouse when pressed. + */ + void mousePressed(gcn::MouseEvent &event); + + /** + * Handles mouse release. + */ + void mouseReleased(gcn::MouseEvent &event); + + private: + void mouseExited(gcn::MouseEvent &event); + void mouseMoved(gcn::MouseEvent &event); + + bool mItemClicked; + Item *mItemMoved; + + ItemPopup *mItemPopup; +}; + +#endif diff --git a/src/gui/widgets/linkhandler.h b/src/gui/widgets/linkhandler.h new file mode 100644 index 00000000..30267f87 --- /dev/null +++ b/src/gui/widgets/linkhandler.h @@ -0,0 +1,41 @@ +/* + * The Mana World + * Copyright (C) 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef LINK_HANDLER_H +#define LINK_HANDLER_H + +#include <string> + +#include <string> + +/** + * A simple interface to windows that need to handle links from BrowserBox + * widget. + */ +class LinkHandler +{ + public: + virtual ~LinkHandler() { } + + virtual void handleLink(const std::string &link) = 0; +}; + +#endif diff --git a/src/gui/widgets/listbox.cpp b/src/gui/widgets/listbox.cpp index aee0f8d3..baedf8e4 100644 --- a/src/gui/widgets/listbox.cpp +++ b/src/gui/widgets/listbox.cpp @@ -21,10 +21,10 @@ #include "gui/widgets/listbox.h" +#include "configuration.h" + #include "gui/palette.h" #include "gui/sdlinput.h" - -#include "configuration.h" #include "gui/skin.h" #include <guichan/font.hpp> diff --git a/src/gui/widgets/playerbox.cpp b/src/gui/widgets/playerbox.cpp new file mode 100644 index 00000000..4c499c36 --- /dev/null +++ b/src/gui/widgets/playerbox.cpp @@ -0,0 +1,109 @@ +/* + * The Mana World + * Copyright (C) 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gui/widgets/playerbox.h" + +#include "animatedsprite.h" +#include "configuration.h" +#include "graphics.h" +#include "player.h" + +#include "resources/image.h" +#include "resources/resourcemanager.h" + +#include "utils/dtor.h" + +int PlayerBox::instances = 0; +float PlayerBox::mAlpha = 1.0; +ImageRect PlayerBox::background; + +PlayerBox::PlayerBox(const Player *player): + mPlayer(player) +{ + setFrameSize(2); + + if (instances == 0) + { + // Load the background skin + ResourceManager *resman = ResourceManager::getInstance(); + Image *textbox = resman->getImage("graphics/gui/deepbox.png"); + int bggridx[4] = {0, 3, 28, 31}; + int bggridy[4] = {0, 3, 28, 31}; + int a = 0, x, y; + + for (y = 0; y < 3; y++) + { + for (x = 0; x < 3; x++) + { + background.grid[a] = textbox->getSubImage( + bggridx[x], bggridy[y], + bggridx[x + 1] - bggridx[x] + 1, + bggridy[y + 1] - bggridy[y] + 1); + background.grid[a]->setAlpha(config.getValue("guialpha", 0.8)); + a++; + } + } + + textbox->decRef(); + } + + instances++; +} + +PlayerBox::~PlayerBox() +{ + instances--; + + if (instances == 0) + { + for_each(background.grid, background.grid + 9, dtor<Image*>()); + } +} + +void PlayerBox::draw(gcn::Graphics *graphics) +{ + if (mPlayer) + { + // Draw character + const int bs = getFrameSize(); + const int x = getWidth() / 2 + bs; + const int y = getHeight() - bs; + mPlayer->draw(static_cast<Graphics*>(graphics), x, y); + } + + if (config.getValue("guialpha", 0.8) != mAlpha) + { + for (int a = 0; a < 9; a++) + { + background.grid[a]->setAlpha(config.getValue("guialpha", 0.8)); + } + } +} + +void PlayerBox::drawFrame(gcn::Graphics *graphics) +{ + int w, h, bs; + bs = getFrameSize(); + w = getWidth() + bs * 2; + h = getHeight() + bs * 2; + + static_cast<Graphics*>(graphics)->drawImageRect(0, 0, w, h, background); +} diff --git a/src/gui/widgets/playerbox.h b/src/gui/widgets/playerbox.h new file mode 100644 index 00000000..7c08defd --- /dev/null +++ b/src/gui/widgets/playerbox.h @@ -0,0 +1,74 @@ +/* + * The Mana World + * Copyright (C) 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PLAYERBOX_H +#define PLAYERBOX_H + +#include <guichan/widgets/scrollarea.hpp> + +class ImageRect; +class Player; + +/** + * A box showing a player character. + * + * \ingroup GUI + */ +class PlayerBox : public gcn::ScrollArea +{ + public: + /** + * Constructor. Takes the initial player character that this box should + * display, which defaults to <code>NULL</code>. + */ + PlayerBox(const Player *player = NULL); + + /** + * Destructor. + */ + ~PlayerBox(); + + /** + * Sets a new player character to be displayed by this box. Setting the + * player to <code>NULL</code> causes the box not to draw any + * character. + */ + void setPlayer(const Player *player) { mPlayer = player; } + + /** + * Draws the scroll area. + */ + void draw(gcn::Graphics *graphics); + + /** + * Draws the background and border of the scroll area. + */ + void drawFrame(gcn::Graphics *graphics); + + private: + const Player *mPlayer; /**< The character used for display */ + + static float mAlpha; + static int instances; + static ImageRect background; +}; + +#endif diff --git a/src/gui/widgets/popup.cpp b/src/gui/widgets/popup.cpp index 41d60ab6..d801bf32 100644 --- a/src/gui/widgets/popup.cpp +++ b/src/gui/widgets/popup.cpp @@ -22,14 +22,14 @@ #include "gui/widgets/popup.h" -#include "gui/widgets/windowcontainer.h" - -#include "gui/skin.h" - #include "configuration.h" #include "graphics.h" #include "log.h" +#include "gui/skin.h" + +#include "gui/widgets/windowcontainer.h" + #include "resources/image.h" #include <guichan/exception.hpp> diff --git a/src/gui/widgets/progressbar.cpp b/src/gui/widgets/progressbar.cpp index 0eda50a1..1b19ed7c 100644 --- a/src/gui/widgets/progressbar.cpp +++ b/src/gui/widgets/progressbar.cpp @@ -21,16 +21,16 @@ #include "gui/widgets/progressbar.h" -#include "gui/gui.h" -#include "gui/palette.h" -#include "gui/textrenderer.h" - #include "configuration.h" #include "graphics.h" +#include "textrenderer.h" + +#include "gui/gui.h" +#include "gui/palette.h" +#include "gui/skin.h" #include "resources/image.h" #include "resources/resourcemanager.h" -#include "gui/skin.h" #include "utils/dtor.h" diff --git a/src/gui/widgets/scrollarea.cpp b/src/gui/widgets/scrollarea.cpp index eed0ff33..5a2b5d61 100644 --- a/src/gui/widgets/scrollarea.cpp +++ b/src/gui/widgets/scrollarea.cpp @@ -24,9 +24,10 @@ #include "configuration.h" #include "graphics.h" +#include "gui/skin.h" + #include "resources/image.h" #include "resources/resourcemanager.h" -#include "gui/skin.h" #include "utils/dtor.h" diff --git a/src/gui/widgets/setuptab.cpp b/src/gui/widgets/setuptab.cpp new file mode 100644 index 00000000..e585fa5d --- /dev/null +++ b/src/gui/widgets/setuptab.cpp @@ -0,0 +1,27 @@ +/* + * The Mana World + * Copyright (C) 2009 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gui/widgets/setuptab.h" + +SetupTab::SetupTab() +{ + setOpaque(false); +} diff --git a/src/gui/widgets/setuptab.h b/src/gui/widgets/setuptab.h new file mode 100644 index 00000000..f0af1ea9 --- /dev/null +++ b/src/gui/widgets/setuptab.h @@ -0,0 +1,62 @@ +/* + * The Mana World + * Copyright (C) 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef GUI_SETUPTAB_H +#define GUI_SETUPTAB_H + +#include "gui/widgets/container.h" + +#include <string> + +/** + * A container for the contents of a tab in the setup window. + */ +class SetupTab : public Container +{ +public: + SetupTab(); + + const std::string &getName() const + { return mName; } + + /** + * Called when the Apply button is pressed in the setup window. + */ + virtual void apply() = 0; + + /** + * Called when the Cancel button is pressed in the setup window. + */ + virtual void cancel() = 0; + +protected: + /** + * Sets the name displayed on the tab. Should be set in the + * constructor of a subclass. + */ + void setName(const std::string &name) + { mName = name; } + +private: + std::string mName; +}; + +#endif diff --git a/src/gui/widgets/shopitems.cpp b/src/gui/widgets/shopitems.cpp new file mode 100644 index 00000000..f59df591 --- /dev/null +++ b/src/gui/widgets/shopitems.cpp @@ -0,0 +1,103 @@ +/* + * The Mana World + * Copyright (C) 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gui/widgets/shopitems.h" + +#include "shopitem.h" + +#include "utils/dtor.h" + +ShopItems::ShopItems(bool mergeDuplicates) : + mMergeDuplicates(mergeDuplicates) +{ +} + +ShopItems::~ShopItems() +{ + clear(); +} + +int ShopItems::getNumberOfElements() +{ + return mShopItems.size(); +} + +std::string ShopItems::getElementAt(int i) +{ + return mShopItems.at(i)->getDisplayName(); +} + +void ShopItems::addItem(int id, int amount, int price) +{ + mShopItems.push_back(new ShopItem(-1, id, amount, price)); +} + +void ShopItems::addItem(int inventoryIndex, int id, int quantity, int price) +{ + ShopItem *item = 0; + if (mMergeDuplicates) + { + item = findItem(id); + } + + if (item) + { + item->addDuplicate (inventoryIndex, quantity); + } + else + { + item = new ShopItem(inventoryIndex, id, quantity, price); + mShopItems.push_back(item); + } +} + +ShopItem *ShopItems::at(int i) const +{ + return mShopItems.at(i); +} + +void ShopItems::erase(int i) +{ + mShopItems.erase(mShopItems.begin() + i); +} + +void ShopItems::clear() +{ + delete_all(mShopItems); + mShopItems.clear(); +} + +ShopItem *ShopItems::findItem(int id) +{ + ShopItem *item; + + std::vector<ShopItem*>::iterator it; + for (it = mShopItems.begin(); it != mShopItems.end(); it++) + { + item = *(it); + if (item->getId() == id) + { + return item; + } + } + + return 0; +} diff --git a/src/gui/widgets/shopitems.h b/src/gui/widgets/shopitems.h new file mode 100644 index 00000000..28f5d4b3 --- /dev/null +++ b/src/gui/widgets/shopitems.h @@ -0,0 +1,115 @@ +/* + * The Mana World + * Copyright (C) 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef SHOP_H +#define SHOP_H + +#include <guichan/listmodel.hpp> + +#include <string> +#include <vector> + +class ShopItem; + +/** + * This class handles the list of items available in a shop. + * + * The addItem routine can automatically check, if an item already exists and + * only adds duplicates to the old item, if one is found. The original + * distribution of the duplicates can be retrieved from the item. + * + * This functionality can be enabled in the constructor. + */ +class ShopItems : public gcn::ListModel +{ + public: + /** + * Constructor. + * + * @param mergeDuplicates lets the Shop look for duplicate entries and + * merges them to one item. + */ + ShopItems(bool mergeDuplicates = false); + + ~ShopItems(); + + /** + * Adds an item to the list. + */ + void addItem(int id, int amount, int price); + + /** + * Adds an item to the list (used by sell dialog). Looks for + * duplicate entries, if mergeDuplicates was turned on. + * + * @param inventoryIndex the inventory index of the item + * @param id the id of the item + * @param quantity number of available copies of the item + * @param price price of the item + */ + void addItem(int inventoryIndex, int id, int amount, int price); + + /** + * Returns the number of items in the shop. + */ + int getNumberOfElements(); + + /** + * Returns the name of item number i in the shop. + * + * @param i the index to retrieve + */ + std::string getElementAt(int i); + + /** + * Returns the item number i in the shop. + */ + ShopItem *at(int i) const; + + /** + * Removes an element from the shop. + * + * @param i index to remove + */ + void erase(int i); + + /** + * Clears the list of items in the shop. + */ + void clear(); + + private: + /** + * Searches the current items in the shop for the specified + * id and returns the item if found, or 0 else. + * + * @return the item found or 0 + */ + ShopItem *findItem(int id); + + /** The list of items in the shop. */ + std::vector<ShopItem*> mShopItems; + + /** Look for duplicate entries on addition. */ + bool mMergeDuplicates; +}; + +#endif // SHOP_H diff --git a/src/gui/widgets/shoplistbox.cpp b/src/gui/widgets/shoplistbox.cpp new file mode 100644 index 00000000..4779b8c2 --- /dev/null +++ b/src/gui/widgets/shoplistbox.cpp @@ -0,0 +1,157 @@ +/* + * The Mana World + * Copyright (C) 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gui/widgets/shoplistbox.h" + +#include "configuration.h" +#include "graphics.h" +#include "shopitem.h" + +#include "gui/itempopup.h" +#include "gui/palette.h" +#include "gui/viewport.h" + +#include "gui/widgets/shopitems.h" + +#include "resources/image.h" + +#include <guichan/font.hpp> +#include <guichan/listmodel.hpp> + +const int ITEM_ICON_SIZE = 32; + +float ShopListBox::mAlpha = 1.0; + +ShopListBox::ShopListBox(gcn::ListModel *listModel): + ListBox(listModel), + mPlayerMoney(0) +{ + mRowHeight = getFont()->getHeight(); + mPriceCheck = true; + + mItemPopup = new ItemPopup; +} + +ShopListBox::ShopListBox(gcn::ListModel *listModel, ShopItems *shopListModel): + ListBox(listModel), + mPlayerMoney(0), + mShopItems(shopListModel) +{ + mRowHeight = std::max(getFont()->getHeight(), ITEM_ICON_SIZE); + mPriceCheck = true; + + mItemPopup = new ItemPopup; +} + +void ShopListBox::setPlayersMoney(int money) +{ + mPlayerMoney = money; +} + +void ShopListBox::draw(gcn::Graphics *gcnGraphics) +{ + if (!mListModel) + return; + + if (config.getValue("guialpha", 0.8) != mAlpha) + mAlpha = config.getValue("guialpha", 0.8); + + int alpha = (int)(mAlpha * 255.0f); + const gcn::Color* highlightColor = + &guiPalette->getColor(Palette::HIGHLIGHT, alpha); + + Graphics *graphics = static_cast<Graphics*>(gcnGraphics); + + graphics->setFont(getFont()); + + // Draw the list elements + for (int i = 0, y = 0; + i < mListModel->getNumberOfElements(); + ++i, y += mRowHeight) + { + gcn::Color temp; + const gcn::Color* backgroundColor = + &guiPalette->getColor(Palette::BACKGROUND, alpha); + + if (mShopItems && + mPlayerMoney < mShopItems->at(i)->getPrice() && mPriceCheck) + if (i != mSelected) + backgroundColor = &guiPalette->getColor(Palette::SHOP_WARNING, + alpha); + else + { + temp = guiPalette->getColor(Palette::SHOP_WARNING, alpha); + temp.r = (temp.r + highlightColor->r) / 2; + temp.g = (temp.g + highlightColor->g) / 2; + temp.b = (temp.g + highlightColor->b) / 2; + backgroundColor = &temp; + } + else if (i == mSelected) + backgroundColor = highlightColor; + + graphics->setColor(*backgroundColor); + graphics->fillRectangle(gcn::Rectangle(0, y, getWidth(), mRowHeight)); + + if (mShopItems) + { + Image *icon = mShopItems->at(i)->getImage(); + if (icon) + { + icon->setAlpha(1.0f); + graphics->drawImage(icon, 1, y); + } + } + graphics->setColor(guiPalette->getColor(Palette::TEXT)); + graphics->drawText(mListModel->getElementAt(i), ITEM_ICON_SIZE + 5, + y + (ITEM_ICON_SIZE - getFont()->getHeight()) / 2); + } +} + +void ShopListBox::adjustSize() +{ + if (mListModel) + { + setHeight(mRowHeight * mListModel->getNumberOfElements()); + } +} + +void ShopListBox::setPriceCheck(bool check) +{ + mPriceCheck = check; +} + +void ShopListBox::mouseMoved(gcn::MouseEvent &event) +{ + if (!mShopItems) + return; + + Item *item = mShopItems->at(event.getY() / mRowHeight); + + if (item) + { + mItemPopup->setItem(item->getInfo()); + mItemPopup->view(viewport->getMouseX(), viewport->getMouseY()); + } + else + { + mItemPopup->setVisible(false); + } +} diff --git a/src/gui/widgets/shoplistbox.h b/src/gui/widgets/shoplistbox.h new file mode 100644 index 00000000..99d3b9bd --- /dev/null +++ b/src/gui/widgets/shoplistbox.h @@ -0,0 +1,96 @@ +/* + * The Mana World + * Copyright (C) 2004 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef SHOPLISTBOX_H +#define SHOPLISTBOX_H + +#include "gui/widgets/listbox.h" + +class ShopItems; +class ItemPopup; + +/** + * A list box, meant to be used inside a scroll area. Same as the Guichan list + * box except this one doesn't have a background, instead completely relying + * on the scroll area. It also adds selection listener functionality. + * + * \ingroup GUI + */ +class ShopListBox : public ListBox +{ + public: + /** + * Constructor. + */ + ShopListBox(gcn::ListModel *listModel); + + /** + * Constructor with shopitems + */ + ShopListBox(gcn::ListModel *listModel, ShopItems *shopListModel); + + /** + * Draws the list box. + */ + void draw(gcn::Graphics *graphics); + + /** + * Returns the height of a row. + */ + unsigned int getRowHeight() const { return mRowHeight; } + + /** + * gives information about the current player's money + */ + void setPlayersMoney(int money); + + /** + * Adjust List draw size + */ + void adjustSize(); + + /** + * Set on/off the disabling of too expensive items. + * (Good for selling mode.) + */ + void setPriceCheck(bool check); + + void mouseMoved(gcn::MouseEvent &event); + + private: + int mPlayerMoney; + + /** + * Keeps another pointer to the same listModel, permitting to + * use the ShopItems specific functions. + */ + ShopItems *mShopItems; + + ItemPopup *mItemPopup; + + unsigned int mRowHeight; /**< Row Height */ + + static float mAlpha; + + bool mPriceCheck; +}; + +#endif // SHOPLISTBOX_H diff --git a/src/gui/widgets/shortcutcontainer.cpp b/src/gui/widgets/shortcutcontainer.cpp new file mode 100644 index 00000000..61524acc --- /dev/null +++ b/src/gui/widgets/shortcutcontainer.cpp @@ -0,0 +1,64 @@ +/* + * The Mana World + * Copyright (C) 2007 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gui/widgets/shortcutcontainer.h" + +#include "configuration.h" + +#include "resources/image.h" + +#include "utils/stringutils.h" + +float ShortcutContainer::mAlpha = 1.0; + +ShortcutContainer::ShortcutContainer(): + mGridWidth(1), + mGridHeight(1) +{ +} + +void ShortcutContainer::widgetResized(const gcn::Event &event) +{ + mGridWidth = getWidth() / mBoxWidth; + + if (mGridWidth < 1) + mGridWidth = 1; + + mGridHeight = mMaxItems / mGridWidth; + + if (mMaxItems % mGridWidth != 0 || mGridHeight < 1) + ++mGridHeight; + + setHeight(mGridHeight * mBoxHeight); +} + +int ShortcutContainer::getIndexFromGrid(int pointX, int pointY) const +{ + const gcn::Rectangle tRect = gcn::Rectangle(0, 0, mGridWidth * mBoxWidth, + mGridHeight * mBoxHeight); + + int index = ((pointY / mBoxHeight) * mGridWidth) + pointX / mBoxWidth; + + if (!tRect.isPointInRect(pointX, pointY) || index >= mMaxItems) + index = -1; + + return index; +} diff --git a/src/gui/widgets/shortcutcontainer.h b/src/gui/widgets/shortcutcontainer.h new file mode 100644 index 00000000..906201be --- /dev/null +++ b/src/gui/widgets/shortcutcontainer.h @@ -0,0 +1,107 @@ +/* + * The Mana World + * Copyright (C) 2007 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef SHORTCUTCONTAINER_H +#define SHORTCUTCONTAINER_H + +#include <guichan/mouselistener.hpp> +#include <guichan/widget.hpp> +#include <guichan/widgetlistener.hpp> + +class Image; + +/** + * A generic shortcut container. + * + * \ingroup GUI + */ +class ShortcutContainer : public gcn::Widget, + public gcn::WidgetListener, + public gcn::MouseListener +{ + public: + /** + * Constructor. Initializes the shortcut container. + */ + ShortcutContainer(); + + /** + * Destructor. + */ + ~ShortcutContainer() {} + + /** + * Draws the shortcuts + */ + virtual void draw(gcn::Graphics *graphics) = 0; + + /** + * Invoked when a widget changes its size. This is used to determine + * the new height of the container. + */ + virtual void widgetResized(const gcn::Event &event); + + /** + * Handles mouse when dragged. + */ + virtual void mouseDragged(gcn::MouseEvent &event) = 0; + + /** + * Handles mouse when pressed. + */ + virtual void mousePressed(gcn::MouseEvent &event) = 0; + + /** + * Handles mouse release. + */ + virtual void mouseReleased(gcn::MouseEvent &event) = 0; + + int getMaxItems() const + { return mMaxItems; } + + int getBoxWidth() const + { return mBoxWidth; } + + int getBoxHeight() const + { return mBoxHeight; } + + protected: + /** + * Gets the index from the grid provided the point is in an item box. + * + * @param pointX X coordinate of the point. + * @param pointY Y coordinate of the point. + * @return index on success, -1 on failure. + */ + int getIndexFromGrid(int pointX, int pointY) const; + + Image *mBackgroundImg; + + static float mAlpha; + + int mMaxItems; + int mBoxWidth; + int mBoxHeight; + int mCursorPosX, mCursorPosY; + int mGridWidth, mGridHeight; +}; + +#endif diff --git a/src/gui/widgets/slider.cpp b/src/gui/widgets/slider.cpp index 66fe780d..693ac0f7 100644 --- a/src/gui/widgets/slider.cpp +++ b/src/gui/widgets/slider.cpp @@ -24,9 +24,10 @@ #include "configuration.h" #include "graphics.h" +#include "gui/skin.h" + #include "resources/image.h" #include "resources/resourcemanager.h" -#include "gui/skin.h" Image *Slider::hStart, *Slider::hMid, *Slider::hEnd, *Slider::hGrip; Image *Slider::vStart, *Slider::vMid, *Slider::vEnd, *Slider::vGrip; diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tab.cpp index a49c4f12..9abe1f58 100644 --- a/src/gui/widgets/tab.cpp +++ b/src/gui/widgets/tab.cpp @@ -21,12 +21,12 @@ #include "gui/widgets/tab.h" -#include "gui/widgets/tabbedarea.h" +#include "configuration.h" +#include "graphics.h" #include "gui/palette.h" -#include "configuration.h" -#include "graphics.h" +#include "gui/widgets/tabbedarea.h" #include "resources/image.h" #include "resources/resourcemanager.h" diff --git a/src/gui/widgets/tabbedarea.cpp b/src/gui/widgets/tabbedarea.cpp index dd2e62dd..563d995f 100644 --- a/src/gui/widgets/tabbedarea.cpp +++ b/src/gui/widgets/tabbedarea.cpp @@ -20,6 +20,7 @@ */ #include "gui/widgets/tabbedarea.h" + #include "gui/widgets/tab.h" #include <guichan/widgets/container.hpp> diff --git a/src/gui/widgets/table.cpp b/src/gui/widgets/table.cpp new file mode 100644 index 00000000..f33d0abe --- /dev/null +++ b/src/gui/widgets/table.cpp @@ -0,0 +1,549 @@ +/* + * The Mana World + * Copyright (C) 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gui/widgets/table.h" + +#include "configuration.h" + +#include "gui/palette.h" +#include "gui/sdlinput.h" + +#include "utils/dtor.h" + +#include <guichan/actionlistener.hpp> +#include <guichan/graphics.hpp> +#include <guichan/key.hpp> + +float GuiTable::mAlpha = 1.0; + +class GuiTableActionListener : public gcn::ActionListener +{ +public: + GuiTableActionListener(GuiTable *_table, gcn::Widget *_widget, int _row, int _column); + + virtual ~GuiTableActionListener(); + + virtual void action(const gcn::ActionEvent& actionEvent); + +protected: + GuiTable *mTable; + int mRow; + int mColumn; + gcn::Widget *mWidget; +}; + + +GuiTableActionListener::GuiTableActionListener(GuiTable *table, gcn::Widget *widget, int row, int column) : + mTable(table), + mRow(row), + mColumn(column), + mWidget(widget) +{ + if (widget) + { + widget->addActionListener(this); + widget->_setParent(table); + } +} + +GuiTableActionListener::~GuiTableActionListener() +{ + if (mWidget) + { + mWidget->removeActionListener(this); + mWidget->_setParent(NULL); + } +} + +void GuiTableActionListener::action(const gcn::ActionEvent& actionEvent) +{ + mTable->setSelected(mRow, mColumn); + mTable->distributeActionEvent(); +} + + +GuiTable::GuiTable(TableModel *initial_model, gcn::Color background, + bool opacity) : + mLinewiseMode(false), + mWrappingEnabled(false), + mOpaque(opacity), + mBackgroundColor(background), + mModel(NULL), + mSelectedRow(0), + mSelectedColumn(0), + mTopWidget(NULL) +{ + setModel(initial_model); + setFocusable(true); + + addMouseListener(this); + addKeyListener(this); +} + +GuiTable::~GuiTable() +{ + uninstallActionListeners(); + delete mModel; +} + +TableModel *GuiTable::getModel() const +{ + return mModel; +} + +void GuiTable::setModel(TableModel *new_model) +{ + if (mModel) + { + uninstallActionListeners(); + mModel->removeListener(this); + } + + mModel = new_model; + installActionListeners(); + + if (new_model) + { + new_model->installListener(this); + recomputeDimensions(); + } +} + +void GuiTable::recomputeDimensions() +{ + int rows_nr = mModel->getRows(); + int columns_nr = mModel->getColumns(); + int width = 0; + int height = 0; + + if (mSelectedRow >= rows_nr) + mSelectedRow = rows_nr - 1; + + if (mSelectedColumn >= columns_nr) + mSelectedColumn = columns_nr - 1; + + for (int i = 0; i < columns_nr; i++) + width += getColumnWidth(i); + + height = getRowHeight() * rows_nr; + + setWidth(width); + setHeight(height); +} + +void GuiTable::setSelected(int row, int column) +{ + mSelectedColumn = column; + mSelectedRow = row; +} + +int GuiTable::getSelectedRow() const +{ + return mSelectedRow; +} + +int GuiTable::getSelectedColumn() const +{ + return mSelectedColumn; +} + +void GuiTable::setLinewiseSelection(bool linewise) +{ + mLinewiseMode = linewise; +} + +int GuiTable::getRowHeight() const +{ + if (mModel) + return mModel->getRowHeight() + 1; // border + else + return 0; +} + +int GuiTable::getColumnWidth(int i) const +{ + if (mModel) + return mModel->getColumnWidth(i) + 1; // border + else + return 0; +} + +void GuiTable::setSelectedRow(int selected) +{ + if (!mModel) + { + mSelectedRow = -1; + } + else + { + if (selected < 0 && !mWrappingEnabled) + { + mSelectedRow = -1; + } + else if (selected >= mModel->getRows() && mWrappingEnabled) + { + mSelectedRow = 0; + } + else if ((selected >= mModel->getRows() && !mWrappingEnabled) || + (selected < 0 && mWrappingEnabled)) + { + mSelectedRow = mModel->getRows() - 1; + } + else + { + mSelectedRow = selected; + } + } +} + +void GuiTable::setSelectedColumn(int selected) +{ + if (!mModel) + { + mSelectedColumn = -1; + } + else + { + if ((selected >= mModel->getColumns() && mWrappingEnabled) || + (selected < 0 && !mWrappingEnabled)) + { + mSelectedColumn = 0; + } + else if ((selected >= mModel->getColumns() && !mWrappingEnabled) || + (selected < 0 && mWrappingEnabled)) + { + mSelectedColumn = mModel->getColumns() - 1; + } + else + { + mSelectedColumn = selected; + } + } +} + +void GuiTable::uninstallActionListeners() +{ + delete_all(mActionListeners); + mActionListeners.clear(); +} + +void GuiTable::installActionListeners() +{ + if (!mModel) + return; + + int rows = mModel->getRows(); + int columns = mModel->getColumns(); + + for (int row = 0; row < rows; ++row) + for (int column = 0; column < columns; ++column) + { + gcn::Widget *widget = mModel->getElementAt(row, column); + mActionListeners.push_back(new GuiTableActionListener(this, widget, + row, column)); + } + + _setFocusHandler(_getFocusHandler()); // propagate focus handler to widgets +} + +// -- widget ops +void GuiTable::draw(gcn::Graphics* graphics) +{ + if (!mModel) + return; + + if (config.getValue("guialpha", 0.8) != mAlpha) + mAlpha = config.getValue("guialpha", 0.8); + + if (mOpaque) + { + graphics->setColor(guiPalette->getColor(Palette::BACKGROUND, + (int)(mAlpha * 255.0f))); + graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight())); + } + + // First, determine how many rows we need to draw, and where we should start. + int first_row = -(getY() / getRowHeight()); + + if (first_row < 0) + first_row = 0; + + int rows_nr = 1 + (getHeight() / getRowHeight()); // May overestimate by one. + + int max_rows_nr = mModel->getRows() - first_row; // clip if neccessary: + if (max_rows_nr < rows_nr) + rows_nr = max_rows_nr; + + // Now determine the first and last column + // Take the easy way out; these are usually bounded and all visible. + int first_column = 0; + int last_column = mModel->getColumns() - 1; + + // Set up everything for drawing + int height = getRowHeight(); + int y_offset = first_row * height; + + for (int r = first_row; r < first_row + rows_nr; ++r) + { + int x_offset = 0; + + for (int c = first_column; c <= last_column; ++c) + { + gcn::Widget *widget = mModel->getElementAt(r, c); + int width = getColumnWidth(c); + if (widget) + { + gcn::Rectangle bounds(x_offset, y_offset, width, height); + + if (widget == mTopWidget) + { + bounds.height = widget->getHeight(); + bounds.width = widget->getWidth(); + } + + widget->setDimension(bounds); + + graphics->setColor(guiPalette->getColor(Palette::HIGHLIGHT, + (int)(mAlpha * 255.0f))); + + if (mLinewiseMode && r == mSelectedRow && c == 0) + { + graphics->fillRectangle(gcn::Rectangle(0, y_offset, + getWidth(), height)); + } + else if (!mLinewiseMode && + c == mSelectedColumn && r == mSelectedRow) + { + graphics->fillRectangle(gcn::Rectangle(x_offset, y_offset, + width, height)); + } + + graphics->pushClipArea(bounds); + widget->draw(graphics); + graphics->popClipArea(); + } + + x_offset += width; + } + + y_offset += height; + } + + if (mTopWidget) + { + gcn::Rectangle bounds = mTopWidget->getDimension(); + graphics->pushClipArea(bounds); + mTopWidget->draw(graphics); + graphics->popClipArea(); + } +} + +void GuiTable::moveToTop(gcn::Widget *widget) +{ + gcn::Widget::moveToTop(widget); + mTopWidget = widget; +} + +void GuiTable::moveToBottom(gcn::Widget *widget) +{ + gcn::Widget::moveToBottom(widget); + if (widget == mTopWidget) + mTopWidget = NULL; +} + +gcn::Rectangle GuiTable::getChildrenArea() const +{ + return gcn::Rectangle(0, 0, getWidth(), getHeight()); +} + +// -- KeyListener notifications +void GuiTable::keyPressed(gcn::KeyEvent& keyEvent) +{ + gcn::Key key = keyEvent.getKey(); + + if (key.getValue() == Key::ENTER || key.getValue() == Key::SPACE) + { + distributeActionEvent(); + keyEvent.consume(); + } + else if (key.getValue() == Key::UP) + { + setSelectedRow(mSelectedRow - 1); + keyEvent.consume(); + } + else if (key.getValue() == Key::DOWN) + { + setSelectedRow(mSelectedRow + 1); + keyEvent.consume(); + } + else if (key.getValue() == Key::LEFT) + { + setSelectedColumn(mSelectedColumn - 1); + keyEvent.consume(); + } + else if (key.getValue() == Key::RIGHT) + { + setSelectedColumn(mSelectedColumn + 1); + keyEvent.consume(); + } + else if (key.getValue() == Key::HOME) + { + setSelectedRow(0); + setSelectedColumn(0); + keyEvent.consume(); + } + else if (key.getValue() == Key::END) + { + setSelectedRow(mModel->getRows() - 1); + setSelectedColumn(mModel->getColumns() - 1); + keyEvent.consume(); + } +} + +// -- MouseListener notifications +void GuiTable::mousePressed(gcn::MouseEvent& mouseEvent) +{ + if (mouseEvent.getButton() == gcn::MouseEvent::LEFT) + { + int row = getRowForY(mouseEvent.getY()); + int column = getColumnForX(mouseEvent.getX()); + + if (row > -1 && column > -1 && + row < mModel->getRows() && column < mModel->getColumns()) + { + mSelectedColumn = column; + mSelectedRow = row; + } + + distributeActionEvent(); + } +} + +void GuiTable::mouseWheelMovedUp(gcn::MouseEvent& mouseEvent) +{ + if (isFocused()) + { + if (getSelectedRow() > 0 || (getSelectedRow() == 0 && mWrappingEnabled)) + { + setSelectedRow(getSelectedRow() - 1); + } + + mouseEvent.consume(); + } +} + +void GuiTable::mouseWheelMovedDown(gcn::MouseEvent& mouseEvent) +{ + if (isFocused()) + { + setSelectedRow(getSelectedRow() + 1); + + mouseEvent.consume(); + } +} + +void GuiTable::mouseDragged(gcn::MouseEvent& mouseEvent) +{ +} + +// -- TableModelListener notifications +void GuiTable::modelUpdated(bool completed) +{ + if (completed) + { + recomputeDimensions(); + installActionListeners(); + } + else + { // before the update? + mTopWidget = NULL; // No longer valid in general + uninstallActionListeners(); + } +} + +gcn::Widget *GuiTable::getWidgetAt(int x, int y) const +{ + int row = getRowForY(y); + int column = getColumnForX(x); + + if (mTopWidget && mTopWidget->getDimension().isPointInRect(x, y)) + return mTopWidget; + + if (row > -1 && column > -1) + { + gcn::Widget *w = mModel->getElementAt(row, column); + if (w && w->isFocusable()) + return w; + else + return NULL; // Grab the event locally + } + else + return NULL; +} + +int GuiTable::getRowForY(int y) const +{ + int row = -1; + + if (getRowHeight() > 0) + row = y / getRowHeight(); + + if (row < 0 || row >= mModel->getRows()) + return -1; + else + return row; +} + +int GuiTable::getColumnForX(int x) const +{ + int column; + int delta = 0; + + for (column = 0; column < mModel->getColumns(); column++) + { + delta += getColumnWidth(column); + if (x <= delta) + break; + } + + if (column < 0 || column >= mModel->getColumns()) + return -1; + else + return column; +} + +void GuiTable::_setFocusHandler(gcn::FocusHandler* focusHandler) +{ + gcn::Widget::_setFocusHandler(focusHandler); + + if (mModel) + { + for (int r = 0; r < mModel->getRows(); ++r) + { + for (int c = 0; c < mModel->getColumns(); ++c) + { + gcn::Widget *w = mModel->getElementAt(r, c); + if (w) + w->_setFocusHandler(focusHandler); + } + } + } +} diff --git a/src/gui/widgets/table.h b/src/gui/widgets/table.h new file mode 100644 index 00000000..d1f445b3 --- /dev/null +++ b/src/gui/widgets/table.h @@ -0,0 +1,185 @@ +/* + * The Mana World + * Copyright (C) 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TABLE_H +#define TABLE_H + +#include "tablemodel.h" + +#include <guichan/keylistener.hpp> +#include <guichan/mouselistener.hpp> +#include <guichan/widget.hpp> + +#include <vector> + +class GuiTableActionListener; + +/** + * A table, with rows and columns made out of sub-widgets. Largely inspired by + * (and can be thought of as a generalisation of) the guichan listbox + * implementation. + * + * Normally you want this within a ScrollArea. + * + * \ingroup GUI + */ +class GuiTable : public gcn::Widget, + public gcn::MouseListener, + public gcn::KeyListener, + public TableModelListener +{ + // so that the action listener can call distributeActionEvent + friend class GuiTableActionListener; + +public: + GuiTable(TableModel * initial_model = NULL, gcn::Color background = 0xffffff, + bool opacity = true); + + virtual ~GuiTable(); + + /** + * Retrieves the active table model + */ + TableModel *getModel() const; + + /** + * Sets the table model + * + * Note that actions issued by widgets returned from the model will update + * the table selection, but only AFTER any event handlers installed within + * the widget have been triggered. To be notified after such an update, add + * an action listener to the table instead. + */ + void setModel(TableModel *m); + + void setSelected(int row, int column); + + int getSelectedRow() const; + + int getSelectedColumn() const; + + void setSelectedRow(int selected); + + void setSelectedColumn(int selected); + + bool isWrappingEnabled() const {return mWrappingEnabled;} + + void setWrappingEnabled(bool wrappingEnabled) + {mWrappingEnabled = wrappingEnabled;} + + gcn::Rectangle getChildrenArea() const; + + /** + * Toggle whether to use linewise selection mode, in which the table selects + * an entire line at a time, rather than a single cell. + * + * Note that column information is tracked even in linewise selection mode; + * this mode therefore only affects visualisation. + * + * Disabled by default. + * + * \param linewise: Whether to enable linewise selection mode + */ + void setLinewiseSelection(bool linewise); + + // Inherited from Widget + virtual void draw(gcn::Graphics* graphics); + + virtual gcn::Widget *getWidgetAt(int x, int y) const; + + virtual void moveToTop(gcn::Widget *child); + + virtual void moveToBottom(gcn::Widget *child); + + virtual void _setFocusHandler(gcn::FocusHandler* focusHandler); + + // Inherited from KeyListener + virtual void keyPressed(gcn::KeyEvent& keyEvent); + + /** + * Sets the table to be opaque, that is sets the table + * to display its background. + * + * @param opaque True if the table should be opaque, false otherwise. + */ + virtual void setOpaque(bool opaque) {mOpaque = opaque;} + + /** + * Checks if the table is opaque, that is if the table area displays its + * background. + * + * @return True if the table is opaque, false otherwise. + */ + virtual bool isOpaque() const {return mOpaque;} + + // Inherited from MouseListener + virtual void mousePressed(gcn::MouseEvent& mouseEvent); + + virtual void mouseWheelMovedUp(gcn::MouseEvent& mouseEvent); + + virtual void mouseWheelMovedDown(gcn::MouseEvent& mouseEvent); + + virtual void mouseDragged(gcn::MouseEvent& mouseEvent); + + // Constraints inherited from TableModelListener + virtual void modelUpdated(bool); + +protected: + /** Frees all action listeners on inner widgets. */ + virtual void uninstallActionListeners(); + /** Installs all action listeners on inner widgets. */ + virtual void installActionListeners(); + + virtual int getRowHeight() const; + virtual int getColumnWidth(int i) const; + +private: + int getRowForY(int y) const; // -1 on error + int getColumnForX(int x) const; // -1 on error + void recomputeDimensions(); + bool mLinewiseMode; + bool mWrappingEnabled; + bool mOpaque; + + static float mAlpha; + + /** + * Holds the background color of the table. + */ + gcn::Color mBackgroundColor; + + TableModel *mModel; + + int mSelectedRow; + int mSelectedColumn; + + /** Number of frames to skip upwards when drawing the selected widget. */ + int mPopFramesNr; + + /** If someone moves a fresh widget to the top, we must display it. */ + gcn::Widget *mTopWidget; + + /** Vector for compactness; used as a list in practice. */ + std::vector<GuiTableActionListener *> mActionListeners; +}; + + +#endif // TABLE_H diff --git a/src/gui/widgets/tablemodel.cpp b/src/gui/widgets/tablemodel.cpp new file mode 100644 index 00000000..db06edec --- /dev/null +++ b/src/gui/widgets/tablemodel.cpp @@ -0,0 +1,161 @@ +/* + * The Mana World + * Copyright (C) 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "gui/widgets/tablemodel.h" + +#include "utils/dtor.h" + +#include <guichan/widget.hpp> + +void TableModel::installListener(TableModelListener *listener) +{ + listeners.insert(listener); +} + +void TableModel::removeListener(TableModelListener *listener) +{ + listeners.erase(listener); +} + +void TableModel::signalBeforeUpdate() +{ + for (std::set<TableModelListener *>::const_iterator it = listeners.begin(); it != listeners.end(); it++) + (*it)->modelUpdated(false); +} + +void TableModel::signalAfterUpdate() +{ + for (std::set<TableModelListener *>::const_iterator it = listeners.begin(); it != listeners.end(); it++) + (*it)->modelUpdated(true); +} + + +#define WIDGET_AT(row, column) (((row) * mColumns) + (column)) +#define DYN_SIZE(h) ((h) >= 0) // determines whether this size is tagged for auto-detection + +StaticTableModel::StaticTableModel(int row, int column) : + mRows(row), + mColumns(column), + mHeight(1) +{ + mTableModel.resize(row * column, NULL); + mWidths.resize(column, 1); +} + +StaticTableModel::~StaticTableModel() +{ + delete_all(mTableModel); +} + +void StaticTableModel::resize() +{ + mRows = getRows(); + mColumns = getColumns(); + mTableModel.resize(mRows * mColumns, NULL); +} + +void StaticTableModel::set(int row, int column, gcn::Widget *widget) +{ + if (row >= mRows || row < 0 + || column >= mColumns || column < 0) + // raise exn? + return; + + if (DYN_SIZE(mHeight) + && widget->getHeight() > mHeight) + mHeight = widget->getHeight(); + + if (DYN_SIZE(mWidths[column]) + && widget->getWidth() > mWidths[column]) + mWidths[column] = widget->getWidth(); + + signalBeforeUpdate(); + + if (mTableModel[WIDGET_AT(row, column)]) + delete mTableModel[WIDGET_AT(row, column)]; + + mTableModel[WIDGET_AT(row, column)] = widget; + + signalAfterUpdate(); +} + +gcn::Widget *StaticTableModel::getElementAt(int row, int column) const +{ + return mTableModel[WIDGET_AT(row, column)]; +} + +void StaticTableModel::fixColumnWidth(int column, int width) +{ + if (width < 0 + || column < 0 || column >= mColumns) + return; + + mWidths[column] = -width; // Negate to tag as fixed +} + +void StaticTableModel::fixRowHeight(int height) +{ + if (height < 0) + return; + + mHeight = -height; +} + +int StaticTableModel::getRowHeight() const +{ + return abs(mHeight); +} + +int StaticTableModel::getColumnWidth(int column) const +{ + if (column < 0 || column >= mColumns) + return 0; + + return abs(mWidths[column]); +} + +int StaticTableModel::getRows() const +{ + return mRows; +} + +int StaticTableModel::getColumns() const +{ + return mColumns; +} + +int StaticTableModel::getWidth() const +{ + int width = 0; + + for (unsigned int i = 0; i < mWidths.size(); i++) + { + width += mWidths[i]; + } + + return width; +} + +int StaticTableModel::getHeight() const +{ + return mColumns * mHeight; +} + diff --git a/src/gui/widgets/tablemodel.h b/src/gui/widgets/tablemodel.h new file mode 100644 index 00000000..129d2089 --- /dev/null +++ b/src/gui/widgets/tablemodel.h @@ -0,0 +1,146 @@ +/* + * The Mana World + * Copyright (C) 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TABLE_MODEL_H +#define TABLE_MODEL_H + +#include <guichanfwd.h> + +#include <set> +#include <vector> + +class TableModelListener +{ +public: + /** + * Must be invoked by the TableModel whenever a global change is about to + * occur or has occurred (e.g., when a row or column is being removed or + * added). + * + * This method is triggered twice, once before and once after the update. + * + * \param completed whether we are signalling the end of the update + */ + virtual void modelUpdated(bool completed) = 0; +}; + +/** + * A model for a regular table of widgets. + */ +class TableModel +{ +public: + virtual ~TableModel() { } + + /** + * Determines the number of rows (lines) in the table + */ + virtual int getRows() const = 0; + + /** + * Determines the number of columns in each row + */ + virtual int getColumns() const = 0; + + /** + * Determines the height for each row + */ + virtual int getRowHeight() const = 0; + + /** + * Determines the width of each individual column + */ + virtual int getColumnWidth(int index) const = 0; + + /** + * Retrieves the widget stored at the specified location within the table. + */ + virtual gcn::Widget *getElementAt(int row, int column) const = 0; + + virtual void installListener(TableModelListener *listener); + + virtual void removeListener(TableModelListener *listener); + +protected: + /** + * Tells all listeners that the table is about to see an update + */ + virtual void signalBeforeUpdate(); + + /** + * Tells all listeners that the table has seen an update + */ + virtual void signalAfterUpdate(); + +private: + std::set<TableModelListener *> listeners; +}; + + +class StaticTableModel : public TableModel +{ +public: + StaticTableModel(int width, int height); + virtual ~StaticTableModel(); + + /** + * Inserts a widget into the table model. + * The model is resized to accomodate the widget's width and height, + * unless column width / row height have been fixed. + */ + virtual void set(int row, int column, gcn::Widget *widget); + + /** + * Fixes the column width for a given column; this overrides dynamic width + * inference. + * + * Semantics are undefined for width 0. + */ + virtual void fixColumnWidth(int column, int width); + + /** + * Fixes the row height; this overrides dynamic height inference. + * + * Semantics are undefined for width 0. + */ + virtual void fixRowHeight(int height); + + /** + * Resizes the table model + */ + virtual void resize(); + + virtual int getRows() const; + virtual int getColumns() const; + virtual int getRowHeight() const; + virtual int getWidth() const; + virtual int getHeight() const; + virtual int getColumnWidth(int index) const; + virtual gcn::Widget *getElementAt(int row, int column) const; + +protected: + int mRows, mColumns; + int mHeight; + std::vector<gcn::Widget *> mTableModel; + std::vector<int> mWidths; +}; + +#endif // TABLE_MODEL_H diff --git a/src/gui/widgets/textfield.cpp b/src/gui/widgets/textfield.cpp index 0f0caa00..c0c42718 100644 --- a/src/gui/widgets/textfield.cpp +++ b/src/gui/widgets/textfield.cpp @@ -21,15 +21,15 @@ #include "gui/widgets/textfield.h" -#include "gui/palette.h" -#include "gui/sdlinput.h" - #include "configuration.h" #include "graphics.h" +#include "gui/palette.h" +#include "gui/sdlinput.h" +#include "gui/skin.h" + #include "resources/image.h" #include "resources/resourcemanager.h" -#include "gui/skin.h" #include "utils/dtor.h" diff --git a/src/gui/widgets/textpreview.cpp b/src/gui/widgets/textpreview.cpp index 0113c09f..ba2b557b 100644 --- a/src/gui/widgets/textpreview.cpp +++ b/src/gui/widgets/textpreview.cpp @@ -21,13 +21,13 @@ #include "gui/widgets/textpreview.h" +#include "configuration.h" +#include "textrenderer.h" + #include "gui/gui.h" #include "gui/palette.h" -#include "gui/textrenderer.h" #include "gui/truetypefont.h" -#include "configuration.h" - #include <typeinfo> float TextPreview::mAlpha = 1.0; diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp index 8d7b442b..ada1e957 100644 --- a/src/gui/widgets/window.cpp +++ b/src/gui/widgets/window.cpp @@ -21,16 +21,16 @@ #include "gui/widgets/window.h" -#include "gui/widgets/layout.h" -#include "gui/widgets/resizegrip.h" -#include "gui/widgets/windowcontainer.h" +#include "configuration.h" +#include "log.h" #include "gui/gui.h" #include "gui/palette.h" #include "gui/skin.h" -#include "configuration.h" -#include "log.h" +#include "gui/widgets/layout.h" +#include "gui/widgets/resizegrip.h" +#include "gui/widgets/windowcontainer.h" #include "resources/image.h" |