From eb201e566677f5ae55d1c443aa4254b99cec9e3e Mon Sep 17 00:00:00 2001
From: Andrei Karas <akaras@inbox.ru>
Date: Wed, 12 Jan 2011 21:56:26 +0200
Subject: Add inventory sorting.

---
 src/gui/inventorywindow.cpp         | 46 ++++++++++++++-----
 src/gui/inventorywindow.h           |  3 +-
 src/gui/widgets/inventoryfilter.cpp |  2 +-
 src/gui/widgets/inventoryfilter.h   |  7 ---
 src/gui/widgets/itemcontainer.cpp   | 92 +++++++++++++++++++++++++++++++------
 src/gui/widgets/itemcontainer.h     |  4 ++
 src/gui/widgets/radiobutton.cpp     |  3 +-
 7 files changed, 123 insertions(+), 34 deletions(-)

diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp
index a02fab4e6..dfa7ce11f 100644
--- a/src/gui/inventorywindow.cpp
+++ b/src/gui/inventorywindow.cpp
@@ -92,16 +92,25 @@ InventoryWindow::InventoryWindow(Inventory *inventory):
     mSlotsLabel = new Label(_("Slots:"));
     mSlotsBar = new ProgressBar(0.0f, 100, 20, Theme::PROG_INVY_SLOTS);
 
-    mFilter = new InventoryFilter(getWindowName(), 20, 10);
+    mFilter = new InventoryFilter("filter_" + getWindowName(), 20, 5);
     mFilter->addActionListener(this);
-    mFilter->setActionEventId("tags");
+    mFilter->setActionEventId("tag_");
+
+    mSorter = new InventoryFilter("sorter_" + getWindowName(), 20, 0);
+    mSorter->addActionListener(this);
+    mSorter->setActionEventId("sort_");
 
     mFilterLabel = new Label(_("Filter:"));
+    mSorterLabel = new Label(_("Sort:"));
 
     std::vector<std::string> tags = ItemDB::getTags();
     for (unsigned f = 0; f < tags.size(); f ++)
         mFilter->add(tags[f]);
 
+    mSorter->add("na");
+    mSorter->add("az");
+    mSorter->add("id");
+
     if (isMainInventory())
     {
         std::string equip = _("Equip");
@@ -131,17 +140,19 @@ InventoryWindow::InventoryWindow(Inventory *inventory):
         place(1, 0, mWeightBar, 3);
         place(4, 0, mSlotsLabel, 1).setPadding(3);
         place(5, 0, mSlotsBar, 2);
+        place(7, 0, mSorterLabel, 1);
+        place(8, 0, mSorter, 3);
 
         place(0, 1, mFilterLabel, 1).setPadding(3);
-        place(1, 1, mFilter, 6).setPadding(3);
+        place(1, 1, mFilter, 10).setPadding(3);
 
-        place(0, 2, invenScroll, 7).setPadding(3);
+        place(0, 2, invenScroll, 11).setPadding(3);
         place(0, 3, mUseButton);
         place(1, 3, mUseButton2);
         place(2, 3, mDropButton);
-        place(4, 3, mSplitButton);
-        place(5, 3, mShopButton);
-        place(6, 3, mOutfitButton);
+        place(8, 3, mSplitButton);
+        place(9, 3, mShopButton);
+        place(10, 3, mOutfitButton);
 
         updateWeight();
     }
@@ -153,14 +164,16 @@ InventoryWindow::InventoryWindow(Inventory *inventory):
 
         place(0, 0, mSlotsLabel).setPadding(3);
         place(1, 0, mSlotsBar, 3);
+        place(4, 0, mSorterLabel, 1);
+        place(5, 0, mSorter, 2);
 
         place(0, 1, mFilterLabel, 1).setPadding(3);
-        place(1, 1, mFilter, 3).setPadding(3);
+        place(1, 1, mFilter, 6).setPadding(3);
 
-        place(0, 2, invenScroll, 4, 4);
+        place(0, 2, invenScroll, 7, 4);
         place(0, 6, mStoreButton);
         place(1, 6, mRetrieveButton);
-        place(3, 6, mCloseButton);
+        place(6, 6, mCloseButton);
     }
 
     Layout &layout = getLayout();
@@ -236,7 +249,18 @@ void InventoryWindow::action(const gcn::ActionEvent &event)
     {
         std::string tagName = event.getId().substr(4);
         mItems->setFilter(ItemDB::getTagId(tagName));
-//        logger->log("eventid: %s", tagName.c_str());
+    }
+    else if (!event.getId().find("sort_") && mItems)
+    {
+        int sortType = 0;
+        std::string str = event.getId().substr(5).c_str();
+        if (str == "na")
+            sortType = 0;
+        else if (str == "az")
+            sortType = 1;
+        else if (str == "id")
+            sortType = 2;
+        mItems->setSortType(sortType);
     }
 
     Item *item = mItems->getSelectedItem();
diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h
index 664a22f4b..bc0fe08c0 100644
--- a/src/gui/inventorywindow.h
+++ b/src/gui/inventorywindow.h
@@ -144,10 +144,11 @@ class InventoryWindow : public Window,
                     *mSplitButton, *mOutfitButton, *mShopButton,
                     *mStoreButton, *mRetrieveButton, *mCloseButton;
 
-        gcn::Label *mWeightLabel, *mSlotsLabel, *mFilterLabel;
+        gcn::Label *mWeightLabel, *mSlotsLabel, *mFilterLabel, *mSorterLabel;
 
         ProgressBar *mWeightBar, *mSlotsBar;
         InventoryFilter *mFilter;
+        InventoryFilter *mSorter;
 
         bool mSplit;
 };
diff --git a/src/gui/widgets/inventoryfilter.cpp b/src/gui/widgets/inventoryfilter.cpp
index faceafa9e..aa2f2a5e4 100644
--- a/src/gui/widgets/inventoryfilter.cpp
+++ b/src/gui/widgets/inventoryfilter.cpp
@@ -38,7 +38,7 @@ void InventoryFilter::add(std::string tag)
 
     RadioButton *radio = new RadioButton(tag, mGroup, mCount == 0);
     radio->adjustSize();
-    radio->setActionEventId("tag_" + tag);
+    radio->setActionEventId(mActionEventId + tag);
     radio->addActionListener(this);
     HorizontContainer::add(radio);
 }
diff --git a/src/gui/widgets/inventoryfilter.h b/src/gui/widgets/inventoryfilter.h
index 28423413f..42f51c895 100644
--- a/src/gui/widgets/inventoryfilter.h
+++ b/src/gui/widgets/inventoryfilter.h
@@ -33,13 +33,6 @@
 #define _UNUSED_
 #endif
 
-//class HorizontContainer;
-
-/**
- * A widget container.
- *
- * This container places it's contents veritcally.
- */
 class InventoryFilter : public HorizontContainer, public gcn::ActionListener
 {
     public:
diff --git a/src/gui/widgets/itemcontainer.cpp b/src/gui/widgets/itemcontainer.cpp
index b9123bc5a..d25e4baa1 100644
--- a/src/gui/widgets/itemcontainer.cpp
+++ b/src/gui/widgets/itemcontainer.cpp
@@ -55,6 +55,44 @@
 static const int BOX_WIDTH = 35;
 static const int BOX_HEIGHT = 43;
 
+class ItemIdPair
+{
+    public:
+        ItemIdPair(int id, Item* item)
+        {
+            mId = id;
+            mItem = item;
+        }
+
+        int mId;
+        Item* mItem;
+};
+
+class SortItemAlphaFunctor
+{
+    public:
+        bool operator() (ItemIdPair* pair1, ItemIdPair* pair2)
+        {
+            if (!pair1 || !pair2)
+                return false;
+
+            return (pair1->mItem->getInfo().getName()
+                    < pair2->mItem->getInfo().getName());
+        }
+} itemAlphaSorter;
+
+class SortItemIdFunctor
+{
+    public:
+        bool operator() (ItemIdPair* pair1, ItemIdPair* pair2)
+        {
+            if (!pair1 || !pair2)
+                return false;
+
+            return pair1->mItem->getId() < pair2->mItem->getId();
+        }
+} itemIdSorter;
+
 ItemContainer::ItemContainer(Inventory *inventory, bool forceQuantity):
     mInventory(inventory),
     mGridColumns(1),
@@ -67,6 +105,7 @@ ItemContainer::ItemContainer(Inventory *inventory, bool forceQuantity):
     mSwapItems(false),
     mDescItems(false),
     mTag(0),
+    mSortType(0),
     mShowMatrix(0)
 {
     mItemPopup = new ItemPopup;
@@ -117,11 +156,6 @@ void ItemContainer::draw(gcn::Graphics *graphics)
 
     g->setFont(getFont());
 
-    int i = 0;
-    int j = 0;
-
-//    int idx = 0;
-
     for (int j = 0; j < mGridRows; j++)
     {
         for (int i = 0; i < mGridColumns; i++)
@@ -401,24 +435,46 @@ void ItemContainer::adjustHeight()
 
 void ItemContainer::updateMatrix()
 {
+    if (!mInventory)
+        return;
+
     delete []mShowMatrix;
     mShowMatrix = new int[mGridRows * mGridColumns];
 
+    std::vector<ItemIdPair*> sortedItems;
     int i = 0;
     int j = 0;
 
-    for (int idx = 0; idx < mInventory->getSize(); idx ++)
+    for (unsigned idx = 0; idx < mInventory->getSize(); idx ++)
     {
-        int itemIndex = idx;
-        if (j >= mGridRows)
-            break;
-
-        Item *item = mInventory->getItem(itemIndex);
+        Item *item = mInventory->getItem(idx);
 
         if (!item || item->getId() == 0 || !item->isHaveTag(mTag))
             continue;
 
-        mShowMatrix[j * mGridColumns + i] = itemIndex;
+        sortedItems.push_back(new ItemIdPair(idx, item));
+    }
+
+    switch (mSortType)
+    {
+        case 0:
+        default:
+            break;
+        case 1:
+            sort(sortedItems.begin(), sortedItems.end(), itemAlphaSorter);
+            break;
+        case 2:
+            sort(sortedItems.begin(), sortedItems.end(), itemIdSorter);
+            break;
+    }
+
+    for (unsigned idx = 0; idx < sortedItems.size(); idx ++)
+    {
+        int itemIndex = idx;
+        if (j >= mGridRows)
+            break;
+
+        mShowMatrix[j * mGridColumns + i] = sortedItems[itemIndex]->mId;
 
         i ++;
         if (i >= mGridColumns)
@@ -430,6 +486,9 @@ void ItemContainer::updateMatrix()
 
     for (int idx = j * mGridColumns + i; idx < mGridRows * mGridColumns; idx ++)
         mShowMatrix[idx] = -1;
+
+    for (unsigned idx = 0; idx < sortedItems.size(); idx ++)
+        delete sortedItems[idx];
 }
 
 int ItemContainer::getSlotIndex(int x, int y) const
@@ -530,4 +589,11 @@ void ItemContainer::setFilter (int tag)
 {
     mTag = tag;
     updateMatrix();
-}
\ No newline at end of file
+}
+
+void ItemContainer::setSortType (int sortType)
+{
+    mSortType = sortType;
+    logger->log("setSortType: %d", sortType);
+    updateMatrix();
+}
diff --git a/src/gui/widgets/itemcontainer.h b/src/gui/widgets/itemcontainer.h
index 9ce819534..003187859 100644
--- a/src/gui/widgets/itemcontainer.h
+++ b/src/gui/widgets/itemcontainer.h
@@ -28,6 +28,7 @@
 #include <guichan/widgetlistener.hpp>
 
 #include <list>
+#include <algorithm>
 
 #ifdef __GNUC__
 #define _UNUSED_  __attribute__ ((unused))
@@ -121,6 +122,8 @@ class ItemContainer : public gcn::Widget,
 
         void setFilter (int tag);
 
+        void setSortType (int sortType);
+
     private:
         enum Direction
         {
@@ -188,6 +191,7 @@ class ItemContainer : public gcn::Widget,
         bool mDescItems;
         int mDragPosX, mDragPosY;
         int mTag;
+        int mSortType;
 
         ItemPopup *mItemPopup;
         int *mShowMatrix;
diff --git a/src/gui/widgets/radiobutton.cpp b/src/gui/widgets/radiobutton.cpp
index c9738e3cd..9683a11a8 100644
--- a/src/gui/widgets/radiobutton.cpp
+++ b/src/gui/widgets/radiobutton.cpp
@@ -148,7 +148,8 @@ void RadioButton::draw(gcn::Graphics* graphics)
     graphics->setColor(getForegroundColor());
 
     int h = getHeight() + getHeight() / 2;
-    graphics->drawText(getCaption(), h - 2, 0);
+//    graphics->drawText(getCaption(), h - 2, 0);
+    graphics->drawText(getCaption(), 16, 0);
 }
 
 void RadioButton::mouseEntered(gcn::MouseEvent& event _UNUSED_)
-- 
cgit v1.2.3-70-g09d2