diff options
| -rw-r--r-- | indra/llui/llnotificationslistener.cpp | 269 | ||||
| -rw-r--r-- | indra/llui/llnotificationslistener.h | 20 | ||||
| -rw-r--r-- | indra/llui/llurlentry.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llavatarlist.cpp | 6 | ||||
| -rw-r--r-- | indra/newview/llcallfloater.cpp | 7 | ||||
| -rw-r--r-- | indra/newview/llcallfloater.h | 2 | ||||
| -rw-r--r-- | indra/newview/llchiclet.cpp | 61 | ||||
| -rw-r--r-- | indra/newview/llchiclet.h | 5 | ||||
| -rw-r--r-- | indra/newview/llmoveview.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/llpanelclassified.cpp | 39 | ||||
| -rw-r--r-- | indra/newview/llpanelclassified.h | 6 | ||||
| -rw-r--r-- | indra/newview/llpanelimcontrolpanel.cpp | 3 | ||||
| -rw-r--r-- | indra/newview/llpanelpicks.cpp | 5 | ||||
| -rw-r--r-- | indra/newview/llparticipantlist.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/llparticipantlist.h | 2 | ||||
| -rw-r--r-- | indra/newview/llspeakers.cpp | 2 | ||||
| -rw-r--r-- | indra/newview/lltoastalertpanel.h | 2 | ||||
| -rw-r--r-- | indra/newview/lltransientfloatermgr.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/floater_customize.xml | 15 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/strings.xml | 2 | 
20 files changed, 432 insertions, 34 deletions
diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp index fe4fbe7510..629964c322 100644 --- a/indra/llui/llnotificationslistener.cpp +++ b/indra/llui/llnotificationslistener.cpp @@ -10,10 +10,10 @@   */  #include "linden_common.h" -  #include "llnotificationslistener.h" -  #include "llnotifications.h" +#include "llsd.h" +#include "llui.h"  LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) :      LLEventAPI("LLNotifications", @@ -24,6 +24,47 @@ LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications          "Add a notification with specified [\"name\"], [\"substitutions\"] and [\"payload\"].\n"          "If optional [\"reply\"] specified, arrange to send user response on that LLEventPump.",          &LLNotificationsListener::requestAdd); +    add("listChannels", +        "Post to [\"reply\"] a map of info on existing channels", +        &LLNotificationsListener::listChannels, +        LLSD().with("reply", LLSD())); +    add("listChannelNotifications", +        "Post to [\"reply\"] an array of info on notifications in channel [\"channel\"]", +        &LLNotificationsListener::listChannelNotifications, +        LLSD().with("reply", LLSD()).with("channel", LLSD())); +    add("respond", +        "Respond to notification [\"uuid\"] with data in [\"response\"]", +        &LLNotificationsListener::respond, +        LLSD().with("uuid", LLSD())); +    add("cancel", +        "Cancel notification [\"uuid\"]", +        &LLNotificationsListener::cancel, +        LLSD().with("uuid", LLSD())); +    add("ignore", +        "Ignore future notification [\"name\"]\n" +        "(from <notification name= > in notifications.xml)\n" +        "according to boolean [\"ignore\"].\n" +        "If [\"name\"] is omitted or undefined, [un]ignore all future notifications.\n" +        "Note that ignored notifications are not forwarded unless intercepted before\n" +        "the \"Ignore\" channel.", +        &LLNotificationsListener::ignore); +    add("forward", +        "Forward to [\"pump\"] future notifications on channel [\"channel\"]\n" +        "according to boolean [\"forward\"]. When enabled, only types matching\n" +        "[\"types\"] are forwarded, as follows:\n" +        "omitted or undefined: forward all notifications\n" +        "string: forward only the specific named [sig]type\n" +        "array of string: forward any notification matching any named [sig]type.\n" +        "When boolean [\"respond\"] is true, we auto-respond to each forwarded\n" +        "notification.", +        &LLNotificationsListener::forward, +        LLSD().with("channel", LLSD())); +} + +// This is here in the .cpp file so we don't need the definition of class +// Forwarder in the header file. +LLNotificationsListener::~LLNotificationsListener() +{  }  void LLNotificationsListener::requestAdd(const LLSD& event_data) const @@ -57,3 +98,227 @@ void LLNotificationsListener::NotificationResponder(const std::string& reply_pum  	reponse_event["response"] = response;  	LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event);  } + +void LLNotificationsListener::listChannels(const LLSD& params) const +{ +    LLReqID reqID(params); +    LLSD response(reqID.makeResponse()); +    for (LLNotifications::ChannelMap::const_iterator cmi(mNotifications.mChannels.begin()), +                                                     cmend(mNotifications.mChannels.end()); +         cmi != cmend; ++cmi) +    { +        LLSD channelInfo; +        channelInfo["parent"] = cmi->second->getParentChannelName(); +        response[cmi->first] = channelInfo; +    } +    LLEventPumps::instance().obtain(params["reply"]).post(response); +} + +void LLNotificationsListener::listChannelNotifications(const LLSD& params) const +{ +    LLReqID reqID(params); +    LLSD response(reqID.makeResponse()); +    LLNotificationChannelPtr channel(mNotifications.getChannel(params["channel"])); +    if (channel) +    { +        LLSD notifications(LLSD::emptyArray()); +        for (LLNotificationChannel::Iterator ni(channel->begin()), nend(channel->end()); +             ni != nend; ++ni) +        { +            notifications.append(asLLSD(*ni)); +        } +        response["notifications"] = notifications; +    } +    LLEventPumps::instance().obtain(params["reply"]).post(response); +} + +void LLNotificationsListener::respond(const LLSD& params) const +{ +    LLNotificationPtr notification(mNotifications.find(params["uuid"])); +    if (notification) +    { +        notification->respond(params["response"]); +    } +} + +void LLNotificationsListener::cancel(const LLSD& params) const +{ +    LLNotificationPtr notification(mNotifications.find(params["uuid"])); +    if (notification) +    { +        mNotifications.cancel(notification); +    } +} + +void LLNotificationsListener::ignore(const LLSD& params) const +{ +    // Calling a method named "ignore", but omitting its "ignore" Boolean +    // argument, should by default cause something to be ignored. Explicitly +    // pass ["ignore"] = false to cancel ignore. +    bool ignore = true; +    if (params.has("ignore")) +    { +        ignore = params["ignore"].asBoolean(); +    } +    // This method can be used to affect either a single notification name or +    // all future notifications. The two use substantially different mechanisms. +    if (params["name"].isDefined()) +    { +        // ["name"] was passed: ignore just that notification +        LLUI::sSettingGroups["ignores"]->setBOOL(params["name"], ignore); +    } +    else +    { +        // no ["name"]: ignore all future notifications +        mNotifications.setIgnoreAllNotifications(ignore); +    } +} + +class LLNotificationsListener::Forwarder: public LLEventTrackable +{ +    LOG_CLASS(LLNotificationsListener::Forwarder); +public: +    Forwarder(LLNotifications& llnotifications, const std::string& channel): +        mNotifications(llnotifications), +        mRespond(false) +    { +        // Connect to the specified channel on construction. Because +        // LLEventTrackable is a base, we should automatically disconnect when +        // destroyed. +        LLNotificationChannelPtr channelptr(llnotifications.getChannel(channel)); +        if (channelptr) +        { +            // Try connecting at the front of the 'changed' signal. That way +            // we shouldn't get starved by preceding listeners. +            channelptr->connectAtFrontChanged(boost::bind(&Forwarder::handle, this, _1)); +        } +    } + +    void setPumpName(const std::string& name) { mPumpName = name; } +    void setTypes(const LLSD& types) { mTypes = types; } +    void setRespond(bool respond) { mRespond = respond; } + +private: +    bool handle(const LLSD& notification) const; +    bool matchType(const LLSD& filter, const std::string& type) const; + +    LLNotifications& mNotifications; +    std::string mPumpName; +    LLSD mTypes; +    bool mRespond; +}; + +void LLNotificationsListener::forward(const LLSD& params) +{ +    std::string channel(params["channel"]); +    // First decide whether we're supposed to start forwarding or stop it. +    // Default to true. +    bool forward = true; +    if (params.has("forward")) +    { +        forward = params["forward"].asBoolean(); +    } +    if (! forward) +    { +        // This is a request to stop forwarding notifications on the specified +        // channel. The rest of the params don't matter. +        // Because mForwarders contains scoped_ptrs, erasing the map entry +        // DOES delete the heap Forwarder object. Because Forwarder derives +        // from LLEventTrackable, destroying it disconnects it from the +        // channel. +        mForwarders.erase(channel); +        return; +    } +    // From here on, we know we're being asked to start (or modify) forwarding +    // on the specified channel. Find or create an appropriate Forwarder. +    ForwarderMap::iterator +        entry(mForwarders.insert(ForwarderMap::value_type(channel, ForwarderMap::mapped_type())).first); +    if (! entry->second) +    { +        entry->second.reset(new Forwarder(mNotifications, channel)); +    } +    // Now, whether this Forwarder is brand-new or not, update it with the new +    // request info. +    Forwarder& fwd(*entry->second); +    fwd.setPumpName(params["pump"]); +    fwd.setTypes(params["types"]); +    fwd.setRespond(params["respond"]); +} + +bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const +{ +    LL_INFOS("LLNotificationsListener") << "handle(" << notification << ")" << LL_ENDL; +    if (notification["sigtype"].asString() == "delete") +    { +        LL_INFOS("LLNotificationsListener") << "ignoring delete" << LL_ENDL; +        return false; +    } +    LLNotificationPtr note(mNotifications.find(notification["id"])); +    if (! note) +    { +        LL_INFOS("LLNotificationsListener") << notification["id"] << " not found" << LL_ENDL; +        return false; +    } +    if (! matchType(mTypes, note->getType())) +    { +        LL_INFOS("LLNotificationsListener") << "didn't match types " << mTypes << LL_ENDL; +        return false; +    } +    LL_INFOS("LLNotificationsListener") << "sending via '" << mPumpName << "'" << LL_ENDL; +    // This is a notification we care about. Forward it through specified +    // LLEventPump. +    LLEventPumps::instance().obtain(mPumpName).post(asLLSD(note)); +    // Are we also being asked to auto-respond? +    if (mRespond) +    { +        LL_INFOS("LLNotificationsListener") << "should respond" << LL_ENDL; +        note->respond(LLSD::emptyMap()); +        // Did that succeed in removing the notification? Only cancel() if +        // it's still around -- otherwise we get an LL_ERRS crash! +        note = mNotifications.find(notification["id"]); +        if (note) +        { +            LL_INFOS("LLNotificationsListener") << "respond() didn't clear, canceling" << LL_ENDL; +            mNotifications.cancel(note); +        } +    } +    return false;                   // let other listeners get same notification +} + +bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std::string& type) const +{ +    // Decide whether this notification matches filter: +    // undefined: forward all notifications +    if (filter.isUndefined()) +    { +        return true; +    } +    // array of string: forward any notification matching any named type +    if (filter.isArray()) +    { +        for (LLSD::array_const_iterator ti(filter.beginArray()), tend(filter.endArray()); +             ti != tend; ++ti) +        { +            if (ti->asString() == type) +            { +                return true; +            } +        } +        // Didn't match any entry in the array +        return false; +    } +    // string: forward only the specific named type +    return (filter.asString() == type); +} + +LLSD LLNotificationsListener::asLLSD(LLNotificationPtr note) +{ +    LLSD notificationInfo(note->asLLSD()); +    // For some reason the following aren't included in asLLSD(). +    notificationInfo["summary"] = note->summarize(); +    notificationInfo["id"]      = note->id(); +    notificationInfo["type"]    = note->getType(); +    notificationInfo["message"] = note->getMessage(); +    notificationInfo["label"]   = note->getLabel(); +    return notificationInfo; +} diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h index 9b405d7b4b..de208b57f0 100644 --- a/indra/llui/llnotificationslistener.h +++ b/indra/llui/llnotificationslistener.h @@ -13,6 +13,10 @@  #define LL_LLNOTIFICATIONSLISTENER_H  #include "lleventapi.h" +#include "llnotificationptr.h" +#include <boost/shared_ptr.hpp> +#include <map> +#include <string>  class LLNotifications;  class LLSD; @@ -21,13 +25,27 @@ class LLNotificationsListener : public LLEventAPI  {  public:      LLNotificationsListener(LLNotifications & notifications); +    ~LLNotificationsListener(); +private:      void requestAdd(LLSD const & event_data) const; -private:  	void NotificationResponder(const std::string& replypump,   							   const LLSD& notification,   							   const LLSD& response) const; + +    void listChannels(const LLSD& params) const; +    void listChannelNotifications(const LLSD& params) const; +    void respond(const LLSD& params) const; +    void cancel(const LLSD& params) const; +    void ignore(const LLSD& params) const; +    void forward(const LLSD& params); + +    static LLSD asLLSD(LLNotificationPtr); + +    class Forwarder; +    typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap; +    ForwarderMap mForwarders;  	LLNotifications & mNotifications;  }; diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 7350457274..95dc2ce027 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -201,7 +201,7 @@ std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string)  //  LLUrlEntryHTTPNoProtocol::LLUrlEntryHTTPNoProtocol()  { -	mPattern = boost::regex("(\\bwww\\.\\S+\\.\\S+|\\S+.com\\S*|\\S+.net\\S*|\\S+.edu\\S*|\\S+.org\\S*)", +	mPattern = boost::regex("(\\bwww\\.\\S+\\.\\S+|\\b[^ \t\n\r\f\v:/]+.com\\S*|\\b[^ \t\n\r\f\v:/]+.net\\S*|\\b[^ \t\n\r\f\v:/]+.edu\\S*|\\b[^ \t\n\r\f\v:/]+.org\\S*)",  							boost::regex::perl|boost::regex::icase);  	mMenuName = "menu_url_http.xml";  	mTooltip = LLTrans::getString("TooltipHttpUrl"); diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 71b23e1383..5865df3e26 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -33,7 +33,7 @@  #include "llviewerprecompiledheaders.h"  #include "llavatarlist.h" -#include "llagent.h" // for comparator +#include "llagentdata.h" // for comparator  // newview  #include "llcallingcard.h" // for LLAvatarTracker @@ -425,11 +425,11 @@ bool LLAvatarItemAgentOnTopComparator::doCompare(const LLAvatarListItem* avatar_  {  	//keep agent on top, if first is agent,   	//then we need to return true to elevate this id, otherwise false. -	if(avatar_item1->getAvatarId() == gAgent.getID()) +	if(avatar_item1->getAvatarId() == gAgentID)  	{  		return true;  	} -	else if (avatar_item2->getAvatarId() == gAgent.getID()) +	else if (avatar_item2->getAvatarId() == gAgentID)  	{  		return false;  	} diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index 20739d2401..1acdb96da6 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -162,6 +162,7 @@ void LLCallFloater::onChange()  	if (NULL == mPaticipants) return;  	mPaticipants->refreshVoiceState(); +  } @@ -243,7 +244,7 @@ void LLCallFloater::updateSession()  	childSetVisible("leave_call_btn", !is_local_chat);  	refreshPartisipantList(); -	updateModeratorState(); +	updateAgentModeratorState();  	//show floater for voice calls  	if (!is_local_chat) @@ -280,7 +281,7 @@ void LLCallFloater::refreshPartisipantList()  	if (!non_avatar_caller)  	{ -		mPaticipants = new LLParticipantList(mSpeakerManager, mAvatarList); +		mPaticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT);  		if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager)  		{ @@ -366,7 +367,7 @@ void LLCallFloater::setModeratorMutedVoice(bool moderator_muted)  	mSpeakingIndicator->setIsMuted(moderator_muted);  } -void LLCallFloater::updateModeratorState() +void LLCallFloater::updateAgentModeratorState()  {  	std::string name;  	gCacheName->getFullName(gAgentID, name); diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index f9c9149085..ac45e283eb 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -101,7 +101,7 @@ private:  	void updateTitle();  	void initAgentData();  	void setModeratorMutedVoice(bool moderator_muted); -	void updateModeratorState(); +	void updateAgentModeratorState();  private:  	LLSpeakerMgr* mSpeakerManager; diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index bb09f34362..17ef1f41a4 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -68,7 +68,8 @@ static const LLRect CHICLET_RECT(0, 25, 25, 0);  static const LLRect CHICLET_ICON_RECT(0, 22, 22, 0);  static const LLRect VOICE_INDICATOR_RECT(50, 25, 70, 0);  static const LLRect COUNTER_RECT(25, 25, 50, 0); -static const S32	OVERLAY_ICON_SHIFT = 2;	// used for shifting of an overlay icon for new massages in a chiclet +static const S32 OVERLAY_ICON_SHIFT = 2;	// used for shifting of an overlay icon for new massages in a chiclet +static const S32 SCROLL_BUTTON_PAD = 5;  // static  const S32 LLChicletPanel::s_scroll_ratio = 10; @@ -186,9 +187,9 @@ void LLSysWellChiclet::setCounter(S32 counter)  	mButton->setLabel(s_count); -	setNewMessagesState(counter > 0); +	setNewMessagesState(counter > mCounter); -	// we have to flash to 'Lit' state each time new unread message is comming. +	// we have to flash to 'Lit' state each time new unread message is coming.  	if (counter > mCounter)  	{  		mFlashToLitTimer->flash(); @@ -1311,7 +1312,6 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)  		chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index));  		arrange(); -		showScrollButtonsIfNeeded();  		return true;  	} @@ -1322,8 +1322,6 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)  void LLChicletPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param)  {  	arrange(); -	trimChiclets(); -	showScrollButtonsIfNeeded();  }  void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD¶m) @@ -1340,8 +1338,6 @@ void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it)  	mChicletList.erase(it);  	arrange(); -	trimChiclets(); -	showScrollButtonsIfNeeded();  }  void LLChicletPanel::removeChiclet(S32 index) @@ -1434,8 +1430,6 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )  {  	LLPanel::reshape(width,height,called_from_parent); -	static const S32 SCROLL_BUTTON_PAD = 5; -  	//Needed once- to avoid error at first call of reshape() before postBuild()  	if(!mLeftScrollButton||!mRightScrollButton)  		return; @@ -1446,9 +1440,21 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )  	scroll_button_rect = mRightScrollButton->getRect();  	mRightScrollButton->setRect(LLRect(width - scroll_button_rect.getWidth(),scroll_button_rect.mTop,  		width, scroll_button_rect.mBottom)); -	mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD, -		height, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); +	 + +	bool need_show_scroll = needShowScroll(); +	if(need_show_scroll) +	{ +		mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD, +			height, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); +	} +	else +	{ +		mScrollArea->setRect(LLRect(0,height, width, 0)); +	} +	  	mShowControls = width >= mMinWidth; +	  	mScrollArea->setVisible(mShowControls);  	trimChiclets(); @@ -1461,8 +1467,8 @@ void LLChicletPanel::arrange()  	if(mChicletList.empty())  		return; +	//initial arrange of chicklets positions  	S32 chiclet_left = getChiclet(0)->getRect().mLeft; -  	S32 size = getChicletCount();  	for( int n = 0; n < size; ++n)  	{ @@ -1476,6 +1482,24 @@ void LLChicletPanel::arrange()  		chiclet_left += chiclet_width + getChicletPadding();  	} + +	//reset size and pos on mScrollArea +	LLRect rect = getRect(); +	LLRect scroll_button_rect = mLeftScrollButton->getRect(); +	 +	bool need_show_scroll = needShowScroll(); +	if(need_show_scroll) +	{ +		mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD, +			rect.getHeight(), rect.getWidth() - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0)); +	} +	else +	{ +		mScrollArea->setRect(LLRect(0,rect.getHeight(), rect.getWidth(), 0)); +	} +	 +	trimChiclets(); +	showScrollButtonsIfNeeded();  }  void LLChicletPanel::trimChiclets() @@ -1493,6 +1517,17 @@ void LLChicletPanel::trimChiclets()  	}  } +bool LLChicletPanel::needShowScroll() +{ +	if(mChicletList.empty()) +		return false; +	 +	S32 chicklet_width  = (*mChicletList.rbegin())->getRect().mRight - (*mChicletList.begin())->getRect().mLeft; + +	return chicklet_width>getRect().getWidth(); +} + +  void LLChicletPanel::showScrollButtonsIfNeeded()  {  	bool can_scroll_left = canScrollLeft(); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 259476c2ad..2ab6abfb5b 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -1050,6 +1050,11 @@ protected:  	bool canScrollRight();  	/** +	 * Returns true if we need to show scroll buttons +	 */ +	bool needShowScroll(); + +	/**  	 * Returns true if chiclets can be scrolled left.  	 */  	bool canScrollLeft(); diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp index 22201aecb2..818e7e0db1 100644 --- a/indra/newview/llmoveview.cpp +++ b/indra/newview/llmoveview.cpp @@ -571,7 +571,7 @@ BOOL LLPanelStandStopFlying::postBuild()  	mStandButton->setVisible(FALSE);  	mStopFlyingButton = getChild<LLButton>("stop_fly_btn"); -	mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE)); +	//mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE));  	mStopFlyingButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStopFlyingButtonClick, this));  	mStopFlyingButton->setVisible(FALSE); diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 0dae667e7f..e29320ffc2 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -1557,6 +1557,11 @@ void LLPanelClassifiedEdit::resetControls()  	childSetValue("price_for_listing", MINIMUM_PRICE_FOR_LISTING);  } +bool LLPanelClassifiedEdit::canClose() +{ +	return isValidName(); +} +  void LLPanelClassifiedEdit::sendUpdate()  {  	LLAvatarClassifiedInfo c_data; @@ -1671,6 +1676,12 @@ void LLPanelClassifiedEdit::onChange()  void LLPanelClassifiedEdit::onSaveClick()  { +	if(!isValidName()) +	{ +		notifyInvalidName(); +		return; +	} +  	sendUpdate();  	resetDirty();  } @@ -1681,6 +1692,34 @@ std::string LLPanelClassifiedEdit::getLocationNotice()  	return location_notice;  } +bool LLPanelClassifiedEdit::isValidName() +{ +	std::string name = getClassifiedName(); +	if (name.empty()) +	{ +		return false; +	} +	if (!isalnum(name[0])) +	{ +		return false; +	} + +	return true; +} + +void LLPanelClassifiedEdit::notifyInvalidName() +{ +	std::string name = getClassifiedName(); +	if (name.empty()) +	{ +		LLNotificationsUtil::add("BlankClassifiedName"); +	} +	else if (!isalnum(name[0])) +	{ +		LLNotificationsUtil::add("ClassifiedMustBeAlphanumeric"); +	} +} +  void LLPanelClassifiedEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl)  {  	ctrl->setVisible(TRUE); diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h index 8b32495854..10fdf60bbe 100644 --- a/indra/newview/llpanelclassified.h +++ b/indra/newview/llpanelclassified.h @@ -305,6 +305,8 @@ public:  	bool isNew() { return mIsNew; } +	bool canClose(); +  protected:  	LLPanelClassifiedEdit(); @@ -325,6 +327,10 @@ protected:  	std::string getLocationNotice(); +	bool isValidName(); + +	void notifyInvalidName(); +  	void onSetLocationClick();  	void onChange();  	void onSaveClick(); diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index 70e4798079..ae1c28c7ab 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -282,8 +282,9 @@ void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id)  	mGroupID = LLIMModel::getInstance()->getOtherParticipantID(session_id); +	// for group and Ad-hoc chat we need to include agent into list   	if(!mParticipantList) -		mParticipantList = new LLParticipantList(mSpeakerManager, getChild<LLAvatarList>("speakers_list")); +		mParticipantList = new LLParticipantList(mSpeakerManager, getChild<LLAvatarList>("speakers_list"), true,false);  } diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 4d22d96072..a52aa6d30f 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -769,6 +769,11 @@ void LLPanelPicks::onPanelPickSave(LLPanel* panel)  void LLPanelPicks::onPanelClassifiedSave(LLPanelClassifiedEdit* panel)  { +	if(!panel->canClose()) +	{ +		return; +	} +  	if(panel->isNew())  	{  		LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), panel->getClassifiedId()); diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index afb9892d12..e8aa1e9831 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -51,12 +51,13 @@  static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR; -LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list,  bool use_context_menu/* = true*/): +LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list,  bool use_context_menu/* = true*/, +		bool exclude_agent /*= true*/):  	mSpeakerMgr(data_source),  	mAvatarList(avatar_list),  	mSortOrder(E_SORT_BY_NAME)  ,	mParticipantListMenu(NULL) -,	mExcludeAgent(true) +,	mExcludeAgent(exclude_agent)  {  	mSpeakerAddListener = new SpeakerAddListener(*this);  	mSpeakerRemoveListener = new SpeakerRemoveListener(*this); @@ -101,7 +102,6 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av  		}  	}  	// we need to exclude agent id for non group chat -	mExcludeAgent = !gAgent.isInGroup(mSpeakerMgr->getSessionID());  	mAvatarList->setDirty(true);  	sort();  } @@ -555,7 +555,7 @@ void LLParticipantList::LLParticipantListMenu::moderateVoiceOtherParticipants(co  bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& userdata)  {  	std::string item = userdata.asString(); -	if (item == "can_mute_text") +	if (item == "can_mute_text" || "can_block" == item)  	{  		return mUUIDs.front() != gAgentID;  	} diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 72c413d188..b85d4c9bc4 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -43,7 +43,7 @@ class LLParticipantList  {  	LOG_CLASS(LLParticipantList);  	public: -		LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu = true); +		LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu = true, bool exclude_agent = true);  		~LLParticipantList();  		void setSpeakingIndicatorsVisible(BOOL visible); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 3861a96355..91b417c61f 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -630,8 +630,6 @@ void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)  void LLIMSpeakerMgr::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute)  { -	if (gAgentID == avatar_id) return; // do not process myself -  	LLPointer<LLSpeaker> speakerp = findSpeaker(avatar_id);  	if (!speakerp) return; diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h index 875ab82c54..43e105a4f1 100644 --- a/indra/newview/lltoastalertpanel.h +++ b/indra/newview/lltoastalertpanel.h @@ -37,6 +37,7 @@  #include "llfloater.h"  #include "llui.h"  #include "llnotificationptr.h" +#include "llerror.h"  class LLButton;  class LLCheckBoxCtrl; @@ -53,6 +54,7 @@ class LLLineEditor;  class LLToastAlertPanel  	: public LLToastPanel  { +	LOG_CLASS(LLToastAlertPanel);  public:  	typedef bool (*display_callback_t)(S32 modal); diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp index 7befb87248..347399f239 100644 --- a/indra/newview/lltransientfloatermgr.cpp +++ b/indra/newview/lltransientfloatermgr.cpp @@ -37,6 +37,7 @@  #include "llrootview.h"  #include "llviewerwindow.h"  #include "lldockablefloater.h" +#include "llmenugl.h"  LLTransientFloaterMgr::LLTransientFloaterMgr() @@ -87,6 +88,13 @@ void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,  	for (controls_set_t::iterator it = mControlsSet.begin(); it  			!= mControlsSet.end(); it++)  	{ +		// don't hide transient floater if any context menu opened +		if (LLMenuGL::sMenuContainer->getVisibleMenu() != NULL) +		{ +			hide = false; +			break; +		} +  		LLView* control_view = *it;  		if (!control_view->getVisible())  		{ diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml index ffdb59d44c..94686f0bb0 100644 --- a/indra/newview/skins/default/xui/en/floater_customize.xml +++ b/indra/newview/skins/default/xui/en/floater_customize.xml @@ -55,6 +55,7 @@           label="Shape"           layout="topleft"           name="Shape" +         help_topic="customize_shape_tab"           width="400">              <icon               follows="top|right" @@ -340,6 +341,7 @@ scratch and wear it.           label="Skin"           layout="topleft"           name="Skin" +         help_topic="customize_skin_tab"           width="400">              <icon               follows="top|right" @@ -591,6 +593,7 @@ scratch and wear it.           label="Hair"           layout="topleft"           name="Hair" +         help_topic="customize_hair_tab"           width="400">              <icon               follows="top|right" @@ -812,6 +815,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Eyes" +         help_topic="customize_eyes_tab"           top_delta="0"           width="389">              <icon @@ -1010,6 +1014,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Shirt" +         help_topic="customize_shirt_tab"           top_delta="0"           width="389">              <icon @@ -1215,6 +1220,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Pants" +         help_topic="customize_pants_tab"           top_delta="0"           width="389">              <icon @@ -1420,6 +1426,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Shoes" +         help_topic="customize_shoes_tab"           top_delta="0"           width="389">              <icon @@ -1625,6 +1632,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Socks" +         help_topic="customize_socks_tab"           top_delta="0"           width="389">              <icon @@ -1830,6 +1838,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Jacket" +         help_topic="customize_jacket_tab"           top_delta="0"           width="389">              <icon @@ -2047,6 +2056,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Gloves" +         help_topic="customize_gloves_tab"           top_delta="0"           width="389">              <icon @@ -2252,6 +2262,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Undershirt" +         help_topic="customize_undershirt_tab"           top_delta="0"           width="389">              <icon @@ -2457,6 +2468,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Underpants" +         help_topic="customize_underpants_tab"           top_delta="0"           width="389">              <icon @@ -2662,6 +2674,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Skirt" +         help_topic="customize_skirt_tab"           top_delta="0"           width="389">              <icon @@ -2867,6 +2880,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Alpha" +         help_topic="customize_alpha_tab"           top_delta="0"           width="389">              <icon @@ -3154,6 +3168,7 @@ scratch and wear it.           layout="topleft"           left_delta="0"           name="Tattoo" +         help_topic="customize_tattoo_tab"           top_delta="0"           width="389">              <icon diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 7438a36ed0..a1f2548f81 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2085,7 +2085,7 @@ this texture in your inventory  	<string name="ATTACH_BELLY">Belly</string>  	<string name="ATTACH_RPEC">Right Pec</string>  	<string name="ATTACH_LPEC">Left Pec</string> -	<string name="ATTACH_HUD_CENTER_2"><HUD Center 2/string> +	<string name="ATTACH_HUD_CENTER_2">HUD Center 2</string>  	<string name="ATTACH_HUD_TOP_RIGHT">HUD Top Right</string>  	<string name="ATTACH_HUD_TOP_CENTER">HUD Top Center</string>  	<string name="ATTACH_HUD_TOP_LEFT">HUD Top Left</string>  | 
