diff --git a/indra/newview/fscontactsfloater.cpp b/indra/newview/fscontactsfloater.cpp index 8b0106e3ec..685fc13dd6 100644 --- a/indra/newview/fscontactsfloater.cpp +++ b/indra/newview/fscontactsfloater.cpp @@ -30,6 +30,7 @@ #include "fscontactsfloater.h" // libs +#include "llagent.h" #include "llavatarname.h" #include "llfloaterreg.h" #include "llfloater.h" @@ -44,6 +45,7 @@ #include "llgroupactions.h" #include "llgrouplist.h" #include "llsidetray.h" +#include "llstartup.h" static const std::string FRIENDS_TAB_NAME = "friends_panel"; static const std::string GROUP_TAB_NAME = "groups_panel"; @@ -127,10 +129,9 @@ BOOL FSFloaterContacts::postBuild() mGroupList->setNoFilteredItemsMsg(getString("no_filtered_groups_msg")); mGroupList->setDoubleClickCallback(boost::bind(&FSFloaterContacts::onGroupChatButtonClicked, this)); - // mGroupList->setCommitCallback(boost::bind(&FSFloaterContacts::updateButtons, this)); + mGroupList->setCommitCallback(boost::bind(&FSFloaterContacts::updateButtons, this)); mGroupList->setReturnCallback(boost::bind(&FSFloaterContacts::onGroupChatButtonClicked, this)); - mGroupsTab->childSetAction("chat_btn", boost::bind(&FSFloaterContacts::onGroupChatButtonClicked, this)); mGroupsTab->childSetAction("info_btn", boost::bind(&FSFloaterContacts::onGroupInfoButtonClicked, this)); mGroupsTab->childSetAction("activate_btn", boost::bind(&FSFloaterContacts::onGroupActivateButtonClicked, this)); @@ -141,6 +142,15 @@ BOOL FSFloaterContacts::postBuild() return TRUE; } +void FSFloaterContacts::updateButtons() +{ + std::vector items; + mGroupList->getItems(items); + + mGroupsTab->getChild("groupcount")->setTextArg("[COUNT]", llformat("%d", gAgent.mGroups.count())); // items.end()));// + mGroupsTab->getChild("groupcount")->setTextArg("[MAX]", llformat("%d", gMaxAgentGroups)); +} + void FSFloaterContacts::onOpen(const LLSD& key) { if (key.asString() == "friends") @@ -150,6 +160,8 @@ void FSFloaterContacts::onOpen(const LLSD& key) else if (key.asString() == "groups") { childShowTab("friends_and_groups", "groups_panel"); + mGroupsTab->getChild("groupcount")->setTextArg("[COUNT]", llformat("%d", gAgent.mGroups.count())); // items.end()));// + mGroupsTab->getChild("groupcount")->setTextArg("[MAX]", llformat("%d", gMaxAgentGroups)); } } diff --git a/indra/newview/fscontactsfloater.h b/indra/newview/fscontactsfloater.h index b0e2d1e96a..685fc13dd6 100644 --- a/indra/newview/fscontactsfloater.h +++ b/indra/newview/fscontactsfloater.h @@ -1,5 +1,5 @@ /** - * @file fscontactsfloater.h + * @file * @brief * * $LicenseInfo:firstyear=2011&license=fsviewerlgpl$ @@ -23,69 +23,341 @@ * The Phoenix Viewer Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA * $/LicenseInfo$ */ - - -#ifndef LL_FSCONTACTSFLOATER_H -#define LL_FSCONTACTSFLOATER_H -#include -#include +#include "llviewerprecompiledheaders.h" + +#include "fscontactsfloater.h" + +// libs +#include "llagent.h" +#include "llavatarname.h" +#include "llfloaterreg.h" #include "llfloater.h" +#include "lltabcontainer.h" -class LLAvatarList; -class LLAvatarName; -class LLGroupList; -class LLPanel; -class LLTabContainer; +#include "llavataractions.h" +#include "llavatarlist.h" +#include "llavatarlistitem.h" +#include "llcallingcard.h" // for LLAvatarTracker +#include "llfloateravatarpicker.h" +#include "llfriendcard.h" +#include "llgroupactions.h" +#include "llgrouplist.h" +#include "llsidetray.h" +#include "llstartup.h" -class FSFloaterContacts : public LLFloater +static const std::string FRIENDS_TAB_NAME = "friends_panel"; +static const std::string GROUP_TAB_NAME = "groups_panel"; + +/** Compares avatar items by online status, then by name */ +class LLAvatarItemStatusComparator : public LLAvatarItemComparator { public: - FSFloaterContacts(const LLSD& seed); - virtual ~FSFloaterContacts(); + LLAvatarItemStatusComparator() {}; - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onOpen(const LLSD& key); +protected: + /** + * @return true if item1 < item2, false otherwise + */ + virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const + { + LLAvatarTracker& at = LLAvatarTracker::instance(); + bool online1 = at.isBuddyOnline(item1->getAvatarId()); + bool online2 = at.isBuddyOnline(item2->getAvatarId()); - static FSFloaterContacts* getInstance(); - static FSFloaterContacts* findInstance(); - - LLPanel* mFriendsTab; - LLAvatarList* mFriendList; - LLPanel* mGroupsTab; - LLGroupList* mGroupList; + if (online1 == online2) + { + std::string name1 = item1->getAvatarName(); + std::string name2 = item2->getAvatarName(); -private: - std::string getActiveTabName() const; - LLUUID getCurrentItemID() const; - void getCurrentItemIDs(uuid_vec_t& selected_uuids) const; - void onAvatarListDoubleClicked(LLUICtrl* ctrl); - - bool isItemsFreeOfFriends(const uuid_vec_t& uuids); - - // misc callbacks - static void onAvatarPicked(const uuid_vec_t& ids, const std::vector names); - - // friend buttons - void onViewProfileButtonClicked(); - void onImButtonClicked(); - void onTeleportButtonClicked(); - void onPayButtonClicked(); - void onDeleteFriendButtonClicked(); - void onAddFriendWizButtonClicked(); - - // group buttons - void onGroupChatButtonClicked(); - void onGroupInfoButtonClicked(); - void onGroupActivateButtonClicked(); - void onGroupLeaveButtonClicked(); - void onGroupCreateButtonClicked(); - void onGroupSearchButtonClicked(); - - LLTabContainer* mTabContainer; - + LLStringUtil::toUpper(name1); + LLStringUtil::toUpper(name2); + + return name1 < name2; + } + + return online1 > online2; + } }; +static const LLAvatarItemStatusComparator STATUS_COMPARATOR; -#endif // LL_FSCONTACTSFLOATER_H + +// +// FSFloaterContacts +// + +FSFloaterContacts::FSFloaterContacts(const LLSD& seed) + : LLFloater(seed), + mTabContainer(NULL), + mFriendList(NULL), + mGroupList(NULL) +{ +} + +FSFloaterContacts::~FSFloaterContacts() +{ +} + +BOOL FSFloaterContacts::postBuild() +{ + mTabContainer = getChild("friends_and_groups"); + + mFriendsTab = getChild(FRIENDS_TAB_NAME); + mFriendList = mFriendsTab->getChild("avatars_all"); + mFriendList->setNoItemsCommentText(getString("no_friends")); + mFriendList->setShowIcons("FriendsListShowIcons"); + mFriendList->showPermissions(TRUE); + mFriendList->setComparator(&STATUS_COMPARATOR); + mFriendList->sort(); + + mFriendList->setItemDoubleClickCallback(boost::bind(&FSFloaterContacts::onAvatarListDoubleClicked, this, _1)); + mFriendList->setReturnCallback(boost::bind(&FSFloaterContacts::onImButtonClicked, this)); + + mFriendsTab->childSetAction("im_btn", boost::bind(&FSFloaterContacts::onImButtonClicked, this)); + mFriendsTab->childSetAction("profile_btn", boost::bind(&FSFloaterContacts::onViewProfileButtonClicked, this)); + mFriendsTab->childSetAction("offer_teleport_btn", boost::bind(&FSFloaterContacts::onTeleportButtonClicked, this)); + mFriendsTab->childSetAction("pay_btn", boost::bind(&FSFloaterContacts::onPayButtonClicked, this)); + + mFriendsTab->childSetAction("remove_btn", boost::bind(&FSFloaterContacts::onDeleteFriendButtonClicked, this)); + mFriendsTab->childSetAction("add_btn", boost::bind(&FSFloaterContacts::onAddFriendWizButtonClicked, this)); + + mGroupsTab = getChild(GROUP_TAB_NAME); + mGroupList = mGroupsTab->getChild("group_list"); + mGroupList->setNoItemsMsg(getString("no_groups_msg")); + mGroupList->setNoFilteredItemsMsg(getString("no_filtered_groups_msg")); + + mGroupList->setDoubleClickCallback(boost::bind(&FSFloaterContacts::onGroupChatButtonClicked, this)); + mGroupList->setCommitCallback(boost::bind(&FSFloaterContacts::updateButtons, this)); + mGroupList->setReturnCallback(boost::bind(&FSFloaterContacts::onGroupChatButtonClicked, this)); + + mGroupsTab->childSetAction("chat_btn", boost::bind(&FSFloaterContacts::onGroupChatButtonClicked, this)); + mGroupsTab->childSetAction("info_btn", boost::bind(&FSFloaterContacts::onGroupInfoButtonClicked, this)); + mGroupsTab->childSetAction("activate_btn", boost::bind(&FSFloaterContacts::onGroupActivateButtonClicked, this)); + mGroupsTab->childSetAction("leave_btn", boost::bind(&FSFloaterContacts::onGroupLeaveButtonClicked, this)); + mGroupsTab->childSetAction("create_btn", boost::bind(&FSFloaterContacts::onGroupCreateButtonClicked, this)); + mGroupsTab->childSetAction("search_btn", boost::bind(&FSFloaterContacts::onGroupSearchButtonClicked, this)); + + return TRUE; +} + +void FSFloaterContacts::updateButtons() +{ + std::vector items; + mGroupList->getItems(items); + + mGroupsTab->getChild("groupcount")->setTextArg("[COUNT]", llformat("%d", gAgent.mGroups.count())); // items.end()));// + mGroupsTab->getChild("groupcount")->setTextArg("[MAX]", llformat("%d", gMaxAgentGroups)); +} + +void FSFloaterContacts::onOpen(const LLSD& key) +{ + if (key.asString() == "friends") + { + childShowTab("friends_and_groups", "friends_panel"); + } + else if (key.asString() == "groups") + { + childShowTab("friends_and_groups", "groups_panel"); + mGroupsTab->getChild("groupcount")->setTextArg("[COUNT]", llformat("%d", gAgent.mGroups.count())); // items.end()));// + mGroupsTab->getChild("groupcount")->setTextArg("[MAX]", llformat("%d", gMaxAgentGroups)); + } +} + + +// +// Friend actions +// + +void FSFloaterContacts::onAvatarListDoubleClicked(LLUICtrl* ctrl) +{ + LLAvatarListItem* item = dynamic_cast(ctrl); + if(!item) + { + return; + } + + LLUUID clicked_id = item->getAvatarId(); + +#if 0 // SJB: Useful for testing, but not currently functional or to spec + LLAvatarActions::showProfile(clicked_id); +#else // spec says open IM window + LLAvatarActions::startIM(clicked_id); +#endif +} + +void FSFloaterContacts::onImButtonClicked() +{ + uuid_vec_t selected_uuids; + getCurrentItemIDs(selected_uuids); + if ( selected_uuids.size() == 1 ) + { + // if selected only one person then start up IM + LLAvatarActions::startIM(selected_uuids.at(0)); + } + else if ( selected_uuids.size() > 1 ) + { + // for multiple selection start up friends conference + LLAvatarActions::startConference(selected_uuids); + } +} + +void FSFloaterContacts::onViewProfileButtonClicked() +{ + LLUUID id = getCurrentItemID(); + LLAvatarActions::showProfile(id); +} + +void FSFloaterContacts::onTeleportButtonClicked() +{ + uuid_vec_t selected_uuids; + getCurrentItemIDs(selected_uuids); + LLAvatarActions::offerTeleport(selected_uuids); +} + +void FSFloaterContacts::onPayButtonClicked() +{ + LLUUID id = getCurrentItemID(); + if (id.notNull()) + LLAvatarActions::pay(id); +} + +void FSFloaterContacts::onDeleteFriendButtonClicked() +{ + uuid_vec_t selected_uuids; + getCurrentItemIDs(selected_uuids); + + if (selected_uuids.size() == 1) + { + LLAvatarActions::removeFriendDialog( selected_uuids.front() ); + } + else if (selected_uuids.size() > 1) + { + LLAvatarActions::removeFriendsDialog( selected_uuids ); + } +} + +bool FSFloaterContacts::isItemsFreeOfFriends(const uuid_vec_t& uuids) +{ + const LLAvatarTracker& av_tracker = LLAvatarTracker::instance(); + for ( uuid_vec_t::const_iterator + id = uuids.begin(), + id_end = uuids.end(); + id != id_end; ++id ) + { + if (av_tracker.isBuddy (*id)) + { + return false; + } + } + return true; +} + +void FSFloaterContacts::onAddFriendWizButtonClicked() +{ + // Show add friend wizard. + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&FSFloaterContacts::onAvatarPicked, _1, _2), FALSE, TRUE); + // Need to disable 'ok' button when friend occurs in selection + if (picker) picker->setOkBtnEnableCb(boost::bind(&FSFloaterContacts::isItemsFreeOfFriends, this, _1)); + LLFloater* root_floater = gFloaterView->getParentFloater(this); + if (root_floater) + { + root_floater->addDependentFloater(picker); + } +} + +// +// Group actions +// + +void FSFloaterContacts::onGroupChatButtonClicked() +{ + LLUUID group_id = getCurrentItemID(); + if (group_id.notNull()) + LLGroupActions::startIM(group_id); +} + +void FSFloaterContacts::onGroupInfoButtonClicked() +{ + LLGroupActions::show(getCurrentItemID()); +} + +void FSFloaterContacts::onGroupActivateButtonClicked() +{ + LLGroupActions::activate(mGroupList->getSelectedUUID()); +} + +void FSFloaterContacts::onGroupLeaveButtonClicked() +{ + LLUUID group_id = getCurrentItemID(); + if (group_id.notNull()) + LLGroupActions::leave(group_id); +} + +void FSFloaterContacts::onGroupCreateButtonClicked() +{ + LLGroupActions::createGroup(); +} + +void FSFloaterContacts::onGroupSearchButtonClicked() +{ + LLGroupActions::search(); +} + + + +std::string FSFloaterContacts::getActiveTabName() const +{ + return mTabContainer->getCurrentPanel()->getName(); +} + +LLUUID FSFloaterContacts::getCurrentItemID() const +{ + std::string cur_tab = getActiveTabName(); + + if (cur_tab == FRIENDS_TAB_NAME) + return mFriendList->getSelectedUUID(); + + if (cur_tab == GROUP_TAB_NAME) + return mGroupList->getSelectedUUID(); + + llassert(0 && "unknown tab selected"); + return LLUUID::null; +} + +void FSFloaterContacts::getCurrentItemIDs(uuid_vec_t& selected_uuids) const +{ + std::string cur_tab = getActiveTabName(); + + if (cur_tab == FRIENDS_TAB_NAME) + mFriendList->getSelectedUUIDs(selected_uuids); + else if (cur_tab == GROUP_TAB_NAME) + mGroupList->getSelectedUUIDs(selected_uuids); + else + llassert(0 && "unknown tab selected"); + +} + + + +// static +void FSFloaterContacts::onAvatarPicked(const uuid_vec_t& ids, const std::vector names) +{ + if (!names.empty() && !ids.empty()) + LLAvatarActions::requestFriendshipDialog(ids[0], names[0].getCompleteName()); +} + + +//static +FSFloaterContacts* FSFloaterContacts::findInstance() +{ + return LLFloaterReg::findTypedInstance("imcontacts"); +} + +FSFloaterContacts* FSFloaterContacts::getInstance() +{ + return LLFloaterReg::getTypedInstance("imcontacts"); +} + +// EOF diff --git a/indra/newview/skins/default/xui/en/fs_panel_contacts_groups.xml b/indra/newview/skins/default/xui/en/fs_panel_contacts_groups.xml index 68a05423fc..a478afdd06 100644 --- a/indra/newview/skins/default/xui/en/fs_panel_contacts_groups.xml +++ b/indra/newview/skins/default/xui/en/fs_panel_contacts_groups.xml @@ -73,4 +73,69 @@ label="Invite..." name="invite_btn" width="80" />--> + +You belong to +[COUNT] out of +[MAX] groups. + +