summaryrefslogblamecommitdiff
path: root/src/gui/socialwindow.cpp
blob: 00211e029b0bcf1d4552695208ddc205a09da256 (plain) (tree)
1
2
3
4
5
  
                   
                                                
  
                                         











                                                                        
                                                                         



                             
                  


                        








                                      









                                    

                            


                              

                 




                              
                          
 
                         





                                            
                                    





                                             
                                     






                              

                                            

                                         





                                                             
                     


                                     
                                                         
 

                                                            




                                                                       
                                                       



                                                        
 

                              
                                                                      
                                                                          

                                                         
             
                                    
         

                                               
                                    
         


                                                           

                                                                   
                                     
         
                                       
         
                                     
         


          
                          




                                                                              
                                         
                                                     


                                               
                         




















                                                                               
                                                                    
 

                                                            

                                                                       
                                                                     

     
                                                       



                                                        
 
                              

                                                                       
                                    
         

                                               
                                    
         


                                            

                                                                   
                                     
         
                                       
         
                                     
         


          
                          




                                                                               
                                          
                                                     


                                               
                         


























                                                                               

                                          

                                                                              









                                                                          
                                                     







                                            



















                                          
                       








                            
                                       













                                                            
                           

                                     
 
                                 
     
                                         
     

                        








                                             
                                     







                                             
                                     
 
                              
     
                        






                                             
                                    

                         
                                           
 

                    




                                          
                                  






                                 

                    







                                               
                                    

                          
                                           
 

                    




                                          
                                   






                                 

                    











                                                        

                                                                        



                                                                        

                                                                        


                                                                         
                              
                                     





                                                     
                                                     



                                                                        
                                                      



                                                                         
                                     


                                       



                                                  
     
                                                                            
     
                                                                   
     
                                                                           
     
                                                                  






                                                         

                                                                     

                   

                          

                                                 

                                                                   
         
 
                                     


                                              
                                     






                                                         

                                                                     

                   

                          

                                                 

                                                                   
         
 
                                     


                                              
                                     






                                                                              
                                                         









                                                                  

                                                                  




                                                                              
                      







                                                                                

                                                                

                                                 
                               
     
                                                                           





























                                                                             
                      









                                                                                
                                 


                                                                          
                                 



                                                        
                                                                              
                                                         

                                                






                                                
/*
 *  The Mana Client
 *  Copyright (C) 2010-2012  The Mana Developers
 *
 *  This file is part of The Mana Client.
 *
 *  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, see <http://www.gnu.org/licenses/>.
 */

#include "gui/socialwindow.h"

#include "event.h"
#include "guild.h"
#include "localplayer.h"
#include "party.h"

#include "gui/confirmdialog.h"
#include "gui/okdialog.h"
#include "gui/setup.h"
#include "gui/textdialog.h"

#include "gui/widgets/avatarlistbox.h"
#include "gui/widgets/browserbox.h"
#include "gui/widgets/button.h"
#include "gui/widgets/linkhandler.h"
#include "gui/widgets/popup.h"
#include "gui/widgets/scrollarea.h"
#include "gui/widgets/tab.h"
#include "gui/widgets/tabbedarea.h"

#include "net/net.h"
#include "net/guildhandler.h"
#include "net/partyhandler.h"

#include "resources/theme.h"

#include "utils/gettext.h"
#include "utils/stringutils.h"

#include <memory>

class SocialTab : public Tab
{
protected:
    friend class SocialWindow;

    SocialTab() = default;

    ~SocialTab() override
    {
        // Cleanup dialogs
        if (mInviteDialog)
        {
            mInviteDialog->close();
            mInviteDialog->scheduleDelete();
            mInviteDialog = nullptr;
        }

        if (mConfirmDialog)
        {
            mConfirmDialog->close();
            mConfirmDialog->scheduleDelete();
            mConfirmDialog = nullptr;
        }
    }

    virtual void invite() = 0;

    virtual void leave() = 0;

    TextDialog *mInviteDialog = nullptr;
    ConfirmDialog *mConfirmDialog = nullptr;
    std::unique_ptr<ScrollArea> mScroll;
    std::unique_ptr<AvatarListBox> mList;
};

class GuildTab : public SocialTab, public gcn::ActionListener
{
public:
    GuildTab(Guild *guild):
        mGuild(guild)
    {
        setCaption(guild->getName());

        setTabColor(&Theme::getThemeColor(Theme::GUILD));

        mList = std::make_unique<AvatarListBox>(guild);
        mScroll = std::make_unique<ScrollArea>(mList.get());

        mScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_AUTO);
        mScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_ALWAYS);
    }

    void action(const gcn::ActionEvent &event) override
    {
        if (event.getId() == "do invite")
        {
            std::string name = mInviteDialog->getText();

            if (!name.empty())
            {
                Net::getGuildHandler()->invite(mGuild->getId(), name);
                SERVER_NOTICE(strprintf(_("Invited user %s to guild %s."),
                              name.c_str(),
                              mGuild->getName().c_str()))
            }
            mInviteDialog = nullptr;
        }
        else if (event.getId() == "~do invite")
        {
            mInviteDialog = nullptr;
        }
        else if (event.getId() == "yes")
        {
            Net::getGuildHandler()->leave(mGuild->getId());
            SERVER_NOTICE(strprintf(_("Guild %s quit requested."),
                                        mGuild->getName().c_str()))
            mConfirmDialog = nullptr;
        }
        else if (event.getId() == "no")
        {
            mConfirmDialog = nullptr;
        }
    }

protected:
    void invite() override
    {
        // TODO - Give feedback on whether the invite succeeded
        mInviteDialog = new TextDialog(_("Member Invite to Guild"),
                     strprintf(_("Who would you like to invite to guild %s?"),
                               mGuild->getName().c_str()),
                     socialWindow, true);
        mInviteDialog->setActionEventId("do invite");
        mInviteDialog->addActionListener(this);
    }

    void leave() override
    {
        mConfirmDialog = new ConfirmDialog(_("Leave Guild?"),
                       strprintf(_("Are you sure you want to leave guild %s?"),
                                 mGuild->getName().c_str()),
                       socialWindow);

        mConfirmDialog->addActionListener(this);
    }

private:
    Guild *mGuild;
};

class PartyTab : public SocialTab, public gcn::ActionListener
{
public:
    PartyTab(Party *party):
            mParty(party)
    {
        setCaption(party->getName());

        setTabColor(&Theme::getThemeColor(Theme::PARTY_SOCIAL_TAB));

        mList = std::make_unique<AvatarListBox>(party);
        mScroll = std::make_unique<ScrollArea>(mList.get());

        mScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_AUTO);
        mScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_AUTO);
    }

    void action(const gcn::ActionEvent &event) override
    {
        if (event.getId() == "do invite")
        {
            std::string name = mInviteDialog->getText();

            if (!name.empty())
                SERVER_NOTICE(strprintf(_("Invited user %s to party."),
                              name.c_str()))
            mInviteDialog = nullptr;
        }
        else if (event.getId() == "~do invite")
        {
            mInviteDialog = nullptr;
        }
        else if (event.getId() == "yes")
        {
            Net::getPartyHandler()->leave();
            SERVER_NOTICE(strprintf(_("Party %s quit requested."),
                                        mParty->getName().c_str()))
            mConfirmDialog = nullptr;
        }
        else if (event.getId() == "no")
        {
            mConfirmDialog = nullptr;
        }
    }

protected:
    void invite() override
    {
        // TODO - Give feedback on whether the invite succeeded
        mInviteDialog = new TextDialog(_("Member Invite to Party"),
                      strprintf(_("Who would you like to invite to party %s?"),
                                mParty->getName().c_str()),
                      socialWindow, true);
        mInviteDialog->setActionEventId("do invite");
        mInviteDialog->addActionListener(this);
    }

    void leave() override
    {
        mConfirmDialog = new ConfirmDialog(_("Leave Party?"),
                       strprintf(_("Are you sure you want to leave party %s?"),
                                 mParty->getName().c_str()),
                       socialWindow);

        mConfirmDialog->addActionListener(this);
    }

private:
    Party *mParty;
};

/*class BuddyTab : public SocialTab
{
    // TODO?
};*/

class CreatePopup : public Popup, public LinkHandler
{
public:
    CreatePopup():
            Popup("SocialCreatePopup")
    {
        mBrowserBox = new BrowserBox;
        mBrowserBox->setPosition(4, 4);
        mBrowserBox->setHighlightMode(BrowserBox::BACKGROUND);
        mBrowserBox->setLinkHandler(this);

        if (Net::getGuildHandler()->isSupported())
            mBrowserBox->addRow(strprintf("@@guild|%s@@", _("Create Guild")));
        mBrowserBox->addRow(strprintf("@@party|%s@@", _("Create Party")));
        mBrowserBox->addRow("##3---");
        mBrowserBox->addRow(strprintf("@@cancel|%s@@", _("Cancel")));

        add(mBrowserBox);

        setContentSize(mBrowserBox->getWidth() + 8,
                       mBrowserBox->getHeight() + 8);
    }

    void handleLink(const std::string &link) override
    {
        if (link == "guild")
        {
            socialWindow->showGuildCreate();
        }
        else if (link == "party")
        {
            socialWindow->showPartyCreate();
        }

        setVisible(false);
    }

    void show(gcn::Widget *parent)
    {
        int x, y;
        parent->getAbsolutePosition(x, y);
        y += parent->getHeight();
        setPosition(x, y);
        setVisible(true);
        requestMoveToTop();
    }

private:
    BrowserBox* mBrowserBox;
};

SocialWindow::SocialWindow() :
    Window(_("Social"))
{
    setWindowName("Social");
    setVisible(false);
    setSaveVisible(true);
    setResizable(true);
    setSaveVisible(true);
    setCloseButton(true);
    setMinWidth(120);
    setMinHeight(55);
    setDefaultSize(590, 200, 150, 124);
    setupWindow->registerWindowForReset(this);

    loadWindowState();

    mCreateButton = new Button(_("Create"), "create", this);
    mInviteButton = new Button(_("Invite"), "invite", this);
    mLeaveButton = new Button(_("Leave"), "leave", this);
    mTabs = new TabbedArea;

    place(0, 0, mCreateButton);
    place(1, 0, mInviteButton);
    place(2, 0, mLeaveButton);
    place(0, 1, mTabs, 4, 4);

    widgetResized(nullptr);

    mCreatePopup = new CreatePopup();

    if (local_player->getParty())
    {
        addTab(local_player->getParty());
    }
    else
        updateButtons();
}

SocialWindow::~SocialWindow()
{
    // Cleanup invites
    if (mGuildAcceptDialog)
    {
        mGuildAcceptDialog->close();
        mGuildAcceptDialog->scheduleDelete();
        mGuildAcceptDialog = nullptr;

        mGuildInvited = 0;
    }

    if (mPartyAcceptDialog)
    {
        mPartyAcceptDialog->close();
        mPartyAcceptDialog->scheduleDelete();
        mPartyAcceptDialog = nullptr;

        mPartyInviter.clear();
    }
    delete mCreatePopup;
}

bool SocialWindow::addTab(Guild *guild)
{
    if (mGuilds.find(guild) != mGuilds.end())
        return false;

    auto *tab = new GuildTab(guild);
    mGuilds[guild] = tab;

    mTabs->addTab(tab, tab->mScroll.get());

    updateButtons();

    return true;
}

bool SocialWindow::removeTab(Guild *guild)
{
    auto it = mGuilds.find(guild);
    if (it == mGuilds.end())
        return false;

    mTabs->removeTab(it->second);
    delete it->second;
    mGuilds.erase(it);

    updateButtons();

    return true;
}

bool SocialWindow::addTab(Party *party)
{
    if (mParties.find(party) != mParties.end())
        return false;

    auto *tab = new PartyTab(party);
    mParties[party] = tab;

    mTabs->addTab(tab, tab->mScroll.get());

    updateButtons();

    return true;
}

bool SocialWindow::removeTab(Party *party)
{
    auto it = mParties.find(party);
    if (it == mParties.end())
        return false;

    mTabs->removeTab(it->second);
    delete it->second;
    mParties.erase(it);

    updateButtons();

    return true;
}

void SocialWindow::action(const gcn::ActionEvent &event)
{
    const std::string &eventId = event.getId();

    if (event.getSource() == mPartyAcceptDialog)
    {
        // check if they accepted the invite
        if (eventId == "yes")
        {
            SERVER_NOTICE(strprintf(_("Accepted party invite from %s."),
                    mPartyInviter.c_str()))
            Net::getPartyHandler()->inviteResponse(mPartyInviter, true);
        }
        else if (eventId == "no")
        {
            SERVER_NOTICE(strprintf(_("Rejected party invite from %s."),
                    mPartyInviter.c_str()))
            Net::getPartyHandler()->inviteResponse(mPartyInviter, false);
        }

        mPartyInviter.clear();
        mPartyAcceptDialog = nullptr;
    }
    else if (event.getSource() == mGuildAcceptDialog)
    {
        // check if they accepted the invite
        if (eventId == "yes")
        {
            SERVER_NOTICE(_("Accepted guild invite"))
            Net::getGuildHandler()->inviteResponse(mGuildInvited, true);
        }
        else if (eventId == "no")
        {
            SERVER_NOTICE(_("Rejected guild invite."))
            Net::getGuildHandler()->inviteResponse(mGuildInvited, false);
        }

        mGuildInvited = 0;
        mGuildAcceptDialog = nullptr;
    }
    else if (event.getId() == "create")
    {
        if (Net::getGuildHandler()->isSupported())
            mCreatePopup->show(mCreateButton);
        else
            showPartyCreate();
    }
    else if (event.getId() == "invite" && mTabs->getSelectedTabIndex() > -1)
    {
        static_cast<SocialTab*>(mTabs->getSelectedTab())->invite();
    }
    else if (event.getId() == "leave" && mTabs->getSelectedTabIndex() > -1)
    {
        static_cast<SocialTab*>(mTabs->getSelectedTab())->leave();
    }
    else if (event.getId() == "create guild")
    {
        std::string name = mGuildCreateDialog->getText();

        if (name.size() > 16)
        {
            SERVER_NOTICE(_("Creating guild failed, please choose a "
                            "shorter name."));
            return;
        }

        if (!name.empty())
        {
            Net::getGuildHandler()->create(name);
            SERVER_NOTICE(strprintf(_("Creating guild called %s."),
                                    name.c_str()));
        }

        mGuildCreateDialog = nullptr;
    }
    else if (event.getId() == "~create guild")
    {
        mGuildCreateDialog = nullptr;
    }
    else if (event.getId() == "create party")
    {
        std::string name = mPartyCreateDialog->getText();

        if (name.size() > 16)
        {
            SERVER_NOTICE(_("Creating party failed, please choose a "
                            "shorter name."));
            return;
        }

        if (!name.empty())
        {
            Net::getPartyHandler()->create(name);
            SERVER_NOTICE(strprintf(_("Creating party called %s."),
                                    name.c_str()));
        }

        mPartyCreateDialog = nullptr;
    }
    else if (event.getId() == "~create party")
    {
        mPartyCreateDialog = nullptr;
    }
}

void SocialWindow::showGuildCreate()
{
    mGuildCreateDialog = new TextDialog(_("Guild Name"),
                                        _("Choose your guild's name."), this);
    mGuildCreateDialog->setActionEventId("create guild");
    mGuildCreateDialog->addActionListener(this);
}

void SocialWindow::showGuildInvite(const std::string &guildName,
                                   const int guildId,
                                   const std::string &inviterName)
{
    // check there isnt already an invite showing
    if (mGuildInvited != 0)
    {
        SERVER_NOTICE(_("Received guild request, but one already "
                "exists."))
        return;
    }

    std::string msg = strprintf(_("%s has invited you to join the guild %s."),
                                inviterName.c_str(), guildName.c_str());
    SERVER_NOTICE(msg)

    // show invite
    mGuildAcceptDialog = new ConfirmDialog(_("Accept Guild Invite"), msg, this);
    mGuildAcceptDialog->addActionListener(this);

    mGuildInvited = guildId;
}

void SocialWindow::showPartyInvite(const std::string &inviter,
                                   const std::string &partyName)
{
    // check there isnt already an invite showing
    if (!mPartyInviter.empty())
    {
        SERVER_NOTICE(_("Received party request, but one already exists."))
        return;
    }

    std::string msg;
    if (inviter.empty())
    {
        if (partyName.empty())
        {
            msg = _("You have been invited you to join a party.");
        }
        else
        {
            msg = strprintf(_("You have been invited to join the %s party."),
                                        partyName.c_str());
        }
    }
    else
    {
        if (partyName.empty())
        {
            msg = strprintf(_("%s has invited you to join their party."),
                                        inviter.c_str());
        }
        else
        {
            msg = strprintf(_("%s has invited you to join the %s party."),
                                        inviter.c_str(), partyName.c_str());
        }
    }

    SERVER_NOTICE(msg)

    // show invite
    mPartyAcceptDialog = new ConfirmDialog(_("Accept Party Invite"), msg, this);
    mPartyAcceptDialog->addActionListener(this);

    mPartyInviter = inviter;
}

void SocialWindow::showPartyCreate()
{
    if (local_player->getParty())
    {
        new OkDialog(_("Create Party"),
                     _("Cannot create party. You are already in a party"),
                     true, this);
        return;
    }

    mPartyCreateDialog = new TextDialog(_("Party Name"),
                                        _("Choose your party's name."), this);
    mPartyCreateDialog->setActionEventId("create party");
    mPartyCreateDialog->addActionListener(this);
}

void SocialWindow::updateButtons()
{
    bool hasTabs = mTabs->getNumberOfTabs() > 0;
    mInviteButton->setEnabled(hasTabs);
    mLeaveButton->setEnabled(hasTabs);
}