summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/llnotificationslistener.cpp269
-rw-r--r--indra/llui/llnotificationslistener.h20
-rw-r--r--indra/llui/llurlentry.cpp2
-rw-r--r--indra/newview/llavatarlist.cpp6
-rw-r--r--indra/newview/llcallfloater.cpp7
-rw-r--r--indra/newview/llcallfloater.h2
-rw-r--r--indra/newview/llchiclet.cpp61
-rw-r--r--indra/newview/llchiclet.h5
-rw-r--r--indra/newview/llmoveview.cpp2
-rw-r--r--indra/newview/llpanelclassified.cpp39
-rw-r--r--indra/newview/llpanelclassified.h6
-rw-r--r--indra/newview/llpanelimcontrolpanel.cpp3
-rw-r--r--indra/newview/llpanelpicks.cpp5
-rw-r--r--indra/newview/llparticipantlist.cpp8
-rw-r--r--indra/newview/llparticipantlist.h2
-rw-r--r--indra/newview/llspeakers.cpp2
-rw-r--r--indra/newview/lltoastalertpanel.h2
-rw-r--r--indra/newview/lltransientfloatermgr.cpp8
-rw-r--r--indra/newview/skins/default/xui/en/floater_customize.xml15
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml2
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&param)
@@ -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>