Mana
Loading...
Searching...
No Matches
socialwindow.cpp
Go to the documentation of this file.
1/*
2 * The Mana Client
3 * Copyright (C) 2010-2012 The Mana Developers
4 *
5 * This file is part of The Mana Client.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include "gui/socialwindow.h"
22
23#include "client.h"
24#include "event.h"
25#include "guild.h"
26#include "localplayer.h"
27#include "party.h"
28
29#include "gui/confirmdialog.h"
30#include "gui/okdialog.h"
31#include "gui/setup.h"
32#include "gui/textdialog.h"
33
36#include "gui/widgets/button.h"
37#include "gui/widgets/layout.h"
39#include "gui/widgets/popup.h"
41#include "gui/widgets/tab.h"
43
44#include "net/net.h"
45#include "net/chathandler.h"
46#include "net/guildhandler.h"
47#include "net/partyhandler.h"
48
49#include "resources/theme.h"
50
51#include "utils/gettext.h"
52#include "utils/stringutils.h"
53
54#include <memory>
55
56class SocialTab : public Tab
57{
58protected:
59 friend class SocialWindow;
60
61 SocialTab() = default;
62
63 ~SocialTab() override
64 {
65 // Cleanup dialogs
66 if (mInviteDialog)
67 {
70 mInviteDialog = nullptr;
71 }
72
74 {
77 mConfirmDialog = nullptr;
78 }
79 }
80
81 virtual void invite() = 0;
82
83 virtual void leave() = 0;
84
87 std::unique_ptr<ScrollArea> mScroll;
88 std::unique_ptr<AvatarListBox> mList;
89};
90
91class GuildTab : public SocialTab, public gcn::ActionListener
92{
93public:
94 GuildTab(Guild *guild):
95 mGuild(guild)
96 {
97 setCaption(guild->getName());
98
100
101 mList = std::make_unique<AvatarListBox>(guild);
102 mScroll = std::make_unique<ScrollArea>(mList.get());
103
104 mScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
105 mScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_AUTO);
106 }
107
108 void action(const gcn::ActionEvent &event) override
109 {
110 if (event.getId() == "do invite")
111 {
112 std::string name = mInviteDialog->getText();
113
114 if (!name.empty())
115 {
117 serverNotice(strprintf(_("Invited user %s to guild %s."),
118 name.c_str(),
119 mGuild->getName().c_str()));
120 }
121 mInviteDialog = nullptr;
122 }
123 else if (event.getId() == "~do invite")
124 {
125 mInviteDialog = nullptr;
126 }
127 else if (event.getId() == "yes")
128 {
130 serverNotice(strprintf(_("Guild %s quit requested."),
131 mGuild->getName().c_str()));
132 mConfirmDialog = nullptr;
133 }
134 else if (event.getId() == "no")
135 {
136 mConfirmDialog = nullptr;
137 }
138 }
139
140protected:
141 void invite() override
142 {
143 // TODO - Give feedback on whether the invite succeeded
144 mInviteDialog = new TextDialog(_("Member Invite to Guild"),
145 strprintf(_("Who would you like to invite to guild %s?"),
146 mGuild->getName().c_str()),
147 socialWindow, true);
148 mInviteDialog->setActionEventId("do invite");
149 mInviteDialog->addActionListener(this);
150 }
151
152 void leave() override
153 {
154 mConfirmDialog = new ConfirmDialog(_("Leave Guild?"),
155 strprintf(_("Are you sure you want to leave guild %s?"),
156 mGuild->getName().c_str()),
158
159 mConfirmDialog->addActionListener(this);
160 }
161
162private:
164};
165
166class PartyTab : public SocialTab, public gcn::ActionListener
167{
168public:
170 mParty(party)
171 {
172 setCaption(party->getName());
173
175
176 mList = std::make_unique<AvatarListBox>(party);
177 mScroll = std::make_unique<ScrollArea>(mList.get());
178
179 mScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
180 mScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_AUTO);
181 }
182
183 void action(const gcn::ActionEvent &event) override
184 {
185 if (event.getId() == "do invite")
186 {
187 std::string name = mInviteDialog->getText();
188
189 if (!name.empty())
190 serverNotice(strprintf(_("Invited user %s to party."),
191 name.c_str()));
192 mInviteDialog = nullptr;
193 }
194 else if (event.getId() == "~do invite")
195 {
196 mInviteDialog = nullptr;
197 }
198 else if (event.getId() == "yes")
199 {
201 serverNotice(strprintf(_("Party %s quit requested."),
202 mParty->getName().c_str()));
203 mConfirmDialog = nullptr;
204 }
205 else if (event.getId() == "no")
206 {
207 mConfirmDialog = nullptr;
208 }
209 }
210
211protected:
212 void invite() override
213 {
214 // TODO - Give feedback on whether the invite succeeded
215 mInviteDialog = new TextDialog(_("Member Invite to Party"),
216 strprintf(_("Who would you like to invite to party %s?"),
217 mParty->getName().c_str()),
218 socialWindow, true);
219 mInviteDialog->setActionEventId("do invite");
220 mInviteDialog->addActionListener(this);
221 }
222
223 void leave() override
224 {
225 mConfirmDialog = new ConfirmDialog(_("Leave Party?"),
226 strprintf(_("Are you sure you want to leave party %s?"),
227 mParty->getName().c_str()),
229
230 mConfirmDialog->addActionListener(this);
231 }
232
233private:
235};
236
238{
239public:
240 ~PlayerList() override
241 {
243 }
244
245 void setPlayers(const std::vector<Avatar*> &players)
246 {
248 mPlayers = players;
249 }
250
254 int getNumberOfElements() override
255 {
256 return mPlayers.size();
257 }
258
259 Avatar *getAvatarAt(int index) override
260 {
261 return mPlayers[index];
262 }
263
264private:
265 std::vector<Avatar*> mPlayers;
266};
267
269{
270public:
272 {
274
275 mList = std::make_unique<AvatarListBox>(mPlayerList);
276 mScroll = std::make_unique<ScrollArea>(mList.get());
277
278 mScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
279 mScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_AUTO);
280 }
281
282 ~PlayerListTab() override
283 {
284 delete mPlayerList;
285 }
286
287 void setPlayers(const std::vector<Avatar*> &players)
288 {
289 mPlayerList->setPlayers(players);
290 }
291
292protected:
293 void invite() override {}
294 void leave() override {}
295
296private:
298};
299
300/*class BuddyTab : public SocialTab
301{
302 // TODO?
303};*/
304
305class CreatePopup : public Popup, public LinkHandler
306{
307public:
309 Popup("SocialCreatePopup")
310 {
314
315 if (Net::getGuildHandler()->isSupported())
316 mBrowserBox->addRow(strprintf("@@guild|%s@@", _("Create Guild")));
317 mBrowserBox->addRow(strprintf("@@party|%s@@", _("Create Party")));
318 mBrowserBox->addRow("##3---");
319 mBrowserBox->addRow(strprintf("@@cancel|%s@@", _("Cancel")));
320
322
323 setContentSize(mBrowserBox->getWidth(),
324 mBrowserBox->getHeight());
325 }
326
327 void handleLink(const std::string &link) override
328 {
329 if (link == "guild")
330 {
332 }
333 else if (link == "party")
334 {
336 }
337
338 setVisible(false);
339 }
340
341 void show(gcn::Widget *parent)
342 {
343 int x, y;
344 parent->getAbsolutePosition(x, y);
345 y += parent->getHeight();
346 setPosition(x, y);
347 setVisible(true);
348 requestMoveToTop();
349 }
350
351private:
353};
354
356 Window(_("Social"))
357{
358 setWindowName("Social");
359 setVisible(false);
360 setSaveVisible(true);
361 setResizable(true);
362 setSaveVisible(true);
363 setCloseButton(true);
365
366 mCreateButton = new Button(_("Create"), "create", this);
367 mInviteButton = new Button(_("Invite"), "invite", this);
368 mLeaveButton = new Button(_("Leave"), "leave", this);
369 mTabs = new TabbedArea;
370
371 place(0, 0, mCreateButton);
372 place(1, 0, mInviteButton);
373 place(2, 0, mLeaveButton);
374 place(0, 1, mTabs, 4, 4);
375
376 // Determine minimum size
377 int width = 0, height = 0;
378 getLayout().reflow(width, height);
379 setMinimumContentSize(width, height);
380
381 setDefaultSize(590, 200, 150, 124);
383
385
387 mPlayerListTab->setCaption(strprintf(_("Online (%u)"), 0u));
388
390
391 if (local_player->getParty())
393 else
395}
396
398{
399 // Cleanup invites
401 {
404 mGuildAcceptDialog = nullptr;
405
406 mGuildInvited = 0;
407 }
408
410 {
413 mPartyAcceptDialog = nullptr;
414
415 mPartyInviter.clear();
416 }
417 delete mCreatePopup;
418 delete mPlayerListTab;
419}
420
422{
423 if (mGuilds.find(guild) != mGuilds.end())
424 return false;
425
426 auto *tab = new GuildTab(guild);
427 mGuilds[guild] = tab;
428
429 mTabs->addTab(tab, tab->mScroll.get());
430
432
433 return true;
434}
435
437{
438 auto it = mGuilds.find(guild);
439 if (it == mGuilds.end())
440 return false;
441
442 mTabs->removeTab(it->second);
443 delete it->second;
444 mGuilds.erase(it);
445
447
448 return true;
449}
450
452{
453 if (mParties.find(party) != mParties.end())
454 return false;
455
456 auto *tab = new PartyTab(party);
457 mParties[party] = tab;
458
459 mTabs->addTab(tab, tab->mScroll.get());
460
462
463 return true;
464}
465
467{
468 auto it = mParties.find(party);
469 if (it == mParties.end())
470 return false;
471
472 mTabs->removeTab(it->second);
473 delete it->second;
474 mParties.erase(it);
475
477
478 return true;
479}
480
481void SocialWindow::action(const gcn::ActionEvent &event)
482{
483 const std::string &eventId = event.getId();
484
485 if (event.getSource() == mPartyAcceptDialog)
486 {
487 // check if they accepted the invite
488 if (eventId == "yes")
489 {
490 serverNotice(strprintf(_("Accepted party invite from %s."),
491 mPartyInviter.c_str()));
493 }
494 else if (eventId == "no")
495 {
496 serverNotice(strprintf(_("Rejected party invite from %s."),
497 mPartyInviter.c_str()));
499 }
500
501 mPartyInviter.clear();
502 mPartyAcceptDialog = nullptr;
503 }
504 else if (event.getSource() == mGuildAcceptDialog)
505 {
506 // check if they accepted the invite
507 if (eventId == "yes")
508 {
509 serverNotice(_("Accepted guild invite"));
511 }
512 else if (eventId == "no")
513 {
514 serverNotice(_("Rejected guild invite."));
516 }
517
518 mGuildInvited = 0;
519 mGuildAcceptDialog = nullptr;
520 }
521 else if (event.getId() == "create")
522 {
523 if (Net::getGuildHandler()->isSupported())
525 else
527 }
528 else if (event.getId() == "invite" && mTabs->getSelectedTabIndex() > -1)
529 {
530 static_cast<SocialTab*>(mTabs->getSelectedTab())->invite();
531 }
532 else if (event.getId() == "leave" && mTabs->getSelectedTabIndex() > -1)
533 {
534 static_cast<SocialTab*>(mTabs->getSelectedTab())->leave();
535 }
536 else if (event.getId() == "create guild")
537 {
538 std::string name = mGuildCreateDialog->getText();
539
540 if (name.size() > 16)
541 {
542 serverNotice(_("Creating guild failed, please choose a "
543 "shorter name."));
544 return;
545 }
546
547 if (!name.empty())
548 {
550 serverNotice(strprintf(_("Creating guild called %s."),
551 name.c_str()));
552 }
553
554 mGuildCreateDialog = nullptr;
555 }
556 else if (event.getId() == "~create guild")
557 {
558 mGuildCreateDialog = nullptr;
559 }
560 else if (event.getId() == "create party")
561 {
562 std::string name = mPartyCreateDialog->getText();
563
564 if (name.size() > 16)
565 {
566 serverNotice(_("Creating party failed, please choose a "
567 "shorter name."));
568 return;
569 }
570
571 if (!name.empty())
572 {
574 serverNotice(strprintf(_("Creating party called %s."),
575 name.c_str()));
576 }
577
578 mPartyCreateDialog = nullptr;
579 }
580 else if (event.getId() == "~create party")
581 {
582 mPartyCreateDialog = nullptr;
583 }
584}
585
587{
588 mGuildCreateDialog = new TextDialog(_("Guild Name"),
589 _("Choose your guild's name."), this);
590 mGuildCreateDialog->setActionEventId("create guild");
591 mGuildCreateDialog->addActionListener(this);
592}
593
594void SocialWindow::showGuildInvite(const std::string &guildName,
595 const int guildId,
596 const std::string &inviterName)
597{
598 // check there isnt already an invite showing
599 if (mGuildInvited != 0)
600 {
601 serverNotice(_("Received guild request, but one already exists."));
602 return;
603 }
604
605 std::string msg = strprintf(_("%s has invited you to join the guild %s."),
606 inviterName.c_str(), guildName.c_str());
607 serverNotice(msg);
608
609 // show invite
610 mGuildAcceptDialog = new ConfirmDialog(_("Accept Guild Invite"), msg, this);
611 mGuildAcceptDialog->addActionListener(this);
612
613 mGuildInvited = guildId;
614}
615
616void SocialWindow::showPartyInvite(const std::string &inviter,
617 const std::string &partyName)
618{
619 // check there isnt already an invite showing
620 if (!mPartyInviter.empty())
621 {
622 serverNotice(_("Received party request, but one already exists."));
623 return;
624 }
625
626 std::string msg;
627 if (inviter.empty())
628 {
629 if (partyName.empty())
630 {
631 msg = _("You have been invited you to join a party.");
632 }
633 else
634 {
635 msg = strprintf(_("You have been invited to join the %s party."),
636 partyName.c_str());
637 }
638 }
639 else
640 {
641 if (partyName.empty())
642 {
643 msg = strprintf(_("%s has invited you to join their party."),
644 inviter.c_str());
645 }
646 else
647 {
648 msg = strprintf(_("%s has invited you to join the %s party."),
649 inviter.c_str(), partyName.c_str());
650 }
651 }
652
653 serverNotice(msg);
654
655 // show invite
656 mPartyAcceptDialog = new ConfirmDialog(_("Accept Party Invite"), msg, this);
657 mPartyAcceptDialog->addActionListener(this);
658
659 mPartyInviter = inviter;
660}
661
663{
664 if (local_player->getParty())
665 {
666 new OkDialog(_("Create Party"),
667 _("Cannot create party. You are already in a party."),
668 true, this);
669 return;
670 }
671
672 mPartyCreateDialog = new TextDialog(_("Party Name"),
673 _("Choose your party's name."), this);
674 mPartyCreateDialog->setActionEventId("create party");
675 mPartyCreateDialog->addActionListener(this);
676}
677
678void SocialWindow::setPlayersOnline(const std::vector<Avatar*> &players)
679{
680 mPlayerListTab->setPlayers(players);
681
682 unsigned playerCount = static_cast<unsigned>(players.size());
683 mPlayerListTab->setCaption(strprintf(_("Online (%u)"), playerCount));
684}
685
687{
689 {
692 }
693
694 Window::logic();
695}
696
698{
699 bool hasTabs = mTabs->getNumberOfTabs() > 0;
700 mInviteButton->setEnabled(hasTabs);
701 mLeaveButton->setEnabled(hasTabs);
702}
Party * getParty() const
Definition being.h:262
A simple browser box able to handle links and forward events to the parent conteiner.
Definition browserbox.h:74
void setHighlightMode(unsigned int mode)
Sets the Highlight mode for links.
Definition browserbox.h:95
void addRow(std::string_view row)
Adds a text row to the browser.
void setLinkHandler(LinkHandler *handler)
Sets the handler for links.
Definition browserbox.h:88
Button widget.
Definition button.h:38
An option dialog.
BrowserBox * mBrowserBox
void handleLink(const std::string &link) override
void show(gcn::Widget *parent)
void leave() override
GuildTab(Guild *guild)
void action(const gcn::ActionEvent &event) override
Guild * mGuild
void invite() override
Definition guild.h:55
const std::string & getName() const
Get the name of the guild.
Definition guild.h:94
short getId() const
Get the id of the guild.
Definition guild.h:103
void reflow(int &nW, int &nH)
Sets the positions of all the widgets.
Definition layout.cpp:321
A simple interface to windows that need to handle links from BrowserBox widget.
Definition linkhandler.h:31
virtual void requestOnlineList()=0
virtual void inviteResponse(int guildId, bool response)=0
virtual void create(const std::string &name)=0
virtual void invite(int guildId, const std::string &name)=0
virtual void leave(int guildId)=0
virtual void leave()=0
virtual void create(const std::string &name=std::string())=0
virtual void inviteResponse(const std::string &inviter, bool accept)=0
An 'Ok' button dialog.
Definition okdialog.h:34
void leave() override
void invite() override
Party * mParty
PartyTab(Party *party)
void action(const gcn::ActionEvent &event) override
Definition party.h:59
const std::string & getName() const
Get the name of the party.
Definition party.h:93
void leave() override
void setPlayers(const std::vector< Avatar * > &players)
~PlayerListTab() override
PlayerList * mPlayerList
void invite() override
std::vector< Avatar * > mPlayers
Avatar * getAvatarAt(int index) override
~PlayerList() override
int getNumberOfElements() override
Returns the number of players in the list.
void setPlayers(const std::vector< Avatar * > &players)
A light version of the Window class.
Definition popup.h:48
void add(gcn::Widget *widget) override
Definition popup.cpp:69
void setContentSize(int width, int height)
Sets the size of this popup.
Definition popup.cpp:127
void registerWindowForReset(Window *window)
Enables the Reset Windows button.
Definition setup.cpp:108
SocialTab()=default
virtual void invite()=0
ConfirmDialog * mConfirmDialog
TextDialog * mInviteDialog
std::unique_ptr< ScrollArea > mScroll
virtual void leave()=0
std::unique_ptr< AvatarListBox > mList
~SocialTab() override
Party window.
void showGuildInvite(const std::string &guildName, int guildId, const std::string &inviterName)
std::map< Guild *, SocialTab * > mGuilds
CreatePopup * mCreatePopup
void showPartyCreate()
void showGuildCreate()
ConfirmDialog * mPartyAcceptDialog
std::string mPartyInviter
TextDialog * mGuildCreateDialog
void logic() override
bool removeTab(Guild *guild)
std::map< Party *, SocialTab * > mParties
TextDialog * mPartyCreateDialog
Button * mCreateButton
TabbedArea * mTabs
Button * mInviteButton
Button * mLeaveButton
ConfirmDialog * mGuildAcceptDialog
bool addTab(Guild *guild)
void action(const gcn::ActionEvent &event) override
Handle events.
Timer mOnlineListUpdateTimer
~SocialWindow() override
PlayerListTab * mPlayerListTab
void showPartyInvite(const std::string &inviter, const std::string &partyName=std::string())
void setPlayersOnline(const std::vector< Avatar * > &players)
A tab, the same as the Guichan tab in 0.8, but extended to allow transparency.
Definition tab.h:33
void setCaption(const std::string &caption)
Sets the caption of the tab.
Definition tab.cpp:49
void setTabColor(const gcn::Color *color)
Set the normal color fo the tab's text.
Definition tab.cpp:117
A tabbed area, the same as the guichan tabbed area in 0.8, but extended.
Definition tabbedarea.h:40
void addTab(gcn::Tab *tab, gcn::Widget *widget) override
Add a tab.
void removeTab(gcn::Tab *tab) override
Override the remove tab function as it's broken in guichan 0.8.
int getNumberOfTabs() const
Return how many tabs have been created.
An option dialog.
Definition textdialog.h:36
const std::string & getText() const
Get the text in the textfield.
static const gcn::Color & getThemeColor(int type)
Gets the color associated with the type in the default palette (0).
Definition theme.cpp:313
@ PARTY_TAB
Definition theme.h:228
@ GUILD
Definition theme.h:246
bool passed() const
Returns whether the timer has passed.
Definition time.h:88
void set(uint32_t ms=0)
Sets the timer with an optional duration in milliseconds.
Definition time.h:69
A window.
Definition window.h:59
virtual void setVisible(bool visible)
Overloads window setVisible by Guichan to allow sticky window handling.
Definition window.cpp:282
virtual void close()
Overrideable functionality for when the window is to close.
Definition window.cpp:327
Layout & getLayout()
Gets the layout handler for this window.
Definition window.cpp:714
void setWindowName(const std::string &name)
Sets the name of the window.
Definition window.h:272
void setMinimumContentSize(int width, int height)
Sets the minimum size of the window content.
Definition window.cpp:168
void setResizable(bool resize)
Sets whether or not the window can be resized.
Definition window.cpp:212
void setSaveVisible(bool save)
Sets whether the window will save it's visibility.
Definition window.h:225
LayoutCell & place(int x, int y, gcn::Widget *, int w=1, int h=1)
Adds a widget to the window and sets it at given cell.
Definition window.cpp:737
void scheduleDelete()
Schedule this window for deletion.
Definition window.cpp:299
void setCloseButton(bool flag)
Sets whether or not the window has a close button.
Definition window.cpp:262
void setDefaultSize()
Set the default win pos and size to the current ones.
Definition window.cpp:545
void loadWindowState()
Reads the position (and the size for resizable windows) in the configuration based on the given strin...
Definition window.cpp:467
void delete_all(Container &c)
Definition dtor.h:46
void serverNotice(const std::string &message)
Definition event.h:319
SocialWindow * socialWindow
Definition game.cpp:108
#define _(s)
Definition gettext.h:38
LocalPlayer * local_player
ChatHandler * getChatHandler()
Definition net.cpp:70
GuildHandler * getGuildHandler()
Definition net.cpp:85
PartyHandler * getPartyHandler()
Definition net.cpp:105
Setup * setupWindow
Definition setup.cpp:120
std::string strprintf(char const *format,...)
A safe version of sprintf that returns a std::string of the result.