summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJared Adams <jaxad0127@gmail.com>2010-02-10 14:51:28 -0700
committerJared Adams <jaxad0127@gmail.com>2010-02-10 14:52:11 -0700
commit6c7bf198fa165c971565f069081c603f068014b1 (patch)
tree28056d3d94f9e8ae3477c39102e4cd5c1bd71267
parent7ec3ae46caf310cf83ece9e90e8e0f668179144b (diff)
downloadmana-6c7bf198fa165c971565f069081c603f068014b1.tar.gz
mana-6c7bf198fa165c971565f069081c603f068014b1.tar.bz2
mana-6c7bf198fa165c971565f069081c603f068014b1.tar.xz
mana-6c7bf198fa165c971565f069081c603f068014b1.zip
Improve look and utility of the SkillDialog
-rw-r--r--src/graphics.h10
-rw-r--r--src/gui/skilldialog.cpp366
-rw-r--r--src/gui/skilldialog.h2
-rw-r--r--src/gui/widgets/progressbar.cpp61
-rw-r--r--src/gui/widgets/progressbar.h8
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;