summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/llflatlistview.cpp14
-rw-r--r--indra/llui/llflatlistview.h2
-rw-r--r--indra/llui/llfloater.cpp6
-rw-r--r--indra/llui/llfloater.h3
-rw-r--r--indra/llui/llscrollbar.cpp9
-rw-r--r--indra/llui/llscrollcontainer.cpp6
-rw-r--r--indra/llui/llview.cpp26
-rw-r--r--indra/llui/llview.h2
-rw-r--r--indra/newview/CMakeLists.txt6
-rw-r--r--indra/newview/llavatariconctrl.cpp56
-rw-r--r--indra/newview/llavatariconctrl.h1
-rw-r--r--indra/newview/llavatarlist.cpp1
-rw-r--r--indra/newview/llavatarlistitem.cpp45
-rw-r--r--indra/newview/llavatarlistitem.h16
-rw-r--r--indra/newview/llbottomtray.cpp12
-rw-r--r--indra/newview/llbottomtray.h1
-rw-r--r--indra/newview/llcallingcard.cpp48
-rw-r--r--indra/newview/llcallingcard.h10
-rw-r--r--indra/newview/llchathistory.cpp126
-rw-r--r--indra/newview/llchathistory.h112
-rw-r--r--indra/newview/llfloaterinventory.cpp51
-rw-r--r--indra/newview/llfloaterinventory.h32
-rw-r--r--indra/newview/llfolderview.cpp41
-rw-r--r--indra/newview/llfolderview.h16
-rw-r--r--indra/newview/llfoldervieweventlistener.h2
-rw-r--r--indra/newview/llfolderviewitem.cpp49
-rw-r--r--indra/newview/llfolderviewitem.h2
-rw-r--r--indra/newview/llgrouplist.cpp2
-rw-r--r--indra/newview/llimfloater.cpp60
-rw-r--r--indra/newview/llimfloater.h7
-rw-r--r--indra/newview/llimview.cpp72
-rw-r--r--indra/newview/llimview.h4
-rw-r--r--indra/newview/llinspectavatar.cpp6
-rw-r--r--indra/newview/llinventorybridge.cpp141
-rw-r--r--indra/newview/llinventorybridge.h27
-rw-r--r--indra/newview/llinventoryclipboard.cpp12
-rw-r--r--indra/newview/llinventoryclipboard.h3
-rw-r--r--indra/newview/lllandmarkactions.cpp40
-rw-r--r--indra/newview/lllandmarkactions.h15
-rw-r--r--indra/newview/llnearbychat.cpp66
-rw-r--r--indra/newview/llnearbychat.h4
-rw-r--r--indra/newview/llnotificationtiphandler.cpp10
-rw-r--r--indra/newview/llpanelavatar.cpp5
-rw-r--r--indra/newview/llpanellandmarks.cpp668
-rw-r--r--indra/newview/llpanellandmarks.h63
-rw-r--r--indra/newview/llpanelpick.h1
-rw-r--r--indra/newview/llpanelplaces.cpp17
-rw-r--r--indra/newview/llpanelteleporthistory.cpp240
-rw-r--r--indra/newview/llpanelteleporthistory.h8
-rw-r--r--indra/newview/llplacesinventorybridge.cpp212
-rw-r--r--indra/newview/llplacesinventorybridge.h91
-rw-r--r--indra/newview/llsidetray.cpp13
-rw-r--r--indra/newview/llsidetray.h1
-rw-r--r--indra/newview/llsyswellwindow.cpp46
-rw-r--r--indra/newview/llsyswellwindow.h1
-rw-r--r--indra/newview/lltoastnotifypanel.cpp332
-rw-r--r--indra/newview/lltoastnotifypanel.h26
-rw-r--r--indra/newview/lltoastpanel.cpp20
-rw-r--r--indra/newview/lltoastpanel.h4
-rw-r--r--indra/newview/llviewerwindow.cpp9
-rw-r--r--indra/newview/skins/default/xui/en/floater_nearby_chat.xml15
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory.xml5
-rw-r--r--indra/newview/skins/default/xui/en/menu_landmark.xml8
-rw-r--r--indra/newview/skins/default/xui/en/menu_places_gear_folder.xml45
-rw-r--r--indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml56
-rw-r--r--indra/newview/skins/default/xui/en/panel_avatar_list_item.xml5
-rw-r--r--indra/newview/skins/default/xui/en/panel_chat_header.xml53
-rw-r--r--indra/newview/skins/default/xui/en/panel_chat_separator.xml16
-rw-r--r--indra/newview/skins/default/xui/en/panel_landmarks.xml158
-rw-r--r--indra/newview/skins/default/xui/en/panel_notification.xml92
-rw-r--r--indra/newview/skins/default/xui/en/panel_teleport_history.xml23
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chat_history.xml14
72 files changed, 2594 insertions, 817 deletions
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index e9df361472..bba5464b00 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -44,6 +44,9 @@ const LLSD UNSELECTED_EVENT = LLSD().insert("selected", false);
static const std::string COMMENT_TEXTBOX = "comment_text";
+//forward declaration
+bool llsds_are_equal(const LLSD& llsd_1, const LLSD& llsd_2);
+
LLFlatListView::Params::Params()
: item_pad("item_pad"),
allow_select("allow_select"),
@@ -333,6 +336,17 @@ void LLFlatListView::sort()
rearrangeItems();
}
+bool LLFlatListView::updateValue(const LLSD& old_value, const LLSD& new_value)
+{
+ if (old_value.isUndefined() || new_value.isUndefined()) return false;
+ if (llsds_are_equal(old_value, new_value)) return false;
+
+ item_pair_t* item_pair = getItemPair(old_value);
+ if (!item_pair) return false;
+
+ item_pair->second = new_value;
+ return true;
+}
//////////////////////////////////////////////////////////////////////////
// PROTECTED STUFF
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
index af5a9cfa9b..888258efdc 100644
--- a/indra/llui/llflatlistview.h
+++ b/indra/llui/llflatlistview.h
@@ -273,6 +273,8 @@ public:
void setComparator(const ItemComparator* comp) { mItemComparator = comp; }
void sort();
+ bool updateValue(const LLSD& old_value, const LLSD& new_value);
+
protected:
/** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 47ca4899df..44c5f8c0de 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -1262,6 +1262,12 @@ BOOL LLFloater::offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons inde
return FALSE;
}
+BOOL LLFloater::handleScrollWheel(S32 x, S32 y, S32 clicks)
+{
+ LLPanel::handleScrollWheel(x,y,clicks);
+ return TRUE;//always
+}
+
// virtual
BOOL LLFloater::handleMouseDown(S32 x, S32 y, MASK mask)
{
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 7a6c3f6863..123de12398 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -206,6 +206,9 @@ public:
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask);
+
+ virtual BOOL handleScrollWheel(S32 x, S32 y, S32 mask);
+
virtual void draw();
virtual void onOpen(const LLSD& key) {}
diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp
index a75a0c6979..0d674528dc 100644
--- a/indra/llui/llscrollbar.cpp
+++ b/indra/llui/llscrollbar.cpp
@@ -409,8 +409,13 @@ BOOL LLScrollbar::handleHover(S32 x, S32 y, MASK mask)
BOOL LLScrollbar::handleScrollWheel(S32 x, S32 y, S32 clicks)
{
- changeLine( clicks * mStepSize, TRUE );
- return TRUE;
+ S32 pos = llclamp(mDocPos + clicks * mStepSize, 0, getDocPosMax());
+ if (pos != mDocPos)
+ {
+ setDocPos(pos, TRUE);
+ return TRUE;
+ }
+ return FALSE;
}
BOOL LLScrollbar::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index 5597d494fe..d8606c6889 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -235,6 +235,8 @@ BOOL LLScrollContainer::handleKeyHere(KEY key, MASK mask)
BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks )
{
+ if(LLUICtrl::handleScrollWheel(x,y,clicks))
+ return TRUE;
for( S32 i = 0; i < SCROLLBAR_COUNT; i++ )
{
// Note: tries vertical and then horizontal
@@ -246,9 +248,7 @@ BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks )
return TRUE;
}
}
-
- // Eat scroll wheel event (to avoid scrolling nested containers?)
- return TRUE;
+ return FALSE;
}
BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask,
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index ff6fe5a7ea..31f12fe312 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -672,6 +672,26 @@ LLView* LLView::childrenHandleToolTip(S32 x, S32 y, MASK mask)
}
+LLView* LLView::childFromPoint(S32 x, S32 y)
+{
+ if (!getVisible() )
+ return false;
+ for ( child_list_iter_t child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it)
+ {
+ LLView* viewp = *child_it;
+ S32 local_x = x - viewp->getRect().mLeft;
+ S32 local_y = y - viewp->getRect().mBottom;
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible() )
+ {
+ continue;
+ }
+ return viewp;
+
+ }
+ return 0;
+}
+
BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
@@ -901,12 +921,6 @@ LLView* LLView::childrenHandleScrollWheel(S32 x, S32 y, S32 clicks)
handled_view = viewp;
break;
}
-
- if (viewp->blockMouseEvent(local_x, local_y))
- {
- handled_view = viewp;
- break;
- }
}
}
return handled_view;
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 5e35068733..73146b2c1f 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -445,6 +445,8 @@ public:
/*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const;
/*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const;
+ virtual LLView* childFromPoint(S32 x, S32 y);
+
// view-specific handlers
virtual void onMouseEnter(S32 x, S32 y, MASK mask);
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index c630a56c8d..51840bf696 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -94,6 +94,7 @@ set(viewer_SOURCE_FILES
llchannelmanager.cpp
llchatbar.cpp
llchatitemscontainerctrl.cpp
+ llchathistory.cpp
llchatmsgbox.cpp
llchiclet.cpp
llclassifiedinfo.cpp
@@ -246,6 +247,7 @@ set(viewer_SOURCE_FILES
llinventoryclipboard.cpp
llinventoryfilter.cpp
llinventorymodel.cpp
+ llinventorysubtreepanel.cpp
lljoystickbutton.cpp
lllandmarkactions.cpp
lllandmarklist.cpp
@@ -344,6 +346,7 @@ set(viewer_SOURCE_FILES
llpanelvolume.cpp
llparcelselection.cpp
llpatchvertexarray.cpp
+ llplacesinventorybridge.cpp
llpolymesh.cpp
llpolymorph.cpp
llpreviewanim.cpp
@@ -564,6 +567,7 @@ set(viewer_HEADER_FILES
llchannelmanager.h
llchatbar.h
llchatitemscontainerctrl.h
+ llchathistory.h
llchatmsgbox.h
llchiclet.h
llclassifiedinfo.h
@@ -716,6 +720,7 @@ set(viewer_HEADER_FILES
llinventoryclipboard.h
llinventoryfilter.h
llinventorymodel.h
+ llinventorysubtreepanel.h
lljoystickbutton.h
lllandmarkactions.h
lllandmarklist.h
@@ -811,6 +816,7 @@ set(viewer_HEADER_FILES
llpanelvolume.h
llparcelselection.h
llpatchvertexarray.h
+ llplacesinventorybridge.h
llpolymesh.h
llpolymorph.h
llpreview.h
diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp
index 3e411583ac..7ae1b5cd4a 100644
--- a/indra/newview/llavatariconctrl.cpp
+++ b/indra/newview/llavatariconctrl.cpp
@@ -181,16 +181,6 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p)
rect.setOriginAndSize(left, bottom, llavatariconctrl_symbol_size, llavatariconctrl_symbol_size);
- LLIconCtrl::Params icparams;
- icparams.name ("Status Symbol");
- icparams.follows.flags (FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
- icparams.rect (rect);
- mStatusSymbol = LLUICtrlFactory::create<LLIconCtrl> (icparams);
- mStatusSymbol->setValue("circle.tga");
- mStatusSymbol->setColor(LLColor4::grey);
-
- addChild(mStatusSymbol);
-
if (p.avatar_id.isProvided())
{
LLSD value(p.avatar_id);
@@ -239,16 +229,13 @@ void LLAvatarIconCtrl::setValue(const LLSD& value)
mAvatarId = value.asUUID();
// *BUG: This will return stale icons if a user changes their
- // profile picture. Also, the online/offline tooltips will be
- // out of date. However, otherwise we send too many upstream
+ // profile picture. However, otherwise we send too many upstream
// AvatarPropertiesRequest messages.
- //
- // *TODO: Implement a timeout on the icon cache, perhaps a day?,
- // and make the cache update if a user views the full-profile for
- // an avatar.
+
+ // to get fresh avatar icon use
+ // LLAvatarIconIDCache::getInstance()->remove(avatar_id);
// Check if cache already contains image_id for that avatar
-
if (!updateFromCache())
{
app->addObserver(mAvatarId, this);
@@ -282,36 +269,6 @@ bool LLAvatarIconCtrl::updateFromCache()
LLIconCtrl::setValue("default_profile_picture.j2c");
}
- // Can only see online status of friends
- if (LLAvatarTracker::instance().isBuddy(mAvatarId))
- {
- if (LLAvatarTracker::instance().isBuddyOnline(mAvatarId))
- {
- // Update color of status symbol and tool tip
- mStatusSymbol->setColor(LLColor4::green);
- if (mDrawTooltip)
- {
- setToolTip((LLStringExplicit)"Online");
- }
- }
- else
- {
- mStatusSymbol->setColor(LLColor4::grey);
- if (mDrawTooltip)
- {
- setToolTip((LLStringExplicit)"Offline");
- }
- }
- }
- else
- {
- // Not a buddy, no information
- mStatusSymbol->setColor(LLColor4::grey);
- if (mDrawTooltip)
- {
- setToolTip((LLStringExplicit)"");
- }
- }
return true;
}
@@ -370,6 +327,11 @@ void LLAvatarIconCtrl::nameUpdatedCallback(
{
mFirstName = first;
mLastName = last;
+
+ if (mDrawTooltip)
+ {
+ setToolTip(mFirstName + " " + mLastName);
+ }
}
}
diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h
index 77390eb233..426fcec514 100644
--- a/indra/newview/llavatariconctrl.h
+++ b/indra/newview/llavatariconctrl.h
@@ -104,7 +104,6 @@ public:
const std::string& getLastName() const { return mLastName; }
protected:
- LLIconCtrl* mStatusSymbol;
LLUUID mAvatarId;
std::string mFirstName;
std::string mLastName;
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 36f9780ad0..ef48420490 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -202,6 +202,7 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is
item->showSpeakingIndicator(true);
item->setName(name);
item->setAvatarId(id);
+ item->setOnline(is_bold);
item->setContextMenu(mContextMenu);
item->childSetVisible("info_btn", false);
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index 4179d7a58d..90408beca0 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -52,11 +52,17 @@ LLAvatarListItem::LLAvatarListItem()
mInfoBtn(NULL),
mProfileBtn(NULL),
mContextMenu(NULL),
- mAvatarId(LLUUID::null)
+ mOnlineStatus(E_UNKNOWN)
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_avatar_list_item.xml");
}
+LLAvatarListItem::~LLAvatarListItem()
+{
+ if (mAvatarId.notNull())
+ LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarId, this);
+}
+
BOOL LLAvatarListItem::postBuild()
{
mAvatarIcon = getChild<LLAvatarIconCtrl>("avatar_icon");
@@ -138,6 +144,36 @@ void LLAvatarListItem::setStatus(const std::string& status)
mStatus->setValue(status);
}
+// virtual, called by LLAvatarTracker
+void LLAvatarListItem::changed(U32 mask)
+{
+ // no need to check mAvatarId for null in this case
+ setOnline(LLAvatarTracker::instance().isBuddyOnline(mAvatarId));
+}
+
+void LLAvatarListItem::setOnline(bool online)
+{
+ // *FIX: setName() overrides font style set by setOnline(). Not an issue ATM.
+ // *TODO: Make the colors configurable via XUI.
+
+ if (mOnlineStatus != E_UNKNOWN && (bool) mOnlineStatus == online)
+ return;
+
+ mOnlineStatus = (EOnlineStatus) online;
+
+ // Change avatar name font style depending on the new online status.
+ LLStyle::Params style_params;
+ style_params.color = online ? LLColor4::white : LLColor4::grey;
+
+ // Rebuild the text to change its style.
+ std::string text = mAvatarName->getText();
+ mAvatarName->setText(LLStringUtil::null);
+ mAvatarName->appendText(text, false, style_params);
+
+ // Make the icon fade if the avatar goes offline.
+ mAvatarIcon->setColor(online ? LLColor4::white : LLColor4::smoke);
+}
+
void LLAvatarListItem::setName(const std::string& name)
{
mAvatarName->setValue(name);
@@ -146,10 +182,17 @@ void LLAvatarListItem::setName(const std::string& name)
void LLAvatarListItem::setAvatarId(const LLUUID& id)
{
+ if (mAvatarId.notNull())
+ LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarId, this);
+
mAvatarId = id;
mAvatarIcon->setValue(id);
mSpeakingIndicator->setSpeakerId(id);
+ // We'll be notified on avatar online status changes
+ if (mAvatarId.notNull())
+ LLAvatarTracker::instance().addParticularFriendObserver(mAvatarId, this);
+
// Set avatar name.
gCacheName->get(id, FALSE, boost::bind(&LLAvatarListItem::onNameCache, this, _2, _3));
}
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index 871441b2d3..2330db5249 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -38,9 +38,11 @@
#include "llbutton.h"
#include "lltextbox.h"
+#include "llcallingcard.h" // for LLFriendObserver
+
class LLAvatarIconCtrl;
-class LLAvatarListItem : public LLPanel
+class LLAvatarListItem : public LLPanel, public LLFriendObserver
{
public:
class ContextMenu
@@ -50,15 +52,17 @@ public:
};
LLAvatarListItem();
- virtual ~LLAvatarListItem() {};
+ virtual ~LLAvatarListItem();
virtual BOOL postBuild();
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
virtual void onMouseEnter(S32 x, S32 y, MASK mask);
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual void setValue(const LLSD& value);
+ virtual void changed(U32 mask); // from LLFriendObserver
void setStatus(const std::string& status);
+ void setOnline(bool online);
void setName(const std::string& name);
void setAvatarId(const LLUUID& id);
@@ -75,6 +79,13 @@ public:
void setContextMenu(ContextMenu* menu) { mContextMenu = menu; }
private:
+
+ typedef enum e_online_status {
+ E_OFFLINE,
+ E_ONLINE,
+ E_UNKNOWN,
+ } EOnlineStatus;
+
void onNameCache(const std::string& first_name, const std::string& last_name);
LLAvatarIconCtrl*mAvatarIcon;
@@ -87,6 +98,7 @@ private:
ContextMenu* mContextMenu;
LLUUID mAvatarId;
+ EOnlineStatus mOnlineStatus;
};
#endif //LL_LLAVATARLISTITEM_H
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 0ff8ca7d26..8987f14e97 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -185,6 +185,18 @@ void LLBottomTray::sessionRemoved(const LLUUID& session_id)
}
}
+void LLBottomTray::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id)
+{
+ //this is only needed in case of outgoing ad-hoc/group chat sessions
+ LLChicletPanel* chiclet_panel = getChicletPanel();
+ if (chiclet_panel)
+ {
+ //it should be ad-hoc im chiclet or group im chiclet
+ LLChiclet* chiclet = chiclet_panel->findChiclet<LLChiclet>(old_session_id);
+ if (chiclet) chiclet->setSessionId(new_session_id);
+ }
+}
+
//virtual
void LLBottomTray::onFocusLost()
{
diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h
index 4724c5ecef..cc35e63524 100644
--- a/indra/newview/llbottomtray.h
+++ b/indra/newview/llbottomtray.h
@@ -67,6 +67,7 @@ public:
// LLIMSessionObserver observe triggers
virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id);
virtual void sessionRemoved(const LLUUID& session_id);
+ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);
virtual void onFocusLost();
virtual void setVisible(BOOL visible);
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index 2b7bd83ca3..359bb23f05 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -260,7 +260,7 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
++new_buddy_count;
mBuddyInfo[agent_id] = (*itr).second;
gCacheName->getName(agent_id, first, last);
- mModifyMask |= LLFriendObserver::ADD;
+ addChangedMask(LLFriendObserver::ADD, agent_id);
lldebugs << "Added buddy " << agent_id
<< ", " << (mBuddyInfo[agent_id]->isOnline() ? "Online" : "Offline")
<< ", TO: " << mBuddyInfo[agent_id]->getRightsGrantedTo()
@@ -333,7 +333,7 @@ void LLAvatarTracker::setBuddyOnline(const LLUUID& id, bool is_online)
if(info)
{
info->online(is_online);
- mModifyMask |= LLFriendObserver::ONLINE;
+ addChangedMask(LLFriendObserver::ONLINE, id);
lldebugs << "Set buddy " << id << (is_online ? " Online" : " Offline") << llendl;
}
else
@@ -488,10 +488,52 @@ void LLAvatarTracker::notifyObservers()
{
(*it)->changed(mModifyMask);
}
+
+ for (changed_buddy_t::iterator it = mChangedBuddyIDs.begin(); it != mChangedBuddyIDs.end(); it++)
+ {
+ notifyParticularFriendObservers(*it);
+ }
+
mModifyMask = LLFriendObserver::NONE;
mChangedBuddyIDs.clear();
}
+void LLAvatarTracker::addParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer)
+{
+ if (buddy_id.notNull() && observer)
+ mParticularFriendObserverMap[buddy_id].insert(observer);
+}
+
+void LLAvatarTracker::removeParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer)
+{
+ if (buddy_id.isNull() || !observer)
+ return;
+
+ observer_map_t::iterator obs_it = mParticularFriendObserverMap.find(buddy_id);
+ if(obs_it == mParticularFriendObserverMap.end())
+ return;
+
+ obs_it->second.erase(observer);
+
+ // purge empty sets from the map
+ if (obs_it->second.size() == 0)
+ mParticularFriendObserverMap.erase(obs_it);
+}
+
+void LLAvatarTracker::notifyParticularFriendObservers(const LLUUID& buddy_id)
+{
+ observer_map_t::iterator obs_it = mParticularFriendObserverMap.find(buddy_id);
+ if(obs_it == mParticularFriendObserverMap.end())
+ return;
+
+ // Notify observers interested in buddy_id.
+ observer_set_t& obs = obs_it->second;
+ for (observer_set_t::iterator ob_it = obs.begin(); ob_it != obs.end(); ob_it++)
+ {
+ (*ob_it)->changed(mModifyMask);
+ }
+}
+
// store flag for change
// and id of object change applies to
void LLAvatarTracker::addChangedMask(U32 mask, const LLUUID& referent)
@@ -610,8 +652,8 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg)
}
}
}
- mModifyMask |= LLFriendObserver::POWERS;
+ addChangedMask(LLFriendObserver::POWERS, agent_id);
notifyObservers();
}
diff --git a/indra/newview/llcallingcard.h b/indra/newview/llcallingcard.h
index 228239b5ba..bd58b2fbe6 100644
--- a/indra/newview/llcallingcard.h
+++ b/indra/newview/llcallingcard.h
@@ -150,6 +150,12 @@ public:
void removeObserver(LLFriendObserver* observer);
void notifyObservers();
+ // Observers interested in updates of a particular avatar.
+ // On destruction these observers are NOT deleted.
+ void addParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer);
+ void removeParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer);
+ void notifyParticularFriendObservers(const LLUUID& buddy_id);
+
/**
* Stores flag for change and id of object change applies to
*
@@ -199,6 +205,10 @@ protected:
typedef std::vector<LLFriendObserver*> observer_list_t;
observer_list_t mObservers;
+ typedef std::set<LLFriendObserver*> observer_set_t;
+ typedef std::map<LLUUID, observer_set_t> observer_map_t;
+ observer_map_t mParticularFriendObserverMap;
+
private:
// do not implement
LLAvatarTracker(const LLAvatarTracker&);
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
new file mode 100644
index 0000000000..80f3867a80
--- /dev/null
+++ b/indra/newview/llchathistory.cpp
@@ -0,0 +1,126 @@
+/**
+ * @file llchathistory.cpp
+ * @brief LLTextEditor base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llchathistory.h"
+#include "llpanel.h"
+#include "lltextbox.h"
+#include "lluictrlfactory.h"
+#include "llscrollcontainer.h"
+#include "llavatariconctrl.h"
+
+static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history");
+static const std::string MESSAGE_USERNAME_DATE_SEPARATOR(" ----- ");
+
+LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
+: LLTextEditor(p),
+mMessageHeaderFilename(p.message_header),
+mMessageSeparatorFilename(p.message_separator),
+mLeftTextPad(p.left_text_pad),
+mRightTextPad(p.right_text_pad),
+mLeftWidgetPad(p.left_widget_pad),
+mRightWidgetPad(p.rigth_widget_pad)
+{
+}
+
+LLChatHistory::~LLChatHistory()
+{
+ this->clear();
+}
+
+/*void LLChatHistory::updateTextRect()
+{
+ static LLUICachedControl<S32> texteditor_border ("UITextEditorBorder", 0);
+
+ LLRect old_text_rect = mTextRect;
+ mTextRect = mScroller->getContentWindowRect();
+ mTextRect.stretch(-texteditor_border);
+ mTextRect.mLeft += mLeftTextPad;
+ mTextRect.mRight -= mRightTextPad;
+ if (mTextRect != old_text_rect)
+ {
+ needsReflow();
+ }
+}*/
+
+LLView* LLChatHistory::getSeparator()
+{
+ LLPanel* separator = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>(mMessageSeparatorFilename, NULL, LLPanel::child_registry_t::instance());
+ return separator;
+}
+
+LLView* LLChatHistory::getHeader(const LLUUID& avatar_id, std::string& from, std::string& time)
+{
+ LLPanel* header = LLUICtrlFactory::getInstance()->createFromFile<LLPanel>(mMessageHeaderFilename, NULL, LLPanel::child_registry_t::instance());
+ LLTextBox* userName = header->getChild<LLTextBox>("user_name");
+ userName->setValue(from);
+ LLTextBox* timeBox = header->getChild<LLTextBox>("time_box");
+ timeBox->setValue(time);
+ if(!avatar_id.isNull())
+ {
+ LLAvatarIconCtrl* icon = header->getChild<LLAvatarIconCtrl>("avatar_icon");
+ icon->setValue(avatar_id);
+ }
+ return header;
+}
+
+void LLChatHistory::appendWidgetMessage(const LLUUID& avatar_id, std::string& from, std::string& time, std::string& message, LLStyle::Params& style_params)
+{
+ LLView* view = NULL;
+ std::string view_text;
+
+ if (mLastFromName == from)
+ {
+ view = getSeparator();
+ view_text = "\n";
+ }
+ else
+ {
+ view = getHeader(avatar_id, from, time);
+ view_text = from + MESSAGE_USERNAME_DATE_SEPARATOR + time;
+ }
+ //Prepare the rect for the view
+ LLRect target_rect = mScroller->getContentWindowRect();
+ target_rect.mLeft += mLeftWidgetPad;
+ target_rect.mRight -= mRightWidgetPad;
+ view->reshape(target_rect.getWidth(), view->getRect().getHeight());
+ view->setOrigin(target_rect.mLeft, view->getRect().mBottom);
+
+ this->appendWidget(view, view_text, FALSE, TRUE);
+
+ //Append the text message
+ this->appendText(message, TRUE, style_params);
+
+ mLastFromName = from;
+ this->blockUndo();
+ this->setCursorAndScrollToEnd();
+}
diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h
new file mode 100644
index 0000000000..d6eccf896a
--- /dev/null
+++ b/indra/newview/llchathistory.h
@@ -0,0 +1,112 @@
+/**
+ * @file llchathistory.h
+ * @brief LLTextEditor base class
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LLCHATHISTORY_H_
+#define LLCHATHISTORY_H_
+
+#include "lltexteditor.h"
+
+//Chat log widget allowing addition of a message as a widget
+class LLChatHistory : public LLTextEditor
+{
+ public:
+ struct Params : public LLInitParam::Block<Params, LLTextEditor::Params>
+ {
+ //Message header filename
+ Optional<std::string> message_header;
+ //Message separator filename
+ Optional<std::string> message_separator;
+ //Text left padding from the scroll rect
+ Optional<S32> left_text_pad;
+ //Text right padding from the scroll rect
+ Optional<S32> right_text_pad;
+ //Widget left padding from the scroll rect
+ Optional<S32> left_widget_pad;
+ //Widget right padding from the scroll rect
+ Optional<S32> rigth_widget_pad;
+
+ Params()
+ : message_header("message_header"),
+ message_separator("message_separator"),
+ left_text_pad("left_text_pad"),
+ right_text_pad("right_text_pad"),
+ left_widget_pad("left_widget_pad"),
+ rigth_widget_pad("rigth_widget_pad")
+ {
+ }
+
+ };
+ protected:
+ LLChatHistory(const Params&);
+ friend class LLUICtrlFactory;
+
+ /**
+ * Redefinition of LLTextEditor::updateTextRect() to considerate text
+ * left/right padding params.
+ */
+ //virtual void updateTextRect();
+ /**
+ * Builds a message separator.
+ * @return pointer to LLView separator object.
+ */
+ LLView* getSeparator();
+ /**
+ * Builds a message header.
+ * @param from owner of a message.
+ * @param time time of a message.
+ * @return pointer to LLView header object.
+ */
+ LLView* getHeader(const LLUUID& avatar_id, std::string& from, std::string& time);
+
+ public:
+ ~LLChatHistory();
+
+ /**
+ * Appends a widget message.
+ * If last user appended message, concurs with current user,
+ * separator is added before the message, otherwise header is added.
+ * @param from owner of a message.
+ * @param time time of a message.
+ * @param message message itself.
+ */
+ void appendWidgetMessage(const LLUUID& avatar_id, std::string& from, std::string& time, std::string& message, LLStyle::Params& style_params);
+
+ private:
+ std::string mLastFromName;
+ std::string mMessageHeaderFilename;
+ std::string mMessageSeparatorFilename;
+ S32 mLeftTextPad;
+ S32 mRightTextPad;
+ S32 mLeftWidgetPad;
+ S32 mRightWidgetPad;
+};
+#endif /* LLCHATHISTORY_H_ */
diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp
index a8ab4303ba..a33a605f50 100644
--- a/indra/newview/llfloaterinventory.cpp
+++ b/indra/newview/llfloaterinventory.cpp
@@ -1161,6 +1161,7 @@ LLUIImagePtr get_item_icon(LLAssetType::EType asset_type,
const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder");
const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder");
const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string("");
+static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER;
LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p)
: LLPanel(p),
@@ -1172,7 +1173,12 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p)
mAllowMultiSelect(p.allow_multi_select),
mHasInventoryConnection(false),
mStartFolderString(p.start_folder)
+, mBuildDefaultHierarchy(true)
+, mRootInventoryItemUUID(LLUUID::null)
+, mInvFVBridgeBuilder(NULL)
{
+ mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER;
+
// contex menu callbacks
mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2));
mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLAssetType::AT_TRASH));
@@ -1237,8 +1243,8 @@ BOOL LLInventoryPanel::postBuild()
const LLAssetType::EType preferred_type = LLAssetType::lookupHumanReadable(mStartFolderString);
mStartFolderID = (preferred_type != LLAssetType::AT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
- // build view of inventory if inventory ready, otherwise wait for modelChanged() callback
- if (mInventory->isInventoryUsable() && !mHasInventoryConnection)
+ // build view of inventory if we need default full hierarchy and inventory ready, otherwise wait for modelChanged() callback
+ if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mHasInventoryConnection)
{
rebuildViewsFor(mStartFolderID);
mHasInventoryConnection = true;
@@ -1456,6 +1462,25 @@ void LLInventoryPanel::modelChanged(U32 mask)
}
}
+void LLInventoryPanel::setInvFVBridgeBuilder(const LLInventoryFVBridgeBuilder* bridge_builder)
+{
+ if (NULL == bridge_builder)
+ {
+ llwarns << "NULL is passed as Inventory Bridge Builder. Default will be used." << llendl;
+ }
+ else
+ {
+ mInvFVBridgeBuilder = bridge_builder;
+ }
+
+ if (mInventory->isInventoryUsable() && !mHasInventoryConnection)
+ {
+ rebuildViewsFor(mRootInventoryItemUUID);
+ mHasInventoryConnection = true;
+ }
+}
+
+
void LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
{
LLFolderViewItem* old_view = NULL;
@@ -1493,11 +1518,11 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
else if (objectp->getType() == LLAssetType::AT_CATEGORY &&
objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)
{
- LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(objectp->getType(),
- objectp->getType(),
- LLInventoryType::IT_CATEGORY,
- this,
- objectp->getUUID());
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(),
+ objectp->getType(),
+ LLInventoryType::IT_CATEGORY,
+ this,
+ objectp->getUUID());
if (new_listener)
{
@@ -1516,12 +1541,12 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
{
// Build new view for item
LLInventoryItem* item = (LLInventoryItem*)objectp;
- LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(item->getType(),
- item->getActualType(),
- item->getInventoryType(),
- this,
- item->getUUID(),
- item->getFlags());
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(),
+ item->getActualType(),
+ item->getInventoryType(),
+ this,
+ item->getUUID(),
+ item->getFlags());
if (new_listener)
{
diff --git a/indra/newview/llfloaterinventory.h b/indra/newview/llfloaterinventory.h
index 33b1a3b6c9..1666f18c05 100644
--- a/indra/newview/llfloaterinventory.h
+++ b/indra/newview/llfloaterinventory.h
@@ -57,6 +57,7 @@ class LLFolderViewItem;
class LLInventoryFilter;
class LLInventoryModel;
class LLInvFVBridge;
+class LLInventoryFVBridgeBuilder;
class LLMenuBarGL;
class LLCheckBoxCtrl;
class LLSpinCtrl;
@@ -110,7 +111,7 @@ protected:
friend class LLUICtrlFactory;
public:
- ~LLInventoryPanel();
+ virtual ~LLInventoryPanel();
LLInventoryModel* getModel() { return mInventory; }
@@ -172,7 +173,10 @@ public:
protected:
// Given the id and the parent, build all of the folder views.
void rebuildViewsFor(const LLUUID& id);
- void buildNewViews(const LLUUID& id);
+ virtual void buildNewViews(const LLUUID& id); // made virtual to support derived classes. EXT-719
+
+ // Be sure that passed pointer will be destroyed where it was created.
+ void setInvFVBridgeBuilder(const LLInventoryFVBridgeBuilder* bridge_builder);
protected:
LLInventoryModel* mInventory;
@@ -180,12 +184,34 @@ protected:
BOOL mAllowMultiSelect;
std::string mSortOrderSetting;
-private:
+//private: // Can not make these private - needed by llinventorysubtreepanel
LLFolderView* mFolders;
std::string mStartFolderString;
LLUUID mStartFolderID;
LLScrollContainer* mScroller;
bool mHasInventoryConnection;
+
+ /**
+ * Flag specified if default inventory hierarchy should be created in postBuild()
+ */
+ bool mBuildDefaultHierarchy;
+
+ /**
+ * Contains UUID of Inventory item from which hierarchy should be built.
+ * Should be set by derived class before modelChanged() is called.
+ * Default is LLUUID::null that means total Inventory hierarchy.
+ */
+ LLUUID mRootInventoryItemUUID;
+
+ /**
+ * Pointer to LLInventoryFVBridgeBuilder.
+ *
+ * It is set in LLInventoryPanel's constructor and can be overridden in derived classes with
+ * another implementation.
+ * Take into account it will not be deleted by LLInventoryPanel itself.
+ */
+ const LLInventoryFVBridgeBuilder* mInvFVBridgeBuilder;
+
};
class LLFloaterInventory;
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 3fd0875709..155262ee13 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -190,6 +190,8 @@ LLFolderView::LLFolderView(const Params& p)
mDragAndDropThisFrame(FALSE),
mCallbackRegistrar(NULL),
mParentPanel(p.parent_panel)
+, mUseEllipses(false)
+, mDraggingOverItem(NULL)
{
LLRect rect = p.rect;
LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom);
@@ -481,6 +483,11 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent)
scroll_rect = mScrollContainer->getContentWindowRect();
}
width = llmax(mMinWidth, scroll_rect.getWidth());
+
+ // restrict width with scroll container's width
+ if (mUseEllipses)
+ width = scroll_rect.getWidth();
+
LLView::reshape(width, height, called_from_parent);
mReshapeSignal(mSelectedItems, FALSE);
@@ -1224,12 +1231,42 @@ void LLFolderView::copy()
BOOL LLFolderView::canCut() const
{
- return FALSE;
+ if (!(getVisible() && getEnabled() && (mSelectedItems.size() > 0)))
+ {
+ return FALSE;
+ }
+
+ for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it)
+ {
+ const LLFolderViewItem* item = *selected_it;
+ const LLFolderViewEventListener* listener = item->getListener();
+ if (!listener || !listener->isItemMovable())
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
}
void LLFolderView::cut()
{
- // implement Windows-style cut-and-leave
+ // clear the inventory clipboard
+ LLInventoryClipboard::instance().reset();
+ S32 count = mSelectedItems.size();
+ if(getVisible() && getEnabled() && (count > 0))
+ {
+ LLFolderViewEventListener* listener = NULL;
+ selected_items_t::iterator item_it;
+ for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it)
+ {
+ listener = (*item_it)->getListener();
+ if(listener)
+ {
+ listener->cutToClipboard();
+ }
+ }
+ }
+ mSearchString.clear();
}
BOOL LLFolderView::canPaste() const
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index c95dc6e5bd..ebfb4efde2 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -180,6 +180,9 @@ public:
BOOL startDrag(LLToolDragAndDrop::ESource source);
void setDragAndDropThisFrame() { mDragAndDropThisFrame = TRUE; }
+ void setDraggingOverItem(LLFolderViewItem* item) { mDraggingOverItem = item; }
+ LLFolderViewItem* getDraggingOverItem() { return mDraggingOverItem; }
+
// deletion functionality
void removeSelectedItems();
@@ -248,6 +251,8 @@ public:
void setShowSingleSelection(BOOL show);
BOOL getShowSingleSelection() { return mShowSingleSelection; }
F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); }
+ void setUseEllipses(bool use_ellipses) { mUseEllipses = use_ellipses; }
+ bool getUseEllipses() { return mUseEllipses; }
void addItemID(const LLUUID& id, LLFolderViewItem* itemp);
void removeItemID(const LLUUID& id);
@@ -327,6 +332,17 @@ protected:
LLPanel* mParentPanel;
+ /**
+ * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll.
+ * NOTE: For now it uses only to cut LLFolderViewItem::mLabel text to be used for Landmarks in Places Panel.
+ */
+ bool mUseEllipses; // See EXT-719
+
+ /**
+ * Contains item under mouse pointer while dragging
+ */
+ LLFolderViewItem* mDraggingOverItem; // See EXT-719
+
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar;
public:
diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h
index 254ce4062a..ff38da279a 100644
--- a/indra/newview/llfoldervieweventlistener.h
+++ b/indra/newview/llfoldervieweventlistener.h
@@ -68,7 +68,7 @@ public:
virtual void showProperties(void) = 0;
virtual BOOL isItemRenameable() const = 0;
virtual BOOL renameItem(const std::string& new_name) = 0;
- virtual BOOL isItemMovable( void ) = 0; // Can be moved to another folder
+ virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder
virtual BOOL isItemRemovable( void ) = 0; // Can be destroyed
virtual BOOL removeItem() = 0;
virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) = 0;
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index 2b1dd83d72..0d74641c5f 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -36,6 +36,7 @@
// viewer includes
#include "llfolderview.h" // Items depend extensively on LLFolderViews
#include "llfoldervieweventlistener.h"
+#include "llinventorybridge.h" // for LLItemBridge in LLInventorySort::operator()
#include "llinventoryfilter.h"
#include "llinventorymodel.h" // *TODO: make it take a pointer to an inventory-model interface
#include "llviewercontrol.h" // gSavedSettings
@@ -130,6 +131,7 @@ LLFolderViewItem::LLFolderViewItem(LLFolderViewItem::Params p)
mListener(p.listener),
mArrowImage(p.folder_arrow_image),
mBoxImage(p.selection_image)
+, mDontShowInHierarhy(false)
{
refresh();
}
@@ -312,7 +314,12 @@ void LLFolderViewItem::arrangeFromRoot()
S32 height = 0;
S32 width = 0;
- root->arrange( &width, &height, 0 );
+ S32 total_height = root->arrange( &width, &height, 0 );
+
+ LLSD params;
+ params["action"] = "size_changes";
+ params["height"] = total_height;
+ getParent()->notifyParent(params);
}
// Utility function for LLFolderView
@@ -385,12 +392,22 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)
}
*width = llmax(*width, mLabelWidth + mIndentation);
+
+ // determine if we need to use ellipses to avoid horizontal scroll. EXT-719
+ bool use_ellipses = getRoot()->getUseEllipses();
+ if (use_ellipses)
+ {
+ // limit to set rect to avoid horizontal scrollbar
+ *width = llmin(*width, getRoot()->getRect().getWidth());
+ }
*height = getItemHeight();
return *height;
}
S32 LLFolderViewItem::getItemHeight()
{
+ if (mDontShowInHierarhy) return 0;
+
S32 icon_height = mIcon->getHeight();
S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight());
return llmax( icon_height, label_height ) + ICON_PAD;
@@ -781,7 +798,10 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
}
if(mParentFolder && !handled)
{
+ // store this item to get it in LLFolderBridge::dragItemIntoFolder on drop event.
+ mRoot->setDraggingOverItem(this);
handled = mParentFolder->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg);
+ mRoot->setDraggingOverItem(NULL);
}
if (handled)
{
@@ -794,6 +814,8 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
void LLFolderViewItem::draw()
{
+ if (mDontShowInHierarhy) return;
+
static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
static LLUIColor sHighlightFgColor = LLUIColorTable::instance().getColor("MenuItemHighlightFgColor", DEFAULT_WHITE);
@@ -948,7 +970,8 @@ void LLFolderViewItem::draw()
font->renderUTF8( mLabel, 0, text_left, y, color,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
- S32_MAX, S32_MAX, &right_x, FALSE );
+ S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE);
+
if (!mLabelSuffix.empty())
{
font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor,
@@ -2456,6 +2479,28 @@ bool LLInventorySort::updateSort(U32 order)
bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b)
{
+ // ignore sort order for landmarks in the Favorites folder.
+ // they should be always sorted as in Favorites bar. See EXT-719
+ if (a->getSortGroup() == SG_ITEM && b->getSortGroup() == SG_ITEM
+ && a->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK
+ && b->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+
+ static LLUUID favorites_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
+
+ LLUUID a_uuid = a->getParentFolder()->getListener()->getUUID();
+ LLUUID b_uuid = b->getParentFolder()->getListener()->getUUID();
+
+ if (a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)
+ {
+ // *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem
+ // or to LLInvFVBridge
+ S32 a_sort = (static_cast<const LLItemBridge*>(a->getListener()))->getItem()->getSortField();
+ S32 b_sort = (static_cast<const LLItemBridge*>(b->getListener()))->getItem()->getSortField();
+ return a_sort < b_sort;
+ }
+ }
+
// We sort by name if we aren't sorting by date
// OR if these are folders and we are sorting folders by name.
bool by_name = (!mByDate
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index 09c97662d9..90c346b381 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -158,6 +158,7 @@ protected:
LLUIImagePtr mBoxImage;
BOOL mIsLoading;
LLTimer mTimeSinceRequestStart;
+ bool mDontShowInHierarhy;
// helper function to change the selection from the root.
void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected);
@@ -200,6 +201,7 @@ public:
// makes sure that this view and it's children are the right size.
virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
virtual S32 getItemHeight();
+ void setDontShowInHierarchy(bool dont_show) { mDontShowInHierarhy = dont_show; }
// applies filters to control visibility of inventory items
virtual void filter( LLInventoryFilter& filter);
diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp
index ae869d9ac4..27e31d4edd 100644
--- a/indra/newview/llgrouplist.cpp
+++ b/indra/newview/llgrouplist.cpp
@@ -315,7 +315,7 @@ void LLGroupListItem::setActive(bool active)
// rebuild the text. This will cause problems if the text contains
// hyperlinks, as their styles will be wrong.
std::string text = mGroupNameBox->getText();
- mGroupNameBox->setText(LLStringUtil::null);// *HACK: replace with clear() when it's fixed.
+ mGroupNameBox->setText(LLStringUtil::null);
mGroupNameBox->appendText(text, false, style_params);
}
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 680106c7bb..a35c04440b 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -63,13 +63,15 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
mDialog(IM_NOTHING_SPECIAL),
mHistoryEditor(NULL),
mInputEditor(NULL),
- mPositioned(false)
+ mPositioned(false),
+ mSessionInitialized(false)
{
- EInstantMessage type = LLIMModel::getInstance()->getType(session_id);
- if(IM_COUNT != type)
+ LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionID);
+ if (im_session)
{
- mDialog = type;
-
+ mSessionInitialized = im_session->mSessionInitialized;
+
+ mDialog = im_session->mType;
if (IM_NOTHING_SPECIAL == mDialog || IM_SESSION_P2P_INVITE == mDialog)
{
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelIMControl, this);
@@ -139,10 +141,16 @@ void LLIMFloater::sendMsg()
std::string utf8_text = wstring_to_utf8str(text);
utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1);
- LLIMModel::sendMessage(utf8_text,
- mSessionID,
- mOtherParticipantUUID,
- mDialog);
+ if (mSessionInitialized)
+ {
+ LLIMModel::sendMessage(utf8_text, mSessionID,
+ mOtherParticipantUUID,mDialog);
+ }
+ else
+ {
+ //queue up the message to send once the session is initialized
+ mQueuedMsgsForInit.append(utf8_text);
+ }
mInputEditor->setText(LLStringUtil::null);
@@ -200,6 +208,8 @@ BOOL LLIMFloater::postBuild()
LLLogChat::loadHistory(getTitle(), &chatFromLogFile, (void *)this);
}
+ //*TODO if session is not initialized yet, add some sort of a warning message like "starting session...blablabla"
+ //see LLFloaterIMPanel for how it is done (IB)
return LLDockableFloater::postBuild();
}
@@ -337,6 +347,37 @@ bool LLIMFloater::toggle(const LLUUID& session_id)
}
}
+//static
+LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id)
+{
+ return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
+}
+
+void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
+{
+ mSessionInitialized = true;
+
+ if (mSessionID != im_session_id)
+ {
+ mSessionID = im_session_id;
+ setKey(im_session_id);
+ }
+
+ //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB)
+
+
+ //need to send delayed messaged collected while waiting for session initialization
+ if (!mQueuedMsgsForInit.size()) return;
+ LLSD::array_iterator iter;
+ for ( iter = mQueuedMsgsForInit.beginArray();
+ iter != mQueuedMsgsForInit.endArray();
+ ++iter)
+ {
+ LLIMModel::sendMessage(iter->asString(), mSessionID,
+ mOtherParticipantUUID, mDialog);
+ }
+}
+
void LLIMFloater::updateMessages()
{
std::list<LLSD> messages = LLIMModel::instance().getMessages(mSessionID, mLastMessageIndex+1);
@@ -457,3 +498,4 @@ void LLIMFloater::chatFromLogFile(LLLogChat::ELogLineType type, std::string line
self->mHistoryEditor->appendText(message, true, LLStyle::Params().color(LLUIColorTable::instance().getColor("ChatHistoryTextColor")));
self->mHistoryEditor->blockUndo();
}
+
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index 5276013568..9b519ee7e3 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -68,6 +68,10 @@ public:
// Returns true iff panel became visible
static bool toggle(const LLUUID& session_id);
+ static LLIMFloater* findInstance(const LLUUID& session_id);
+
+ void sessionInitReplyReceived(const LLUUID& im_session_id);
+
// get new messages from LLIMModel
void updateMessages();
static void onSendMsg( LLUICtrl*, void*);
@@ -108,6 +112,9 @@ private:
LLViewerTextEditor* mHistoryEditor;
LLLineEditor* mInputEditor;
bool mPositioned;
+
+ bool mSessionInitialized;
+ LLSD mQueuedMsgsForInit;
};
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 2ecd3eb448..6aa6c3f461 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -144,6 +144,8 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
// All participants will be added to the list of people we've recently interacted with.
mSpeakers->addListener(&LLRecentPeople::instance(), "add");
+ //we need to wait for session initialization for outgoing ad-hoc and group chat session
+ //correct session id for initiated ad-hoc chat will be received from the server
if (!LLIMModel::getInstance()->sendStartSession(mSessionID, mOtherParticipantID,
mInitialTargetIDs, mType))
{
@@ -181,26 +183,44 @@ LLIMModel::LLIMSession::~LLIMSession()
mVoiceChannel = NULL;
}
+void LLIMModel::LLIMSession::sessionInitReplyReceived(const LLUUID& new_session_id)
+{
+ mSessionInitialized = true;
+
+ if (new_session_id != mSessionID)
+ {
+ mSessionID = new_session_id;
+ mVoiceChannel->updateSessionID(new_session_id);
+ }
+}
+
LLIMModel::LLIMSession* LLIMModel::findIMSession(const LLUUID& session_id) const
{
return get_if_there(LLIMModel::instance().sSessionsMap, session_id,
(LLIMModel::LLIMSession*) NULL);
}
+//*TODO change name to represent session initialization aspect (IB)
void LLIMModel::updateSessionID(const LLUUID& old_session_id, const LLUUID& new_session_id)
{
- if (new_session_id == old_session_id) return;
-
LLIMSession* session = findIMSession(old_session_id);
if (session)
{
- session->mSessionID = new_session_id;
- session->mVoiceChannel->updateSessionID(new_session_id);
+ session->sessionInitReplyReceived(new_session_id);
- session->mSessionInitialized = true;
+ if (old_session_id != new_session_id)
+ {
+ sSessionsMap.erase(old_session_id);
+ sSessionsMap[new_session_id] = session;
- sSessionsMap.erase(old_session_id);
- sSessionsMap[new_session_id] = session;
+ gIMMgr->notifyObserverSessionIDUpdated(old_session_id, new_session_id);
+ }
+
+ LLIMFloater* im_floater = LLIMFloater::findInstance(old_session_id);
+ if (im_floater)
+ {
+ im_floater->sessionInitReplyReceived(new_session_id);
+ }
}
//*TODO remove this "floater" stuff when Communicate Floater is gone
@@ -736,18 +756,10 @@ bool LLIMModel::sendStartSession(
temp_session_id,
other_participant_id,
dialog);
-
- switch(dialog)
- {
- case IM_SESSION_GROUP_START:
- gMessageSystem->addBinaryDataFast(
+ gMessageSystem->addBinaryDataFast(
_PREHASH_BinaryBucket,
EMPTY_BINARY_BUCKET,
EMPTY_BINARY_BUCKET_SIZE);
- break;
- default:
- break;
- }
gAgent.sendReliableMessage();
return true;
@@ -789,6 +801,9 @@ bool LLIMModel::sendStartSession(
other_participant_id,
agents);
}
+
+ //we also need to wait for reply from the server in case of ad-hoc chat (we'll get new session id)
+ return true;
}
return false;
@@ -1291,9 +1306,16 @@ void LLIMMgr::addMessage(
new_session_id = computeSessionID(dialog, other_participant_id);
}
+ //*NOTE session_name is empty in case of incoming P2P sessions
+ std::string fixed_session_name = from;
+ if(!session_name.empty() && session_name.size()>1)
+ {
+ fixed_session_name = session_name;
+ }
+
if (!LLIMModel::getInstance()->findIMSession(new_session_id))
{
- LLIMModel::instance().newSession(session_id, session_name, dialog, other_participant_id);
+ LLIMModel::getInstance()->newSession(session_id, fixed_session_name, dialog, other_participant_id);
}
floater = findFloaterBySession(new_session_id);
@@ -1310,17 +1332,12 @@ void LLIMMgr::addMessage(
// create IM window as necessary
if(!floater)
{
- std::string name = from;
- if(!session_name.empty() && session_name.size()>1)
- {
- name = session_name;
- }
floater = createFloater(
new_session_id,
other_participant_id,
- name,
+ fixed_session_name,
dialog,
FALSE);
@@ -1869,6 +1886,15 @@ void LLIMMgr::notifyObserverSessionRemoved(const LLUUID& session_id)
}
}
+void LLIMMgr::notifyObserverSessionIDUpdated( const LLUUID& old_session_id, const LLUUID& new_session_id )
+{
+ for (session_observers_list_t::iterator it = mSessionObservers.begin(); it != mSessionObservers.end(); it++)
+ {
+ (*it)->sessionIDUpdated(old_session_id, new_session_id);
+ }
+
+}
+
void LLIMMgr::addSessionObserver(LLIMSessionObserver *observer)
{
mSessionObservers.push_back(observer);
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index df28c16bb1..84646a9a6f 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -56,6 +56,8 @@ public:
const EInstantMessage& type, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids);
virtual ~LLIMSession();
+ void sessionInitReplyReceived(const LLUUID& new_session_id);
+
LLUUID mSessionID;
std::string mName;
EInstantMessage mType;
@@ -153,6 +155,7 @@ public:
virtual ~LLIMSessionObserver() {}
virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) = 0;
virtual void sessionRemoved(const LLUUID& session_id) = 0;
+ virtual void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id) = 0;
};
@@ -304,6 +307,7 @@ private:
void notifyObserverSessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id);
void notifyObserverSessionRemoved(const LLUUID& session_id);
+ void notifyObserverSessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);
private:
std::set<LLHandle<LLFloater> > mFloaters;
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index 44dd11dd86..14dd0cdbce 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -54,6 +54,8 @@
#include "lltooltip.h" // positionViewNearMouse()
#include "lluictrl.h"
+#include "llavatariconctrl.h"
+
class LLFetchAvatarData;
@@ -347,6 +349,10 @@ void LLInspectAvatar::requestUpdate()
// and this may result in the image being visible sooner.
// *NOTE: This may generate a duplicate avatar properties request, but that
// will be suppressed internally in the avatar properties processor.
+
+ //remove avatar id from cache to get fresh info
+ LLAvatarIconIDCache::getInstance()->remove(mAvatarID);
+
childSetValue("avatar_icon", LLSD(mAvatarID) );
gCacheName->get(mAvatarID, FALSE,
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index e807240e4e..db7d4f4c8f 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -257,11 +257,22 @@ void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string&
}
// Can be moved to another folder
-BOOL LLInvFVBridge::isItemMovable()
+BOOL LLInvFVBridge::isItemMovable() const
{
return TRUE;
}
+/*virtual*/
+/**
+ * @brief Adds this item into clipboard storage
+ */
+void LLInvFVBridge::cutToClipboard()
+{
+ if(isItemMovable())
+ {
+ LLInventoryClipboard::instance().cut(mUUID);
+ }
+}
// *TODO: make sure this does the right thing
void LLInvFVBridge::showProperties()
{
@@ -912,6 +923,24 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
}
// +=================================================+
+// | InventoryFVBridgeBuilder |
+// +=================================================+
+LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags /* = 0x00 */) const
+{
+ return LLInvFVBridge::createBridge(asset_type,
+ actual_asset_type,
+ inv_type,
+ inventory,
+ uuid,
+ flags);
+}
+
+// +=================================================+
// | LLItemBridge |
// +=================================================+
@@ -1321,7 +1350,7 @@ BOOL LLItemBridge::isItemPermissive() const
LLFolderBridge* LLFolderBridge::sSelf=NULL;
// Can be moved to another folder
-BOOL LLFolderBridge::isItemMovable()
+BOOL LLFolderBridge::isItemMovable() const
{
LLInventoryObject* obj = getInventoryObject();
if(obj)
@@ -2184,19 +2213,28 @@ void LLFolderBridge::pasteFromClipboard()
LLDynamicArray<LLUUID> objects;
LLInventoryClipboard::instance().retrieve(objects);
S32 count = objects.count();
- LLUUID parent_id(mUUID);
+ const LLUUID parent_id(mUUID);
for(S32 i = 0; i < count; i++)
{
item = model->getItem(objects.get(i));
if (item)
{
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- parent_id,
- std::string(),
- LLPointer<LLInventoryCallback>(NULL));
+ if(LLInventoryClipboard::instance().isCutMode())
+ {
+ // move_inventory_item() is not enough,
+ //we have to update inventory locally too
+ changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE);
+ }
+ else
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ parent_id,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
}
}
}
@@ -2668,6 +2706,56 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
return false;
}
+/*
+Next functions intended to reorder items in the inventory folder and save order on server
+Is now used for Favorites folder.
+
+*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel
+*/
+void saveItemsOrder(LLInventoryModel::item_array_t& items)
+{
+ int sortField = 0;
+
+ // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ LLViewerInventoryItem* item = *i;
+
+ item->setSortField(++sortField);
+ item->setComplete(TRUE);
+ item->updateServer(FALSE);
+
+ gInventory.updateItem(item);
+ }
+
+ gInventory.notifyObservers();
+}
+
+LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id)
+{
+ LLInventoryModel::item_array_t::iterator result = items.end();
+
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ if ((*i)->getUUID() == id)
+ {
+ result = i;
+ break;
+ }
+ }
+
+ return result;
+}
+
+void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId)
+{
+ LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId);
+ LLViewerInventoryItem* destItem = gInventory.getItem(destItemId);
+
+ items.erase(findItemByUUID(items, srcItem->getUUID()));
+ items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
+}
+
BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
BOOL drop)
{
@@ -2726,7 +2814,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
}
}
- accept = is_movable && (mUUID != inv_item->getParentUUID());
+ LLUUID favorites_id = model->findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
+
+ // we can move item inside a folder only if this folder is Favorites. See EXT-719
+ accept = is_movable && ((mUUID != inv_item->getParentUUID()) || (mUUID == favorites_id));
if(accept && drop)
{
if (inv_item->getType() == LLAssetType::AT_GESTURE
@@ -2748,8 +2839,28 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
}
}
- LLUUID favorites_id = model->findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
- if (favorites_id == mUUID) // if target is the favorites folder we use copy
+ // if dragging from/into favorites folder only reorder items
+ if ((mUUID == inv_item->getParentUUID()) && (favorites_id == mUUID))
+ {
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLIsType is_type(LLAssetType::AT_LANDMARK);
+ model->collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
+
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
+ if (itemp)
+ {
+ LLUUID srcItemId = inv_item->getUUID();
+ LLUUID destItemId = itemp->getListener()->getUUID();
+
+ // update order
+ updateItemsOrder(items, srcItemId, destItemId);
+
+ saveItemsOrder(items);
+ }
+ }
+ else if (favorites_id == mUUID) // if target is the favorites folder we use copy
{
copy_inventory_item(
gAgent.getID(),
@@ -3023,14 +3134,14 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
items.push_back(std::string("Landmark Separator"));
- items.push_back(std::string("Teleport To Landmark"));
+ items.push_back(std::string("About Landmark"));
// Disable "About Landmark" menu item for
// multiple landmarks selected. Only one landmark
// info panel can be shown at a time.
if ((flags & FIRST_SELECTED_ITEM) == 0)
{
- disabled_items.push_back(std::string("Teleport To Landmark"));
+ disabled_items.push_back(std::string("About Landmark"));
}
hideContextEntries(menu, items, disabled_items);
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index bc950520aa..d1d2c57f07 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -120,6 +120,11 @@ protected:
LLInventoryPanel* mIP;
};
+const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type);
+void hideContextEntries(LLMenuGL& menu,
+ const std::vector<std::string> &entries_to_show,
+ const std::vector<std::string> &disabled_entries);
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInvFVBridge (& it's derived classes)
//
@@ -168,13 +173,13 @@ public:
virtual BOOL isItemRenameable() const { return TRUE; }
//virtual BOOL renameItem(const std::string& new_name) {}
virtual BOOL isItemRemovable();
- virtual BOOL isItemMovable();
+ virtual BOOL isItemMovable() const;
//virtual BOOL removeItem() = 0;
virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch);
virtual void move(LLFolderViewEventListener* new_parent_bridge) {}
virtual BOOL isItemCopyable() const { return FALSE; }
virtual BOOL copyToClipboard() const { return FALSE; }
- virtual void cutToClipboard() {}
+ virtual void cutToClipboard();
virtual BOOL isClipboardPasteable() const;
virtual BOOL isClipboardPasteableAsLink() const;
virtual void pasteFromClipboard() {}
@@ -221,6 +226,22 @@ protected:
void purgeItem(LLInventoryModel *model, const LLUUID &uuid);
};
+/**
+ * This class intended to build Folder View Bridge via LLInvFVBridge::createBridge.
+ * It can be overridden with another way of creation necessary Inventory-Folder-View-Bridge.
+ */
+class LLInventoryFVBridgeBuilder
+{
+public:
+ virtual ~LLInventoryFVBridgeBuilder(){}
+ virtual LLInvFVBridge* createBridge(LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags = 0x00) const;
+};
+
class LLItemBridge : public LLInvFVBridge
{
@@ -291,7 +312,7 @@ public:
void* cargo_data);
virtual BOOL isItemRemovable();
- virtual BOOL isItemMovable();
+ virtual BOOL isItemMovable() const ;
virtual BOOL isUpToDate() const;
virtual BOOL isItemCopyable() const;
virtual BOOL isClipboardPasteableAsLink() const;
diff --git a/indra/newview/llinventoryclipboard.cpp b/indra/newview/llinventoryclipboard.cpp
index 94ffcbd457..71a5e12332 100644
--- a/indra/newview/llinventoryclipboard.cpp
+++ b/indra/newview/llinventoryclipboard.cpp
@@ -47,6 +47,7 @@ LLInventoryClipboard LLInventoryClipboard::sInstance;
///----------------------------------------------------------------------------
LLInventoryClipboard::LLInventoryClipboard()
+: mCutMode(false)
{
}
@@ -77,6 +78,16 @@ void LLInventoryClipboard::store(const LLDynamicArray<LLUUID>& inv_objects)
}
}
+void LLInventoryClipboard::cut(const LLUUID& object)
+{
+ if(!mCutMode && !mObjects.empty())
+ {
+ //looks like there are some stored items, reset clipboard state
+ reset();
+ }
+ mCutMode = true;
+ add(object);
+}
void LLInventoryClipboard::retrieve(LLDynamicArray<LLUUID>& inv_objects) const
{
inv_objects.reset();
@@ -90,6 +101,7 @@ void LLInventoryClipboard::retrieve(LLDynamicArray<LLUUID>& inv_objects) const
void LLInventoryClipboard::reset()
{
mObjects.reset();
+ mCutMode = false;
}
// returns true if the clipboard has something pasteable in it.
diff --git a/indra/newview/llinventoryclipboard.h b/indra/newview/llinventoryclipboard.h
index 7a2cf15d62..7e221d650c 100644
--- a/indra/newview/llinventoryclipboard.h
+++ b/indra/newview/llinventoryclipboard.h
@@ -60,6 +60,7 @@ public:
// this method stores an array of objects
void store(const LLDynamicArray<LLUUID>& inventory_objects);
+ void cut(const LLUUID& object);
// this method gets the objects in the clipboard by copying them
// into the array provided.
void retrieve(LLDynamicArray<LLUUID>& inventory_objects) const;
@@ -69,11 +70,13 @@ public:
// returns true if the clipboard has something pasteable in it.
BOOL hasContents() const;
+ bool isCutMode() const { return mCutMode; }
protected:
static LLInventoryClipboard sInstance;
LLDynamicArray<LLUUID> mObjects;
+ bool mCutMode;
public:
// please don't actually call these
diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp
index 7c759e22a8..2e6615dd91 100644
--- a/indra/newview/lllandmarkactions.cpp
+++ b/indra/newview/lllandmarkactions.cpp
@@ -42,16 +42,18 @@
#include "llnotifications.h"
#include "llagent.h"
+#include "llagentui.h"
#include "llinventorymodel.h"
#include "lllandmarklist.h"
#include "llslurl.h"
+#include "llstring.h"
#include "llviewerinventory.h"
#include "llviewerparcelmgr.h"
+#include "llviewerwindow.h"
+#include "llwindow.h"
#include "llworldmap.h"
-#include "lllandmark.h"
-#include "llinventorymodel.h"
-#include "llagentui.h"
+void copy_slurl_to_clipboard_callback(const std::string& slurl);
class LLFetchlLandmarkByPos : public LLInventoryCollectFunctor
{
@@ -303,15 +305,39 @@ void LLLandmarkActions::onRegionResponse(slurl_callback_t cb,
bool LLLandmarkActions::getLandmarkGlobalPos(const LLUUID& landmarkInventoryItemID, LLVector3d& posGlobal)
{
+ LLLandmark* landmark = LLLandmarkActions::getLandmark(landmarkInventoryItemID);
+
+ if (NULL == landmark)
+ return false;
+
+ return landmark->getGlobalPos(posGlobal);
+}
+
+LLLandmark* LLLandmarkActions::getLandmark(const LLUUID& landmarkInventoryItemID)
+{
LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID);
if (NULL == item)
return false;
const LLUUID& asset_id = item->getAssetUUID();
- LLLandmark* landmark = gLandmarkList.getAsset(asset_id, NULL);
+ return gLandmarkList.getAsset(asset_id, NULL);
+}
- if (NULL == landmark)
- return false;
+void LLLandmarkActions::copySLURLtoClipboard(const LLUUID& landmarkInventoryItemID)
+{
+ LLLandmark* landmark = LLLandmarkActions::getLandmark(landmarkInventoryItemID);
+ if(landmark)
+ {
+ LLVector3d global_pos;
+ landmark->getGlobalPos(global_pos);
+ LLLandmarkActions::getSLURLfromPosGlobal(global_pos,&copy_slurl_to_clipboard_callback,true);
+ }
+}
- return landmark->getGlobalPos(posGlobal);
+void copy_slurl_to_clipboard_callback(const std::string& slurl)
+{
+ gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(slurl));
+ LLSD args;
+ args["SLURL"] = slurl;
+ LLNotifications::instance().add("CopySLURL", args);
}
diff --git a/indra/newview/lllandmarkactions.h b/indra/newview/lllandmarkactions.h
index ab8cc4d6a5..e882db0a92 100644
--- a/indra/newview/lllandmarkactions.h
+++ b/indra/newview/lllandmarkactions.h
@@ -35,6 +35,7 @@
#include "llinventorymodel.h"
+class LLLandmark;
/**
* @brief Provides helper functions to manage landmarks
*/
@@ -101,6 +102,20 @@ public:
// *TODO: mantipov: profide callback for cases, when Landmark is not loaded yet.
static bool getLandmarkGlobalPos(const LLUUID& landmarkInventoryItemID, LLVector3d& posGlobal);
+ /**
+ * @brief Retrieve a landmark from gLandmarkList by inventory item's id
+ *
+ * @return pointer to loaded landmark from gLandmarkList or NULL if landmark does not exist.
+ */
+ static LLLandmark* getLandmark(const LLUUID& landmarkInventoryItemID);
+
+ /**
+ * @brief Performs standard action of copying of SLURL from landmark to user's clipboard.
+ * This action requires additional server request. The user will be notified by info message,
+ * when URL is copied .
+ */
+ static void copySLURLtoClipboard(const LLUUID& landmarkInventoryItemID);
+
private:
LLLandmarkActions();
LLLandmarkActions(const LLLandmarkActions&);
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 91862112a0..7160cce5cb 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -48,11 +48,9 @@
#include "llnearbychathandler.h"
#include "llchannelmanager.h"
-//for LLViewerTextEditor support
#include "llagent.h" // gAgent
#include "llfloaterscriptdebug.h"
-#include "llslurl.h"
-#include "llviewertexteditor.h"
+#include "llchathistory.h"
#include "llstylemap.h"
#include "lldraghandle.h"
@@ -64,7 +62,7 @@ LLNearbyChat::LLNearbyChat(const LLSD& key) :
LLFloater(key),
mEChatTearofState(CHAT_PINNED),
mChatCaptionPanel(NULL),
- mChatHistoryEditor(NULL)
+ mChatHistory(NULL)
{
m_isDirty = false;
}
@@ -110,7 +108,7 @@ BOOL LLNearbyChat::postBuild()
gSavedSettings.declareS32("nearbychat_showicons_and_names",2,"NearByChat header settings",true);
mChatCaptionPanel = getChild<LLPanel>("chat_caption", false);
- mChatHistoryEditor = getChild<LLViewerTextEditor>("Chat History Editor");
+ mChatHistory = getChild<LLChatHistory>("chat_history");
reshape(getRect().getWidth(), getRect().getHeight(), FALSE);
@@ -185,44 +183,6 @@ LLColor4 nearbychat_get_text_color(const LLChat& chat)
void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& color)
{
- std::string line = chat.mText;
-
- //chat.mText starts with Avatar Name if entered message was "/me <action>".
- // In this case output chat message should be "<Avatar Name> <action>". See EXT-656
- // See also process_chat_from_simulator() in the llviewermessage.cpp where ircstyle = TRUE;
- if (CHAT_STYLE_IRC != chat.mChatStyle)
- line = chat.mFromName + ": " + line;
-
- bool prepend_newline = true;
- if (gSavedSettings.getBOOL("ChatShowTimestamps"))
- {
- mChatHistoryEditor->appendTime(prepend_newline);
- prepend_newline = false;
- }
-
- // If the msg is from an agent (not yourself though),
- // extract out the sender name and replace it with the hotlinked name.
-
- std::string str_URL = chat.mURL;
-
- if (chat.mSourceType == CHAT_SOURCE_AGENT &&
- chat.mFromID != LLUUID::null)
- {
- str_URL = LLSLURL::buildCommand("agent", chat.mFromID, "inspect");
- }
-
- // If the chat line has an associated url, link it up to the name.
- if (!str_URL.empty()
- && (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0))
- {
- std::string start_line = line.substr(0, chat.mFromName.length() + 1);
- line = line.substr(chat.mFromName.length() + 1);
- mChatHistoryEditor->appendText(start_line, prepend_newline,
- LLStyleMap::instance().lookup(chat.mFromID,str_URL));
- mChatHistoryEditor->blockUndo();
- prepend_newline = false;
- }
-
S32 font_size = gSavedSettings.getS32("ChatFontSize");
const LLFontGL* fontp = NULL;
@@ -240,8 +200,14 @@ void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& colo
break;
}
- mChatHistoryEditor->appendText(line, prepend_newline, LLStyle::Params().color(color).font(fontp));
- mChatHistoryEditor->blockUndo();
+ LLStyle::Params style_params;
+ style_params.color(color);
+ style_params.font(fontp);
+ LLUUID uuid = chat.mFromID;
+ std::string from = chat.mFromName;
+ std::string time = "";
+ std::string message = chat.mText;
+ mChatHistory->appendWidgetMessage(uuid, from, time, message, style_params);
}
void LLNearbyChat::addMessage(const LLChat& chat)
@@ -315,7 +281,7 @@ void LLNearbyChat::reshape(S32 width, S32 height, BOOL called_from_parent)
mResizeBar[LLResizeBar::RIGHT]->setRect(resize_rect);
}
- // *NOTE: we must check mChatCaptionPanel and mChatHistoryEditor against NULL because reshape is called from the
+ // *NOTE: we must check mChatCaptionPanel and mChatHistory against NULL because reshape is called from the
// LLView::initFromParams BEFORE postBuild is called and child controls are not exist yet
LLRect caption_rect;
if (NULL != mChatCaptionPanel)
@@ -326,12 +292,12 @@ void LLNearbyChat::reshape(S32 width, S32 height, BOOL called_from_parent)
mChatCaptionPanel->setRect(caption_rect);
}
- if (NULL != mChatHistoryEditor)
+ if (NULL != mChatHistory)
{
- LLRect scroll_rect = mChatHistoryEditor->getRect();
+ LLRect scroll_rect = mChatHistory->getRect();
scroll_rect.setLeftTopAndSize( 2, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS, width - 4, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS*2);
- mChatHistoryEditor->reshape( width - 4, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS*2, 1);
- mChatHistoryEditor->setRect(scroll_rect);
+ mChatHistory->reshape( width - 4, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS*2, 1);
+ mChatHistory->setRect(scroll_rect);
}
//
diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h
index 7c8ffa3b94..47cae8ed0d 100644
--- a/indra/newview/llnearbychat.h
+++ b/indra/newview/llnearbychat.h
@@ -38,7 +38,7 @@
#include "llchat.h"
class LLResizeBar;
-class LLViewerTextEditor;
+class LLChatHistory;
class LLNearbyChat: public LLFloater
{
@@ -89,7 +89,7 @@ private:
LLHandle<LLView> mPopupMenuHandle;
LLPanel* mChatCaptionPanel;
- LLViewerTextEditor* mChatHistoryEditor;
+ LLChatHistory* mChatHistory;
bool m_isDirty;
};
diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp
index 5186a93569..c08f92b983 100644
--- a/indra/newview/llnotificationtiphandler.cpp
+++ b/indra/newview/llnotificationtiphandler.cpp
@@ -33,6 +33,8 @@
#include "llviewerprecompiledheaders.h" // must be first include
+#include "llfloaterreg.h"
+#include "llnearbychat.h"
#include "llnotificationhandler.h"
#include "lltoastnotifypanel.h"
#include "llviewercontrol.h"
@@ -96,6 +98,14 @@ bool LLTipHandler::processNotification(const LLSD& notify)
LLScreenChannel* channel = dynamic_cast<LLScreenChannel*>(mChannel);
if(channel)
channel->addToast(p);
+
+ // archive message in nearby chat
+ LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+ if(nearby_chat)
+ {
+ LLChat chat_msg(notification->getMessage());
+ nearby_chat->addMessage(chat_msg);
+ }
}
else if (notify["sigtype"].asString() == "delete")
{
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index 3a3ea1fc3c..7670a5120c 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -43,6 +43,7 @@
#include "lltexturectrl.h"
#include "lltooldraganddrop.h"
#include "llscrollcontainer.h"
+#include "llavatariconctrl.h"
#include "llweb.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -447,6 +448,10 @@ void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_g
void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data)
{
+ //remove avatar id from cache to get fresh info
+ LLAvatarIconIDCache::getInstance()->remove(avatar_data->avatar_id);
+
+
childSetValue("register_date", avatar_data->born_on );
childSetValue("sl_description_edit", avatar_data->about_text);
childSetValue("fl_description_edit",avatar_data->fl_about_text);
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 1d79ea4a21..5f96407d7d 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -35,32 +35,50 @@
#include "llbutton.h"
#include "llfloaterreg.h"
-#include "lllandmark.h"
+#include "llsdutil.h"
+#include "llaccordionctrltab.h"
+#include "llagent.h"
+#include "llagentui.h"
#include "llfloaterworldmap.h"
-#include "llfloaterinventory.h"
-#include "llfoldervieweventlistener.h"
-#include "lllandmarklist.h"
+#include "llfolderviewitem.h"
+#include "llinventorysubtreepanel.h"
+#include "lllandmarkactions.h"
+#include "llplacesinventorybridge.h"
#include "llsidetray.h"
-#include "lltabcontainer.h"
-#include "llworldmap.h"
+#include "llviewermenu.h"
+#include "llviewerregion.h"
// Not yet implemented; need to remove buildPanel() from constructor when we switch
//static LLRegisterPanelClassWrapper<LLLandmarksPanel> t_landmarks("panel_landmarks");
+static const std::string OPTIONS_BUTTON_NAME = "options_gear_btn";
+static const std::string ADD_LANDMARK_BUTTON_NAME = "add_landmark_btn";
+static const std::string ADD_FOLDER_BUTTON_NAME = "add_folder_btn";
+static const std::string TRASH_BUTTON_NAME = "trash_btn";
+
+static const LLPlacesInventoryBridgeBuilder PLACES_INVENTORY_BUILDER;
+
+// helper functions
+static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string);
+
+
LLLandmarksPanel::LLLandmarksPanel()
- : LLPanelPlacesTab(),
- mInventoryPanel(NULL)
+ : LLPanelPlacesTab()
+ , mFavoritesInventoryPanel(NULL)
+ , mLandmarksInventoryPanel(NULL)
+ , mMyInventoryPanel(NULL)
+ , mLibraryInventoryPanel(NULL)
+ , mCurrentSelectedList(NULL)
+ , mListCommands(NULL)
+ , mGearFolderMenu(NULL)
+ , mGearLandmarkMenu(NULL)
{
- mSavedFolderState = new LLSaveFolderState();
- mSavedFolderState->setApply(FALSE);
-
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_landmarks.xml");
}
LLLandmarksPanel::~LLLandmarksPanel()
{
- delete mSavedFolderState;
}
BOOL LLLandmarksPanel::postBuild()
@@ -68,19 +86,13 @@ BOOL LLLandmarksPanel::postBuild()
if (!gInventory.isInventoryUsable())
return FALSE;
- mInventoryPanel = getChild<LLInventoryPanel>("landmarks_list");
- mInventoryPanel->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK);
- mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
- mInventoryPanel->openDefaultFolderForType(LLAssetType::AT_LANDMARK);
- mInventoryPanel->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, _1, _2));
+ // mast be called before any other initXXX methods to init Gear menu
+ initListCommandsHandlers();
- LLFolderView* root_folder = mInventoryPanel->getRootFolder();
- root_folder->setReshapeCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, _1, _2));
-
- mActionBtn = getChild<LLButton>("selector");
- root_folder->addChild(mActionBtn);
- mActionBtn->setEnabled(TRUE);
- childSetAction("selector", boost::bind(&LLLandmarksPanel::onSelectorButtonClicked, this), this);
+ initFavoritesInventroyPanel();
+ initLandmarksInventroyPanel();
+ initMyInventroyPanel();
+ initLibraryInventroyPanel();
return TRUE;
}
@@ -88,53 +100,21 @@ BOOL LLLandmarksPanel::postBuild()
// virtual
void LLLandmarksPanel::onSearchEdit(const std::string& string)
{
- if (string == "")
- {
- mInventoryPanel->setFilterSubString(LLStringUtil::null);
-
- // re-open folders that were initially open
- mSavedFolderState->setApply(TRUE);
- mInventoryPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
- LLOpenFoldersWithSelection opener;
- mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener);
- mInventoryPanel->getRootFolder()->scrollToShowSelection();
- }
-
- gInventory.startBackgroundFetch();
-
- if (mInventoryPanel->getFilterSubString().empty() && string.empty())
- {
- // current filter and new filter empty, do nothing
- return;
- }
-
- // save current folder open state if no filter currently applied
- if (mInventoryPanel->getRootFolder()->getFilterSubString().empty())
- {
- mSavedFolderState->setApply(FALSE);
- mInventoryPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
- }
-
- // set new filter string
- mInventoryPanel->setFilterSubString(string);
+ filter_list(mFavoritesInventoryPanel, string);
+ filter_list(mLandmarksInventoryPanel, string);
+ filter_list(mMyInventoryPanel, string);
+ filter_list(mLibraryInventoryPanel, string);
}
// virtual
void LLLandmarksPanel::onShowOnMap()
{
- LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
- if (!current_item)
- return;
-
- LLFolderViewEventListener* listenerp = current_item->getListener();
- if (listenerp->getInventoryType() != LLInventoryType::IT_LANDMARK)
- return;
-
- LLInventoryItem* inventory_item = gInventory.getItem(listenerp->getUUID());
- if (!inventory_item)
+ if (NULL == mCurrentSelectedList)
+ {
+ llwarns << "There are no selected list. No actions are performed." << llendl;
return;
-
- LLLandmark* landmark = gLandmarkList.getAsset(inventory_item->getAssetUUID());
+ }
+ LLLandmark* landmark = getCurSelectedLandmark();
if (!landmark)
return;
@@ -153,9 +133,12 @@ void LLLandmarksPanel::onShowOnMap()
// virtual
void LLLandmarksPanel::onTeleport()
{
- LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
+ LLFolderViewItem* current_item = getCurSelectedItem();
if (!current_item)
+ {
+ llwarns << "There are no selected list. No actions are performed." << llendl;
return;
+ }
LLFolderViewEventListener* listenerp = current_item->getListener();
if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
@@ -164,117 +147,546 @@ void LLLandmarksPanel::onTeleport()
}
}
-/*
// virtual
-void LLLandmarksPanel::onCopySLURL()
+void LLLandmarksPanel::updateVerbs()
{
- LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
- if (!current_item)
+ if (!isTabVisible())
return;
- LLFolderViewEventListener* listenerp = current_item->getListener();
- if (listenerp->getInventoryType() != LLInventoryType::IT_LANDMARK)
- return;
+ BOOL enabled = isLandmarkSelected();
+ mTeleportBtn->setEnabled(enabled);
+ mShowOnMapBtn->setEnabled(enabled);
- LLInventoryItem* inventory_item = gInventory.getItem(listenerp->getUUID());
- if (!inventory_item)
- return;
+ // TODO: mantipov: Uncomment when mShareBtn is supported
+ // Share button should be enabled when neither a folder nor a landmark is selected
+ //mShareBtn->setEnabled(NULL != current_item);
- LLLandmark* landmark = gLandmarkList.getAsset(inventory_item->getAssetUUID());
- if (!landmark)
- return;
+ updateListCommands();
+}
- LLVector3d landmark_global_pos;
- if (!landmark->getGlobalPos(landmark_global_pos))
+void LLLandmarksPanel::onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
+{
+ if (user_action && (items.size() > 0))
+ {
+ deselectOtherThan(inventory_list);
+ mCurrentSelectedList = inventory_list;
+ }
+
+ LLFolderViewItem* current_item = inventory_list->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
return;
- U64 new_region_handle = to_region_handle(landmark_global_pos);
+ updateVerbs();
+}
+
+void LLLandmarksPanel::onSelectorButtonClicked()
+{
+ // TODO: mantipov: update getting of selected item
+ // TODO: bind to "i" button
+ LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem();
- LLWorldMap::url_callback_t cb = boost::bind(
- &LLPanelPlacesTab::onRegionResponse, this,
- landmark_global_pos, _1, _2, _3, _4);
+ LLFolderViewEventListener* listenerp = cur_item->getListener();
+ if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+ LLSD key;
+ key["type"] = "landmark";
+ key["id"] = listenerp->getUUID();
- LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, cb, std::string("unused"), false);
+ LLSideTray::getInstance()->showPanel("panel_places", key);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// PROTECTED METHODS
+//////////////////////////////////////////////////////////////////////////
+
+bool LLLandmarksPanel::isLandmarkSelected() const
+{
+ LLFolderViewItem* current_item = getCurSelectedItem();
+ if(current_item && current_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+LLLandmark* LLLandmarksPanel::getCurSelectedLandmark() const
+{
+
+ LLFolderViewItem* cur_item = getCurSelectedItem();
+ if(cur_item && cur_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+ return LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID());
+ }
+ return NULL;
+}
+
+LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem () const
+{
+ return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL;
}
-*/
// virtual
-void LLLandmarksPanel::updateVerbs()
+void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)
{
- if (!isTabVisible())
- return;
+ //this function will be called after user will try to create a pick for selected landmark.
+ // We have to make request to sever to get parcel_id and snaption_id.
+ if(isLandmarkSelected())
+ {
+ LLLandmark* landmark = getCurSelectedLandmark();
+ LLFolderViewItem* cur_item = getCurSelectedItem();
+ LLUUID id = cur_item->getListener()->getUUID();
+ LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id);
+ if(landmark)
+ {
+ LLPanelPick* panel_pick = new LLPanelPick(TRUE);
+ LLSD params;
+ LLVector3d landmark_global_pos;
+ landmark->getGlobalPos(landmark_global_pos);
+ panel_pick->prepareNewPick(landmark_global_pos,cur_item->getName(),inv_item->getDescription(),
+ parcel_data.snapshot_id,parcel_data.parcel_id);
+ // by default save button should be enabled
+ panel_pick->childSetEnabled("save_changes_btn", TRUE);
+ // let's toggle pick panel into panel places
+ LLPanel* panel_places = LLSideTray::getInstance()->getChild<LLPanel>("panel_places");//-> sidebar_places
+ panel_places->addChild(panel_pick);
+ LLRect paren_rect(panel_places->getRect());
+ panel_pick->reshape(paren_rect.getWidth(),paren_rect.getHeight(), TRUE);
+ panel_pick->setRect(paren_rect);
+ params["parcel_id"] =parcel_data.parcel_id;
+ /* set exit callback to get back onto panel places
+ in callback we will make cleaning up( delete pick_panel instance,
+ remove landmark panel from observer list
+ */
+ panel_pick->setExitCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
+ panel_pick, panel_places,params));
+ }
+ }
+}
+
+// virtual
+void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id)
+{
+ if (!parcel_id.isNull())
+ {
+ LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
+ LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
+ }
+}
+
+// virtual
+void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason)
+{
+ llerrs<< "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// PRIVATE METHODS
+//////////////////////////////////////////////////////////////////////////
+
+void LLLandmarksPanel::initFavoritesInventroyPanel()
+{
+ mFavoritesInventoryPanel = getChild<LLInventorySubTreePanel>("favorites_list");
+
+ LLUUID start_folder_id = mFavoritesInventoryPanel->getModel()->findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
+
+ initLandmarksPanel(mFavoritesInventoryPanel, start_folder_id);
+
+ initAccordion("tab_favorites", mFavoritesInventoryPanel);
+}
+
+void LLLandmarksPanel::initLandmarksInventroyPanel()
+{
+ mLandmarksInventoryPanel = getChild<LLInventorySubTreePanel>("landmarks_list");
+
+ LLUUID start_folder_id = mLandmarksInventoryPanel->getModel()->findCategoryUUIDForType(LLAssetType::AT_LANDMARK);
+
+ initLandmarksPanel(mLandmarksInventoryPanel, start_folder_id);
+ mLandmarksInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS);
+
+ // subscribe to have auto-rename functionality while creating New Folder
+ mLandmarksInventoryPanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mLandmarksInventoryPanel, _1, _2));
+
+ initAccordion("tab_landmarks", mLandmarksInventoryPanel);
+}
+
+void LLLandmarksPanel::initMyInventroyPanel()
+{
+ mMyInventoryPanel= getChild<LLInventorySubTreePanel>("my_inventory_list");
+
+ LLUUID start_folder_id = mMyInventoryPanel->getModel()->getRootFolderID();
+
+ initLandmarksPanel(mMyInventoryPanel, start_folder_id);
+
+ initAccordion("tab_inventory", mMyInventoryPanel);
+}
+
+void LLLandmarksPanel::initLibraryInventroyPanel()
+{
+ mLibraryInventoryPanel = getChild<LLInventorySubTreePanel>("library_list");
+
+ LLUUID start_folder_id = mLibraryInventoryPanel->getModel()->getLibraryRootFolderID();
+
+ initLandmarksPanel(mLibraryInventoryPanel, start_folder_id);
+
+ initAccordion("tab_library", mLibraryInventoryPanel);
+}
+
+
+void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_list, const LLUUID& start_folder_id)
+{
+ inventory_list->buildSubtreeViewsFor(start_folder_id, &PLACES_INVENTORY_BUILDER);
+
+ inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK);
+ inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2));
+
+ inventory_list->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+
+ LLPlacesFolderView* root_folder = dynamic_cast<LLPlacesFolderView*>(inventory_list->getRootFolder());
+ if (root_folder)
+ {
+ root_folder->setupMenuHandle(LLInventoryType::IT_CATEGORY, mGearFolderMenu->getHandle());
+ root_folder->setupMenuHandle(LLInventoryType::IT_LANDMARK, mGearLandmarkMenu->getHandle());
+ }
+}
+
+void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list)
+{
+ LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name);
+ accordion_tab->setDropDownStateChangedCallback(
+ boost::bind(&LLLandmarksPanel::onAccordionExpandedCollapsed, this, _2, inventory_list));
+}
+
+void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list)
+{
+ bool expanded = param.asBoolean();
+
+ if(!expanded && (mCurrentSelectedList == inventory_list))
+ {
+ inventory_list->getRootFolder()->clearSelection();
+
+ mCurrentSelectedList = NULL;
+ updateVerbs();
+ }
+}
+
+void LLLandmarksPanel::deselectOtherThan(const LLInventorySubTreePanel* inventory_list)
+{
+ if (inventory_list != mFavoritesInventoryPanel)
+ {
+ mFavoritesInventoryPanel->getRootFolder()->clearSelection();
+ }
+
+ if (inventory_list != mLandmarksInventoryPanel)
+ {
+ mLandmarksInventoryPanel->getRootFolder()->clearSelection();
+ }
+ if (inventory_list != mMyInventoryPanel)
+ {
+ mMyInventoryPanel->getRootFolder()->clearSelection();
+ }
+ if (inventory_list != mLibraryInventoryPanel)
+ {
+ mLibraryInventoryPanel->getRootFolder()->clearSelection();
+ }
+}
+
+// List Commands Handlers
+void LLLandmarksPanel::initListCommandsHandlers()
+{
+ mListCommands = getChild<LLPanel>("bottom_panel");
- BOOL enabled = FALSE;
+ mListCommands->childSetAction(OPTIONS_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onActionsButtonClick, this));
+ mListCommands->childSetAction(ADD_LANDMARK_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddLandmarkButtonClick, this));
+ mListCommands->childSetAction(ADD_FOLDER_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddFolderButtonClick, this));
+ mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this));
+
+
+ mCommitCallbackRegistrar.add("Places.LandmarksGear.Add.Action", boost::bind(&LLLandmarksPanel::onAddAction, this, _2));
+ mCommitCallbackRegistrar.add("Places.LandmarksGear.CopyPaste.Action", boost::bind(&LLLandmarksPanel::onCopyPasteAction, this, _2));
+ mCommitCallbackRegistrar.add("Places.LandmarksGear.Custom.Action", boost::bind(&LLLandmarksPanel::onCustomAction, this, _2));
+ mCommitCallbackRegistrar.add("Places.LandmarksGear.Folding.Action", boost::bind(&LLLandmarksPanel::onFoldingAction, this, _2));
+ mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2));
+ mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+}
+
+
+void LLLandmarksPanel::updateListCommands()
+{
+ // TODO: should be false when "Received" folder is selected
+ bool add_folder_enabled = mCurrentSelectedList == mLandmarksInventoryPanel;
+ bool trash_enabled = false; // TODO: should be false when "Received" folder is selected
+
+ LLFolderViewItem* current_item = getCurSelectedItem();
- LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
if (current_item)
{
LLFolderViewEventListener* listenerp = current_item->getListener();
if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
{
- enabled = TRUE;
+ trash_enabled = mCurrentSelectedList != mLibraryInventoryPanel;
}
}
- mTeleportBtn->setEnabled(enabled);
- mShowOnMapBtn->setEnabled(enabled);
+ // keep Options & Add Landmark buttons always enabled
+ mListCommands->childSetEnabled(ADD_FOLDER_BUTTON_NAME, add_folder_enabled);
+ mListCommands->childSetEnabled(TRASH_BUTTON_NAME, trash_enabled);
}
-void LLLandmarksPanel::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
+void LLLandmarksPanel::onActionsButtonClick()
{
- LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
- if (!current_item)
+ LLFolderViewItem* cur_item = NULL;
+ if(mCurrentSelectedList)
+ cur_item = mCurrentSelectedList->getRootFolder()->getCurSelectedItem();
+
+ if(!cur_item)
return;
-
- LLFolderViewEventListener* listenerp = current_item->getListener();
+
+ LLFolderViewEventListener* listenerp = cur_item->getListener();
+
+ LLMenuGL* menu =NULL;
if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
{
- S32 bottom = 0;
- LLFolderViewItem* folder = current_item->getParentFolder();
+ menu = mGearLandmarkMenu;
+ }
+ else if (listenerp->getInventoryType() == LLInventoryType::IT_CATEGORY)
+ {
+ mGearFolderMenu->getChild<LLMenuItemCallGL>("expand")->setVisible(!cur_item->isOpen());
+ mGearFolderMenu->getChild<LLMenuItemCallGL>("collapse")->setVisible(cur_item->isOpen());
+ menu = mGearFolderMenu;
+ }
+ if(menu)
+ {
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLView* actions_btn = getChild<LLView>(OPTIONS_BUTTON_NAME);
+ S32 menu_x, menu_y;
+ actions_btn->localPointToOtherView(0,actions_btn->getRect().getHeight(),&menu_x,&menu_y, this);
+ menu_y += menu->getRect().getHeight();
+ LLMenuGL::showPopup(this, menu, menu_x,menu_y);
+ }
+}
- while ( folder->getParentFolder() != NULL )
+void LLLandmarksPanel::onAddLandmarkButtonClick() const
+{
+ if(LLLandmarkActions::landmarkAlreadyExists())
+ {
+ std::string location;
+ LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_FULL);
+ llwarns<<" Landmark already exists at location: "<< location<<llendl;
+ return;
+ }
+ LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark"));
+}
+
+void LLLandmarksPanel::onAddFolderButtonClick() const
+{
+ LLFolderViewItem* item = getCurSelectedItem();
+ if(item && mCurrentSelectedList == mLandmarksInventoryPanel)
+ {
+ LLFolderBridge *parentBridge = NULL;
+ if(item-> getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+ parentBridge = dynamic_cast<LLFolderBridge*>(item->getParentFolder()->getListener());
+ /*WORKAROUND:*
+ LLFolderView::doIdle() is calling in each frame,
+ it changes selected items before LLFolderView::startRenamingSelectedItem.
+ To avoid it we have to change keyboardFocus.
+ */
+ gFocusMgr.setKeyboardFocus(item->getParentFolder());
+ }
+ else if (item-> getListener()->getInventoryType() == LLInventoryType::IT_CATEGORY)
{
- bottom += folder->getRect().mBottom;
- folder = folder->getParentFolder();
+ parentBridge = dynamic_cast<LLFolderBridge*>(item->getListener());
+ gFocusMgr.setKeyboardFocus(item);
}
+ menu_create_inventory_item(mCurrentSelectedList->getRootFolder(),parentBridge, LLSD("category"));
+ }
+}
- LLRect rect = current_item->getRect();
- LLRect btn_rect(
- rect.mRight - mActionBtn->getRect().getWidth(),
- bottom + rect.mTop,
- rect.mRight,
- bottom + rect.mBottom);
+void LLLandmarksPanel::onTrashButtonClick() const
+{
+ if(!mCurrentSelectedList) return;
- mActionBtn->setRect(btn_rect);
+ mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(), "delete");
+}
- if (!mActionBtn->getVisible())
- mActionBtn->setVisible(TRUE);
+void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
+{
+ std::string command_name = userdata.asString();
+ if("add_landmark" == command_name)
+ {
+ onAddLandmarkButtonClick();
+ }
+ else if ("category" == command_name)
+ {
+ onAddFolderButtonClick();
+ }
+}
+
+void LLLandmarksPanel::onCopyPasteAction(const LLSD& userdata) const
+{
+ if(!mCurrentSelectedList)
+ return;
+ std::string command_name = userdata.asString();
+ if("copy_slurl" == command_name)
+ {
+ LLFolderViewItem* cur_item = getCurSelectedItem();
+ if(cur_item)
+ LLLandmarkActions::copySLURLtoClipboard(cur_item->getListener()->getUUID());
+ }
+ else if ( "paste" == command_name)
+ {
+ mCurrentSelectedList->getRootFolder()->paste();
+ }
+ else if ( "cut" == command_name)
+ {
+ mCurrentSelectedList->getRootFolder()->cut();
}
else
{
- if (mActionBtn->getVisible())
- mActionBtn->setVisible(FALSE);
+ mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(),command_name);
}
-
- updateVerbs();
}
-void LLLandmarksPanel::onSelectorButtonClicked()
+void LLLandmarksPanel::onFoldingAction(const LLSD& userdata) const
{
- LLFolderViewItem* cur_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
+ if(!mCurrentSelectedList) return;
- LLFolderViewEventListener* listenerp = cur_item->getListener();
- if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ LLFolderView* root_folder = mCurrentSelectedList->getRootFolder();
+ std::string command_name = userdata.asString();
+
+ if ("expand_all" == command_name)
{
- LLSD key;
- key["type"] = "landmark";
- key["id"] = listenerp->getUUID();
+ root_folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN);
+ root_folder->arrangeAll();
+ }
+ else if ("collapse_all" == command_name)
+ {
+ root_folder->closeAllFolders();
+ }
+ else
+ {
+ root_folder->doToSelected(&gInventory, userdata);
+ }
+}
- LLSideTray::getInstance()->showPanel("panel_places", key);
+bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
+{
+ std::string command_name = userdata.asString();
+ if("category" == command_name)
+ {
+ return mCurrentSelectedList == mLandmarksInventoryPanel;
+ }
+ else if("paste" == command_name)
+ {
+ return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->canPaste() : false;
+ }
+ return true;
+}
+
+void LLLandmarksPanel::onCustomAction(const LLSD& userdata)
+{
+ LLFolderViewItem* cur_item = getCurSelectedItem();
+ if(!cur_item)
+ return ;
+ std::string command_name = userdata.asString();
+ if("more_info" == command_name)
+ {
+ cur_item->getListener()->performAction(mCurrentSelectedList->getRootFolder(),mCurrentSelectedList->getModel(),"about");
}
+ else if ("teleport" == command_name)
+ {
+ onTeleport();
+ }
+ else if ("show_on_map" == command_name)
+ {
+ onShowOnMap();
+ }
+ else if ("create_pick" == command_name)
+ {
+ LLLandmark* landmark = getCurSelectedLandmark();
+ if(!landmark) return;
+
+ LLViewerRegion* region = gAgent.getRegion();
+ if (!region) return;
+
+ LLGlobalVec pos_global;
+ LLUUID region_id;
+ landmark->getGlobalPos(pos_global);
+ landmark->getRegionID(region_id);
+ LLVector3 region_pos((F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS),
+ (F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS),
+ (F32)pos_global.mdV[VZ]);
+
+ LLSD body;
+ std::string url = region->getCapability("RemoteParcelRequest");
+ if (!url.empty())
+ {
+ body["location"] = ll_sd_from_vector3(region_pos);
+ if (!region_id.isNull())
+ {
+ body["region_id"] = region_id;
+ }
+ if (!pos_global.isExactlyZero())
+ {
+ U64 region_handle = to_region_handle(pos_global);
+ body["region_handle"] = ll_sd_from_U64(region_handle);
+ }
+ LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle()));
+ }
+ else
+ {
+ llwarns << "Can't create pick for landmark for region" << region_id
+ << ". Region: " << region->getName()
+ << " does not support RemoteParcelRequest" << llendl;
+ }
+ }
+}
+
+void LLLandmarksPanel::onPickPanelExit( LLPanelPick* pick_panel, LLView* owner, const LLSD& params)
+{
+ pick_panel->setVisible(FALSE);
+ owner->removeChild(pick_panel);
+ //we need remove observer to avoid processParcelInfo in the future.
+ LLRemoteParcelInfoProcessor::getInstance()->removeObserver(params["parcel_id"].asUUID(), this);
+
+ delete pick_panel;
+ pick_panel = NULL;
}
-void LLLandmarksPanel::setSelectedItem(const LLUUID& obj_id)
+
+//////////////////////////////////////////////////////////////////////////
+// HELPER FUNCTIONS
+//////////////////////////////////////////////////////////////////////////
+static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string)
{
- mInventoryPanel->setSelection(obj_id, FALSE);
+ if (string == "")
+ {
+ inventory_list->setFilterSubString(LLStringUtil::null);
+
+ // re-open folders that were initially open
+ inventory_list->restoreFolderState();
+ }
+
+ gInventory.startBackgroundFetch();
+
+ if (inventory_list->getFilterSubString().empty() && string.empty())
+ {
+ // current filter and new filter empty, do nothing
+ return;
+ }
+
+ // save current folder open state if no filter currently applied
+ if (inventory_list->getRootFolder()->getFilterSubString().empty())
+ {
+ inventory_list->saveFolderState();
+ }
+
+ // set new filter string
+ inventory_list->setFilterSubString(string);
}
+// EOF
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index 14cbbd6123..e74a7fdc88 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -33,14 +33,20 @@
#ifndef LL_LLPANELLANDMARKS_H
#define LL_LLPANELLANDMARKS_H
+#include "lllandmark.h"
+
+// newview
#include "llinventorymodel.h"
#include "llpanelplacestab.h"
+#include "llpanelpick.h"
+#include "llremoteparcelrequest.h"
class LLFolderViewItem;
+class LLMenuGL;
class LLInventoryPanel;
-class LLSaveFolderState;
+class LLInventorySubTreePanel;
-class LLLandmarksPanel : public LLPanelPlacesTab
+class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
{
public:
LLLandmarksPanel();
@@ -50,17 +56,58 @@ public:
/*virtual*/ void onSearchEdit(const std::string& string);
/*virtual*/ void onShowOnMap();
/*virtual*/ void onTeleport();
- ///*virtual*/ void onCopySLURL();
/*virtual*/ void updateVerbs();
- void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+ void onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action);
void onSelectorButtonClicked();
- void setSelectedItem(const LLUUID& obj_id);
+
+protected:
+ /**
+ * @return true - if current selected panel is not null and selected item is a landmark
+ */
+ bool isLandmarkSelected() const;
+ LLLandmark* getCurSelectedLandmark() const;
+ LLFolderViewItem* getCurSelectedItem () const;
+ //LLRemoteParcelInfoObserver interface
+ /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
+ /*virtual*/ void setParcelID(const LLUUID& parcel_id);
+ /*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+
private:
- LLInventoryPanel* mInventoryPanel;
- LLSaveFolderState* mSavedFolderState;
- LLButton* mActionBtn;
+ void initFavoritesInventroyPanel();
+ void initLandmarksInventroyPanel();
+ void initMyInventroyPanel();
+ void initLibraryInventroyPanel();
+ void initLandmarksPanel(LLInventorySubTreePanel* inventory_list, const LLUUID& start_folder_id);
+ void initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list);
+ void onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list);
+ void deselectOtherThan(const LLInventorySubTreePanel* inventory_list);
+
+ // List Commands Handlers
+ void initListCommandsHandlers();
+ void updateListCommands();
+ void onActionsButtonClick();
+ void onAddLandmarkButtonClick() const;
+ void onAddFolderButtonClick() const;
+ void onTrashButtonClick() const;
+ void onAddAction(const LLSD& command_name) const;
+ void onCopyPasteAction(const LLSD& command_name) const;
+ void onFoldingAction(const LLSD& command_name) const;
+ bool isActionEnabled(const LLSD& command_name) const;
+ void onCustomAction(const LLSD& command_name);
+ void onPickPanelExit( LLPanelPick* pick_panel, LLView* owner, const LLSD& params);
+
+private:
+ LLInventorySubTreePanel* mFavoritesInventoryPanel;
+ LLInventorySubTreePanel* mLandmarksInventoryPanel;
+ LLInventorySubTreePanel* mMyInventoryPanel;
+ LLInventorySubTreePanel* mLibraryInventoryPanel;
+ LLMenuGL* mGearLandmarkMenu;
+ LLMenuGL* mGearFolderMenu;
+ LLInventorySubTreePanel* mCurrentSelectedList;
+
+ LLPanel* mListCommands;
};
#endif //LL_LLPANELLANDMARKS_H
diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h
index 82cba72bc4..7cc2a04c53 100644
--- a/indra/newview/llpanelpick.h
+++ b/indra/newview/llpanelpick.h
@@ -39,6 +39,7 @@
#include "llpanel.h"
#include "llremoteparcelrequest.h"
+#include "llavatarpropertiesprocessor.h"
class LLTextureCtrl;
class LLMessageSystem;
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index d415b17538..b2541ac1b0 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -650,6 +650,23 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param)
mPlaceInfo->createPick(mPosGlobal, mPickPanel);
}
+ else if (item == "add_to_favbar")
+ {
+ if ( mItem.notNull() )
+ {
+ LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
+ if ( favorites_id.notNull() )
+ {
+ copy_inventory_item(gAgent.getID(),
+ mItem->getPermissions().getOwner(),
+ mItem->getUUID(),
+ favorites_id,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ llinfos << "Copied inventory item #" << mItem->getUUID() << " to favorites." << llendl;
+ }
+ }
+ }
}
void LLPanelPlaces::onBackButtonClicked()
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index e1e3fe4677..96efb885dd 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -47,6 +47,10 @@
#include "lllandmarkactions.h"
#include "llclipboard.h"
+// Maximum number of items that can be added to a list in one pass.
+// Used to limit time spent for items list update per frame.
+static const U32 ADD_LIMIT = 50;
+
class LLTeleportHistoryFlatItem : public LLPanel
{
public:
@@ -56,6 +60,7 @@ public:
virtual BOOL postBuild();
S32 getIndex() { return mIndex; }
+ const std::string& getRegionName() { return mRegionName;}
/*virtual*/ void setValue(const LLSD& value);
@@ -211,9 +216,10 @@ void LLTeleportHistoryPanel::ContextMenu::onCopy()
LLTeleportHistoryPanel::LLTeleportHistoryPanel()
: LLPanelPlacesTab(),
mFilterSubString(LLStringUtil::null),
+ mDirty(true),
+ mCurrentItem(0),
mTeleportHistory(NULL),
mHistoryAccordion(NULL),
- mStarButton(NULL),
mAccordionTabMenu(NULL),
mLastSelectedScrollList(NULL)
{
@@ -277,13 +283,19 @@ BOOL LLTeleportHistoryPanel::postBuild()
if(gear_menu)
mGearMenuHandle = gear_menu->getHandle();
- mStarButton = getChild<LLButton>("star_btn");
- mStarButton->setCommitCallback(boost::bind(&LLTeleportHistoryPanel::onStarButtonCommit, this));
-
return TRUE;
}
// virtual
+void LLTeleportHistoryPanel::draw()
+{
+ if (mDirty)
+ refresh();
+
+ LLPanelPlacesTab::draw();
+}
+
+// virtual
void LLTeleportHistoryPanel::onSearchEdit(const std::string& string)
{
if (mFilterSubString != string)
@@ -361,8 +373,6 @@ void LLTeleportHistoryPanel::updateVerbs()
{
mTeleportBtn->setEnabled(false);
mShowOnMapBtn->setEnabled(false);
- mStarButton->setEnabled(false);
- mStarButton->setToolTip(LLStringExplicit(""));
return;
}
@@ -370,141 +380,138 @@ void LLTeleportHistoryPanel::updateVerbs()
mTeleportBtn->setEnabled(NULL != itemp && itemp->getIndex() < (S32)mTeleportHistory->getItems().size() - 1);
mShowOnMapBtn->setEnabled(NULL != itemp);
+}
+
+void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, LLDate& tab_date)
+{
+ const U32 seconds_in_day = 24 * 60 * 60;
+
+ S32 tabs_cnt = mItemContainers.size();
+ S32 curr_year = 0, curr_month = 0, curr_day = 0;
+
+ tab_date = LLDate::now();
+ tab_date.split(&curr_year, &curr_month, &curr_day);
+ tab_date.fromYMDHMS(curr_year, curr_month, curr_day); // Set hour, min, and sec to 0
+ tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() + seconds_in_day);
- if (NULL != itemp)
+ tab_idx = -1;
+
+ while (tab_idx < tabs_cnt - 1 && item_date < tab_date)
{
- LLViewerInventoryItem *landmark = LLLandmarkActions::findLandmarkForGlobalPos(
- mTeleportHistory->getItems()[itemp->getIndex()].mGlobalPos);
+ tab_idx++;
- mStarButton->setEnabled(true);
- if (!landmark || landmark->getUUID().isNull())
+ if (tab_idx <= tabs_cnt - 4)
{
- mStarButton->setToggleState(true);
- // Landmark can be created only for current agent positon, which is most recent (last) item in teleport history.
- // mTeleportBtn is disabled only for that item.
- mStarButton->setToolTip(mTeleportBtn->getEnabled() ? getString("cant_create_lm_here") : getString("create_landmark"));
+ tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() - seconds_in_day);
}
- else
+ else if (tab_idx == tabs_cnt - 3) // 6 day and older, low boundary is 1 month
{
- mStarButton->setToggleState(false);
- mStarButton->setToolTip(getString("open_landmark"));
+ tab_date = LLDate::now();
+ tab_date.split(&curr_year, &curr_month, &curr_day);
+ curr_month--;
+ if (0 == curr_month)
+ {
+ curr_month = 12;
+ curr_year--;
+ }
+ tab_date.fromYMDHMS(curr_year, curr_month, curr_day);
+ }
+ else if (tab_idx == tabs_cnt - 2) // 1 month and older, low boundary is 6 months
+ {
+ tab_date = LLDate::now();
+ tab_date.split(&curr_year, &curr_month, &curr_day);
+ if (curr_month > 6)
+ {
+ curr_month -= 6;
+ }
+ else
+ {
+ curr_month += 6;
+ curr_year--;
+ }
+ tab_date.fromYMDHMS(curr_year, curr_month, curr_day);
+ }
+ else // 6 months and older
+ {
+ tab_date.secondsSinceEpoch(0);
}
- }
- else
- {
- mStarButton->setEnabled(false);
- mStarButton->setToolTip(LLStringExplicit(""));
}
}
-void LLTeleportHistoryPanel::showTeleportHistory()
+void LLTeleportHistoryPanel::refresh()
{
if (!mHistoryAccordion)
+ {
+ mDirty = false;
return;
+ }
- const LLTeleportHistoryStorage::slurl_list_t& hist_items = mTeleportHistory->getItems();
-
- const U32 seconds_in_day = 24 * 60 * 60;
- LLDate curr_date = LLDate::now();
-
- S32 curr_tab = -1;
- S32 tabs_cnt = mItemContainers.size();
- S32 curr_year = 0, curr_month = 0, curr_day = 0;
-
- curr_date.split(&curr_year, &curr_month, &curr_day);
- curr_date.fromYMDHMS(curr_year, curr_month, curr_day); // Set hour, min, and sec to 0
- curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() + seconds_in_day);
+ const LLTeleportHistoryStorage::slurl_list_t& items = mTeleportHistory->getItems();
+ LLDate tab_boundary_date = LLDate::now();
LLFlatListView* curr_flat_view = NULL;
- S32 index = hist_items.size() - 1;
-
- for (LLTeleportHistoryStorage::slurl_list_t::const_reverse_iterator iter = hist_items.rbegin();
- iter != hist_items.rend(); ++iter, --index)
+ U32 added_items = 0;
+ while (mCurrentItem >= 0)
{
- std::string landmark_title = (*iter).mTitle;
+ std::string landmark_title = items[mCurrentItem].mTitle;
LLStringUtil::toUpper(landmark_title);
std::string::size_type match_offset = mFilterSubString.size() ? landmark_title.find(mFilterSubString) : std::string::npos;
bool passed = mFilterSubString.size() == 0 || match_offset != std::string::npos;
if (!passed)
+ {
+ mCurrentItem--;
continue;
+ }
- if (curr_tab < tabs_cnt - 1)
- {
- const LLDate &date = (*iter).mDate;
+ const LLDate &date = items[mCurrentItem].mDate;
- if (date < curr_date)
- {
- LLAccordionCtrlTab* tab = NULL;
- while (curr_tab < tabs_cnt - 1 && date < curr_date)
- {
- curr_tab++;
-
- tab = mItemContainers.get(mItemContainers.size() - 1 - curr_tab);
- tab->setVisible(false);
-
- if (curr_tab <= tabs_cnt - 4)
- {
- curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() - seconds_in_day);
- }
- else if (curr_tab == tabs_cnt - 3) // 6 day and older, low boundary is 1 month
- {
- curr_date = LLDate::now();
- curr_date.split(&curr_year, &curr_month, &curr_day);
- curr_month--;
- if (0 == curr_month)
- {
- curr_month = 12;
- curr_year--;
- }
- curr_date.fromYMDHMS(curr_year, curr_month, curr_day);
- }
- else if (curr_tab == tabs_cnt - 2) // 1 month and older, low boundary is 6 months
- {
- curr_date = LLDate::now();
- curr_date.split(&curr_year, &curr_month, &curr_day);
- if (curr_month > 6)
- {
- curr_month -= 6;
- }
- else
- {
- curr_month += 6;
- curr_year--;
- }
- curr_date.fromYMDHMS(curr_year, curr_month, curr_day);
- }
- else // 6 months and older
- {
- curr_date.secondsSinceEpoch(0);
- }
- }
+ if (date < tab_boundary_date)
+ {
+ S32 tab_idx = 0;
+ getNextTab(date, tab_idx, tab_boundary_date);
- tab->setVisible(true);
+ LLAccordionCtrlTab* tab = mItemContainers.get(mItemContainers.size() - 1 - tab_idx);
+ tab->setVisible(true);
- curr_flat_view = getFlatListViewFromTab(tab);
- if (curr_flat_view)
- {
- curr_flat_view->clear();
- }
- }
+ curr_flat_view = getFlatListViewFromTab(tab);
}
if (curr_flat_view)
- {
- curr_flat_view->addItem(new LLTeleportHistoryFlatItem(index, &mContextMenu, (*iter).mTitle));
- }
- }
+ curr_flat_view->addItem(new LLTeleportHistoryFlatItem(mCurrentItem, &mContextMenu, items[mCurrentItem].mTitle));
+
+ mCurrentItem--;
- // Hide empty tabs from current to bottom
- for (curr_tab++; curr_tab < tabs_cnt; curr_tab++)
- mItemContainers.get(mItemContainers.size() - 1 - curr_tab)->setVisible(false);
+ if (++added_items >= ADD_LIMIT)
+ break;
+ }
mHistoryAccordion->arrange();
updateVerbs();
+
+ if (mCurrentItem < 0)
+ mDirty = false;
+}
+
+void LLTeleportHistoryPanel::showTeleportHistory()
+{
+ mDirty = true;
+ mCurrentItem = mTeleportHistory->getItems().size() - 1;
+
+ for (S32 n = mItemContainers.size() - 1; n >= 0; --n)
+ {
+ LLAccordionCtrlTab* tab = mItemContainers.get(n);
+ tab->setVisible(false);
+
+ LLFlatListView* fv = getFlatListViewFromTab(tab);
+ if (fv)
+ fv->clear();
+ }
+
+ refresh();
}
void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected)
@@ -667,28 +674,3 @@ void LLTeleportHistoryPanel::onGearButtonClicked()
LLMenuGL::showPopup(this, menu, menu_x, menu_y);
}
-void LLTeleportHistoryPanel::onStarButtonCommit()
-{
- if (!mLastSelectedScrollList)
- return;
-
- LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedScrollList->getSelectedItem());
- if(!itemp)
- return;
-
- if (itemp->getIndex() < (S32)mTeleportHistory->getItems().size() - 1)
- {
- LLTeleportHistoryFlatItem::showPlaceInfoPanel(itemp->getIndex());
- }
- else
- {
- LLViewerInventoryItem *landmark = LLLandmarkActions::findLandmarkForGlobalPos(
- mTeleportHistory->getItems()[itemp->getIndex()].mGlobalPos);
-
- if (!landmark || landmark->getUUID().isNull())
- LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark"));
- else
- LLTeleportHistoryFlatItem::showPlaceInfoPanel(itemp->getIndex());
- }
-}
-
diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h
index f487c92836..bc3595e66d 100644
--- a/indra/newview/llpanelteleporthistory.h
+++ b/indra/newview/llpanelteleporthistory.h
@@ -69,6 +69,8 @@ public:
virtual ~LLTeleportHistoryPanel();
/*virtual*/ BOOL postBuild();
+ /*virtual*/ void draw();
+
/*virtual*/ void onSearchEdit(const std::string& string);
/*virtual*/ void onShowOnMap();
/*virtual*/ void onTeleport();
@@ -86,17 +88,19 @@ private:
void onClearTeleportHistory();
bool onClearTeleportHistoryDialog(const LLSD& notification, const LLSD& response);
+ void refresh();
+ void getNextTab(const LLDate& item_date, S32& curr_tab, LLDate& tab_date);
void showTeleportHistory();
void handleItemSelect(LLFlatListView* );
LLFlatListView* getFlatListViewFromTab(LLAccordionCtrlTab *);
void onGearButtonClicked();
- void onStarButtonCommit();
LLTeleportHistoryStorage* mTeleportHistory;
LLAccordionCtrl* mHistoryAccordion;
- LLButton * mStarButton;
LLFlatListView* mLastSelectedScrollList;
+ bool mDirty;
+ S32 mCurrentItem;
std::string mFilterSubString;
typedef LLDynamicArray<LLAccordionCtrlTab*> item_containers_t;
diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp
new file mode 100644
index 0000000000..ef02882c0d
--- /dev/null
+++ b/indra/newview/llplacesinventorybridge.cpp
@@ -0,0 +1,212 @@
+/**
+ * @file llplacesinventorybridge.cpp
+ * @brief Implementation of the Inventory-Folder-View-Bridge classes for Places Panel.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llmenugl.h"
+
+#include "llplacesinventorybridge.h"
+
+#include "llfloaterinventory.h" // for LLInventoryPanel
+#include "llfolderview.h" // for FIRST_SELECTED_ITEM
+
+
+static const std::string LANDMARKS_INVENTORY_LIST_NAME("landmarks_list");
+
+bool is_landmarks_panel(const LLInventoryPanel* inv_panel)
+{
+ if (NULL == inv_panel)
+ return false;
+ return inv_panel->getName() == LANDMARKS_INVENTORY_LIST_NAME;
+}
+
+void fill_items_with_menu_items(std::vector<std::string>& items, LLMenuGL& menu)
+{
+ LLView::child_list_const_iter_t itor;
+ for (itor = menu.beginChild(); itor != menu.endChild(); ++itor)
+ {
+ std::string name = (*itor)->getName();
+ items.push_back(name);
+ }
+}
+
+// virtual
+void LLPlacesLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ fill_items_with_menu_items(items, menu);
+
+ // Disable "Landmark More Information" menu item for
+ // multiple landmarks selected. Only one landmark
+ // info panel can be shown at a time.
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("more_info"));
+ }
+ }
+
+ hideContextEntries(menu, items, disabled_items);
+}
+
+
+
+void LLPlacesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ {
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ LLInventoryPanel* inv_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ bool is_open = false;
+ bool disable_changing = true;
+ if (inv_panel)
+ {
+ LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID));
+ is_open = (NULL != folder) && folder->isOpen();
+
+ disable_changing = !is_landmarks_panel(inv_panel);
+ }
+
+ // collect all items' names
+ fill_items_with_menu_items(items, menu);
+
+ // remove expand or collapse menu item depend on folder state
+ std::string collapse_expand_item_to_hide(is_open ? "expand" : "collapse");
+ std::vector<std::string>::iterator it = std::find(items.begin(), items.end(), collapse_expand_item_to_hide);
+ if (it != items.end()) items.erase(it);
+
+ if (disable_changing)
+ {
+ disabled_items.push_back(std::string("add_folder"));
+ disabled_items.push_back(std::string("rename"));
+ disabled_items.push_back(std::string("delete"));
+ }
+
+ // repeat parent functionality
+ sSelf = this; // necessary for "New Folder" functionality
+
+ hideContextEntries(menu, items, disabled_items);
+ }
+}
+
+//virtual
+void LLPlacesFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("expand" == action)
+ {
+ LLFolderViewFolder* act_folder = getFolder();
+ act_folder->toggleOpen();
+ }
+ else if ("collapse" == action)
+ {
+ LLFolderViewFolder* act_folder = getFolder();
+ act_folder->toggleOpen();
+ }
+ else
+ {
+ LLFolderBridge::performAction(folder, model, action);
+ }
+}
+
+LLFolderViewFolder* LLPlacesFolderBridge::getFolder()
+{
+ LLFolderViewFolder* folder = NULL;
+ LLInventoryPanel* inv_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ if (inv_panel)
+ {
+ folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID));
+ }
+
+ return folder;
+}
+
+// virtual
+LLInvFVBridge* LLPlacesInventoryBridgeBuilder::createBridge(
+ LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags/* = 0x00*/) const
+{
+ LLInvFVBridge* new_listener = NULL;
+ switch(asset_type)
+ {
+ case LLAssetType::AT_LANDMARK:
+ if(!(inv_type == LLInventoryType::IT_LANDMARK))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLPlacesLandmarkBridge(inv_type, inventory, uuid, flags);
+ break;
+ case LLAssetType::AT_CATEGORY:
+ if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
+ {
+ // *TODO: Create a link folder handler instead if it is necessary
+ new_listener = LLInventoryFVBridgeBuilder::createBridge(
+ asset_type,
+ actual_asset_type,
+ inv_type,
+ inventory,
+ uuid,
+ flags);
+ break;
+ }
+ new_listener = new LLPlacesFolderBridge(inv_type, inventory, uuid);
+ break;
+ default:
+ new_listener = LLInventoryFVBridgeBuilder::createBridge(
+ asset_type,
+ actual_asset_type,
+ inv_type,
+ inventory,
+ uuid,
+ flags);
+ }
+ return new_listener;
+}
+
+// EOF
diff --git a/indra/newview/llplacesinventorybridge.h b/indra/newview/llplacesinventorybridge.h
new file mode 100644
index 0000000000..66a8e8e54d
--- /dev/null
+++ b/indra/newview/llplacesinventorybridge.h
@@ -0,0 +1,91 @@
+/**
+ * @file llplacesinventorybridge.h
+ * @brief Declaration of the Inventory-Folder-View-Bridge classes for Places Panel.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPLACESINVENTORYBRIDGE_H
+#define LL_LLPLACESINVENTORYBRIDGE_H
+
+#include "llinventorybridge.h"
+
+class LLFolderViewFolder;
+
+/**
+ * Overridden version of the Inventory-Folder-View-Bridge for Places Panel (Landmarks Tab)
+ */
+class LLPlacesLandmarkBridge : public LLLandmarkBridge
+{
+ friend class LLPlacesInventoryBridgeBuilder;
+
+public:
+ /*virtual*/ void buildContextMenu(LLMenuGL& menu, U32 flags);
+
+protected:
+ LLPlacesLandmarkBridge(LLInventoryType::EType type, LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags = 0x00)
+ : LLLandmarkBridge(inventory, uuid, flags) {mInvType = type;}
+};
+
+/**
+ * Overridden version of the Inventory-Folder-View-Bridge for Folders
+ */
+class LLPlacesFolderBridge : public LLFolderBridge
+{
+ friend class LLPlacesInventoryBridgeBuilder;
+
+public:
+ /*virtual*/ void buildContextMenu(LLMenuGL& menu, U32 flags);
+ /*virtual*/ void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
+
+protected:
+ LLPlacesFolderBridge(LLInventoryType::EType type, LLInventoryPanel* inventory, const LLUUID& uuid)
+ : LLFolderBridge(inventory, uuid) {mInvType = type;}
+
+ LLFolderViewFolder* getFolder();
+};
+
+
+/**
+ * This class intended to override default InventoryBridgeBuilder for Inventory Panel.
+ *
+ * It builds Bridges for Landmarks and Folders in Places Landmarks Panel
+ */
+class LLPlacesInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder
+{
+public:
+ /*virtual*/ LLInvFVBridge* createBridge(
+ LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags = 0x00) const;
+};
+
+#endif // LL_LLPLACESINVENTORYBRIDGE_H
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index 4db849c159..ff95f8adce 100644
--- a/indra/newview/llsidetray.cpp
+++ b/indra/newview/llsidetray.cpp
@@ -559,6 +559,15 @@ void LLSideTray::highlightFocused()
}
+BOOL LLSideTray::handleScrollWheel(S32 x, S32 y, S32 mask)
+{
+ BOOL ret = LLPanel::handleScrollWheel(x,y,mask);
+
+ if(!ret && childFromPoint(x,y) != 0 )
+ return TRUE;//mouse wheel over sidetray buttons, eat mouse wheel
+ return ret;
+}
+
//virtual
BOOL LLSideTray::handleMouseDown (S32 x, S32 y, MASK mask)
{
@@ -641,7 +650,9 @@ LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& para
LLView* view = (*child_it)->findChildView(panel_name,true);
if(view)
{
- onTabButtonClick((*child_it)->getName());
+ selectTabByName ((*child_it)->getName());
+ if(mCollapsed)
+ expandSideBar();
LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(view->getParent());
if(container)
diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h
index 13acbbb659..6ea6bafac9 100644
--- a/indra/newview/llsidetray.h
+++ b/indra/newview/llsidetray.h
@@ -203,6 +203,7 @@ public:
bool addChild (LLView* view, S32 tab_group);
BOOL handleMouseDown (S32 x, S32 y, MASK mask);
+ BOOL handleScrollWheel(S32 x, S32 y, S32 mask);
void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE);
S32 getTrayWidth();
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 67a0528a06..6714fe908f 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -45,29 +45,6 @@
#include "llnotificationmanager.h"
-// IM session ID can be the same as Avatar UUID. (See LLIMMgr::computeSessionID)
-// Probably notification ID also can be the same as Avatar UUID.
-// In case when session ID & notification ID are the same it will be impossible to add both
-// appropriate Items into Flat List.
-// Functions below are intended to wrap passed LLUUID into LLSD value with different "type".
-// Use them anywhere you need to add, get, remove items via the list
-inline
-LLSD get_notification_value(const LLUUID& notification_id)
-{
- return LLSD()
- .insert("type", "notification")
- .insert("uuid", notification_id);
-}
-
-inline
-LLSD get_session_value(const LLUUID& session_id)
-{
- return LLSD()
- .insert("type", "im_chiclet")
- .insert("uuid", session_id);
-}
-
-
//---------------------------------------------------------------------------------
LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key),
mChannel(NULL),
@@ -157,7 +134,7 @@ LLSysWellWindow::~LLSysWellWindow()
//---------------------------------------------------------------------------------
void LLSysWellWindow::addItem(LLSysWellItem::Params p)
{
- LLSD value = get_notification_value(p.notification_id);
+ LLSD value = p.notification_id;
// do not add clones
if( mMessageList->getItemByValue(value))
return;
@@ -191,7 +168,7 @@ void LLSysWellWindow::clear()
//---------------------------------------------------------------------------------
void LLSysWellWindow::removeItemByID(const LLUUID& id)
{
- if(mMessageList->removeItemByValue(get_notification_value(id)))
+ if(mMessageList->removeItemByValue(id))
{
handleItemRemoved(IT_NOTIFICATION);
reshapeWindow();
@@ -357,7 +334,7 @@ void LLSysWellWindow::reshapeWindow()
LLChiclet* LLSysWellWindow::findIMChiclet(const LLUUID& sessionId)
{
LLChiclet* res = NULL;
- RowPanel* panel = mMessageList->getTypedItemByValue<RowPanel>(get_session_value(sessionId));
+ RowPanel* panel = mMessageList->getTypedItemByValue<RowPanel>(sessionId);
if (panel != NULL)
{
res = panel->mChiclet;
@@ -371,7 +348,7 @@ void LLSysWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter,
const std::string& name, const LLUUID& otherParticipantId)
{
RowPanel* item = new RowPanel(this, sessionId, chicletCounter, name, otherParticipantId);
- if (mMessageList->insertItemAfter(mSeparator, item, get_session_value(sessionId)))
+ if (mMessageList->insertItemAfter(mSeparator, item, sessionId))
{
handleItemAdded(IT_INSTANT_MESSAGE);
}
@@ -389,7 +366,7 @@ void LLSysWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter,
//---------------------------------------------------------------------------------
void LLSysWellWindow::delIMRow(const LLUUID& sessionId)
{
- if (mMessageList->removeItemByValue(get_session_value(sessionId)))
+ if (mMessageList->removeItemByValue(sessionId))
{
handleItemRemoved(IT_INSTANT_MESSAGE);
}
@@ -423,7 +400,7 @@ void LLSysWellWindow::sessionAdded(const LLUUID& session_id,
const std::string& name, const LLUUID& other_participant_id)
{
//*TODO get rid of get_session_value, session_id's are unique, cause performance degradation with lots chiclets (IB)
- if (mMessageList->getItemByValue(get_session_value(session_id)) == NULL)
+ if (mMessageList->getItemByValue(session_id) == NULL)
{
S32 chicletCounter = LLIMModel::getInstance()->getNumUnread(session_id);
if (chicletCounter > -1)
@@ -443,6 +420,17 @@ void LLSysWellWindow::sessionRemoved(const LLUUID& sessionId)
LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications();
}
+void LLSysWellWindow::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id)
+{
+ //for outgoing ad-hoc and group im sessions only
+ LLChiclet* chiclet = findIMChiclet(old_session_id);
+ if (chiclet)
+ {
+ chiclet->setSessionId(new_session_id);
+ mMessageList->updateValue(old_session_id, new_session_id);
+ }
+}
+
void LLSysWellWindow::handleItemAdded(EItemType added_item_type)
{
bool should_be_shown = ++mTypedItemsCount[added_item_type] == 1 && anotherTypeExists(added_item_type);
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index 0c3f4d0587..fa6a1abea4 100644
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -108,6 +108,7 @@ private:
// LLIMSessionObserver observe triggers
virtual void sessionAdded(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id);
virtual void sessionRemoved(const LLUUID& session_id);
+ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);
// pointer to a corresponding channel's instance
LLNotificationsUI::LLScreenChannel* mChannel;
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index 86b162247a..0c23947a8c 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -36,178 +36,106 @@
#include "llviewercontrol.h"
#include "lluiconstants.h"
#include "llrect.h"
-#include "lliconctrl.h"
-#include "lltexteditor.h"
-#include "lltextbox.h"
-#include "lldbstrings.h"
-#include "llchat.h"
-#include "llfloaterchat.h"
#include "lltrans.h"
-#include "lloverlaybar.h"
-
const S32 BOTTOM_PAD = VPAD * 3;
+const S32 BUTTON_WIDTH = 90;
//static
const LLFontGL* LLToastNotifyPanel::sFont = NULL;
const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL;
-LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : LLToastPanel(notification) {
- mIsTip = notification->getType() == "notifytip";
- mNumOptions = 0;
- mNumButtons = 0;
- mIsScriptDialog = (notification->getName() == "ScriptDialog"
- || notification->getName() == "ScriptDialogGroup");
- mAddedDefaultBtn = false;
+LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) :
+LLToastPanel(notification),
+mTextBox(NULL),
+mIcon(NULL),
+mInfoPanel(NULL),
+mControlPanel(NULL),
+mNumOptions(0),
+mNumButtons(0),
+mAddedDefaultBtn(false)
+{
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_notification.xml");
+ mInfoPanel = getChild<LLPanel>("info_panel");
+ mControlPanel = getChild<LLPanel>("control_panel");
+ mIcon = getChild<LLIconCtrl>("info_icon");
- // clicking on a button does not steal current focus
- setIsChrome(TRUE);
+ // customize panel's attributes
+ // is it intended for displaying a tip
+ mIsTip = notification->getType() == "notifytip";
+ // is it a script dialog
+ mIsScriptDialog = (notification->getName() == "ScriptDialog" || notification->getName() == "ScriptDialogGroup");
+ // is it a caution
+ //
+ // caution flag can be set explicitly by specifying it in the notification payload, or it can be set implicitly if the
+ // notify xml template specifies that it is a caution
+ // tip-style notification handle 'caution' differently -they display the tip in a different color
+ mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH;
- // class init
+ // setup parameters
+ // get a notification message
+ mMessage = notification->getMessage();
+ // init font variables
if (!sFont)
{
sFont = LLFontGL::getFontSansSerif();
sFontSmall = LLFontGL::getFontSansSerifSmall();
}
-
- // setup paramaters
- mMessage = notification->getMessage();
-
+ // clicking on a button does not steal current focus
+ setIsChrome(TRUE);
// initialize
setFocusRoot(!mIsTip);
-
- // caution flag can be set explicitly by specifying it in the
- // notification payload, or it can be set implicitly if the
- // notify xml template specifies that it is a caution
- //
- // tip-style notification handle 'caution' differently -
- // they display the tip in a different color
- mIsCaution = notification->getPriority() >= NOTIFICATION_PRIORITY_HIGH;
-
+ // get a form for the notification
LLNotificationFormPtr form(notification->getForm());
-
+ // get number of elements
mNumOptions = form->getNumElements();
- LLRect rect = mIsTip ? getNotifyTipRect(mMessage)
- : getNotifyRect(mNumOptions, mIsScriptDialog, mIsCaution);
- setRect(rect);
- setFollows(mIsTip ? (FOLLOWS_BOTTOM|FOLLOWS_RIGHT) : (FOLLOWS_TOP|FOLLOWS_RIGHT));
- setBackgroundVisible(FALSE);
- setBackgroundOpaque(TRUE);
-
- LLIconCtrl* icon;
- LLTextEditor* text;
-
- const S32 TOP = getRect().getHeight() - (mIsTip ? (S32)sFont->getLineHeight() : 32);
- const S32 BOTTOM = (S32)sFont->getLineHeight();
- S32 x = HPAD + HPAD;
- S32 y = TOP;
-
- LLIconCtrl::Params common_params;
- common_params.rect(LLRect(x, y, x+32, TOP-32));
- common_params.mouse_opaque(false);
- common_params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP);
+ // customize panel's outfit
+ // preliminary adjust panel's layout
+ mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form);
+ // choose a right icon
if (mIsTip)
{
// use the tip notification icon
- common_params.image(LLUI::getUIImage("notify_tip_icon.tga"));
- icon = LLUICtrlFactory::create<LLIconCtrl> (common_params);
+ mIcon->setValue("notify_tip_icon.tga");
+ LLRect icon_rect = mIcon->getRect();
+ icon_rect.setLeftTopAndSize(icon_rect.mLeft, getRect().getHeight() - VPAD, icon_rect.getWidth(), icon_rect.getHeight());
+ mIcon->setRect(icon_rect);
}
else if (mIsCaution)
{
// use the caution notification icon
- common_params.image(LLUI::getUIImage("notify_caution_icon.tga"));
- icon = LLUICtrlFactory::create<LLIconCtrl> (common_params);
+ mIcon->setValue("notify_caution_icon.tga");
}
else
{
// use the default notification icon
- common_params.image(LLUI::getUIImage("notify_box_icon.tga"));
- icon = LLUICtrlFactory::create<LLIconCtrl> (common_params);
+ mIcon->setValue("notify_box_icon.tga");
}
- icon->setMouseOpaque(FALSE);
- addChild(icon);
-
- x += HPAD + HPAD + 32;
-
+ // adjust text options according to the notification type
// add a caution textbox at the top of a caution notification
- LLTextBox* caution_box = NULL;
if (mIsCaution && !mIsTip)
{
- S32 caution_height = ((S32)sFont->getLineHeight() * 2) + VPAD;
- LLTextBox::Params params;
- params.name("caution_box");
- params.rect(LLRect(x, y, getRect().getWidth() - 2, caution_height));
- params.font(sFont);
- params.mouse_opaque(false);
- params.font.style("BOLD");
- params.text_color(LLUIColorTable::instance().getColor("NotifyCautionWarnColor"));
- params.bg_readonly_color(LLUIColorTable::instance().getColor("NotifyCautionBoxColor"));
- params.border_visible(false);
- params.wrap(true);
- caution_box = LLUICtrlFactory::create<LLTextBox> (params);
- caution_box->setValue(notification->getMessage());
-
- addChild(caution_box);
-
- // adjust the vertical position of the next control so that
- // it appears below the caution textbox
- y = y - caution_height;
+ mTextBox = getChild<LLTextBox>("caution_text_box");
}
else
{
-
- const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD);
-
- // Tokenization on \n is handled by LLTextBox
-
- const S32 MAX_LENGTH = 512 + 20 +
- DB_FIRST_NAME_BUF_SIZE +
- DB_LAST_NAME_BUF_SIZE +
- DB_INV_ITEM_NAME_BUF_SIZE; // For script dialogs: add space for title.
-
- LLTextEditor::Params params;
- params.name("box");
- params.rect(LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16));
- params.max_text_length(MAX_LENGTH);
- params.read_only(true);
- params.default_text(mMessage);
- params.font(sFont);
- params.embedded_items(false);
- params.wrap(true);
- params.tab_stop(false);
- params.mouse_opaque(false);
- params.bg_readonly_color(LLColor4::transparent);
- params.text_readonly_color(LLUIColorTable::instance().getColor("NotifyTextColor"));
- params.enabled(false);
- params.border_visible(false);
- text = LLUICtrlFactory::create<LLTextEditor> (params);
- addChild(text);
+ mTextBox = getChild<LLTextEditor>("text_editor_box");
}
- if (mIsTip)
- {
- // TODO: Make a separate archive for these.
- LLChat chat(mMessage);
- chat.mSourceType = CHAT_SOURCE_SYSTEM;
- LLFloaterChat::addChatHistory(chat);
- }
- else
- {
- LLButton::Params p;
- p.name(std::string("next"));
- p.rect(LLRect(getRect().getWidth()-26, BOTTOM_PAD + 20, getRect().getWidth()-2, BOTTOM_PAD));
- p.image_selected.name("notify_next.png");
- p.image_unselected.name("notify_next.png");
- p.font(sFont);
- p.scale_image(true);
- p.tool_tip(LLTrans::getString("next").c_str());
+ // *TODO: magic numbers(???) - copied from llnotify.cpp(250)
+ const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE;
+
+ mTextBox->setVisible(TRUE);
+ mTextBox->setValue(notification->getMessage());
+ // add buttons for a script notification
+ if (!mIsTip)
+ {
for (S32 i = 0; i < mNumOptions; i++)
{
-
LLSD form_element = form->getElement(i);
if (form_element["type"].asString() != "button")
{
@@ -222,137 +150,63 @@ LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : LLToas
addButton("OK", LLTrans::getString("ok"), FALSE, TRUE);
mAddedDefaultBtn = true;
}
-
-
}
+
+ // adjust panel's height to the text size
+ mInfoPanel->setFollowsAll();
+ snapToMessageHeight(mTextBox, MAX_LENGTH);
}
-LLToastNotifyPanel::~LLToastNotifyPanel() {
+LLToastNotifyPanel::~LLToastNotifyPanel()
+{
std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer());
}
-LLRect LLToastNotifyPanel::getNotifyRect(S32 num_options, BOOL mIsScriptDialog, BOOL is_caution)
+void LLToastNotifyPanel::adjustPanelForScriptNotice(const LLNotificationFormPtr form)
{
- S32 notify_height = gSavedSettings.getS32("NotifyBoxHeight");
- if (is_caution)
+ F32 buttons_num = 0;
+ S32 button_rows = 0;
+
+ // calculate number of buttons
+ for (S32 i = 0; i < mNumOptions; i++)
{
- // make caution-style dialog taller to accomodate extra text,
- // as well as causing the accept/decline buttons to be drawn
- // in a different position, to help prevent "quick-click-through"
- // of many permissions prompts
- notify_height = gSavedSettings.getS32("PermissionsCautionNotifyBoxHeight");
+ if (form->getElement(i)["type"].asString() == "button")
+ {
+ buttons_num++;
+ }
}
- const S32 NOTIFY_WIDTH = gSavedSettings.getS32("NotifyBoxWidth");
- const S32 TOP = getRect().getHeight();
- const S32 RIGHT =getRect().getWidth();
- const S32 LEFT = RIGHT - NOTIFY_WIDTH;
-
- if (num_options < 1)
+ // calculate necessary height for the button panel
+ // if notification form contains no buttons - reserve a place for OK button
+ // script notifications have extra line for an IGNORE button
+ if(mIsScriptDialog)
{
- num_options = 1;
+ button_rows = llceil((buttons_num - 1) / 3.0f) + 1;
}
-
- // Add two "blank" option spaces.
- if (mIsScriptDialog)
+ else
{
- num_options += 2;
+ button_rows = llmax( 1, llceil(buttons_num / 3.0f));
}
- S32 additional_lines = (num_options-1) / 3;
-
- notify_height += additional_lines * (BTN_HEIGHT + VPAD);
+ S32 button_panel_height = button_rows * BTN_HEIGHT + (button_rows + 1) * VPAD + BOTTOM_PAD;
- return LLRect(LEFT, TOP, RIGHT, TOP-notify_height);
+ //adjust layout
+ LLRect button_rect = mControlPanel->getRect();
+ reshape(getRect().getWidth(), mInfoPanel->getRect().getHeight() + button_panel_height);
+ mControlPanel->reshape(button_rect.getWidth(), button_panel_height);
}
// static
-LLRect LLToastNotifyPanel::getNotifyTipRect(const std::string &utf8message)
+void LLToastNotifyPanel::adjustPanelForTipNotice()
{
- S32 line_count = 1;
- LLWString message = utf8str_to_wstring(utf8message);
- S32 message_len = message.length();
-
- const S32 NOTIFY_WIDTH = gSavedSettings.getS32("NotifyBoxWidth");
- // Make room for the icon area.
- const S32 text_area_width = NOTIFY_WIDTH - HPAD * 4 - 32;
-
- const llwchar* wchars = message.c_str();
- const llwchar* start = wchars;
- const llwchar* end;
- S32 total_drawn = 0;
- BOOL done = FALSE;
-
- do
- {
- line_count++;
-
- for (end=start; *end != 0 && *end != '\n'; end++)
- ;
-
- if( *end == 0 )
- {
- end = wchars + message_len;
- done = TRUE;
- }
-
- S32 remaining = end - start;
- while( remaining )
- {
- S32 drawn = sFont->maxDrawableChars( start, (F32)text_area_width, remaining, TRUE );
-
- if( 0 == drawn )
- {
- drawn = 1; // Draw at least one character, even if it doesn't all fit. (avoids an infinite loop)
- }
-
- total_drawn += drawn;
- start += drawn;
- remaining -= drawn;
-
- if( total_drawn < message_len )
- {
- if( (wchars[ total_drawn ] != '\n') )
- {
- // wrap because line was too long
- line_count++;
- }
- }
- else
- {
- done = TRUE;
- }
- }
-
- total_drawn++; // for '\n'
- end++;
- start = end;
- } while( !done );
+ LLRect info_rect = mInfoPanel->getRect();
+ LLRect this_rect = getRect();
- const S32 MIN_NOTIFY_HEIGHT = 72;
- const S32 MAX_NOTIFY_HEIGHT = 600;
- S32 notify_height = llceil((F32) (line_count+1) * sFont->getLineHeight());
- if(gOverlayBar)
- {
- notify_height += gOverlayBar->getBoundingRect().mTop;
- }
- else
- {
- // *FIX: this is derived from the padding caused by the
- // rounded rects, shouldn't be a const here.
- notify_height += 10;
- }
- notify_height += VPAD;
- notify_height = llclamp(notify_height, MIN_NOTIFY_HEIGHT, MAX_NOTIFY_HEIGHT);
-
- const S32 RIGHT = getRect().getWidth();
- const S32 LEFT = RIGHT - NOTIFY_WIDTH;
-
- return LLRect(LEFT, notify_height, RIGHT, 0);
+ mControlPanel->setVisible(FALSE);
+ reshape(getRect().getWidth(), mInfoPanel->getRect().getHeight());
}
-
// static
void LLToastNotifyPanel::onClickButton(void* data)
{
@@ -371,10 +225,6 @@ void LLToastNotifyPanel::onClickButton(void* data)
// virtual
LLButton* LLToastNotifyPanel::addButton(const std::string& name, const std::string& label, BOOL is_option, BOOL is_default)
{
- // make caution notification buttons slightly narrower
- // so that 3 of them can fit without overlapping the "next" button
- S32 btn_width = mIsCaution? 84 : 90;
-
LLRect btn_rect;
LLButton* btn;
S32 btn_height= BTN_HEIGHT;
@@ -397,9 +247,9 @@ LLButton* LLToastNotifyPanel::addButton(const std::string& name, const std::stri
}
}
- btn_rect.setOriginAndSize(x + (index % 3) * (btn_width+HPAD+HPAD) + ignore_pad,
+ btn_rect.setOriginAndSize(x + (index % 3) * (BUTTON_WIDTH+HPAD+HPAD) + ignore_pad,
BOTTOM_PAD + (index / 3) * (BTN_HEIGHT+VPAD),
- btn_width - 2*ignore_pad,
+ BUTTON_WIDTH - 2*ignore_pad,
btn_height);
InstanceAndS32* userdata = new InstanceAndS32;
@@ -422,7 +272,7 @@ LLButton* LLToastNotifyPanel::addButton(const std::string& name, const std::stri
btn = LLUICtrlFactory::create<LLButton>(p);
- addChild(btn, -1);
+ mControlPanel->addChild(btn, -1);
if (is_default)
{
diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h
index df58c06f25..66534edcdf 100644
--- a/indra/newview/lltoastnotifypanel.h
+++ b/indra/newview/lltoastnotifypanel.h
@@ -38,6 +38,9 @@
#include "llnotifications.h"
#include "llbutton.h"
#include "lltoastpanel.h"
+#include "lliconctrl.h"
+#include "lltexteditor.h"
+#include "lltextbox.h"
/**
@@ -46,15 +49,15 @@
*
* Replaces class LLNotifyBox.
*/
-class LLToastNotifyPanel: public LLToastPanel {
+class LLToastNotifyPanel: public LLToastPanel
+{
public:
LLToastNotifyPanel(LLNotificationPtr&);
virtual ~LLToastNotifyPanel();
- bool isTip() {return mIsTip;}
- static LLToastNotifyPanel * buildNotifyPanel(LLNotificationPtr notification);
protected:
LLButton* addButton(std::string const &name, const std::string& label, BOOL is_option, BOOL is_default);
+
// Used for callbacks
struct InstanceAndS32
{
@@ -65,16 +68,23 @@ protected:
private:
- // Returns the rect, relative to gNotifyView, where this
- // notify box should be placed.
- LLRect getNotifyRect(S32 num_options, BOOL layout_script_dialog, BOOL is_caution);
- LLRect getNotifyTipRect(const std::string &message);
+ void adjustPanelForScriptNotice(const LLNotificationFormPtr form);
+ void adjustPanelForTipNotice();
+
+ // panel elements
+ LLTextBase* mTextBox;
+ LLIconCtrl* mIcon;
+ LLPanel* mInfoPanel; // a panel, that contains an information
+ LLPanel* mControlPanel; // a panel, that contains buttons (if present)
+
// internal handler for button being clicked
static void onClickButton(void* data);
+
bool mIsTip;
bool mAddedDefaultBtn;
bool mIsScriptDialog;
- bool mIsCaution; // is this a caution notification?
+ bool mIsCaution;
+
std::string mMessage;
S32 mNumOptions;
S32 mNumButtons;
diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp
index 7b477470aa..ef75e06047 100644
--- a/indra/newview/lltoastpanel.cpp
+++ b/indra/newview/lltoastpanel.cpp
@@ -34,6 +34,9 @@
#include "lltoastpanel.h"
+//static
+const S32 LLToastPanel::MIN_PANEL_HEIGHT = 40; // VPAD(4)*2 + ICON_HEIGHT(32)
+
LLToastPanel::LLToastPanel(LLNotificationPtr& notification)
{
mNotification = notification;
@@ -50,8 +53,13 @@ std::string LLToastPanel::getTitle()
}
//snap to the message height if it is visible
-void LLToastPanel::snapToMessageHeight(LLTextBox* message, S32 maxLineCount)
+void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount)
{
+ if(!message)
+ {
+ return;
+ }
+
//Add message height if it is visible
if (message->getVisible())
{
@@ -61,22 +69,16 @@ void LLToastPanel::snapToMessageHeight(LLTextBox* message, S32 maxLineCount)
LLRect messageRect = message->getRect();
S32 oldTextHeight = messageRect.getHeight();
- //Reshape the toast to give the message max height.
- //This needed to calculate lines count according to specified text
- heightDelta = maxTextHeight - oldTextHeight;
- reshape( getRect().getWidth(), getRect().getHeight() + heightDelta);
-
//Knowing the height is set to max allowed, getTextPixelHeight returns needed text height
//Perhaps we need to pass maxLineCount as parameter to getTextPixelHeight to avoid previous reshape.
- S32 requiredTextHeight = message->getTextPixelHeight();
+ S32 requiredTextHeight = message->getContentsRect().getHeight();
S32 newTextHeight = llmin(requiredTextHeight, maxTextHeight);
//Calculate last delta height deducting previous heightDelta
heightDelta = newTextHeight - oldTextHeight - heightDelta;
//reshape the panel with new height
- reshape( getRect().getWidth(), getRect().getHeight() + heightDelta);
+ reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT));
}
-
}
diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h
index 418373e8c6..a88127b008 100644
--- a/indra/newview/lltoastpanel.h
+++ b/indra/newview/lltoastpanel.h
@@ -58,9 +58,11 @@ public:
virtual std::string getTitle();
virtual const LLUUID& getID() { return mNotification->id();}
+
+ static const S32 MIN_PANEL_HEIGHT;
protected:
LLNotificationPtr mNotification;
- void snapToMessageHeight(LLTextBox* message, S32 maxLineCount);
+ void snapToMessageHeight(LLTextBase* message, S32 maxLineCount);
};
#endif /* LL_TOASTPANEL_H */
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 273ca8bd1a..5f95e9ccf1 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -2293,7 +2293,9 @@ void LLViewerWindow::handleScrollWheel(S32 clicks)
}
// Zoom the camera in and out behavior
- gAgent.handleScrollWheel(clicks);
+
+ if(top_ctrl == 0 && mWorldViewRect.pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) )
+ gAgent.handleScrollWheel(clicks);
return;
}
@@ -4168,8 +4170,9 @@ void LLViewerWindow::drawMouselookInstructions()
instructions, 0,
getVirtualWorldViewRect().getCenterX(),
getVirtualWorldViewRect().mBottom + INSTRUCTIONS_PAD,
- LLColor4( 0.0f, 0.0f, 0.0f, 0.6f ),
- LLFontGL::HCENTER, LLFontGL::TOP);
+ LLColor4( 1.0f, 1.0f, 1.0f, 0.5f ),
+ LLFontGL::HCENTER, LLFontGL::TOP,
+ LLFontGL::NORMAL,LLFontGL::DROP_SHADOW);
}
S32 LLViewerWindow::getWindowHeight() const
diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
index f1976afb4a..6fbfed5f60 100644
--- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
@@ -30,23 +30,18 @@
color="1 1 1 1" enabled="true" image_name="closebox.tga"
name="close_btn"/>
</panel>
- <text_editor
+ <chat_history
allow_html="true"
bg_readonly_color="ChatHistoryBgColor"
bg_writeable_color="ChatHistoryBgColor"
- follows="left|top|right|bottom"
+ follows="left|top|right"
font="SansSerif"
layout="topleft"
- height="320"
- max_length="2147483647"
- name="Chat History Editor"
+ height="320"
+ name="chat_history"
parse_highlights="true"
- read_only="true"
text_color="ChatHistoryTextColor"
text_readonly_color="ChatHistoryTextColor"
- bottom="0"
- track_bottom="true"
- width="250"
- word_wrap="true" />
+ width="250"/>
</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 6dc08ad3ef..7785492651 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -478,11 +478,12 @@
parameter="open" />
</menu_item_call>
<menu_item_separator
- layout="topleft" />
+ layout="topleft"
+ name="Landmark Separator" />
<menu_item_call
label="About Landmark"
layout="topleft"
- name="Teleport To Landmark">
+ name="About Landmark">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="about" />
diff --git a/indra/newview/skins/default/xui/en/menu_landmark.xml b/indra/newview/skins/default/xui/en/menu_landmark.xml
index 64fec3ab40..54a4095967 100644
--- a/indra/newview/skins/default/xui/en/menu_landmark.xml
+++ b/indra/newview/skins/default/xui/en/menu_landmark.xml
@@ -29,4 +29,12 @@
function="Places.OverflowMenu.Action"
parameter="pick" />
</menu_item_call>
+ <menu_item_call
+ label="Add to Favorites Bar"
+ layout="topleft"
+ name="add_to_favbar">
+ <menu_item_call.on_click
+ function="Places.OverflowMenu.Action"
+ parameter="add_to_favbar" />
+ </menu_item_call>
</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
new file mode 100644
index 0000000000..b31a0d88a4
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
@@ -0,0 +1,45 @@
+<menu name="menu_folder_gear"
+ left="0" bottom="0" visible="false"
+ mouse_opaque="false" opaque="true"
+ color="MenuDefaultBgColor" drop_shadow="true">
+ <menu_item_call name="add_landmark" label="Add Landmark">
+ <menu_item_call.on_click function="Places.LandmarksGear.Add.Action" userdata="add_landmark" />
+ </menu_item_call>
+ <menu_item_call name="add_folder" label="Add Folder">
+ <menu_item_call.on_click function="Places.LandmarksGear.Add.Action" userdata="category" />
+ <menu_item_call.on_enable function="Places.LandmarksGear.Enable" userdata="category" />
+ </menu_item_call>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call name="cut" label="Cut">
+ <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="cut" />
+ </menu_item_call>
+ <menu_item_call name="copy_folder" label="Copy">
+ <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="copy" />
+ </menu_item_call>
+ <menu_item_call name="paste" label="Paste">
+ <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="paste" />
+ <menu_item_call.on_enable function="Places.LandmarksGear.Enable" userdata="paste" />
+ </menu_item_call>
+ <menu_item_call name="rename" label="Rename">
+ <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="rename" />
+ </menu_item_call>
+ <menu_item_call name="delete" label="Delete">
+ <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="delete" />
+ </menu_item_call>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call name="expand" label="Expand">
+ <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="expand" />
+ </menu_item_call>
+ <menu_item_call name="collapse" label="Collapse">
+ <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="collapse" />
+ </menu_item_call>
+ <menu_item_call name="expand_all" label="Expand all folders">
+ <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="expand_all" />
+ </menu_item_call>
+ <menu_item_call name="collapse_all" label="Collapse all folders">
+ <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="collapse_all" />
+ </menu_item_call>
+ <menu_item_call name="sort_by_date" label="Sort by Date">
+ <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="sort_by_date" />
+ </menu_item_call>
+</menu> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
new file mode 100644
index 0000000000..2d8bb0dcb9
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
@@ -0,0 +1,56 @@
+<menu name="menu_ladmark_gear"
+ left="0" bottom="0" visible="false"
+ mouse_opaque="false" opaque="true"
+ color="MenuDefaultBgColor" drop_shadow="true">
+ <menu_item_call name="teleport" label="Teleport">
+ <menu_item_call.on_click function="Places.LandmarksGear.Custom.Action" userdata="teleport" />
+ </menu_item_call>
+ <menu_item_call name="more_info" label="More Information">
+ <menu_item_call.on_click function="Places.LandmarksGear.Custom.Action" userdata="more_info" />
+ </menu_item_call>
+ <menu_item_call name="show_on_map" label="Show on Map">
+ <menu_item_call.on_click function="Places.LandmarksGear.Custom.Action" userdata="show_on_map" />
+ </menu_item_call>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call name="add_landmark" label="Add Landmark">
+ <menu_item_call.on_click function="Places.LandmarksGear.Add.Action" userdata="add_landmark" />
+ </menu_item_call>
+ <menu_item_call name="add_folder" label="Add Folder">
+ <menu_item_call.on_click function="Places.LandmarksGear.Add.Action" userdata="category" />
+ <menu_item_call.on_enable function="Places.LandmarksGear.Enable" userdata="category" />
+ </menu_item_call>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call name="cut" label="Cut">
+ <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="cut" />
+ </menu_item_call>
+ <menu_item_call name="copy_landmark" label="Copy Landmark">
+ <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="copy" />
+ </menu_item_call>
+ <menu_item_call name="copy_slurl" label="Copy SLURL">
+ <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="copy_slurl" />
+ </menu_item_call>
+ <menu_item_call name="paste" label="Paste">
+ <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="paste" />
+ <menu_item_call.on_enable function="Places.LandmarksGear.Enable" userdata="paste" />
+ </menu_item_call>
+ <menu_item_call name="rename" label="Rename">
+ <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="rename" />
+ </menu_item_call>
+ <menu_item_call name="delete" label="Delete">
+ <menu_item_call.on_click function="Places.LandmarksGear.CopyPaste.Action" userdata="delete" />
+ </menu_item_call>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call name="expand_all" label="Expand all folders">
+ <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="expand_all" />
+ </menu_item_call>
+ <menu_item_call name="collapse_all" label="Collapse all folders">
+ <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="collapse_all" />
+ </menu_item_call>
+ <menu_item_call name="sort_by_date" label="Sort by Date">
+ <menu_item_call.on_click function="Places.LandmarksGear.Folding.Action" userdata="sort_by_date" />
+ </menu_item_call>
+ <menu_item_separator layout="topleft" />
+ <menu_item_call name="create_pick" label="Create Pick">
+ <menu_item_call.on_click function="Places.LandmarksGear.Custom.Action" userdata="create_pick" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
index f7f08b9b6a..69d90e4c7d 100644
--- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
@@ -38,12 +38,13 @@
width="20" />
<text
follows="left|right"
- font="SansSerifSmallBold"
+ font="SansSerifSmall"
+ font.style="BOLD"
height="20"
layout="topleft"
left_pad="5"
name="avatar_name"
- text_color="white"
+ text_color="grey"
top="4"
use_ellipses="true"
value="Unknown"
diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml
new file mode 100644
index 0000000000..a9f622e018
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="left|top|right"
+ height="57"
+ label="im_header_container"
+ layout="topleft"
+ left="8"
+ name="im_header_container">
+ <panel
+ background_visible="true"
+ bevel_style="in"
+ bg_alpha_color="black"
+ follows="left|top|right"
+ height="30"
+ label="im_header"
+ layout="topleft"
+ name="im_header"
+ top_pad="17">
+ <avatar_icon
+ follows="left"
+ height="20"
+ image_name="icon_avatar_online.tga"
+ layout="topleft"
+ left="5"
+ mouse_opaque="true"
+ name="avatar_icon"
+ top="5"
+ width="20" />
+ <text
+ follows="left|right"
+ font="SansSerifBigBold"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ right="-50"
+ name="user_name"
+ text_color="white"
+ top="5"
+ value="Darth Vader"
+ use_ellipses="true" />
+ <text
+ follows="right"
+ font="SansSerifBig"
+ height="20"
+ layout="topleft"
+ name="time_box"
+ right="0"
+ text_color="white"
+ top="5"
+ value="23:30"
+ width="50" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_chat_separator.xml b/indra/newview/skins/default/xui/en/panel_chat_separator.xml
new file mode 100644
index 0000000000..dd27595cdb
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_chat_separator.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="left|right|top"
+ height="10"
+ layout="topleft"
+ left="8"
+ name="chat_separator_container">
+ <panel
+ background_visible="true"
+ bg_alpha_color="black"
+ follows="left|right|top"
+ height="1"
+ layout="topleft"
+ name="chat_separator_panel"
+ top_pad="5" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml
index ae33d6da3e..7c7561f922 100644
--- a/indra/newview/skins/default/xui/en/panel_landmarks.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml
@@ -1,35 +1,143 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
name="Landmarks"
- bottom="0"
- height="326"
+ top="0"
+ height="400"
+ layout="topleft"
left="0"
width="380"
border="true"
background_visible="true"
bg_alpha_color="DkGray2"
follows="left|top|right|bottom">
- <inventory_panel
- allow_multi_select="true"
- border="true"
- bottom="0"
- follows="left|top|right|bottom"
- height="326"
- left="0"
- mouse_opaque="true"
- name="landmarks_list"
- start_folder="landmark"
- width="380"/>
- <button
- bottom="0"
- halign="center"
- height="16"
- label=">"
- enabled="false"
- mouse_opaque="false"
- name="selector"
- width="20"
- left="0"
- follows="right|bottom"
- tool_tip="View landmark properties"/>
+ <accordion
+ follows="left|top|right|bottom"
+ height="368"
+ layout="topleft"
+ left="0"
+ name="landmarks_accordion"
+ top="2"
+ width="380">
+ <accordion_tab
+ layout="topleft"
+ name="tab_favorites"
+ title="Favorites bar">
+ <inventory_subtree_panel
+ allow_multi_select="true"
+ border="true"
+ bottom="0"
+ follows="left|top|right|bottom"
+ height="126"
+ left="0"
+ mouse_opaque="true"
+ name="favorites_list"
+ width="380"/>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="tab_landmarks"
+ title="Landmarks">
+ <inventory_subtree_panel
+ allow_multi_select="true"
+ border="true"
+ bottom="0"
+ follows="left|top|right|bottom"
+ height="126"
+ left="0"
+ mouse_opaque="true"
+ name="landmarks_list"
+ start_folder="landmark"
+ width="380"/>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="tab_inventory"
+ title="My Inventory">
+ <inventory_subtree_panel
+ allow_multi_select="true"
+ border="true"
+ bottom="0"
+ follows="left|top|right|bottom"
+ height="126"
+ left="0"
+ mouse_opaque="true"
+ name="my_inventory_list"
+ width="380"/>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="tab_library"
+ title="Library">
+ <inventory_subtree_panel
+ allow_multi_select="true"
+ border="true"
+ bottom="0"
+ follows="left|top|right|bottom"
+ height="120"
+ left="0"
+ mouse_opaque="true"
+ name="library_list"
+ width="380"/>
+ </accordion_tab>
+ </accordion>
+ <panel
+ background_visible="true"
+ bevel_style="none"
+ bottom="0"
+ follows="left|right|bottom"
+ height="30"
+ layout="bottomleft"
+ left="0"
+ name="bottom_panel"
+ width="380">
+ <button
+ follows="bottom|left"
+ tool_tip="Show additional options"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="options_gear_btn"
+ picture_style="true"
+ top="6"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="5"
+ name="add_landmark_btn"
+ picture_style="true"
+ tool_tip="Add New Landmark"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="5"
+ name="add_folder_btn"
+ picture_style="true"
+ tool_tip="Add New Folder"
+ width="18" />
+ <button
+ follows="bottom|right"
+ height="18"
+ image_selected="TrashItem_Press"
+ image_unselected="TrashItem_Off"
+ layout="topleft"
+ right="-5"
+ name="trash_btn"
+ picture_style="true"
+ tool_tip="Remove selected Landmark"
+ top="6"
+ width="18" />
+ </panel>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml
new file mode 100644
index 0000000000..4d890b1d46
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_notification.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_opaque="true"
+ background_visible="false"
+ bg_alpha_color="0.3 0.3 0.3 0"
+ height="140"
+ label="notification_panel"
+ layout="topleft"
+ left="0"
+ name="notification_panel"
+ top="0"
+ width="350">
+ <panel
+ background_visible="true"
+ follows="left|right|top"
+ height="100"
+ label="info_panel"
+ layout="topleft"
+ left="0"
+ name="info_panel"
+ top="0"
+ width="350">
+ <text
+ border_visible="false"
+ follows="left|right|top|bottom"
+ font="SansSerif"
+ height="90"
+ layout="topleft"
+ left="45"
+ name="text_box"
+ read_only="true"
+ text_color="white"
+ top="5"
+ visible="false"
+ width="300"
+ wrap="true"/>
+ <text
+ border_visible="false"
+ follows="left|right|top|bottom"
+ font="SansSerifBold"
+ height="90"
+ layout="topleft"
+ left="45"
+ name="caution_text_box"
+ text_color="1 0.82 0.46 1"
+ top="5"
+ visible="false"
+ width="300"
+ wrap="true"/>
+ <text_editor
+ bg_readonly_color="0.0 0.0 0.0 0"
+ border_visible="false"
+ embedded_items="false"
+ enabled="false"
+ follows="left|right|top|bottom"
+ font="SansSerif"
+ height="90"
+ layout="topleft"
+ left="45"
+ mouse_opaque="false"
+ name="text_editor_box"
+ read_only="true"
+ tab_stop="false"
+ text_color="white"
+ text_readonly_color="white"
+ top="5"
+ visible="false"
+ width="300"
+ wrap="true"/>
+ </panel>
+ <panel
+ background_visible="true"
+ follows="left|right|bottom"
+ height="40"
+ label="control_panel"
+ layout="topleft"
+ left="0"
+ name="control_panel"
+ top_pad="0"
+ width="350">
+ </panel>
+ <icon
+ follows="left|top"
+ height="32"
+ image_name="notify_tip_icon.tga"
+ layout="topleft"
+ left="8"
+ mouse_opaque="false"
+ name="info_icon"
+ top="20"
+ width="32" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history.xml b/indra/newview/skins/default/xui/en/panel_teleport_history.xml
index b0cd75117f..4169c6245b 100644
--- a/indra/newview/skins/default/xui/en/panel_teleport_history.xml
+++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml
@@ -1,15 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="Teleport History" bottom="0" height="326" left="0" width="380"
border="true" follows="left|top|right|bottom">
- <string
- name="cant_create_lm_here"
- value="Please teleport to selected location before creating Landmark. " />
- <string
- name="create_landmark"
- value="Create Landmark" />
- <string
- name="open_landmark"
- value="Open Landmark panel" />
<accordion
follows="left|top|right|bottom"
height="300"
@@ -188,19 +179,5 @@
picture_style="true"
top="5"
width="18" />
- <button
- follows="bottom|left"
- font="SansSerifBigBold"
- height="18"
- image_selected="Favorite_Star_Active"
- image_disabled="Favorite_Star_Off"
- image_unselected="Favorite_Star_Press"
- layout="topleft"
- left_pad="5"
- name="star_btn"
- picture_style="true"
- tool_tip=""
- top_delta="0"
- width="18" />
</panel>
</panel>
diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml
new file mode 100644
index 0000000000..b72d59524e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chat_history
+ message_header="panel_chat_header.xml"
+ message_separator="panel_chat_separator.xml"
+ left_text_pad="10"
+ right_text_pad="15"
+ left_widget_pad="5"
+ rigth_widget_pad="10"
+ max_length="2147483647"
+ enabled="false"
+ track_bottom="true"
+ name="chat_history"
+ type="string"
+ word_wrap="true" /> \ No newline at end of file