diff options
-rw-r--r-- | src/graphics.h | 10 | ||||
-rw-r--r-- | src/gui/skilldialog.cpp | 366 | ||||
-rw-r--r-- | src/gui/skilldialog.h | 2 | ||||
-rw-r--r-- | src/gui/widgets/progressbar.cpp | 61 | ||||
-rw-r--r-- | src/gui/widgets/progressbar.h | 8 |
5 files changed, 288 insertions, 159 deletions
diff --git a/src/graphics.h b/src/graphics.h index 591b4166..2b38608f 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -173,6 +173,16 @@ class Graphics : public gcn::SDLGraphics const ImageRect &imgRect); /** + * Draws a rectangle using images. 4 corner images, 4 side images and 1 + * image for the inside. + */ + inline void drawImageRect(const gcn::Rectangle &area, + const ImageRect &imgRect) + { + drawImageRect(area.x, area.y, area.width, area.height, imgRect); + } + + /** * Updates the screen. This is done by either copying the buffer to the * screen or swapping pages. */ diff --git a/src/gui/skilldialog.cpp b/src/gui/skilldialog.cpp index ceec3273..132b1a49 100644 --- a/src/gui/skilldialog.cpp +++ b/src/gui/skilldialog.cpp @@ -28,7 +28,6 @@ #include "gui/widgets/button.h" #include "gui/widgets/container.h" -#include "gui/widgets/icon.h" #include "gui/widgets/label.h" #include "gui/widgets/layouthelper.h" #include "gui/widgets/listbox.h" @@ -36,50 +35,151 @@ #include "gui/widgets/scrollarea.h" #include "gui/widgets/tab.h" #include "gui/widgets/tabbedarea.h" -#include "gui/widgets/vertcontainer.h" #include "gui/widgets/windowcontainer.h" #include "net/net.h" #include "net/playerhandler.h" +#include "resources/image.h" +#include "resources/resourcemanager.h" + #include "utils/dtor.h" #include "utils/gettext.h" #include "utils/stringutils.h" #include "utils/xml.h" +#include <guichan/font.hpp> + +#include <set> #include <string> +class SkillModel; class SkillEntry; struct SkillInfo { unsigned short id; std::string name; - std::string icon; + Image *icon; bool modifiable; - SkillEntry *display; + bool visible; + SkillModel *model; + + std::string skillLevel; + int skillLevelWidth; + + std::string skillExp; + float progress; + + ~SkillInfo() + { + icon->decRef(); + } + + void setIcon(std::string iconPath) + { + ResourceManager *res = ResourceManager::getInstance(); + if (!iconPath.empty()) + { + icon = res->getImage(iconPath); + } + else + { + icon = res->getImage("graphics/gui/unknown-item.png"); + } + + icon->incRef(); + } + + void update(); + + void draw(Graphics *graphics, int y, int width); }; -class SkillEntry : public Container, gcn::WidgetListener +typedef std::vector<SkillInfo*> SkillList; + +class SkillModel : public gcn::ListModel { - public: - SkillEntry(SkillInfo *info); +public: + int getNumberOfElements() { return mVisibleSkills.size(); } + SkillInfo *getSkillAt(int i) { return mVisibleSkills.at(i); } + std::string getElementAt(int i) { return getSkillAt(i)->name; } + void updateVisibilities(); + void addSkill(SkillInfo *info) { mSkills.push_back(info); } + +private: + SkillList mSkills; + SkillList mVisibleSkills; +}; - void widgetResized(const gcn::Event &event); +class SkillListBox : public ListBox +{ +public: + SkillListBox(SkillModel *model): + ListBox(model) + {} - void update(); + SkillInfo *getSelectedInfo() + { + return static_cast<SkillModel*>(mListModel)->getSkillAt(getSelected()); + } - protected: - friend class SkillDialog; - SkillInfo *mInfo; + void draw(gcn::Graphics *gcnGraphics) + { + SkillModel* model = dynamic_cast<SkillModel*>(mListModel); + + if (!model) + return; + + updateAlpha(); + + Graphics *graphics = static_cast<Graphics*>(gcnGraphics); - private: - Icon *mIcon; - Label *mNameLabel; - Label *mLevelLabel; - Label *mExpLabel; - Button *mIncrease; - ProgressBar *mProgress; + graphics->setColor(guiPalette->getColor(Palette::HIGHLIGHT, + (int)(mAlpha * 255.0f))); + graphics->setFont(getFont()); + + // Draw filled rectangle around the selected list element + if (mSelected >= 0) + { + graphics->fillRectangle(gcn::Rectangle(0, getRowHeight() * mSelected, + getWidth(), getRowHeight())); + } + + // Draw the list elements + graphics->setColor(guiPalette->getColor(Palette::TEXT)); + for (int i = 0, y = 1; + i < model->getNumberOfElements(); + ++i, y += getRowHeight()) + { + SkillInfo *e = model->getSkillAt(i); + + if (e) + { + e->draw(graphics, y, getWidth()); + } + } + } + + unsigned int getRowHeight() const { return 34; } +}; + +class SkillTab : public Tab +{ +public: + SkillTab(const std::string &name, SkillListBox *listBox): + mListBox(listBox) + { + setCaption(name); + } + + SkillInfo *getSelectedInfo() + { + return mListBox->getSelectedInfo(); + } + +private: + SkillListBox *mListBox; }; SkillDialog::SkillDialog(): @@ -94,9 +194,11 @@ SkillDialog::SkillDialog(): mTabs = new TabbedArea(); mPointsLabel = new Label("0"); + mIncreaseButton = new Button(_("Up"), "inc", this); place(0, 0, mTabs, 5, 5); - place(0, 5, mPointsLabel, 2); + place(0, 5, mPointsLabel, 4); + place(4, 5, mIncreaseButton); setLocationRelativeTo(getParent()); loadWindowState(); @@ -112,15 +214,23 @@ void SkillDialog::action(const gcn::ActionEvent &event) { if (event.getId() == "inc") { - SkillEntry *disp = dynamic_cast<SkillEntry*>(event.getSource()->getParent()); + SkillTab *tab = dynamic_cast<SkillTab*>(mTabs->getSelectedTab()); + + if (tab) + { + SkillInfo *info = tab->getSelectedInfo(); - if (disp) - Net::getPlayerHandler()->increaseSkill(disp->mInfo->id); + Net::getPlayerHandler()->increaseSkill(info->id); + } } else if (event.getId() == "close") { setVisible(false); } + else + { + printf("Unknown event '%s'\n", event.getId().c_str()); + } } std::string SkillDialog::update(int id) @@ -130,7 +240,7 @@ std::string SkillDialog::update(int id) if (i != mSkills.end()) { SkillInfo *info = i->second; - info->display->update(); + info->update(); return info->name; } @@ -146,22 +256,25 @@ void SkillDialog::update() for (SkillMap::iterator it = mSkills.begin(); it != mSkills.end(); it++) { if ((*it).second->modifiable) - (*it).second->display->update(); + (*it).second->update(); } } void SkillDialog::loadSkills(const std::string &file) { - // TODO: mTabs->clear(); - while (mTabs->getSelectedTabIndex() != -1) + // Fixes issues with removing tabs + if (mTabs->getSelectedTabIndex() != -1) { - mTabs->removeTabWithIndex(mTabs->getSelectedTabIndex()); - } + mTabs->setSelectedTab((unsigned int) 0); - for (SkillMap::iterator it = mSkills.begin(); it != mSkills.end(); it++) - { - delete (*it).second->display; + while (mTabs->getSelectedTabIndex() != -1) + { + gcn::Tab *tab = mTabs->getSelectedTab(); + mTabs->removeTabWithIndex(mTabs->getSelectedTabIndex()); + delete tab; + } } + delete_all(mSkills); mSkills.clear(); @@ -180,7 +293,8 @@ void SkillDialog::loadSkills(const std::string &file) int setCount = 0; std::string setName; ScrollArea *scroll; - VertContainer *container; + SkillListBox *listbox; + SkillTab *tab; for_each_xml_child_node(set, root) { @@ -189,14 +303,8 @@ void SkillDialog::loadSkills(const std::string &file) setCount++; setName = XML::getProperty(set, "name", strprintf(_("Skill Set %d"), setCount)); - container = new VertContainer(32); - container->setOpaque(false); - scroll = new ScrollArea(container); - scroll->setOpaque(false); - scroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER); - scroll->setVerticalScrollPolicy(ScrollArea::SHOW_ALWAYS); + SkillModel *model = new SkillModel(); - mTabs->addTab(setName, scroll); for_each_xml_child_node(node, set) { if (xmlStrEqual(node->name, BAD_CAST "skill")) @@ -208,15 +316,29 @@ void SkillDialog::loadSkills(const std::string &file) SkillInfo *skill = new SkillInfo; skill->id = id; skill->name = name; - skill->icon = icon; - skill->modifiable = 0; - skill->display = new SkillEntry(skill); + skill->setIcon(icon); + skill->modifiable = false; + skill->visible = false; + skill->model = model; + skill->update(); - container->add(skill->display); + model->addSkill(skill); mSkills[id] = skill; } } + + model->updateVisibilities(); + + listbox = new SkillListBox(model); + scroll = new ScrollArea(listbox); + scroll->setOpaque(false); + scroll->setHorizontalScrollPolicy(ScrollArea::SHOW_NEVER); + scroll->setVerticalScrollPolicy(ScrollArea::SHOW_ALWAYS); + + tab = new SkillTab(setName, listbox); + + mTabs->addTab(tab, scroll); } } update(); @@ -224,133 +346,103 @@ void SkillDialog::loadSkills(const std::string &file) void SkillDialog::setModifiable(int id, bool modifiable) { - SkillMap::iterator i = mSkills.find(id); + SkillMap::iterator it = mSkills.find(id); - if (i != mSkills.end()) + if (it != mSkills.end()) { - SkillInfo *info = i->second; + SkillInfo *info = it->second; info->modifiable = modifiable; - info->display->update(); + info->update(); } } -SkillEntry::SkillEntry(SkillInfo *info) : - mInfo(info), - mIcon(NULL), - mNameLabel(new Label(info->name)), - mLevelLabel(new Label("999")), - mIncrease(new Button(_("+"), "inc", skillDialog)), - mProgress(new ProgressBar(0.0f, 200, 20, gcn::Color(150, 150, 150))) +void SkillModel::updateVisibilities() { - setFrameSize(1); - setOpaque(false); - - addWidgetListener(this); - - if (!info->icon.empty()) - mIcon = new Icon(info->icon); - else - mIcon = new Icon("graphics/gui/unknown-item.png"); + mVisibleSkills.clear(); - mIcon->setPosition(1, 0); - add(mIcon); - - mNameLabel->setPosition(35, 0); - add(mNameLabel); - - mLevelLabel->setPosition(165, 0); - add(mLevelLabel); - - mProgress->setPosition(35, 13); - add(mProgress); - - mIncrease->setPosition(getWidth() - mIncrease->getWidth(), 13); - add(mIncrease); - - update(); -} - -void SkillEntry::widgetResized(const gcn::Event &event) -{ - gcn::Rectangle size = getChildrenArea(); - - if (mProgress->isVisible() && mIncrease->isVisible()) - { - mLevelLabel->setPosition(size.width - mLevelLabel->getWidth() - - mIncrease->getWidth() - 4, 0); - mProgress->setWidth(size.width - mIncrease->getWidth() - 39); - mIncrease->setPosition(getWidth() - mIncrease->getWidth() - 2, 6); - } - else if (mProgress->isVisible()) - { - mLevelLabel->setPosition(size.width - mLevelLabel->getWidth(), 0); - mProgress->setWidth(size.width - 39); - } - else if (mIncrease->isVisible()) + for (SkillList::iterator it = mSkills.begin(); it != mSkills.end(); it++) { - mLevelLabel->setPosition(size.width - mLevelLabel->getWidth() - - mIncrease->getWidth() - 4, 0); - mIncrease->setPosition(getWidth() - mIncrease->getWidth() - 2, 6); + if ((*it)->visible) + { + mVisibleSkills.push_back((*it)); + } } - else - mLevelLabel->setPosition(size.width - mLevelLabel->getWidth(), 0); } -void SkillEntry::update() +void SkillInfo::update() { - int baseLevel = player_node->getAttributeBase(mInfo->id); - int effLevel = player_node->getAttributeEffective(mInfo->id); + int baseLevel = player_node->getAttributeBase(id); + int effLevel = player_node->getAttributeEffective(id); + + std::pair<int, int> exp = player_node->getExperience(id); - if (baseLevel <= 0 && !mInfo->modifiable) + if (!modifiable && baseLevel == 0 && effLevel == 0 && exp.second == 0) { - setVisible(false); + if (visible) + { + visible = false; + model->updateVisibilities(); + } + return; } - setVisible(true); - - std::string skillLevel; + bool updateVisibility = !visible; + visible = true; if (effLevel != baseLevel) { - skillLevel = strprintf(_("Lvl: %d (%+d)"), - baseLevel, baseLevel - effLevel); + skillLevel = strprintf(_("Lvl: %d (%+d)"), baseLevel, + effLevel - baseLevel); } else { - skillLevel = strprintf(_("Lvl: %d"), baseLevel); + if (baseLevel == 0) + { + skillLevel.clear(); + } + else + { + skillLevel = strprintf(_("Lvl: %d"), baseLevel); + } } - - mLevelLabel->setCaption(skillLevel); - - std::pair<int, int> exp = player_node->getExperience(mInfo->id); - std::string sExp (toString(exp.first) + " / " + toString(exp.second)); - - mLevelLabel->adjustSize(); + skillLevelWidth = -1; if (exp.second) { - mProgress->setVisible(true); - mProgress->setText(sExp); - - // More intense red as exp grows - int color = 150 - (int)(150 * ((float) exp.first / exp.second)); - mProgress->setColor(244, color, color); - mProgress->setProgress((float) exp.first / exp.second); + skillExp = strprintf("%d / %d", exp.first, exp.second); + progress = (float) exp.first / exp.second; } else - mProgress->setVisible(false); + { + skillExp.clear(); + progress = 0.0f; + } - if (mInfo->modifiable) + if (updateVisibility) { - mIncrease->setVisible(true); - mIncrease->setEnabled(player_node->getSkillPoints()); + model->updateVisibilities(); } - else +} + +void SkillInfo::draw(Graphics *graphics, int y, int width) +{ + graphics->drawImage(icon, 1, y); + graphics->drawText(name, 34, y); + + if (skillLevelWidth < 0) { - mIncrease->setVisible(false); - mIncrease->setEnabled(false); + // Add one for padding + skillLevelWidth = graphics->getFont()->getWidth(skillLevel) + 1; } - widgetResized(NULL); + graphics->drawText(skillLevel, width - skillLevelWidth, y); + + if (!skillExp.empty()) + { + gcn::Rectangle rect(33, y + 15, width - 33, 17); + + ProgressBar::render(graphics, rect, gcn::Color(143, 192, 211), + progress, skillExp); + } } diff --git a/src/gui/skilldialog.h b/src/gui/skilldialog.h index 6ac2d7da..a40c8649 100644 --- a/src/gui/skilldialog.h +++ b/src/gui/skilldialog.h @@ -30,6 +30,7 @@ #include <map> +class Button; class Label; class ScrollArea; class Tab; @@ -73,6 +74,7 @@ class SkillDialog : public Window, public gcn::ActionListener SkillMap mSkills; TabbedArea *mTabs; Label *mPointsLabel; + Button *mIncreaseButton; }; extern SkillDialog *skillDialog; diff --git a/src/gui/widgets/progressbar.cpp b/src/gui/widgets/progressbar.cpp index cb064899..98c31873 100644 --- a/src/gui/widgets/progressbar.cpp +++ b/src/gui/widgets/progressbar.cpp @@ -141,31 +141,14 @@ void ProgressBar::draw(gcn::Graphics *graphics) { updateAlpha(); - static_cast<Graphics*>(graphics)-> - drawImageRect(0, 0, getWidth(), getHeight(), mBorder); - mColor.a = (int) (mAlpha * 255); - // The bar - if (mProgress > 0) - { - graphics->setColor(mColor); - graphics->fillRectangle(gcn::Rectangle(4, 4, - (int) (mProgress * (getWidth() - 8)), - getHeight() - 8)); - } - - // The label - if (!mText.empty()) - { - const int textX = getWidth() / 2; - const int textY = (getHeight() - boldFont->getHeight()) / 2; + gcn::Rectangle rect = getDimension(); + rect.x = 0; + rect.y = 0; - TextRenderer::renderText(graphics, mText, textX, textY, - gcn::Graphics::CENTER, - guiPalette->getColor(Palette::PROGRESS_BAR), - gui->getFont(), true, false); - } + render(static_cast<Graphics*>(graphics), rect, mColor, + mProgress, mText); } void ProgressBar::setProgress(float progress) @@ -184,3 +167,37 @@ void ProgressBar::setColor(const gcn::Color &color) if (!mSmoothColorChange) mColor = color; } + +void ProgressBar::render(Graphics *graphics, const gcn::Rectangle &area, + const gcn::Color &color, float progress, + const std::string &text) +{ + gcn::Font *oldFont = graphics->getFont(); + gcn::Color oldColor = graphics->getColor(); + + graphics->drawImageRect(area, mBorder); + + // The bar + if (progress > 0) + { + graphics->setColor(color); + graphics->fillRectangle(gcn::Rectangle(area.x + 4, area.y + 4, + (int) (progress * (area.width - 8)), + area.height - 8)); + } + + // The label + if (!text.empty()) + { + const int textX = area.x + area.width / 2; + const int textY = area.y + (area.height - boldFont->getHeight()) / 2; + + TextRenderer::renderText(graphics, text, textX, textY, + gcn::Graphics::CENTER, + guiPalette->getColor(Palette::PROGRESS_BAR), + gui->getFont(), true, false); + } + + graphics->setFont(oldFont); + graphics->setColor(oldColor); +} diff --git a/src/gui/widgets/progressbar.h b/src/gui/widgets/progressbar.h index 4a314690..daa872a1 100644 --- a/src/gui/widgets/progressbar.h +++ b/src/gui/widgets/progressbar.h @@ -26,6 +26,7 @@ #include <string> +class Graphics; class ImageRect; /** @@ -112,6 +113,13 @@ class ProgressBar : public gcn::Widget void setSmoothColorChange(bool smoothColorChange) { mSmoothColorChange = smoothColorChange; } + /** + * Renders a progressbar with the given properties. + */ + static void render(Graphics *graphics, const gcn::Rectangle &area, + const gcn::Color &color, float progress, + const std::string &text = ""); + private: float mProgress, mProgressToGo; bool mSmoothProgress; |