summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/lldockablefloater.h3
-rw-r--r--indra/llui/lldockcontrol.h3
-rw-r--r--indra/llui/lltexteditor.cpp3
-rw-r--r--indra/newview/app_settings/settings.xml13
-rw-r--r--indra/newview/llappviewer.cpp11
-rw-r--r--indra/newview/llchiclet.cpp77
-rw-r--r--indra/newview/llchiclet.h37
-rw-r--r--indra/newview/llimfloater.cpp2
-rw-r--r--indra/newview/llimview.cpp58
-rw-r--r--indra/newview/llimview.h10
-rw-r--r--indra/newview/llpanelgroup.cpp67
-rw-r--r--indra/newview/llpanelgroup.h8
-rw-r--r--indra/newview/llpanellandmarks.cpp48
-rw-r--r--indra/newview/llpanellandmarks.h6
-rw-r--r--indra/newview/llparticipantlist.cpp10
-rw-r--r--indra/newview/llscreenchannel.cpp123
-rw-r--r--indra/newview/llscreenchannel.h6
-rw-r--r--indra/newview/llsyswellwindow.cpp2
-rw-r--r--indra/newview/lltoast.cpp23
-rw-r--r--indra/newview/lltoast.h9
-rw-r--r--indra/newview/lltooldraganddrop.cpp3
-rw-r--r--indra/newview/llvoiceclient.cpp15
-rw-r--r--indra/newview/llvoiceclient.h2
-rw-r--r--indra/newview/skins/default/xui/en/floater_incoming_call.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_bottomtray.xml12
-rw-r--r--indra/newview/skins/default/xui/en/panel_notes.xml5
-rw-r--r--indra/newview/skins/default/xui/en/panel_profile.xml6
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml4
28 files changed, 500 insertions, 78 deletions
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h
index 46491d8a29..2c339f4a3f 100644
--- a/indra/llui/lldockablefloater.h
+++ b/indra/llui/lldockablefloater.h
@@ -83,6 +83,8 @@ public:
virtual void onDockHidden();
virtual void onDockShown();
+ LLDockControl* getDockControl();
+
private:
/**
* Provides unique of dockable floater.
@@ -92,7 +94,6 @@ private:
protected:
void setDockControl(LLDockControl* dockControl);
- LLDockControl* getDockControl();
const LLUIImagePtr& getDockTongue();
private:
diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h
index 30a45bedc7..550955c4c5 100644
--- a/indra/llui/lldockcontrol.h
+++ b/indra/llui/lldockcontrol.h
@@ -76,6 +76,9 @@ public:
// gets a rect that bounds possible positions for a dockable control (EXT-1111)
void getAllowedRect(LLRect& rect);
+ S32 getTongueWidth() { return mDockTongue->getWidth(); }
+ S32 getTongueHeight() { return mDockTongue->getHeight(); }
+
private:
virtual void moveDockable();
private:
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index e68affc36c..faf9ccbeb8 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -1887,9 +1887,10 @@ void LLTextEditor::doDelete()
removeChar();
}
- onKeyStroke();
}
+ onKeyStroke();
+
needsReflow();
}
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index c43032a3cf..5e2c6554d2 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -5039,7 +5039,18 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <integer>35</integer>
+ <integer>5</integer>
+ </map>
+ <key>NotificationChannelHeightRatio</key>
+ <map>
+ <key>Comment</key>
+ <string>Notification channel and World View ratio(0.0 - always show 1 notification, 1.0 - max ratio).</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.5</real>
</map>
<key>OverflowToastHeight</key>
<map>
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 508badcc6f..9a1b749ba7 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -78,6 +78,8 @@
#include "lllocationhistory.h"
#include "llfasttimerview.h"
#include "llvoicechannel.h"
+#include "llsidetray.h"
+
#include "llweb.h"
#include "llsecondlifeurls.h"
@@ -2854,6 +2856,8 @@ void LLAppViewer::requestQuit()
gFloaterView->closeAllChildren(true);
}
+ LLSideTray::getInstance()->notifyChildren(LLSD().with("request","quit"));
+
send_stats();
gLogoutTimer.reset();
@@ -3758,6 +3762,13 @@ void LLAppViewer::idleShutdown()
{
return;
}
+
+ if (LLSideTray::getInstance()->notifyChildren(LLSD().with("request","wait_quit")))
+ {
+ return;
+ }
+
+
// ProductEngine: Try moving this code to where we shut down sTextureCache in cleanup()
// *TODO: ugly
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 4b3b7a99d8..d90901612a 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -78,29 +78,73 @@ boost::signals2::signal<LLChiclet* (const LLUUID&),
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
+/**
+ * Updates the Well's 'Lit' state to flash it when "new messages" are come.
+ *
+ * It gets callback which will be called 2*N times with passed period. See EXT-3147
+ */
+class LLSysWellChiclet::FlashToLitTimer : public LLEventTimer
+{
+public:
+ typedef boost::function<void()> callback_t;
+ FlashToLitTimer(S32 count, F32 period, callback_t cb)
+ : LLEventTimer(period)
+ , mCallback(cb)
+ , mFlashCount(2 * count)
+ , mCurrentFlashCount(0)
+ {
+ mEventTimer.stop();
+ }
+
+ BOOL tick()
+ {
+ mCallback();
+
+ if (++mCurrentFlashCount == mFlashCount) mEventTimer.stop();
+ return FALSE;
+ }
+
+ void flash()
+ {
+ mCurrentFlashCount = 0;
+ mEventTimer.start();
+ }
+
+private:
+ callback_t mCallback;
+ S32 mFlashCount;
+ S32 mCurrentFlashCount;
+};
+
LLSysWellChiclet::Params::Params()
: button("button")
, unread_notifications("unread_notifications")
+, max_displayed_count("max_displayed_count", 9)
+, flash_to_lit_count("flash_to_lit_count", 3)
+, flash_period("flash_period", 0.5F)
{
button.name("button");
button.tab_stop(FALSE);
button.label(LLStringUtil::null);
-
}
LLSysWellChiclet::LLSysWellChiclet(const Params& p)
: LLChiclet(p)
, mButton(NULL)
, mCounter(0)
+, mMaxDisplayedCount(p.max_displayed_count)
+, mFlashToLitTimer(NULL)
{
LLButton::Params button_params = p.button;
mButton = LLUICtrlFactory::create<LLButton>(button_params);
addChild(mButton);
+
+ mFlashToLitTimer = new FlashToLitTimer(p.flash_to_lit_count, p.flash_period, boost::bind(&LLSysWellChiclet::changeLitState, this));
}
LLSysWellChiclet::~LLSysWellChiclet()
{
-
+ delete mFlashToLitTimer;
}
void LLSysWellChiclet::setCounter(S32 counter)
@@ -108,11 +152,30 @@ void LLSysWellChiclet::setCounter(S32 counter)
std::string s_count;
if(counter != 0)
{
- s_count = llformat("%d", counter);
+ static std::string more_messages_exist("+");
+ std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : "");
+ s_count = llformat("%d%s"
+ , llmin(counter, mMaxDisplayedCount)
+ , more_messages.c_str()
+ );
}
mButton->setLabel(s_count);
+ /*
+ Emulate 4 states of button by background images, see detains in EXT-3147
+ xml attribute Description
+ image_unselected "Unlit" - there are no new messages
+ image_selected "Unlit" + "Selected" - there are no new messages and the Well is open
+ image_pressed "Lit" - there are new messages
+ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open
+ */
+ mButton->setForcePressedState(counter > 0);
+
+ if (mCounter == 0 && counter > 0)
+ {
+ mFlashToLitTimer->flash();
+ }
mCounter = counter;
}
@@ -126,6 +189,14 @@ void LLSysWellChiclet::setToggleState(BOOL toggled) {
mButton->setToggleState(toggled);
}
+void LLSysWellChiclet::changeLitState()
+{
+ static bool set_lit = false;
+
+ mButton->setForcePressedState(set_lit);
+
+ set_lit ^= true;
+}
/************************************************************************/
/* LLIMWellChiclet implementation */
diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h
index 609ce16713..06d25f081a 100644
--- a/indra/newview/llchiclet.h
+++ b/indra/newview/llchiclet.h
@@ -745,7 +745,7 @@ private:
/**
* Implements notification chiclet. Used to display total amount of unread messages
- * across all IM sessions, total amount of system notifications.
+ * across all IM sessions, total amount of system notifications. See EXT-3147 for details
*/
class LLSysWellChiclet : public LLChiclet
{
@@ -757,6 +757,24 @@ public:
Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications;
+ /**
+ * Contains maximum displayed count of unread messages. Default value is 9.
+ *
+ * If count is less than "max_unread_count" will be displayed as is.
+ * Otherwise 9+ will be shown (for default value).
+ */
+ Optional<S32> max_displayed_count;
+
+ /**
+ * How many time chiclet should flash before set "Lit" state. Default value is 3.
+ */
+ Optional<S32> flash_to_lit_count;
+
+ /**
+ * Period of flashing while setting "Lit" state, in seconds. Default value is 0.5.
+ */
+ Optional<F32> flash_period;
+
Params();
};
@@ -778,9 +796,26 @@ protected:
LLSysWellChiclet(const Params& p);
friend class LLUICtrlFactory;
+ /**
+ * Change Well 'Lit' state from 'Lit' to 'Unlit' and vice-versa.
+ *
+ * There is an assumption that it will be called 2*N times to do not change its start state.
+ * @see FlashToLitTimer
+ */
+ void changeLitState();
+
protected:
+ class FlashToLitTimer;
LLButton* mButton;
S32 mCounter;
+ S32 mMaxDisplayedCount;
+
+ /**
+ * How many times Well will blink.
+ */
+ S32 mFlashToLitCount;
+ FlashToLitTimer* mFlashToLitTimer;
+
};
/**
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 2bc07d0c27..40ae112e4b 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -415,6 +415,7 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock)
if(channel)
{
channel->updateShowToastsState();
+ channel->redrawToasts();
}
}
@@ -439,6 +440,7 @@ void LLIMFloater::setVisible(BOOL visible)
if(channel)
{
channel->updateShowToastsState();
+ channel->redrawToasts();
}
if (visible && mChatHistory && mInputEditor)
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 6c4af0522f..6a9853913a 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -116,6 +116,13 @@ void toast_callback(const LLSD& msg){
return;
}
+ // Skip toasting if we have open window of IM with this session id
+ LLIMFloater* open_im_floater = LLIMFloater::findInstance(msg["session_id"]);
+ if (open_im_floater && open_im_floater->getVisible())
+ {
+ return;
+ }
+
LLSD args;
args["MESSAGE"] = msg["message"];
args["TIME"] = msg["time"];
@@ -154,7 +161,6 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
mInitialTargetIDs(ids),
mVoiceChannel(NULL),
mSpeakers(NULL),
- mCallDialogManager(NULL),
mSessionInitialized(false),
mCallBackEnabled(true),
mTextIMPossible(true),
@@ -287,9 +293,6 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES
LLIMModel::LLIMSession::~LLIMSession()
{
- delete mCallDialogManager;
- mCallDialogManager = NULL;
-
delete mSpeakers;
mSpeakers = NULL;
@@ -1079,7 +1082,7 @@ public:
if ( 404 == statusNum )
{
std::string error_string;
- error_string = "does not exist";
+ error_string = "session_does_not_exist_error";
gIMMgr->showSessionStartError(error_string, mSessionID);
}
}
@@ -1268,6 +1271,7 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat
{
LLSD mCallDialogPayload;
LLOutgoingCallDialog* ocd;
+ bool is_incoming;
mCallDialogPayload["session_id"] = sSession->mSessionID;
mCallDialogPayload["session_name"] = sSession->mName;
@@ -1277,8 +1281,10 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat
switch(new_state)
{
case LLVoiceChannel::STATE_CALL_STARTED :
- // do not show "Calling to..." if it is incoming P2P call
- if(sSession->mSessionType == LLIMModel::LLIMSession::P2P_SESSION && static_cast<LLVoiceChannelP2P*>(sSession->mVoiceChannel)->isIncomingCall())
+ // do not show "Calling to..." if it is incoming call
+ is_incoming = LLVoiceClient::getInstance()->isSessionIncoming(sSession->mSessionID);
+ // *TODO: implement for AdHoc and Group voice chats
+ if(is_incoming)
{
return;
}
@@ -1290,6 +1296,7 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat
ocd->getChild<LLTextBox>("leaving")->setVisible(true);
ocd->getChild<LLTextBox>("connecting")->setVisible(false);
ocd->getChild<LLTextBox>("noanswer")->setVisible(false);
+ ocd->getChild<LLButton>("Cancel")->setVisible(true);
}
return;
@@ -1301,10 +1308,12 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat
ocd->getChild<LLTextBox>("leaving")->setVisible(true);
ocd->getChild<LLTextBox>("connecting")->setVisible(true);
ocd->getChild<LLTextBox>("noanswer")->setVisible(false);
+ ocd->getChild<LLButton>("Cancel")->setVisible(true);
}
return;
case LLVoiceChannel::STATE_ERROR :
+ mCallDialogPayload["start_timer"] = true;
ocd = dynamic_cast<LLOutgoingCallDialog*>(LLFloaterReg::showInstance("outgoing_call", mCallDialogPayload, TRUE));
if (ocd)
{
@@ -1312,6 +1321,7 @@ void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EStat
ocd->getChild<LLTextBox>("leaving")->setVisible(false);
ocd->getChild<LLTextBox>("connecting")->setVisible(false);
ocd->getChild<LLTextBox>("noanswer")->setVisible(true);
+ ocd->getChild<LLButton>("Cancel")->setVisible(false);
}
return;
@@ -1363,6 +1373,33 @@ LLCallDialog(payload)
instance->onCancel(instance);
}
}
+void LLOutgoingCallDialog::draw()
+{
+ if (lifetimeHasExpired())
+ {
+ onLifetimeExpired();
+ }
+ LLDockableFloater::draw();
+}
+
+bool LLOutgoingCallDialog::lifetimeHasExpired()
+{
+ if (mLifetimeTimer.getStarted())
+ {
+ F32 elapsed_time = mLifetimeTimer.getElapsedTimeF32();
+ if (elapsed_time > LIFETIME)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void LLOutgoingCallDialog::onLifetimeExpired()
+{
+ mLifetimeTimer.stop();
+ closeFloater();
+}
void LLOutgoingCallDialog::onOpen(const LLSD& key)
{
@@ -1391,6 +1428,13 @@ void LLOutgoingCallDialog::onOpen(const LLSD& key)
childSetTextArg("connecting", "[CALLEE_NAME]", callee_name);
LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
icon->setValue(callee_id);
+
+ // stop timer by default
+ mLifetimeTimer.stop();
+ if(mPayload.has("start_timer"))
+ {
+ mLifetimeTimer.reset();
+ }
}
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index c002434a18..d85a4cda82 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -81,7 +81,6 @@ public:
SType mSessionType;
LLUUID mOtherParticipantID;
std::vector<LLUUID> mInitialTargetIDs;
- LLCallDialogManager* mCallDialogManager;
// connection to voice channel state change signal
boost::signals2::connection mVoiceChannelStateChangeConnection;
@@ -493,7 +492,16 @@ public:
static void onCancel(void* user_data);
+ // check timer state
+ /*virtual*/ void draw();
+
private:
+ // lifetime timer for NO_ANSWER notification
+ LLTimer mLifetimeTimer;
+ // lifetime duration for NO_ANSWER notification
+ static const S32 LIFETIME = 5;
+ bool lifetimeHasExpired();
+ void onLifetimeExpired();
};
// Globals
diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp
index 2cb3967685..e0f159cfeb 100644
--- a/indra/newview/llpanelgroup.cpp
+++ b/indra/newview/llpanelgroup.cpp
@@ -90,6 +90,7 @@ LLPanelGroup::LLPanelGroup()
: LLPanel(),
LLGroupMgrObserver( LLUUID() ),
mAllowEdit( TRUE )
+ ,mShowingNotifyDialog(false)
{
// Set up the factory callbacks.
// Roles sub tabs
@@ -538,3 +539,69 @@ void LLPanelGroup::showNotice(const std::string& subject,
}
+bool LLPanelGroup::canClose()
+{
+ if(getVisible() == false)
+ return true;
+
+ bool need_save = false;
+ std::string mesg;
+ for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it)
+ if(need_save|=(*it)->needsApply(mesg))
+ break;
+ if(!need_save)
+ return false;
+ // If no message was provided, give a generic one.
+ if (mesg.empty())
+ {
+ mesg = mDefaultNeedsApplyMesg;
+ }
+ // Create a notify box, telling the user about the unapplied tab.
+ LLSD args;
+ args["NEEDS_APPLY_MESSAGE"] = mesg;
+ args["WANT_APPLY_MESSAGE"] = mWantApplyMesg;
+
+ LLNotificationsUtil::add("SaveChanges", args, LLSD(), boost::bind(&LLPanelGroup::handleNotifyCallback,this, _1, _2));
+
+ mShowingNotifyDialog = true;
+
+ return false;
+}
+
+bool LLPanelGroup::notifyChildren(const LLSD& info)
+{
+ if(info.has("request") && mID.isNull() )
+ {
+ std::string str_action = info["request"];
+
+ if (str_action == "quit" )
+ {
+ canClose();
+ return true;
+ }
+ if(str_action == "wait_quit")
+ return mShowingNotifyDialog;
+ }
+ return false;
+}
+bool LLPanelGroup::handleNotifyCallback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ mShowingNotifyDialog = false;
+ switch (option)
+ {
+ case 0: // "Apply Changes"
+ apply();
+ break;
+ case 1: // "Ignore Changes"
+ break;
+ case 2: // "Cancel"
+ default:
+ // Do nothing. The user is canceling the action.
+ // If we were quitting, we didn't really mean it.
+ LLAppViewer::instance()->abortQuit();
+ break;
+ }
+ return false;
+}
+
diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h
index 306e6575fc..f6aefdb676 100644
--- a/indra/newview/llpanelgroup.h
+++ b/indra/newview/llpanelgroup.h
@@ -89,7 +89,10 @@ public:
const std::string& inventory_name,
LLOfferInfo* inventory_offer);
-
+
+ bool notifyChildren (const LLSD& info);
+ bool handleNotifyCallback(const LLSD&, const LLSD&);
+
protected:
virtual void update(LLGroupChange gc);
@@ -107,6 +110,9 @@ protected:
protected:
bool apply(LLPanelGroupTab* tab);
+ bool canClose();
+
+ bool mShowingNotifyDialog;
LLTimer mRefreshTimer;
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index e87b70f6a5..faa0aa95b9 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -66,6 +66,30 @@ static const std::string TRASH_BUTTON_NAME = "trash_btn";
// helper functions
static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string);
+static void save_folder_state_if_no_filter(LLInventorySubTreePanel* inventory_list);
+
+/**
+ * Bridge to support knowing when the inventory has changed to update folder (open/close) state
+ * for landmarks panels.
+ *
+ * Due to Inventory data are loaded in background we need to save folder state each time
+ * next level is loaded. See EXT-3094.
+ */
+class LLLandmarksPanelObserver : public LLInventoryObserver
+{
+public:
+ LLLandmarksPanelObserver(LLLandmarksPanel* lp) : mLP(lp) {}
+ virtual ~LLLandmarksPanelObserver() {}
+ /*virtual*/ void changed(U32 mask);
+
+private:
+ LLLandmarksPanel* mLP;
+};
+
+void LLLandmarksPanelObserver::changed(U32 mask)
+{
+ mLP->saveFolderStateIfNoFilter();
+}
LLLandmarksPanel::LLLandmarksPanel()
: LLPanelPlacesTab()
@@ -78,11 +102,18 @@ LLLandmarksPanel::LLLandmarksPanel()
, mGearFolderMenu(NULL)
, mGearLandmarkMenu(NULL)
{
+ mInventoryObserver = new LLLandmarksPanelObserver(this);
+ gInventory.addObserver(mInventoryObserver);
+
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_landmarks.xml");
}
LLLandmarksPanel::~LLLandmarksPanel()
{
+ if (gInventory.containsObserver(mInventoryObserver))
+ {
+ gInventory.removeObserver(mInventoryObserver);
+ }
}
BOOL LLLandmarksPanel::postBuild()
@@ -226,6 +257,14 @@ void LLLandmarksPanel::onSelectorButtonClicked()
}
}
+void LLLandmarksPanel::saveFolderStateIfNoFilter()
+{
+ save_folder_state_if_no_filter(mFavoritesInventoryPanel);
+ save_folder_state_if_no_filter(mLandmarksInventoryPanel);
+ save_folder_state_if_no_filter(mMyInventoryPanel);
+ save_folder_state_if_no_filter(mLibraryInventoryPanel);
+}
+
//////////////////////////////////////////////////////////////////////////
// PROTECTED METHODS
//////////////////////////////////////////////////////////////////////////
@@ -1020,4 +1059,13 @@ static void filter_list(LLInventorySubTreePanel* inventory_list, const std::stri
// set new filter string
inventory_list->setFilterSubString(string);
}
+
+static void save_folder_state_if_no_filter(LLInventorySubTreePanel* inventory_list)
+{
+ // save current folder open state if no filter currently applied
+ if (inventory_list->getRootFolder() && inventory_list->getRootFolder()->getFilterSubString().empty())
+ {
+ inventory_list->saveFolderState();
+ }
+}
// EOF
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index bee141d051..b0e537f647 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -67,6 +67,11 @@ public:
mCurrentSelectedList = inventory_list;
}
+ /**
+ * Saves folder state for all Inventory Panels if there are no applied filter.
+ */
+ void saveFolderStateIfNoFilter();
+
protected:
/**
* @return true - if current selected panel is not null and selected item is a landmark
@@ -151,6 +156,7 @@ private:
LLMenuGL* mGearFolderMenu;
LLMenuGL* mMenuAdd;
LLInventorySubTreePanel* mCurrentSelectedList;
+ LLInventoryObserver* mInventoryObserver;
LLPanel* mListCommands;
bool mSortByDate;
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 13f195a1be..0aed123191 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -278,6 +278,16 @@ void LLParticipantList::addAvatarIDExceptAgent(std::vector<LLUUID>& existing_lis
//
bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
{
+ /**
+ * We need to filter speaking objects. These objects shouldn't appear in the list
+ * @c LLFloaterChat::addChat() in llviewermessage.cpp to get detailed call hierarchy
+ */
+ const LLUUID& speaker_id = event->getValue().asUUID();
+ LLPointer<LLSpeaker> speaker = mParent.mSpeakerMgr->findSpeaker(speaker_id);
+ if(speaker.isNull() || speaker->mType == LLSpeaker::SPEAKER_OBJECT)
+ {
+ return false;
+ }
return mParent.onAddItemEvent(event, userdata);
}
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index 4f0c873c61..222b462d1a 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -125,6 +125,8 @@ LLScreenChannelBase(id)
void LLScreenChannel::init(S32 channel_left, S32 channel_right)
{
LLScreenChannelBase::init(channel_left, channel_right);
+ LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
+ updatePositionAndSize(world_rect, world_rect);
}
//--------------------------------------------------------------------------
@@ -136,7 +138,23 @@ LLScreenChannel::~LLScreenChannel()
//--------------------------------------------------------------------------
void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_world_rect)
{
- LLScreenChannelBase::updatePositionAndSize(old_world_rect, new_world_rect);
+ S32 right_delta = old_world_rect.mRight - new_world_rect.mRight;
+ LLRect this_rect = getRect();
+
+ this_rect.mTop = (S32) (new_world_rect.getHeight() * getHeightRatio());
+ switch(mChannelAlignment)
+ {
+ case CA_LEFT :
+ break;
+ case CA_CENTRE :
+ this_rect.setCenterAndSize(new_world_rect.getWidth() / 2, new_world_rect.getHeight() / 2, this_rect.getWidth(), this_rect.getHeight());
+ break;
+ case CA_RIGHT :
+ this_rect.mLeft -= right_delta;
+ this_rect.mRight -= right_delta;
+ }
+ setRect(this_rect);
+ redrawToasts();
}
//--------------------------------------------------------------------------
@@ -169,6 +187,7 @@ void LLScreenChannel::addToast(const LLToast::Params& p)
if(show_toast)
{
mToastList.push_back(new_toast_elem);
+ updateShowToastsState();
redrawToasts();
}
else // store_toast
@@ -224,6 +243,7 @@ void LLScreenChannel::deleteToast(LLToast* toast)
if(mHoveredToast == toast)
{
mHoveredToast = NULL;
+ startFadingToasts();
}
// close the toast
@@ -405,26 +425,27 @@ void LLScreenChannel::showToastsBottom()
{
if( it != mToastList.rend()-1)
{
- stop_showing_toasts = ((*it).toast->getRect().mTop + gSavedSettings.getS32("OverflowToastHeight") + gSavedSettings.getS32("ToastGap")) > getRect().mTop;
+ S32 toast_top = (*it).toast->getRect().mTop + gSavedSettings.getS32("ToastGap");
+ stop_showing_toasts = toast_top > getRect().mTop;
}
}
+ // at least one toast should be visible
+ if(it == mToastList.rbegin())
+ {
+ stop_showing_toasts = false;
+ }
+
if(stop_showing_toasts)
break;
if( !(*it).toast->getVisible() )
{
- if((*it).toast->isFirstLook())
- {
- (*it).toast->setVisible(TRUE);
- }
- else
- {
- // HACK
- // EXT-2653: it is necessary to prevent overlapping for secondary showed toasts
- (*it).toast->setVisible(TRUE);
- gFloaterView->sendChildToBack((*it).toast);
- }
+ // HACK
+ // EXT-2653: it is necessary to prevent overlapping for secondary showed toasts
+ (*it).toast->setVisible(TRUE);
+ // Show toast behind floaters. (EXT-3089)
+ gFloaterView->sendChildToBack((*it).toast);
}
}
@@ -566,6 +587,21 @@ void LLScreenChannel::createStartUpToast(S32 notif_num, F32 timer)
mStartUpToastPanel->setVisible(TRUE);
}
+// static --------------------------------------------------------------------------
+F32 LLScreenChannel::getHeightRatio()
+{
+ F32 ratio = gSavedSettings.getF32("NotificationChannelHeightRatio");
+ if(0.0f > ratio)
+ {
+ ratio = 0.0f;
+ }
+ else if(1.0f < ratio)
+ {
+ ratio = 1.0f;
+ }
+ return ratio;
+}
+
//--------------------------------------------------------------------------
void LLScreenChannel::updateStartUpString(S32 num)
{
@@ -685,39 +721,28 @@ void LLScreenChannel::removeToastsBySessionID(LLUUID id)
//--------------------------------------------------------------------------
void LLScreenChannel::onToastHover(LLToast* toast, bool mouse_enter)
{
- // because of LLViewerWindow::updateUI() that ALWAYS calls onMouseEnter BEFORE onMouseLeave
- // we must check this to prevent incorrect setting for hovering in a channel
- std::map<LLToast*, bool>::iterator it_first, it_second;
- S32 stack_size = mToastEventStack.size();
- if(mouse_enter)
- {
- mHoveredToast = toast;
- }
- else
+ // because of LLViewerWindow::updateUI() that NOT ALWAYS calls onMouseEnter BEFORE onMouseLeave
+ // we must check hovering directly to prevent incorrect setting for hovering in a channel
+ S32 x,y;
+ if (mouse_enter)
{
- mHoveredToast = NULL;
- }
-
- switch(stack_size)
- {
- case 0:
- mToastEventStack.insert(std::pair<LLToast*, bool>(toast, mouse_enter));
- break;
- case 1:
- it_first = mToastEventStack.begin();
- if((*it_first).second && !mouse_enter && ((*it_first).first != toast) )
+ toast->screenPointToLocal(gViewerWindow->getCurrentMouseX(),
+ gViewerWindow->getCurrentMouseY(), &x, &y);
+ bool hover = toast->pointInView(x, y) == TRUE;
+ if (hover)
{
- mToastEventStack.clear();
mHoveredToast = toast;
}
- else
+ }
+ else if (mHoveredToast != NULL)
+ {
+ mHoveredToast->screenPointToLocal(gViewerWindow->getCurrentMouseX(),
+ gViewerWindow->getCurrentMouseY(), &x, &y);
+ bool hover = mHoveredToast->pointInView(x, y) == TRUE;
+ if (!hover)
{
- mToastEventStack.clear();
- mToastEventStack.insert(std::pair<LLToast*, bool>(toast, mouse_enter));
+ mHoveredToast = NULL;
}
- break;
- default:
- LL_ERRS ("LLScreenChannel::onToastHover: stack size error " ) << stack_size << llendl;
}
if(!isHovering())
@@ -727,7 +752,7 @@ void LLScreenChannel::onToastHover(LLToast* toast, bool mouse_enter)
//--------------------------------------------------------------------------
void LLScreenChannel::updateShowToastsState()
{
- LLFloater* floater = LLDockableFloater::getInstanceHandle().get();
+ LLDockableFloater* floater = dynamic_cast<LLDockableFloater*>(LLDockableFloater::getInstanceHandle().get());
if(!floater)
{
@@ -735,27 +760,17 @@ void LLScreenChannel::updateShowToastsState()
return;
}
- // for IM floaters showed in a docked state - prohibit showing of ani toast
- if(dynamic_cast<LLIMFloater*>(floater)
- || dynamic_cast<LLScriptFloater*>(floater) )
- {
- setShowToasts(!(floater->getVisible() && floater->isDocked()));
- if (!getShowToasts())
- {
- removeAndStoreAllStorableToasts();
- }
- }
-
// *TODO: mantipov: what we have to do with derived classes: LLNotificationWellWindow & LLIMWelWindow?
// See EXT-3081 for details
// for Message Well floater showed in a docked state - adjust channel's height
- if(dynamic_cast<LLSysWellWindow*>(floater))
+ if(dynamic_cast<LLSysWellWindow*>(floater) || dynamic_cast<LLIMFloater*>(floater))
{
S32 channel_bottom = gViewerWindow->getWorldViewRectScaled().mBottom + gSavedSettings.getS32("ChannelBottomPanelMargin");;
LLRect this_rect = getRect();
if(floater->getVisible() && floater->isDocked())
{
- channel_bottom += (floater->getRect().getHeight() + gSavedSettings.getS32("ToastGap"));
+ channel_bottom += floater->getRect().getHeight();
+ channel_bottom += floater->getDockControl()->getTongueHeight();
}
if(channel_bottom != this_rect.mBottom)
diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h
index 67f1c9bdc6..b551732133 100644
--- a/indra/newview/llscreenchannel.h
+++ b/indra/newview/llscreenchannel.h
@@ -265,6 +265,11 @@ private:
// create the StartUp Toast
void createStartUpToast(S32 notif_num, F32 timer);
+ /**
+ * Notification channel and World View ratio(0.0 - always show 1 notification, 1.0 - max ratio).
+ */
+ static F32 getHeightRatio();
+
// Channel's flags
static bool mWasStartUpToastShown;
@@ -274,7 +279,6 @@ private:
std::vector<ToastElem> mToastList;
std::vector<ToastElem> mStoredToastList;
- std::map<LLToast*, bool> mToastEventStack;
};
}
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index bef7f5d6aa..28bdfbf271 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -170,6 +170,7 @@ void LLSysWellWindow::setVisible(BOOL visible)
if(mChannel)
{
mChannel->updateShowToastsState();
+ mChannel->redrawToasts();
}
}
@@ -188,6 +189,7 @@ void LLSysWellWindow::setDocked(bool docked, bool pop_on_undock)
if(mChannel)
{
mChannel->updateShowToastsState();
+ mChannel->redrawToasts();
}
}
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp
index fc7c029a17..4131e2755a 100644
--- a/indra/newview/lltoast.cpp
+++ b/indra/newview/lltoast.cpp
@@ -67,7 +67,8 @@ LLToast::LLToast(const LLToast::Params& p)
mHideBtn(NULL),
mNotification(p.notification),
mIsHidden(false),
- mHideBtnPressed(false)
+ mHideBtnPressed(false),
+ mIsTip(p.is_tip)
{
LLUICtrlFactory::getInstance()->buildFloater(this, "panel_toast.xml", NULL);
@@ -98,10 +99,30 @@ BOOL LLToast::postBuild()
mTimer.stop();
}
+ if (mIsTip)
+ {
+ mTextEditor = mPanel->getChild<LLTextEditor>("text_editor_box");
+
+ if (mTextEditor)
+ {
+ mTextEditor->setMouseUpCallback(boost::bind(&LLToast::hide,this));
+ mPanel->setMouseUpCallback(boost::bind(&LLToast::handleTipToastClick, this, _2, _3, _4));
+ }
+ }
+
return TRUE;
}
//--------------------------------------------------------------------------
+void LLToast::handleTipToastClick(S32 x, S32 y, MASK mask)
+{
+ if (!mTextEditor->getRect().pointInRect(x, y))
+ {
+ hide();
+ }
+}
+
+//--------------------------------------------------------------------------
void LLToast::setHideButtonEnabled(bool enabled)
{
if(mHideBtn)
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
index d08e46e160..0c3c598704 100644
--- a/indra/newview/lltoast.h
+++ b/indra/newview/lltoast.h
@@ -40,6 +40,7 @@
#include "llnotificationptr.h"
#include "llviewercontrol.h"
+#include "lltexteditor.h"
#define MOUSE_LEAVE false
#define MOUSE_ENTER true
@@ -155,6 +156,8 @@ public:
private:
+ void handleTipToastClick(S32 x, S32 y, MASK mask);
+
// check timer
bool lifetimeHasExpired();
// on timer finished function
@@ -169,8 +172,9 @@ private:
F32 mToastLifetime; // in seconds
F32 mToastFadingTime; // in seconds
- LLPanel* mPanel;
- LLButton* mHideBtn;
+ LLPanel* mPanel;
+ LLButton* mHideBtn;
+ LLTextEditor* mTextEditor;
LLColor4 mBgColor;
bool mCanFade;
@@ -178,6 +182,7 @@ private:
bool mHideBtnEnabled;
bool mHideBtnPressed;
bool mIsHidden; // this flag is TRUE when a toast has faded or was hidden with (x) button (EXT-1849)
+ bool mIsTip;
};
}
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 2d0a14dc70..aa35f22930 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -772,6 +772,9 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop,
{
LLInventoryObject* cargo = locateInventory(item, cat);
+ // fix for EXT-3191
+ if (NULL == cargo) return;
+
EAcceptance item_acceptance = ACCEPT_NO;
handled = handled && root_view->handleDragAndDrop(x, y, mask, FALSE,
mCargoTypes[mCurItemIndex],
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 7e1e7c940f..63acba50e7 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -4279,6 +4279,7 @@ void LLVoiceClient::mediaStreamUpdatedEvent(
{
// Send the voice chat invite to the GUI layer
// *TODO: Question: Should we correlate with the mute list here?
+ session->mIncoming = true;
session->mIMSessionID = LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, session->mCallerID);
session->mVoiceInvitePending = true;
if(session->mName.empty())
@@ -6353,6 +6354,20 @@ LLVoiceClient::sessionState *LLVoiceClient::findSession(const LLUUID &participan
return result;
}
+bool LLVoiceClient::isSessionIncoming(const LLUUID &session_id)
+{
+ for(sessionIterator iter = sessionsBegin(); iter != sessionsEnd(); iter++)
+ {
+ sessionState *session = *iter;
+ if(session->mIMSessionID == session_id)
+ {
+ return session->mIncoming;
+ break;
+ }
+ }
+ return false;
+}
+
LLVoiceClient::sessionState *LLVoiceClient::addSession(const std::string &uri, const std::string &handle)
{
sessionState *result = NULL;
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 347fae6156..edfe0173f8 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -527,6 +527,8 @@ static void updatePosition(void);
// Currently this will be false only for PSTN P2P calls.
// NOTE: this will return true if the session can't be found.
bool isSessionTextIMPossible(const LLUUID &session_id);
+
+ bool isSessionIncoming(const LLUUID &session_id);
private:
diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
index 526fda90d1..acd59b6f09 100644
--- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml
+++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
@@ -36,21 +36,25 @@
top="35"
width="36" />
<text
+ clip_partial="true"
font="SansSerifLarge"
- height="20"
+ height="37"
layout="topleft"
left="77"
name="caller name"
- top="27"
+ top="20"
+ use_ellipses="true"
width="315"
word_wrap="true" />
<text
+ clip_partial="true"
font="SansSerif"
- height="50"
+ height="30"
layout="topleft"
left="77"
name="question"
- top="52"
+ top_pad="5"
+ use_ellipses="true"
width="315"
word_wrap="true">
Do you want to leave [CURRENT_CHAT] and join this voice chat?
diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
index 7f847237ce..e77960f200 100644
--- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml
+++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
@@ -324,6 +324,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.
min_width="34"
user_resize="false">
<chiclet_im_well
+ flash_period="0.3"
follows="right"
height="23"
layout="topleft"
@@ -331,6 +332,14 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.
name="im_well"
top="4"
width="34">
+ <!--
+Emulate 4 states of button by background images, see detains in EXT-3147. The same should be for notification_well button
+xml attribute Description
+image_unselected "Unlit" - there are no new messages
+image_selected "Unlit" + "Selected" - there are no new messages and the Well is open
+image_pressed "Lit" - there are new messages
+image_pressed_selected "Lit" + "Selected" - there are new messages and the Well is open
+ -->
<button
auto_resize="true"
flash_color="EmphasisColor"
@@ -343,6 +352,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.
image_pressed_selected="PushButton_Selected_Press"
image_selected="PushButton_Selected_Press"
left="0"
+ max_displayed_count="99"
name="Unread IM messages"
pad_left="0"
pad_right="0"
@@ -365,10 +375,12 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.
min_width="34"
user_resize="false">
<chiclet_notification
+ flash_period="0.25"
follows="right"
height="23"
layout="topleft"
left="0"
+ max_displayed_count="99"
name="notification_well"
top="4"
width="34">
diff --git a/indra/newview/skins/default/xui/en/panel_notes.xml b/indra/newview/skins/default/xui/en/panel_notes.xml
index c02dabed2c..9e7c9477d4 100644
--- a/indra/newview/skins/default/xui/en/panel_notes.xml
+++ b/indra/newview/skins/default/xui/en/panel_notes.xml
@@ -120,6 +120,7 @@
left="0"
mouse_opaque="false"
name="add_friend"
+ tool_tip="Offer friendship to the resident"
top="5"
width="55" />
<button
@@ -128,6 +129,7 @@
label="IM"
layout="topleft"
name="im"
+ tool_tip="Open instant message session"
top="5"
left_pad="5"
width="40" />
@@ -137,6 +139,7 @@
label="Call"
layout="topleft"
name="call"
+ tool_tip="Call this resident"
left_pad="5"
top="5"
width="55" />
@@ -147,6 +150,7 @@
label="Map"
layout="topleft"
name="show_on_map_btn"
+ tool_tip="Show the resident on the map"
top="5"
left_pad="5"
width="50" />
@@ -156,6 +160,7 @@
label="Teleport"
layout="topleft"
name="teleport"
+ tool_tip="Offer teleport"
left_pad="5"
top="5"
width="90" />
diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml
index 6be203ef9c..638bc3cabd 100644
--- a/indra/newview/skins/default/xui/en/panel_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile.xml
@@ -286,6 +286,7 @@
left="0"
mouse_opaque="false"
name="add_friend"
+ tool_tip="Offer friendship to the resident"
top="5"
width="77" />
<button
@@ -294,6 +295,7 @@
label="IM"
layout="topleft"
name="im"
+ tool_tip="Open instant message session"
top="5"
left_pad="5"
width="33" />
@@ -303,6 +305,7 @@
label="Call"
layout="topleft"
name="call"
+ tool_tip="Call this resident"
left_pad="5"
top="5"
width="40" />
@@ -313,6 +316,7 @@
label="Map"
layout="topleft"
name="show_on_map_btn"
+ tool_tip="Show the resident on the map"
top="5"
left_pad="5"
width="44" />
@@ -322,6 +326,7 @@
label="Teleport"
layout="topleft"
name="teleport"
+ tool_tip="Offer teleport"
left_pad="5"
top="5"
width="67" />
@@ -331,6 +336,7 @@
label="▼"
layout="topleft"
name="overflow_btn"
+ tool_tip="Pay money to or share inventory with the resident"
right="-1"
top="5"
width="21" />
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 7fafa63e57..9703373c7f 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2855,6 +2855,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="inventory_item_offered-im">
Inventory item offered
</string>
+ <string name="share_alert">
+ Drag items from inventory here
+ </string>
+
<string name="only_user_message">
You are the only user in this session.