diff options
author | Gilbert Gonzales <gilbert@lindenlab.com> | 2012-09-28 18:22:05 -0700 |
---|---|---|
committer | Gilbert Gonzales <gilbert@lindenlab.com> | 2012-09-28 18:22:05 -0700 |
commit | 11a148415e810706f2a1835b6b717a0a062d458f (patch) | |
tree | 5a81746fe6c3b4f34e4b96261facd1a3171f4614 /indra/newview | |
parent | 609fef130176c11dd7b14c305acf2f4331babad1 (diff) |
CHUI-102: Now the participants and one-on-one conversations have right-click-menus. These menus are functional as well, but 'chat history' does not yet work.
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/llconversationmodel.cpp | 44 | ||||
-rwxr-xr-x | indra/newview/llconversationmodel.h | 18 | ||||
-rw-r--r-- | indra/newview/llimfloater.h | 1 | ||||
-rwxr-xr-x | indra/newview/llimfloatercontainer.cpp | 192 | ||||
-rw-r--r-- | indra/newview/llimfloatercontainer.h | 5 | ||||
-rw-r--r-- | indra/newview/llinventorypanel.cpp | 1 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/menu_conversation.xml | 109 |
7 files changed, 367 insertions, 3 deletions
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 7d0ffa0788..1c4c7aefae 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -28,6 +28,7 @@ #include "llviewerprecompiledheaders.h" #include "llconversationmodel.h" +#include "llmenugl.h" // // Conversation items : common behaviors @@ -84,6 +85,24 @@ void LLConversationItem::showProperties(void) { } +void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items) +{ + items.push_back(std::string("view_profile")); + items.push_back(std::string("im")); + items.push_back(std::string("offer_teleport")); + items.push_back(std::string("voice_call")); + items.push_back(std::string("chat_history")); + items.push_back(std::string("separator_chat_history")); + items.push_back(std::string("add_friend")); + items.push_back(std::string("remove_friend")); + items.push_back(std::string("invite_to_group")); + items.push_back(std::string("separator_invite_to_group")); + items.push_back(std::string("map")); + items.push_back(std::string("share")); + items.push_back(std::string("pay")); + items.push_back(std::string("block_unblock")); +} + // // LLConversationItemSession // @@ -191,6 +210,22 @@ void LLConversationItemSession::setDistance(const LLUUID& participant_id, F64 di } } +void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + lldebugs << "LLConversationItemParticipant::buildContextMenu()" << llendl; + menuentry_vec_t items; + menuentry_vec_t disabled_items; + + if(this->getType() == CONV_SESSION_1_ON_1) + { + items.push_back(std::string("close_conversation")); + items.push_back(std::string("separator_disconnect_from_voice")); + buildParticipantMenuOptions(items); + } + + hide_context_entries(menu, items, disabled_items); +} + // The time of activity of a session is the time of the most recent activity, session and participants included const bool LLConversationItemSession::getTime(F64& time) const { @@ -249,6 +284,15 @@ LLConversationItemParticipant::LLConversationItemParticipant(const LLUUID& uuid, mConvType = CONV_PARTICIPANT; } +void LLConversationItemParticipant::buildContextMenu(LLMenuGL& menu, U32 flags) +{ + menuentry_vec_t items; + menuentry_vec_t disabled_items; + + buildParticipantMenuOptions(items); + hide_context_entries(menu, items, disabled_items); +} + void LLConversationItemParticipant::onAvatarNameCache(const LLAvatarName& av_name) { mName = av_name.mUsername; diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 30f94d51ae..43fa66e8e2 100755 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -41,6 +41,8 @@ class LLConversationItemParticipant; typedef std::map<LLUUID, LLConversationItem*> conversations_items_map; typedef std::map<LLUUID, LLFolderViewItem*> conversations_widgets_map; +typedef std::vector<std::string> menuentry_vec_t; + // Conversation items: we hold a list of those and create an LLFolderViewItem widget for each // that we tuck into the mConversationsListPanel. class LLConversationItem : public LLFolderViewModelItemCommon @@ -124,6 +126,8 @@ public: void resetRefresh() { mNeedsRefresh = false; } bool needsRefresh() { return mNeedsRefresh; } + void buildParticipantMenuOptions(menuentry_vec_t& items); + protected: std::string mName; // Name of the session or the participant LLUUID mUUID; // UUID of the session or the participant @@ -155,6 +159,7 @@ public: bool isLoaded() { return mIsLoaded; } + void buildContextMenu(LLMenuGL& menu, U32 flags); virtual const bool getTime(F64& time) const; void dumpDebugData(); @@ -178,7 +183,8 @@ public: void setIsModerator(bool is_moderator) { mIsModerator = is_moderator; mNeedsRefresh = true; } void setTimeNow() { mLastActiveTime = LLFrameTimer::getElapsedSeconds(); mNeedsRefresh = true; } void setDistance(F64 dist) { mDistToAgent = dist; mNeedsRefresh = true; } - + + void buildContextMenu(LLMenuGL& menu, U32 flags); void onAvatarNameCache(const LLAvatarName& av_name); virtual const bool getDistanceToAgent(F64& dist) const { dist = mDistToAgent; return (dist >= 0.0); } @@ -273,4 +279,14 @@ public: private: }; +// Utility function to hide all entries except those in the list +// Can be called multiple times on the same menu (e.g. if multiple items +// are selected). If "append" is false, then only common enabled items +// are set as enabled. + +//(defined in inventorybridge.cpp) +void hide_context_entries(LLMenuGL& menu, + const menuentry_vec_t &entries_to_show, + const menuentry_vec_t &disabled_entries); + #endif // LL_LLCONVERSATIONMODEL_H diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index e4a67a3d56..fbaf009939 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -128,6 +128,7 @@ public: static void onIMChicletCreated(const LLUUID& session_id); bool getStartConferenceInSameFloater() const { return mStartConferenceInSameFloater; } + LLUUID getOtherParticipantUUID() {return mOtherParticipantUUID;} static boost::signals2::connection setIMFloaterShowedCallback(const floater_showed_signal_t::slot_type& cb); static floater_showed_signal_t sIMFloaterShowedSignal; diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp index 14d40d4685..b4802c71f9 100755 --- a/indra/newview/llimfloatercontainer.cpp +++ b/indra/newview/llimfloatercontainer.cpp @@ -58,8 +58,12 @@ LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) mConversationsRoot(NULL), mInitialized(false) { + mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLIMFloaterContainer::isActionChecked, this, _2)); mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLIMFloaterContainer::onCustomAction, this, _2)); - mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLIMFloaterContainer::isActionChecked, this, _2)); + + mEnableCallbackRegistrar.add("Avatar.CheckItem", boost::bind(&LLIMFloaterContainer::checkContextMenuItem, this, _2)); + mEnableCallbackRegistrar.add("Avatar.EnableItem", boost::bind(&LLIMFloaterContainer::enableContextMenuItem, this, _2)); + mCommitCallbackRegistrar.add("Avatar.DoToSelected", boost::bind(&LLIMFloaterContainer::doToSelected, this, _2)); // Firstly add our self to IMSession observers, so we catch session events LLIMMgr::getInstance()->addSessionObserver(this); @@ -133,7 +137,9 @@ BOOL LLIMFloaterContainer::postBuild() p.listener = base_item; p.view_model = &mConversationViewModel; p.root = NULL; + p.options_menu = "menu_conversation.xml"; mConversationsRoot = LLUICtrlFactory::create<LLFolderView>(p); + mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); // a scroller for folder view LLRect scroller_view_rect = mConversationsListPanel->getRect(); @@ -341,7 +347,7 @@ void LLIMFloaterContainer::idle(void* user_data) { self->setNearbyDistances(); } - + self->mConversationsRoot->update(); } @@ -661,6 +667,188 @@ void LLIMFloaterContainer::setSortOrder(const LLConversationSort& order) gSavedSettings.setU32("ConversationSortOrder", (U32)order); } +void LLIMFloaterContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids) +{ + const std::set<LLFolderViewItem*> selectedItems = mConversationsRoot->getSelectionList(); + + std::set<LLFolderViewItem*>::const_iterator it = selectedItems.begin(); + const std::set<LLFolderViewItem*>::const_iterator it_end = selectedItems.end(); + LLConversationItem * conversationItem; + + for (; it != it_end; ++it) + { + conversationItem = static_cast<LLConversationItem *>((*it)->getViewModelItem()); + selected_uuids.push_back(conversationItem->getUUID()); + } +} +void LLIMFloaterContainer::doToSelected(const LLSD& userdata) +{ + std::string command = userdata.asString(); + uuid_vec_t selected_uuids; + LLUUID currentSelectedUUID; + LLIMFloater * conversation; + + getSelectedUUIDs(selected_uuids); + conversation = LLIMFloater::findInstance(selected_uuids.front()); + + if(conversation && + static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem())->getType() == LLConversationItem::CONV_SESSION_1_ON_1) + { + currentSelectedUUID = conversation->getOtherParticipantUUID(); + } + else + { + currentSelectedUUID = selected_uuids.front(); + } + + //Close the selected conversation + if(conversation && "close_conversation" == command) + { + LLFloater::onClickClose(conversation); + } + else if ("view_profile" == command) + { + LLAvatarActions::showProfile(currentSelectedUUID); + } + else if("im" == command) + { + LLAvatarActions::startIM(currentSelectedUUID); + } + else if("offer_teleport" == command) + { + LLAvatarActions::offerTeleport(selected_uuids); + } + else if("voice_call" == command) + { + LLAvatarActions::startCall(currentSelectedUUID); + } + else if("add_friend" == command) + { + LLAvatarActions::requestFriendshipDialog(currentSelectedUUID); + } + else if("remove_friend" == command) + { + LLAvatarActions::removeFriendDialog(currentSelectedUUID); + } + else if("invite_to_group" == command) + { + LLAvatarActions::inviteToGroup(currentSelectedUUID); + } + else if("map" == command) + { + LLAvatarActions::showOnMap(currentSelectedUUID); + } + else if("share" == command) + { + LLAvatarActions::share(currentSelectedUUID); + } + else if("pay" == command) + { + LLAvatarActions::pay(currentSelectedUUID); + } + else if("block_unblock" == command) + { + LLAvatarActions::toggleBlock(currentSelectedUUID); + } +} + +bool LLIMFloaterContainer::enableContextMenuItem(const LLSD& userdata) +{ + std::string item = userdata.asString(); + uuid_vec_t mUUIDs; + getSelectedUUIDs(mUUIDs); + + // Note: can_block and can_delete is used only for one person selected menu + // so we don't need to go over all uuids. + + if (item == std::string("can_block")) + { + const LLUUID& id = mUUIDs.front(); + return LLAvatarActions::canBlock(id); + } + else if (item == std::string("can_add")) + { + // We can add friends if: + // - there are selected people + // - and there are no friends among selection yet. + + //EXT-7389 - disable for more than 1 + if(mUUIDs.size() > 1) + { + return false; + } + + bool result = (mUUIDs.size() > 0); + + uuid_vec_t::const_iterator + id = mUUIDs.begin(), + uuids_end = mUUIDs.end(); + + for (;id != uuids_end; ++id) + { + if ( LLAvatarActions::isFriend(*id) ) + { + result = false; + break; + } + } + + return result; + } + else if (item == std::string("can_delete")) + { + // We can remove friends if: + // - there are selected people + // - and there are only friends among selection. + + bool result = (mUUIDs.size() > 0); + + uuid_vec_t::const_iterator + id = mUUIDs.begin(), + uuids_end = mUUIDs.end(); + + for (;id != uuids_end; ++id) + { + if ( !LLAvatarActions::isFriend(*id) ) + { + result = false; + break; + } + } + + return result; + } + else if (item == std::string("can_call")) + { + return LLAvatarActions::canCall(); + } + else if (item == std::string("can_show_on_map")) + { + const LLUUID& id = mUUIDs.front(); + + return (LLAvatarTracker::instance().isBuddyOnline(id) && is_agent_mappable(id)) + || gAgent.isGodlike(); + } + else if(item == std::string("can_offer_teleport")) + { + return LLAvatarActions::canOfferTeleport(mUUIDs); + } + return false; +} + +bool LLIMFloaterContainer::checkContextMenuItem(const LLSD& userdata) +{ + std::string item = userdata.asString(); + const LLUUID& id = static_cast<LLConversationItem *>(mConversationsRoot->getCurSelectedItem()->getViewModelItem())->getUUID(); + + if (item == std::string("is_blocked")) + { + return LLAvatarActions::isBlocked(id); + } + + return false; +} + void LLIMFloaterContainer::repositioningWidgets() { if (!mInitialized) diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h index e8d185297c..cc2d0ce6ab 100644 --- a/indra/newview/llimfloatercontainer.h +++ b/indra/newview/llimfloatercontainer.h @@ -111,6 +111,11 @@ private: void setSortOrderParticipants(const LLConversationFilter::ESortOrderType order); void setSortOrder(const LLConversationSort& order); + void getSelectedUUIDs(uuid_vec_t& selected_uuids); + void doToSelected(const LLSD& userdata); + bool checkContextMenuItem(const LLSD& userdata); + bool enableContextMenuItem(const LLSD& userdata); + LLButton* mExpandCollapseBtn; LLLayoutPanel* mMessagesPane; LLLayoutPanel* mConversationsPane; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 2a84616ddf..6e692adf2a 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -172,6 +172,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id ) p.show_empty_message = mShowEmptyMessage; p.show_item_link_overlays = mShowItemLinkOverlays; p.root = NULL; + p.options_menu = "menu_inventory.xml"; return LLUICtrlFactory::create<LLFolderView>(p); } diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml new file mode 100644 index 0000000000..94399be61c --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + bottom="806" + layout="topleft" + left="0" + mouse_opaque="false" + name="menu_conversation_participant" + visible="false"> + <menu_item_call + label="Close conversation" + layout="topleft" + name="close_conversation"> + <on_click function="Avatar.DoToSelected" parameter="close_conversation"/> + </menu_item_call> + <menu_item_call + label="Open voice conversation" + layout="topleft" + name="open_voice_conversation"> + <on_click function="Avatar.DoToSelected" parameter="open_voice_conversation"/> + </menu_item_call> + <menu_item_call + label="Disconnect from voice" + layout="topleft" + name="disconnect_from_voice"> + <on_click function="Avatar.DoToSelected" parameter="disconnect_from_voice"/> + </menu_item_call> + <menu_item_separator layout="topleft" name="separator_disconnect_from_voice"/> + <menu_item_call + label="View Profile" + layout="topleft" + name="view_profile"> + <on_click function="Avatar.DoToSelected" parameter="view_profile"/> + </menu_item_call> + <menu_item_call + label="IM" + layout="topleft" + name="im"> + <on_click function="Avatar.DoToSelected" parameter="im"/> + </menu_item_call> + <menu_item_call + label="Offer teleport" + layout="topleft" + name="offer_teleport"> + <on_click function="Avatar.DoToSelected" parameter="offer_teleport"/> + <on_enable function="Avatar.EnableItem" parameter="can_offer_teleport"/> + </menu_item_call> + <menu_item_call + label="Voice call" + layout="topleft" + name="voice_call"> + <on_click function="Avatar.DoToSelected" parameter="voice_call"/> + <on_enable function="Avatar.EnableItem" parameter="can_call" /> + </menu_item_call> + <menu_item_call + label="Chat history..." + layout="topleft" + name="chat_history"> + <on_click function="Avatar.DoToSelected" parameter="chat_history"/> + </menu_item_call> + <menu_item_separator layout="topleft" name="separator_chat_history"/> + <menu_item_call + label="Add friend" + layout="topleft" + name="add_friend"> + <on_click function="Avatar.DoToSelected" parameter="add_friend"/> + <on_enable function="Avatar.EnableItem" parameter="can_add" /> + </menu_item_call> + <menu_item_call + label="Remove friend" + layout="topleft" + name="remove_friend"> + <on_click function="Avatar.DoToSelected" parameter="remove_friend" /> + <on_enable function="Avatar.EnableItem" parameter="can_delete" /> + </menu_item_call> + <menu_item_call + label="Invite to group..." + layout="topleft" + name="invite_to_group"> + <on_click function="Avatar.DoToSelected" parameter="invite_to_group" /> + </menu_item_call> + <menu_item_separator layout="topleft" name="separator_invite_to_group"/> + <menu_item_call + label="Map" + layout="topleft" + name="map"> + <on_click function="Avatar.DoToSelected" parameter="map" /> + <on_enable function="Avatar.EnableItem" parameter="can_show_on_map" /> + </menu_item_call> + <menu_item_call + label="Share" + layout="topleft" + name="share"> + <on_click function="Avatar.DoToSelected" parameter="share" /> + </menu_item_call> + <menu_item_call + label="Pay" + layout="topleft" + name="pay"> + <on_click function="Avatar.DoToSelected" parameter="pay" /> + </menu_item_call> + <menu_item_check + label="Block / unblock" + layout="topleft" + name="block_unblock"> + <on_click function="Avatar.DoToSelected" parameter="block_unblock" /> + <on_check function="Avatar.CheckItem" parameter="is_blocked" /> + <on_enable function="Avatar.EnableItem" parameter="can_block" /> + </menu_item_check> +</toggleable_menu> |