From 6065690856ffc750404c9c0940d9a1f3a0cdd42c Mon Sep 17 00:00:00 2001
From: Andrei Karas <akaras@inbox.ru>
Date: Tue, 13 Aug 2013 23:54:06 +0300
Subject: Add player/item/other counter in social window.

---
 src/gui/socialwindow.cpp    | 166 +++++++++++++++++++++++++++++++++++++++++++-
 src/gui/socialwindow.h      |   8 +++
 src/guild.h                 |   6 +-
 src/guildmanager.cpp        |   6 ++
 src/net/ea/guildhandler.cpp |   9 +++
 src/net/ea/partyhandler.cpp |   1 +
 6 files changed, 193 insertions(+), 3 deletions(-)

diff --git a/src/gui/socialwindow.cpp b/src/gui/socialwindow.cpp
index edbd5a0d3..38f8d22f5 100644
--- a/src/gui/socialwindow.cpp
+++ b/src/gui/socialwindow.cpp
@@ -117,7 +117,8 @@ protected:
         mInviteDialog(nullptr),
         mConfirmDialog(nullptr),
         mScroll(nullptr),
-        mList(nullptr)
+        mList(nullptr),
+        mCounterString()
     {
     }
 
@@ -139,10 +140,27 @@ protected:
         }
     }
 
+    void setCurrent() override
+    {
+        updateCounter();
+    }
+
+    void updateCounter()
+    {
+        if (socialWindow)
+            socialWindow->setCounter(this, mCounterString);
+    }
+
+    virtual void buildCounter(const int online A_UNUSED = 0,
+                              const int total A_UNUSED = 0)
+    {
+    }
+
     TextDialog *mInviteDialog;
     ConfirmDialog *mConfirmDialog;
     ScrollArea *mScroll;
     AvatarListBox *mList;
+    std::string mCounterString;
 };
 
 class SocialGuildTab final : public SocialTab, public gcn::ActionListener
@@ -243,6 +261,38 @@ public:
         mConfirmDialog->addActionListener(this);
     }
 
+    void buildCounter(const int online0, const int total0)
+    {
+        if (online0 || total0)
+        {
+            // TRANSLATORS: social window label
+            mCounterString = strprintf(_("Members: %u/%u"), online0, total0);
+        }
+        else
+        {
+            if (!player_node)
+                return;
+
+            const Guild *const guild = player_node->getGuild();
+            if (!guild)
+                return;
+
+            const Guild::MemberList *const members = guild->getMembers();
+            int online = 0;
+            int total = 0;
+            FOR_EACHP (Guild::MemberList::const_iterator, it, members)
+            {
+                if ((*it)->getOnline())
+                    online ++;
+                total ++;
+            }
+
+            // TRANSLATORS: social window label
+            mCounterString = strprintf(_("Players: %u/%u"), online, total);
+        }
+        updateCounter();
+    }
+
 private:
     Guild *mGuild;
 };
@@ -287,6 +337,30 @@ public:
     void action(const gcn::ActionEvent &event A_UNUSED) override
     {
     }
+
+    void buildCounter(const int online0, const int total0)
+    {
+        if (!player_node)
+            return;
+
+        const Guild *const guild = player_node->getGuild();
+        if (!guild)
+            return;
+
+        const Guild::MemberList *const members = guild->getMembers();
+        int online = 0;
+        int total = 0;
+        FOR_EACHP (Guild::MemberList::const_iterator, it, members)
+        {
+            if ((*it)->getOnline())
+                online ++;
+            total ++;
+        }
+
+        // TRANSLATORS: social window label
+        mCounterString = strprintf(_("Players: %u/%u"), online, total);
+        updateCounter();
+    }
 };
 
 class SocialPartyTab final : public SocialTab, public gcn::ActionListener
@@ -386,6 +460,30 @@ public:
         mConfirmDialog->addActionListener(this);
     }
 
+    void buildCounter(const int online0 A_UNUSED, const int total0 A_UNUSED)
+    {
+        if (!player_node)
+            return;
+
+        const Party *const party = player_node->getParty();
+        if (!party)
+            return;
+
+        const Party::MemberList *const members = party->getMembers();
+        int online = 0;
+        int total = 0;
+        FOR_EACHP (Party::MemberList::const_iterator, it, members)
+        {
+            if ((*it)->getOnline())
+                online ++;
+            total ++;
+        }
+
+        // TRANSLATORS: social window label
+        mCounterString = strprintf(_("Players: %u/%u"), online, total);
+        updateCounter();
+    }
+
 private:
     Party *mParty;
 };
@@ -579,6 +677,10 @@ public:
                 ++i;
             }
         }
+        // TRANSLATORS: social window label
+        mCounterString = strprintf(_("Visible players: %d"),
+            static_cast<int>(avatars->size()));
+        updateCounter();
     }
 
 private:
@@ -645,6 +747,9 @@ public:
 
         avatars->clear();
 
+        int online = 0;
+        int total = 0;
+
         int idx = 0;
         while (i != portals.end())
         {
@@ -669,6 +774,10 @@ public:
             ava->setY(y);
             avatars->push_back(ava);
 
+            if (ava->getOnline())
+                online ++;
+            total ++;
+
             if (config.getBoolValue("drawHotKeys") && idx < 80 && outfitWindow)
             {
                 Being *const being = actorSpriteManager
@@ -695,6 +804,10 @@ public:
         }
         if (socialWindow)
             socialWindow->setProcessedPortals(true);
+
+        // TRANSLATORS: social window label
+        mCounterString = strprintf(_("Portals: %u/%u"), online, total);
+        updateCounter();
     }
 
 
@@ -1055,6 +1168,9 @@ public:
         if (!players)
             return;
 
+        int online = 0;
+        int total = 0;
+
         FOR_EACHP (StringVectCIter, it, players)
         {
             Avatar *const ava = new Avatar(*it);
@@ -1062,11 +1178,17 @@ public:
                 || players2.find(*it) != players2.end())
             {
                 ava->setOnline(true);
+                online ++;
             }
+            total ++;
             avatars->push_back(ava);
         }
         std::sort(avatars->begin(), avatars->end(), friendSorter);
         delete players;
+
+        // TRANSLATORS: social window label
+        mCounterString = strprintf(_("Friends: %u/%u"), online, total);
+        updateCounter();
     }
 
 private:
@@ -1162,6 +1284,7 @@ SocialWindow::SocialWindow() :
     mInviteButton(new Button(this, _("Invite"), "invite", this)),
     // TRANSLATORS: social window button
     mLeaveButton(new Button(this, _("Leave"), "leave", this)),
+    mCountLabel(new Label(this, "1000 / 1000")),
     mTabs(new TabbedArea(this)),
     mMap(nullptr),
     mLastUpdateTime(0),
@@ -1184,7 +1307,8 @@ SocialWindow::SocialWindow() :
     place(0, 0, mCreateButton);
     place(1, 0, mInviteButton);
     place(2, 0, mLeaveButton);
-    place(0, 1, mTabs, 4, 4);
+    place(0, 1, mCountLabel);
+    place(0, 2, mTabs, 4, 4);
 
     widgetResized(gcn::Event(nullptr));
 
@@ -1702,6 +1826,20 @@ void SocialWindow::updatePickupFilter()
         mPickupFilter->updateList();
 }
 
+void SocialWindow::updateParty()
+{
+    if (!player_node)
+        return;
+
+    Party *const party = player_node->getParty();
+    PartyMap::iterator it = mParties.find(party);
+    if (it != mParties.end())
+    {
+        SocialTab *const tab = (*it).second;
+        tab->buildCounter();
+    }
+}
+
 void SocialWindow::widgetResized(const gcn::Event &event)
 {
     Window::widgetResized(event);
@@ -1709,6 +1847,30 @@ void SocialWindow::widgetResized(const gcn::Event &event)
         mTabs->adjustSize();
 }
 
+void SocialWindow::setCounter(const SocialTab *const tab,
+                              const std::string &str)
+{
+    if (mTabs->getSelectedTab() == tab)
+    {
+        mCountLabel->setCaption(str);
+        mCountLabel->adjustSize();
+    }
+}
+
+void SocialWindow::updateGuildCounter(const int online, const int total)
+{
+    if (!player_node)
+        return;
+
+    Guild *const guild = player_node->getGuild();
+    GuildMap::iterator it = mGuilds.find(guild);
+    if (it != mGuilds.end())
+    {
+        SocialTab *const tab = (*it).second;
+        tab->buildCounter(online, total);
+    }
+}
+
 #ifdef USE_PROFILER
 void SocialWindow::logicChildren()
 {
diff --git a/src/gui/socialwindow.h b/src/gui/socialwindow.h
index b8ed73655..66cb32741 100644
--- a/src/gui/socialwindow.h
+++ b/src/gui/socialwindow.h
@@ -35,6 +35,7 @@ class Button;
 class ConfirmDialog;
 class CreatePopup;
 class Guild;
+class Label;
 class Map;
 class NavigateTab;
 class Party;
@@ -90,6 +91,8 @@ public:
 
     void updatePortalNames();
 
+    void updateParty();
+
     int getPortalIndex(const int x, const int y) A_WARN_UNUSED;
 
     void addPortal(const int x, const int y);
@@ -120,6 +123,10 @@ public:
 
     void widgetResized(const gcn::Event &event) override;
 
+    void setCounter(const SocialTab *const tab, const std::string &str);
+
+    void updateGuildCounter(const int online = 0, const int total = 0);
+
 #ifdef USE_PROFILER
     void logicChildren();
 #endif
@@ -154,6 +161,7 @@ protected:
     Button *mCreateButton;
     Button *mInviteButton;
     Button *mLeaveButton;
+    Label *mCountLabel;
     TabbedArea *mTabs;
     Map *mMap;
 
diff --git a/src/guild.h b/src/guild.h
index e6f237304..a1057552b 100644
--- a/src/guild.h
+++ b/src/guild.h
@@ -195,6 +195,11 @@ public:
     bool getServerGuild() const A_WARN_UNUSED
     { return mServerGuild; }
 
+    typedef std::vector<GuildMember*> MemberList;
+
+    const MemberList *getMembers() const A_WARN_UNUSED
+    { return &mMembers; }
+
 private:
     typedef std::map<int, Guild*> GuildMap;
     static GuildMap guilds;
@@ -204,7 +209,6 @@ private:
      */
     explicit Guild(const int16_t id);
 
-    typedef std::vector<GuildMember*> MemberList;
     MemberList mMembers;
     std::string mName;
     int16_t mId;
diff --git a/src/guildmanager.cpp b/src/guildmanager.cpp
index 62b478a5a..6fbf15666 100644
--- a/src/guildmanager.cpp
+++ b/src/guildmanager.cpp
@@ -211,6 +211,8 @@ void GuildManager::updateList()
             actorSpriteManager->updatePlayerGuild();
             actorSpriteManager->updatePlayerColors();
         }
+        if (socialWindow)
+            socialWindow->updateGuildCounter();
     }
     mTempList.clear();
     mSentInfoRequest = false;
@@ -273,6 +275,8 @@ bool GuildManager::process(std::string msg)
         mRequest = false;
         if (mTab)
             mTab->showOnline(msg, false);
+        if (socialWindow)
+            socialWindow->updateGuildCounter();
         return true;
     }
     else if (!haveNick && findCutLast(msg, " is now Online."))
@@ -291,6 +295,8 @@ bool GuildManager::process(std::string msg)
         mRequest = false;
         if (mTab)
             mTab->showOnline(msg, true);
+        if (socialWindow)
+            socialWindow->updateGuildCounter();
         return true;
     }
     else if (findCutFirst(msg, "Welcome to the "))
diff --git a/src/net/ea/guildhandler.cpp b/src/net/ea/guildhandler.cpp
index b2a78f7da..e19b44592 100644
--- a/src/net/ea/guildhandler.cpp
+++ b/src/net/ea/guildhandler.cpp
@@ -145,6 +145,8 @@ void GuildHandler::processGuildMemberLogin(Net::MessageIn &msg) const
             m->setOnline(online);
             if (guildTab)
                 guildTab->showOnline(m->getName(), online);
+            if (socialWindow)
+                socialWindow->updateGuildCounter();
         }
     }
 }
@@ -234,6 +236,8 @@ void GuildHandler::processGuildMemberList(Net::MessageIn &msg) const
 
     taGuild->clearMembers();
 
+    int onlineNum = 0;
+    int totalNum = 0;
     for (int i = 0; i < count; i++)
     {
         const int id = msg.readInt32();      // Account ID
@@ -274,6 +278,9 @@ void GuildHandler::processGuildMemberList(Net::MessageIn &msg) const
                     }
                 }
             }
+            if (online)
+                onlineNum ++;
+            totalNum ++;
         }
     }
     taGuild->sort();
@@ -282,6 +289,8 @@ void GuildHandler::processGuildMemberList(Net::MessageIn &msg) const
         actorSpriteManager->updatePlayerGuild();
         actorSpriteManager->updatePlayerColors();
     }
+    if (socialWindow)
+        socialWindow->updateGuildCounter(onlineNum, totalNum);
 }
 
 void GuildHandler::processGuildPosNameList(Net::MessageIn &msg) const
diff --git a/src/net/ea/partyhandler.cpp b/src/net/ea/partyhandler.cpp
index a8233bbf6..819b2f133 100644
--- a/src/net/ea/partyhandler.cpp
+++ b/src/net/ea/partyhandler.cpp
@@ -142,6 +142,7 @@ void PartyHandler::processPartyInfo(Net::MessageIn &msg) const
     {
         player_node->setParty(Ea::taParty);
         player_node->setPartyName(Ea::taParty->getName());
+        socialWindow->updateParty();
     }
 }
 
-- 
cgit v1.2.3-70-g09d2