Merging revisions 2046-2068 of https://svn.aws.productengine.com/secondlife/pe/stable-2 into P:\svn\viewer-2.0.0, respecting ancestry
* Bugs: EXT-1414 EXT-1213 EXT-1539 EXT-1253 EXT-1446 EXT-1438 EXT-1233 EXT-1466 EXT-1446 EXT-1512 EXT-1231 * Dev: EXT-719 (landmarks) EXT-747 EXT-1446 EXT-1378 EXT-397 EXT-1476 * IM changesmaster
parent
4ee757b45d
commit
8103710c05
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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) {}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,6 @@ public:
|
|||
const std::string& getLastName() const { return mLastName; }
|
||||
|
||||
protected:
|
||||
LLIconCtrl* mStatusSymbol;
|
||||
LLUUID mAvatarId;
|
||||
std::string mFirstName;
|
||||
std::string mLastName;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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&);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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_ */
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
@ -911,6 +922,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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID);
|
||||
if (NULL == item)
|
||||
return false;
|
||||
|
||||
const LLUUID& asset_id = item->getAssetUUID();
|
||||
LLLandmark* landmark = gLandmarkList.getAsset(asset_id, NULL);
|
||||
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();
|
||||
return gLandmarkList.getAsset(asset_id, NULL);
|
||||
}
|
||||
|
||||
void LLLandmarkActions::copySLURLtoClipboard(const LLUUID& landmarkInventoryItemID)
|
||||
{
|
||||
LLLandmark* landmark = LLLandmarkActions::getLandmark(landmarkInventoryItemID);
|
||||
if(landmark)
|
||||
{
|
||||
LLVector3d global_pos;
|
||||
landmark->getGlobalPos(global_pos);
|
||||
LLLandmarkActions::getSLURLfromPosGlobal(global_pos,©_slurl_to_clipboard_callback,true);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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&);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
LLLandmarksPanel::LLLandmarksPanel()
|
||||
: LLPanelPlacesTab(),
|
||||
mInventoryPanel(NULL)
|
||||
{
|
||||
mSavedFolderState = new LLSaveFolderState();
|
||||
mSavedFolderState->setApply(FALSE);
|
||||
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()
|
||||
, mFavoritesInventoryPanel(NULL)
|
||||
, mLandmarksInventoryPanel(NULL)
|
||||
, mMyInventoryPanel(NULL)
|
||||
, mLibraryInventoryPanel(NULL)
|
||||
, mCurrentSelectedList(NULL)
|
||||
, mListCommands(NULL)
|
||||
, mGearFolderMenu(NULL)
|
||||
, mGearLandmarkMenu(NULL)
|
||||
{
|
||||
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)
|
||||
if (NULL == mCurrentSelectedList)
|
||||
{
|
||||
llwarns << "There are no selected list. No actions are performed." << llendl;
|
||||
return;
|
||||
|
||||
LLFolderViewEventListener* listenerp = current_item->getListener();
|
||||
if (listenerp->getInventoryType() != LLInventoryType::IT_LANDMARK)
|
||||
return;
|
||||
|
||||
LLInventoryItem* inventory_item = gInventory.getItem(listenerp->getUUID());
|
||||
if (!inventory_item)
|
||||
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,104 +147,43 @@ void LLLandmarksPanel::onTeleport()
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// virtual
|
||||
void LLLandmarksPanel::onCopySLURL()
|
||||
{
|
||||
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)
|
||||
return;
|
||||
|
||||
LLLandmark* landmark = gLandmarkList.getAsset(inventory_item->getAssetUUID());
|
||||
if (!landmark)
|
||||
return;
|
||||
|
||||
LLVector3d landmark_global_pos;
|
||||
if (!landmark->getGlobalPos(landmark_global_pos))
|
||||
return;
|
||||
|
||||
U64 new_region_handle = to_region_handle(landmark_global_pos);
|
||||
|
||||
LLWorldMap::url_callback_t cb = boost::bind(
|
||||
&LLPanelPlacesTab::onRegionResponse, this,
|
||||
landmark_global_pos, _1, _2, _3, _4);
|
||||
|
||||
LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, cb, std::string("unused"), false);
|
||||
}
|
||||
*/
|
||||
|
||||
// virtual
|
||||
void LLLandmarksPanel::updateVerbs()
|
||||
{
|
||||
if (!isTabVisible())
|
||||
return;
|
||||
|
||||
BOOL enabled = FALSE;
|
||||
|
||||
LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
|
||||
if (current_item)
|
||||
{
|
||||
LLFolderViewEventListener* listenerp = current_item->getListener();
|
||||
if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
|
||||
{
|
||||
enabled = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL enabled = isLandmarkSelected();
|
||||
mTeleportBtn->setEnabled(enabled);
|
||||
mShowOnMapBtn->setEnabled(enabled);
|
||||
|
||||
// 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);
|
||||
|
||||
updateListCommands();
|
||||
}
|
||||
|
||||
void LLLandmarksPanel::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
|
||||
void LLLandmarksPanel::onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
|
||||
{
|
||||
LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
|
||||
if (user_action && (items.size() > 0))
|
||||
{
|
||||
deselectOtherThan(inventory_list);
|
||||
mCurrentSelectedList = inventory_list;
|
||||
}
|
||||
|
||||
LLFolderViewItem* current_item = inventory_list->getRootFolder()->getCurSelectedItem();
|
||||
if (!current_item)
|
||||
return;
|
||||
|
||||
LLFolderViewEventListener* listenerp = current_item->getListener();
|
||||
if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
|
||||
{
|
||||
S32 bottom = 0;
|
||||
LLFolderViewItem* folder = current_item->getParentFolder();
|
||||
|
||||
while ( folder->getParentFolder() != NULL )
|
||||
{
|
||||
bottom += folder->getRect().mBottom;
|
||||
folder = folder->getParentFolder();
|
||||
}
|
||||
|
||||
LLRect rect = current_item->getRect();
|
||||
LLRect btn_rect(
|
||||
rect.mRight - mActionBtn->getRect().getWidth(),
|
||||
bottom + rect.mTop,
|
||||
rect.mRight,
|
||||
bottom + rect.mBottom);
|
||||
|
||||
mActionBtn->setRect(btn_rect);
|
||||
|
||||
if (!mActionBtn->getVisible())
|
||||
mActionBtn->setVisible(TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mActionBtn->getVisible())
|
||||
mActionBtn->setVisible(FALSE);
|
||||
}
|
||||
|
||||
updateVerbs();
|
||||
}
|
||||
|
||||
void LLLandmarksPanel::onSelectorButtonClicked()
|
||||
{
|
||||
LLFolderViewItem* cur_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
|
||||
// TODO: mantipov: update getting of selected item
|
||||
// TODO: bind to "i" button
|
||||
LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem();
|
||||
|
||||
LLFolderViewEventListener* listenerp = cur_item->getListener();
|
||||
if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
|
||||
|
|
@ -274,7 +196,497 @@ void LLLandmarksPanel::onSelectorButtonClicked()
|
|||
}
|
||||
}
|
||||
|
||||
void LLLandmarksPanel::setSelectedItem(const LLUUID& obj_id)
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// PROTECTED METHODS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool LLLandmarksPanel::isLandmarkSelected() const
|
||||
{
|
||||
mInventoryPanel->setSelection(obj_id, FALSE);
|
||||
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::processParcelInfo(const LLParcelData& parcel_data)
|
||||
{
|
||||
//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");
|
||||
|
||||
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();
|
||||
|
||||
if (current_item)
|
||||
{
|
||||
LLFolderViewEventListener* listenerp = current_item->getListener();
|
||||
if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
|
||||
{
|
||||
trash_enabled = mCurrentSelectedList != mLibraryInventoryPanel;
|
||||
}
|
||||
}
|
||||
|
||||
// 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::onActionsButtonClick()
|
||||
{
|
||||
LLFolderViewItem* cur_item = NULL;
|
||||
if(mCurrentSelectedList)
|
||||
cur_item = mCurrentSelectedList->getRootFolder()->getCurSelectedItem();
|
||||
|
||||
if(!cur_item)
|
||||
return;
|
||||
|
||||
LLFolderViewEventListener* listenerp = cur_item->getListener();
|
||||
|
||||
LLMenuGL* menu =NULL;
|
||||
if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
parentBridge = dynamic_cast<LLFolderBridge*>(item->getListener());
|
||||
gFocusMgr.setKeyboardFocus(item);
|
||||
}
|
||||
menu_create_inventory_item(mCurrentSelectedList->getRootFolder(),parentBridge, LLSD("category"));
|
||||
}
|
||||
}
|
||||
|
||||
void LLLandmarksPanel::onTrashButtonClick() const
|
||||
{
|
||||
if(!mCurrentSelectedList) return;
|
||||
|
||||
mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(), "delete");
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(),command_name);
|
||||
}
|
||||
}
|
||||
|
||||
void LLLandmarksPanel::onFoldingAction(const LLSD& userdata) const
|
||||
{
|
||||
if(!mCurrentSelectedList) return;
|
||||
|
||||
LLFolderView* root_folder = mCurrentSelectedList->getRootFolder();
|
||||
std::string command_name = userdata.asString();
|
||||
|
||||
if ("expand_all" == command_name)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// HELPER FUNCTIONS
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string)
|
||||
{
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
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:
|
||||
LLInventoryPanel* mInventoryPanel;
|
||||
LLSaveFolderState* mSavedFolderState;
|
||||
LLButton* mActionBtn;
|
||||
LLInventorySubTreePanel* mFavoritesInventoryPanel;
|
||||
LLInventorySubTreePanel* mLandmarksInventoryPanel;
|
||||
LLInventorySubTreePanel* mMyInventoryPanel;
|
||||
LLInventorySubTreePanel* mLibraryInventoryPanel;
|
||||
LLMenuGL* mGearLandmarkMenu;
|
||||
LLMenuGL* mGearFolderMenu;
|
||||
LLInventorySubTreePanel* mCurrentSelectedList;
|
||||
|
||||
LLPanel* mListCommands;
|
||||
};
|
||||
|
||||
#endif //LL_LLPANELLANDMARKS_H
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include "llpanel.h"
|
||||
#include "llremoteparcelrequest.h"
|
||||
#include "llavatarpropertiesprocessor.h"
|
||||
|
||||
class LLTextureCtrl;
|
||||
class LLMessageSystem;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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,12 +283,18 @@ 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)
|
||||
{
|
||||
|
|
@ -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);
|
||||
|
||||
if (NULL != itemp)
|
||||
{
|
||||
LLViewerInventoryItem *landmark = LLLandmarkActions::findLandmarkForGlobalPos(
|
||||
mTeleportHistory->getItems()[itemp->getIndex()].mGlobalPos);
|
||||
|
||||
mStarButton->setEnabled(true);
|
||||
if (!landmark || landmark->getUUID().isNull())
|
||||
{
|
||||
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"));
|
||||
}
|
||||
else
|
||||
{
|
||||
mStarButton->setToggleState(false);
|
||||
mStarButton->setToolTip(getString("open_landmark"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mStarButton->setEnabled(false);
|
||||
mStarButton->setToolTip(LLStringExplicit(""));
|
||||
}
|
||||
}
|
||||
|
||||
void LLTeleportHistoryPanel::showTeleportHistory()
|
||||
void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, LLDate& tab_date)
|
||||
{
|
||||
if (!mHistoryAccordion)
|
||||
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);
|
||||
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);
|
||||
|
||||
tab_idx = -1;
|
||||
|
||||
while (tab_idx < tabs_cnt - 1 && item_date < tab_date)
|
||||
{
|
||||
tab_idx++;
|
||||
|
||||
if (tab_idx <= tabs_cnt - 4)
|
||||
{
|
||||
tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() - seconds_in_day);
|
||||
}
|
||||
else if (tab_idx == tabs_cnt - 3) // 6 day and older, low boundary is 1 month
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLTeleportHistoryPanel::refresh()
|
||||
{
|
||||
if (!mHistoryAccordion)
|
||||
{
|
||||
mDirty = false;
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
continue;
|
||||
|
||||
if (curr_tab < tabs_cnt - 1)
|
||||
{
|
||||
const LLDate &date = (*iter).mDate;
|
||||
mCurrentItem--;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (date < curr_date)
|
||||
{
|
||||
LLAccordionCtrlTab* tab = NULL;
|
||||
while (curr_tab < tabs_cnt - 1 && date < curr_date)
|
||||
{
|
||||
curr_tab++;
|
||||
const LLDate &date = items[mCurrentItem].mDate;
|
||||
|
||||
tab = mItemContainers.get(mItemContainers.size() - 1 - curr_tab);
|
||||
tab->setVisible(false);
|
||||
if (date < tab_boundary_date)
|
||||
{
|
||||
S32 tab_idx = 0;
|
||||
getNextTab(date, tab_idx, tab_boundary_date);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
LLAccordionCtrlTab* tab = mItemContainers.get(mItemContainers.size() - 1 - tab_idx);
|
||||
tab->setVisible(true);
|
||||
|
||||
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));
|
||||
|
||||
// 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);
|
||||
mCurrentItem--;
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
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");
|
||||
|
||||
// customize panel's attributes
|
||||
// is it intended for displaying a tip
|
||||
mIsTip = notification->getType() == "notifytip";
|
||||
mNumOptions = 0;
|
||||
mNumButtons = 0;
|
||||
mIsScriptDialog = (notification->getName() == "ScriptDialog"
|
||||
|| notification->getName() == "ScriptDialogGroup");
|
||||
mAddedDefaultBtn = false;
|
||||
// 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;
|
||||
|
||||
// clicking on a button does not steal current focus
|
||||
setIsChrome(TRUE);
|
||||
|
||||
// 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,136 +150,62 @@ 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");
|
||||
}
|
||||
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)
|
||||
{
|
||||
num_options = 1;
|
||||
}
|
||||
|
||||
// Add two "blank" option spaces.
|
||||
if (mIsScriptDialog)
|
||||
{
|
||||
num_options += 2;
|
||||
}
|
||||
|
||||
S32 additional_lines = (num_options-1) / 3;
|
||||
|
||||
notify_height += additional_lines * (BTN_HEIGHT + VPAD);
|
||||
|
||||
return LLRect(LEFT, TOP, RIGHT, TOP-notify_height);
|
||||
}
|
||||
|
||||
// static
|
||||
LLRect LLToastNotifyPanel::getNotifyTipRect(const std::string &utf8message)
|
||||
{
|
||||
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 )
|
||||
if (form->getElement(i)["type"].asString() == "button")
|
||||
{
|
||||
end = wchars + message_len;
|
||||
done = TRUE;
|
||||
buttons_num++;
|
||||
}
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
const S32 MIN_NOTIFY_HEIGHT = 72;
|
||||
const S32 MAX_NOTIFY_HEIGHT = 600;
|
||||
S32 notify_height = llceil((F32) (line_count+1) * sFont->getLineHeight());
|
||||
if(gOverlayBar)
|
||||
// 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)
|
||||
{
|
||||
notify_height += gOverlayBar->getBoundingRect().mTop;
|
||||
button_rows = llceil((buttons_num - 1) / 3.0f) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// *FIX: this is derived from the padding caused by the
|
||||
// rounded rects, shouldn't be a const here.
|
||||
notify_height += 10;
|
||||
button_rows = llmax( 1, llceil(buttons_num / 3.0f));
|
||||
}
|
||||
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;
|
||||
S32 button_panel_height = button_rows * BTN_HEIGHT + (button_rows + 1) * VPAD + BOTTOM_PAD;
|
||||
|
||||
return LLRect(LEFT, notify_height, RIGHT, 0);
|
||||
//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
|
||||
void LLToastNotifyPanel::adjustPanelForTipNotice()
|
||||
{
|
||||
LLRect info_rect = mInfoPanel->getRect();
|
||||
LLRect this_rect = getRect();
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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" />
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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" />
|
||||
Loading…
Reference in New Issue