Merging revisions 2094-2099 of https://svn.aws.productengine.com/secondlife/pe/stable-2 into P:\svn\viewer-2.0.0, respecting ancestry

* Bugs: EXT-1612 EXT-1604 EXT-1163 EXT-1163 EXT-1167
* Dev: EXT-1516
meow-7.2.2
Steven Bennetts 2009-10-21 03:39:04 +00:00
parent b782560865
commit fe9719e804
15 changed files with 324 additions and 11 deletions

View File

@ -134,8 +134,9 @@ LLIMChiclet* LLBottomTray::createIMChiclet(const LLUUID& session_id)
case LLIMChiclet::TYPE_IM:
return getChicletPanel()->createChiclet<LLIMP2PChiclet>(session_id);
case LLIMChiclet::TYPE_GROUP:
case LLIMChiclet::TYPE_AD_HOC:
return getChicletPanel()->createChiclet<LLIMGroupChiclet>(session_id);
case LLIMChiclet::TYPE_AD_HOC:
return getChicletPanel()->createChiclet<LLAdHocChiclet>(session_id);
case LLIMChiclet::TYPE_UNKNOWN:
break;
}

View File

@ -468,6 +468,115 @@ void LLIMP2PChiclet::setShowSpeaker(bool show)
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
LLAdHocChiclet::Params::Params()
: avatar_icon("avatar_icon")
, unread_notifications("unread_notifications")
, speaker("speaker")
, show_speaker("show_speaker")
{
// *TODO Vadim: Get rid of hardcoded values.
rect(LLRect(0, 25, 45, 0));
avatar_icon.name("avatar_icon");
avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
// *NOTE dzaporozhan
// Changed icon height from 25 to 24 to fix ticket EXT-794.
// In some cases(after changing UI scale) 25 pixel height icon was
// drawn incorrectly, i'm not sure why.
avatar_icon.rect(LLRect(0, 24, 25, 0));
avatar_icon.mouse_opaque(false);
unread_notifications.name("unread");
unread_notifications.rect(LLRect(25, 25, 45, 0));
unread_notifications.font(LLFontGL::getFontSansSerif());
unread_notifications.font_halign(LLFontGL::HCENTER);
unread_notifications.v_pad(5);
unread_notifications.text_color(LLColor4::white);
unread_notifications.mouse_opaque(false);
speaker.name("speaker");
speaker.rect(LLRect(45, 25, 65, 0));
show_speaker = false;
}
LLAdHocChiclet::LLAdHocChiclet(const Params& p)
: LLIMChiclet(p)
, mChicletIconCtrl(NULL)
, mCounterCtrl(NULL)
, mSpeakerCtrl(NULL)
, mPopupMenu(NULL)
{
LLChicletAvatarIconCtrl::Params avatar_params = p.avatar_icon;
mChicletIconCtrl = LLUICtrlFactory::create<LLChicletAvatarIconCtrl>(avatar_params);
addChild(mChicletIconCtrl);
LLChicletNotificationCounterCtrl::Params unread_params = p.unread_notifications;
mCounterCtrl = LLUICtrlFactory::create<LLChicletNotificationCounterCtrl>(unread_params);
addChild(mCounterCtrl);
setCounter(getCounter());
setShowCounter(getShowCounter());
LLChicletSpeakerCtrl::Params speaker_params = p.speaker;
mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params);
addChild(mSpeakerCtrl);
setShowSpeaker(p.show_speaker);
}
void LLAdHocChiclet::setSessionId(const LLUUID& session_id)
{
LLChiclet::setSessionId(session_id);
LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
mChicletIconCtrl->setValue(im_session->mOtherParticipantID);
}
void LLAdHocChiclet::setCounter(S32 counter)
{
mCounterCtrl->setCounter(counter);
if(getShowCounter())
{
LLRect counter_rect = mCounterCtrl->getRect();
LLRect required_rect = mCounterCtrl->getRequiredRect();
bool needs_resize = required_rect.getWidth() != counter_rect.getWidth();
if(needs_resize)
{
counter_rect.mRight = counter_rect.mLeft + required_rect.getWidth();
mCounterCtrl->reshape(counter_rect.getWidth(), counter_rect.getHeight());
mCounterCtrl->setRect(counter_rect);
onChicletSizeChanged();
}
}
}
LLRect LLAdHocChiclet::getRequiredRect()
{
LLRect rect(0, 0, mChicletIconCtrl->getRect().getWidth(), 0);
if(getShowCounter())
{
rect.mRight += mCounterCtrl->getRequiredRect().getWidth();
}
if(getShowSpeaker())
{
rect.mRight += mSpeakerCtrl->getRect().getWidth();
}
return rect;
}
BOOL LLAdHocChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
{
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
LLIMGroupChiclet::Params::Params()
: group_icon("group_icon")
{

View File

@ -441,6 +441,65 @@ private:
LLMenuGL* mPopupMenu;
};
/**
* Implements AD-HOC chiclet.
*/
class LLAdHocChiclet : public LLIMChiclet
{
public:
struct Params : public LLInitParam::Block<Params, LLChiclet::Params>
{
Optional<LLChicletAvatarIconCtrl::Params> avatar_icon;
Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications;
Optional<LLChicletSpeakerCtrl::Params> speaker;
Optional<bool> show_speaker;
Params();
};
/**
* Sets session id.
* Session ID for group chat is actually Group ID.
*/
/*virtual*/ void setSessionId(const LLUUID& session_id);
/*
* Sets number of unread messages. Will update chiclet's width if number text
* exceeds size of counter and notify it's parent about size change.
*/
/*virtual*/ void setCounter(S32);
/*
* Returns number of unread messages.
*/
/*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); }
/*
* Returns rect, required to display chiclet.
* Width is the only valid value.
*/
/*virtual*/ LLRect getRequiredRect();
protected:
LLAdHocChiclet(const Params& p);
friend class LLUICtrlFactory;
/*
* Displays popup menu.
*/
virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
private:
LLChicletAvatarIconCtrl* mChicletIconCtrl;
LLChicletNotificationCounterCtrl* mCounterCtrl;
LLChicletSpeakerCtrl* mSpeakerCtrl;
LLMenuGL* mPopupMenu;
};
/**
* Implements Group chat chiclet.
*/

View File

@ -125,6 +125,12 @@ void LLFloaterCamera::onOpen(const LLSD& key)
}
void LLFloaterCamera::onClose(bool app_quitting)
{
//We don't care of camera mode if app is quitting
if(!app_quitting)
switchMode(CAMERA_CTRL_MODE_ORBIT);
}
LLFloaterCamera::LLFloaterCamera(const LLSD& val)
: LLDockableFloater(NULL, val),

View File

@ -69,6 +69,7 @@ public:
static void updateIfNotInAvatarViewMode();
virtual void onOpen(const LLSD& key);
virtual void onClose(bool app_quitting);
LLJoystickCameraRotate* mRotate;
LLJoystickCameraZoom* mZoom;

View File

@ -1240,7 +1240,9 @@ BOOL LLFolderView::canCut() const
{
const LLFolderViewItem* item = *selected_it;
const LLFolderViewEventListener* listener = item->getListener();
if (!listener || !listener->isItemMovable())
// *WARKAROUND: it is too many places where the "isItemRemovable" method should be changed with "const" modifier
if (!listener || !(const_cast<LLFolderViewEventListener*>(listener))->isItemRemovable())
{
return FALSE;
}

View File

@ -202,6 +202,7 @@ public:
virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
virtual S32 getItemHeight();
void setDontShowInHierarchy(bool dont_show) { mDontShowInHierarhy = dont_show; }
bool getDontShowInHierarchy() { return mDontShowInHierarhy; }
// applies filters to control visibility of inventory items
virtual void filter( LLInventoryFilter& filter);

View File

@ -1547,6 +1547,12 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
// BAP - restrictions?
is_movable = true;
}
if (mUUID == gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE))
{
is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604
}
if( is_movable )
{
gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE );

View File

@ -213,6 +213,17 @@ bool LLLandmarksPanel::isLandmarkSelected() const
return false;
}
bool LLLandmarksPanel::isReceivedFolderSelected() const
{
// Received Folder can be only in Landmarks accordion
if (mCurrentSelectedList != mLandmarksInventoryPanel) return false;
// *TODO: it should be filled with logic when EXT-976 is done.
llwarns << "Not implemented yet until EXT-976 is done." << llendl;
return false;
}
LLLandmark* LLLandmarksPanel::getCurSelectedLandmark() const
{
@ -612,13 +623,19 @@ void LLLandmarksPanel::onFoldingAction(const LLSD& userdata)
bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
{
std::string command_name = userdata.asString();
LLPlacesFolderView* rootFolderView = mCurrentSelectedList ?
static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder()) : NULL;
if (NULL == rootFolderView) return false;
if("category" == command_name)
{
return mCurrentSelectedList == mLandmarksInventoryPanel;
}
else if("paste" == command_name)
else if("paste" == command_name || "rename" == command_name || "cut" == command_name || "delete" == command_name)
{
return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->canPaste() : false;
return canSelectedBeModified(command_name);
}
else if ( "sort_by_date" == command_name)
{
@ -627,14 +644,17 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
// do not allow teleport and more info for multi-selections
else if ("teleport" == command_name || "more_info" == command_name)
{
return mCurrentSelectedList ?
static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder())->getSelectedCount() == 1 : false;
return rootFolderView->getSelectedCount() == 1;
}
// we can add folder, or change item/folder only in Landmarks Accordion
else if ("add_folder" == command_name || "rename" == command_name || "delete" == command_name)
else if ("add_folder" == command_name)
{
return mLandmarksInventoryPanel == mCurrentSelectedList;
}
else
{
llwarns << "Unprocessed command has come: " << command_name << llendl;
}
return true;
}
@ -698,6 +718,75 @@ void LLLandmarksPanel::onCustomAction(const LLSD& userdata)
}
}
/*
Processes such actions: cut/rename/delete/paste actions
Rules:
1. We can't perform any action in Library
2. For Landmarks we can:
- cut/rename/delete in any other accordions
- paste - only in Favorites, Landmarks accordions
3. For Folders we can: perform any action in Landmarks accordion, except Received folder
4. We can not paste folders from Clipboard (processed by LLFolderView::canPaste())
5. Check LLFolderView/Inventory Bridges rules
*/
bool LLLandmarksPanel::canSelectedBeModified(const std::string& command_name) const
{
// validate own rules first
// nothing can be modified in Library
if (mLibraryInventoryPanel == mCurrentSelectedList) return false;
bool can_be_modified = false;
// landmarks can be modified in any other accordion...
if (isLandmarkSelected())
{
can_be_modified = true;
// we can modify landmarks anywhere except paste to My Inventory
if ("paste" == command_name)
{
can_be_modified = (mCurrentSelectedList != mMyInventoryPanel);
}
}
else
{
// ...folders only in the Landmarks accordion...
can_be_modified = mLandmarksInventoryPanel == mCurrentSelectedList;
// ...except "Received" folder
can_be_modified &= !isReceivedFolderSelected();
}
// then ask LLFolderView permissions
if (can_be_modified)
{
if ("cut" == command_name)
{
can_be_modified = mCurrentSelectedList->getRootFolder()->canCut();
}
else if ("rename" == command_name)
{
can_be_modified = getCurSelectedItem()->getListener()->isItemRenameable();
}
else if ("delete" == command_name)
{
can_be_modified = getCurSelectedItem()->getListener()->isItemRemovable();
}
else if("paste" == command_name)
{
return mCurrentSelectedList->getRootFolder()->canPaste();
}
else
{
llwarns << "Unprocessed command has come: " << command_name << llendl;
}
}
return can_be_modified;
}
void LLLandmarksPanel::onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params)
{
pick_panel->setVisible(FALSE);

View File

@ -66,6 +66,7 @@ protected:
* @return true - if current selected panel is not null and selected item is a landmark
*/
bool isLandmarkSelected() const;
bool isReceivedFolderSelected() const;
LLLandmark* getCurSelectedLandmark() const;
LLFolderViewItem* getCurSelectedItem () const;
void updateSortOrder(LLInventoryPanel* panel, bool byDate);
@ -97,6 +98,14 @@ private:
void onFoldingAction(const LLSD& command_name);
bool isActionEnabled(const LLSD& command_name) const;
void onCustomAction(const LLSD& command_name);
/**
* Determines if selected item can be modified via context/gear menu.
*
* It validates Places Landmarks rules first. And then LLFolderView permissions.
* For now it checks cut/rename/delete/paste actions.
*/
bool canSelectedBeModified(const std::string& command_name) const;
void onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params);
private:

View File

@ -91,7 +91,12 @@ void* LLPanelPicks::create(void* data /* = NULL */)
void LLPanelPicks::updateData()
{
LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId());
// Send Picks request only when we need to, not on every onOpen(during tab switch).
if(isDirty())
{
mPicksList->clear();
LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId());
}
}
void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
@ -134,6 +139,7 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
picture->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this));
}
resetDirty();
LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this);
updateButtons();
}
@ -183,8 +189,6 @@ void LLPanelPicks::onOpen(const LLSD& key)
// Disable buttons when viewing profile for first time
if(getAvatarId() != id)
{
clear();
childSetEnabled(XML_BTN_INFO,FALSE);
childSetEnabled(XML_BTN_TELEPORT,FALSE);
childSetEnabled(XML_BTN_SHOW_ON_MAP,FALSE);
@ -204,6 +208,8 @@ void LLPanelPicks::onOpen(const LLSD& key)
if(getAvatarId() != id)
{
mPicksList->goToTop();
// Set dummy value to make panel dirty and make it reload picks
setValue(LLSD());
}
LLPanelProfileTab::onOpen(key);

View File

@ -192,8 +192,9 @@ void LLPanelProfile::openPanel(LLPanel* panel, const LLSD& params)
void LLPanelProfile::notifyParent(const LLSD& info)
{
std::string action = info["action"];
// lets update Picks list after Pick was saved
if("save_new_pick" == info["action"])
if("save_new_pick" == action)
{
onOpen(info);
return;

View File

@ -46,6 +46,7 @@ static LLRegisterPanelClassWrapper<LLPanelProfileView> t_panel_target_profile("p
static std::string PANEL_NOTES = "panel_notes";
static const std::string PANEL_PROFILE = "panel_profile";
static const std::string PANEL_PICKS = "panel_picks";
LLPanelProfileView::LLPanelProfileView()
: LLPanelProfile()
@ -103,6 +104,10 @@ BOOL LLPanelProfileView::postBuild()
void LLPanelProfileView::onBackBtnClick()
{
// Set dummy value to make picks panel dirty,
// This will make Picks reload on next open.
getTabContainer()[PANEL_PICKS]->setValue(LLSD());
LLSideTrayPanelContainer* parent = dynamic_cast<LLSideTrayPanelContainer*>(getParent());
if(parent)
{

View File

@ -34,6 +34,9 @@
<on_click
function="Places.LandmarksGear.CopyPaste.Action"
parameter="cut" />
<on_enable
function="Places.LandmarksGear.Enable"
parameter="cut" />
</menu_item_call>
<menu_item_call
label="Copy"
@ -61,6 +64,9 @@
<on_click
function="Places.LandmarksGear.CopyPaste.Action"
parameter="rename" />
<on_enable
function="Places.LandmarksGear.Enable"
parameter="rename" />
</menu_item_call>
<menu_item_call
label="Delete"
@ -69,6 +75,9 @@
<on_click
function="Places.LandmarksGear.CopyPaste.Action"
parameter="delete" />
<on_enable
function="Places.LandmarksGear.Enable"
parameter="delete" />
</menu_item_call>
<menu_item_separator
layout="topleft" />

View File

@ -66,6 +66,9 @@
<on_click
function="Places.LandmarksGear.CopyPaste.Action"
parameter="cut" />
<on_enable
function="Places.LandmarksGear.Enable"
parameter="cut" />
</menu_item_call>
<menu_item_call
label="Copy Landmark"
@ -101,6 +104,9 @@
<on_click
function="Places.LandmarksGear.CopyPaste.Action"
parameter="rename" />
<on_enable
function="Places.LandmarksGear.Enable"
parameter="rename" />
</menu_item_call>
<menu_item_call
label="Delete"
@ -109,6 +115,9 @@
<on_click
function="Places.LandmarksGear.CopyPaste.Action"
parameter="delete" />
<on_enable
function="Places.LandmarksGear.Enable"
parameter="delete" />
</menu_item_call>
<menu_item_separator
layout="topleft" />