diff options
Diffstat (limited to 'indra/newview/llinspectgroup.cpp')
-rw-r--r-- | indra/newview/llinspectgroup.cpp | 331 |
1 files changed, 331 insertions, 0 deletions
diff --git a/indra/newview/llinspectgroup.cpp b/indra/newview/llinspectgroup.cpp new file mode 100644 index 0000000000..7fd7b69021 --- /dev/null +++ b/indra/newview/llinspectgroup.cpp @@ -0,0 +1,331 @@ +/** + * @file llinspectgroup.cpp + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llinspectgroup.h" + +// viewer files +#include "llgroupactions.h" +#include "llgroupmgr.h" +#include "llinspect.h" +#include "llstartup.h" + +// Linden libraries +#include "llcontrol.h" // LLCachedControl +#include "llfloater.h" +#include "llfloaterreg.h" +#include "llresmgr.h" // getMonetaryString() +#include "lltooltip.h" // positionViewNearMouse() +#include "lltrans.h" +#include "lluictrl.h" + +class LLFetchGroupData; + + +////////////////////////////////////////////////////////////////////////////// +// LLInspectGroup +////////////////////////////////////////////////////////////////////////////// + +/// Group Inspector, a small information window used when clicking +/// on group names in the 2D UI +class LLInspectGroup : public LLInspect +{ + friend class LLFloaterReg; + +public: + // key["group_id"] - Group ID for which to show information + // Inspector will be positioned relative to current mouse position + LLInspectGroup(const LLSD& key); + virtual ~LLInspectGroup(); + + // Because floater is single instance, need to re-parse data on each spawn + // (for example, inspector about same group but in different position) + /*virtual*/ void onOpen(const LLSD& group_id); + + // When closing they should close their gear menu + /*virtual*/ void onClose(bool app_quitting); + + // Update view based on information from group manager + void processGroupData(); + + // Make network requests for all the data to display in this view. + // Used on construction and if avatar id changes. + void requestUpdate(); + + // Callback for gCacheName to look up group name + // Faster than waiting for group properties to return + void nameUpdatedCallback(const LLUUID& id, + const std::string& first, + const std::string& last, + BOOL is_group); + + // Button/menu callbacks + void onClickViewProfile(); + void onClickJoin(); + void onClickLeave(); + +private: + LLUUID mGroupID; + // an in-flight network request for group properties + // is represented by this object + LLFetchGroupData* mPropertiesRequest; +}; + +////////////////////////////////////////////////////////////////////////////// +// LLFetchGroupData +////////////////////////////////////////////////////////////////////////////// + +// This object represents a pending request for avatar properties information +class LLFetchGroupData : public LLGroupMgrObserver +{ +public: + // If the inspector closes it will delete the pending request object, so the + // inspector pointer will be valid for the lifetime of this object + LLFetchGroupData(const LLUUID& group_id, LLInspectGroup* inspector) + : LLGroupMgrObserver(group_id), + mInspector(inspector) + { + LLGroupMgr* mgr = LLGroupMgr::getInstance(); + // register ourselves as an observer + mgr->addObserver(this); + // send a request + mgr->sendGroupPropertiesRequest(group_id); + } + + ~LLFetchGroupData() + { + // remove ourselves as an observer + LLGroupMgr::getInstance()->removeObserver(this); + } + + void changed(LLGroupChange gc) + { + if (gc == GC_PROPERTIES) + { + mInspector->processGroupData(); + } + } + + LLInspectGroup* mInspector; +}; + +LLInspectGroup::LLInspectGroup(const LLSD& sd) +: LLInspect( LLSD() ), // single_instance, doesn't really need key + mGroupID(), // set in onOpen() + mPropertiesRequest(NULL) +{ + mCommitCallbackRegistrar.add("InspectGroup.ViewProfile", + boost::bind(&LLInspectGroup::onClickViewProfile, this)); + mCommitCallbackRegistrar.add("InspectGroup.Join", + boost::bind(&LLInspectGroup::onClickJoin, this)); + mCommitCallbackRegistrar.add("InspectGroup.Leave", + boost::bind(&LLInspectGroup::onClickLeave, this)); + + // can't make the properties request until the widgets are constructed + // as it might return immediately, so do it in postBuild. +} + +LLInspectGroup::~LLInspectGroup() +{ + // clean up any pending requests so they don't call back into a deleted + // view + delete mPropertiesRequest; + mPropertiesRequest = NULL; +} + + +// Multiple calls to showInstance("inspect_avatar", foo) will provide different +// LLSD for foo, which we will catch here. +//virtual +void LLInspectGroup::onOpen(const LLSD& data) +{ + // start fade animation + LLInspect::onOpen(data); + + mGroupID = data["group_id"]; + + // Position the inspector relative to the mouse cursor + // Similar to how tooltips are positioned + // See LLToolTipMgr::createToolTip + if (data.has("pos")) + { + LLUI::positionViewNearMouse(this, data["pos"]["x"].asInteger(), data["pos"]["y"].asInteger()); + } + else + { + LLUI::positionViewNearMouse(this); + } + + // can't call from constructor as widgets are not built yet + requestUpdate(); +} + +// virtual +void LLInspectGroup::onClose(bool app_quitting) +{ + // *TODO: If we add a gear menu, close it here +} + +void LLInspectGroup::requestUpdate() +{ + // Don't make network requests when spawning from the debug menu at the + // login screen (which is useful to work on the layout). + if (mGroupID.isNull()) + { + if (LLStartUp::getStartupState() >= STATE_STARTED) + { + // once we're running we don't want to show the test floater + // for bogus LLUUID::null links + closeFloater(); + } + return; + } + + // Clear out old data so it doesn't flash between old and new + getChild<LLUICtrl>("group_name")->setValue(""); + getChild<LLUICtrl>("group_subtitle")->setValue(""); + getChild<LLUICtrl>("group_details")->setValue(""); + getChild<LLUICtrl>("group_cost")->setValue(""); + // Must have a visible button so the inspector can take focus + getChild<LLUICtrl>("view_profile_btn")->setVisible(true); + getChild<LLUICtrl>("leave_btn")->setVisible(false); + getChild<LLUICtrl>("join_btn")->setVisible(false); + + // Make a new request for properties + delete mPropertiesRequest; + mPropertiesRequest = new LLFetchGroupData(mGroupID, this); + + // Name lookup will be faster out of cache, use that + gCacheName->get(mGroupID, TRUE, + boost::bind(&LLInspectGroup::nameUpdatedCallback, + this, _1, _2, _3, _4)); +} + +void LLInspectGroup::nameUpdatedCallback( + const LLUUID& id, + const std::string& first, + const std::string& last, + BOOL is_group) +{ + if (id == mGroupID) + { + // group names are returned as a first name + childSetValue("group_name", LLSD(first) ); + } + + // Otherwise possibly a request for an older inspector, ignore it +} + +void LLInspectGroup::processGroupData() +{ + LLGroupMgrGroupData* data = + LLGroupMgr::getInstance()->getGroupData(mGroupID); + + if (data) + { + // Noun pluralization depends on language + std::string lang = LLUI::getLanguage(); + std::string members = + LLTrans::getCountString(lang, "GroupMembers", data->mMemberCount); + getChild<LLUICtrl>("group_subtitle")->setValue( LLSD(members) ); + + getChild<LLUICtrl>("group_details")->setValue( LLSD(data->mCharter) ); + + getChild<LLUICtrl>("group_icon")->setValue( LLSD(data->mInsigniaID) ); + + std::string cost; + bool is_member = LLGroupActions::isInGroup(mGroupID); + if (is_member) + { + cost = getString("YouAreMember"); + } + else if (data->mOpenEnrollment) + { + if (data->mMembershipFee == 0) + { + cost = getString("FreeToJoin"); + } + else + { + std::string amount = + LLResMgr::getInstance()->getMonetaryString( + data->mMembershipFee); + LLStringUtil::format_map_t args; + args["[AMOUNT]"] = amount; + cost = getString("CostToJoin", args); + } + } + else + { + cost = getString("PrivateGroup"); + } + getChild<LLUICtrl>("group_cost")->setValue(cost); + + getChild<LLUICtrl>("join_btn")->setVisible(!is_member); + getChild<LLUICtrl>("leave_btn")->setVisible(is_member); + + // Only enable join button if you are allowed to join + bool can_join = !is_member && data->mOpenEnrollment; + getChild<LLUICtrl>("join_btn")->setEnabled(can_join); + } + + // Delete the request object as it has been satisfied + delete mPropertiesRequest; + mPropertiesRequest = NULL; +} + +void LLInspectGroup::onClickViewProfile() +{ + closeFloater(); + LLGroupActions::show(mGroupID); +} + +void LLInspectGroup::onClickJoin() +{ + closeFloater(); + LLGroupActions::join(mGroupID); +} + +void LLInspectGroup::onClickLeave() +{ + closeFloater(); + LLGroupActions::leave(mGroupID); +} + +////////////////////////////////////////////////////////////////////////////// +// LLInspectGroupUtil +////////////////////////////////////////////////////////////////////////////// +void LLInspectGroupUtil::registerFloater() +{ + LLFloaterReg::add("inspect_group", "inspect_group.xml", + &LLFloaterReg::build<LLInspectGroup>); +} |