From 59f61e2ff2f6cedb480d691f130a8d5e6b16c302 Mon Sep 17 00:00:00 2001
From: Andrey Kleshchev <andreykproductengine@lindenlab.com>
Date: Mon, 22 Feb 2021 21:34:17 +0200
Subject: SL-14842 Apply toolstrip layout to Places floater Part #1

Menus
---
 indra/newview/llpanellandmarks.cpp                 | 163 +++++-----
 indra/newview/llpanellandmarks.h                   |  44 +--
 indra/newview/llpanelplaces.cpp                    |  85 ++++-
 indra/newview/llpanelplaces.h                      |  12 +
 indra/newview/llpanelplacestab.h                   |  12 +
 indra/newview/llpanelteleporthistory.cpp           | 346 +++++++++++----------
 indra/newview/llpanelteleporthistory.h             |  50 ++-
 .../skins/default/xui/en/menu_place_add_button.xml |  23 +-
 .../default/xui/en/menu_places_gear_folder.xml     |  33 --
 .../default/xui/en/menu_places_gear_landmark.xml   |  38 ---
 .../default/xui/en/menu_places_gear_sorting.xml    |  43 +++
 .../default/xui/en/menu_teleport_history_gear.xml  |  12 +-
 .../default/xui/en/menu_teleport_history_item.xml  |  37 ++-
 .../skins/default/xui/en/panel_landmarks.xml       | 102 +-----
 .../newview/skins/default/xui/en/panel_places.xml  | 129 +++++++-
 .../default/xui/en/panel_teleport_history.xml      |  35 +--
 16 files changed, 618 insertions(+), 546 deletions(-)
 create mode 100644 indra/newview/skins/default/xui/en/menu_places_gear_sorting.xml

(limited to 'indra')

diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 7eda9c1aa7..3902c615a1 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -42,7 +42,6 @@
 #include "llagentui.h"
 #include "llavataractions.h"
 #include "llcallbacklist.h"
-#include "lldndbutton.h"
 #include "llfloatersidepanelcontainer.h"
 #include "llfloaterworldmap.h"
 #include "llfolderviewitem.h"
@@ -61,12 +60,6 @@
 // Not yet implemented; need to remove buildPanel() from constructor when we switch
 //static LLRegisterPanelClassWrapper<LLLandmarksPanel> t_landmarks("panel_landmarks");
 
-static const std::string OPTIONS_BUTTON_NAME = "options_gear_btn";
-static const std::string ADD_BUTTON_NAME = "add_btn";
-static const std::string ADD_FOLDER_BUTTON_NAME = "add_folder_btn";
-static const std::string TRASH_BUTTON_NAME = "trash_btn";
-
-
 // helper functions
 static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string);
 static bool category_has_descendents(LLPlacesInventoryPanel* inventory_list);
@@ -196,10 +189,10 @@ LLLandmarksPanel::LLLandmarksPanel()
 	,	mMyInventoryPanel(NULL)
 	,	mLibraryInventoryPanel(NULL)
 	,	mCurrentSelectedList(NULL)
-	,	mListCommands(NULL)
-	,	mGearButton(NULL)
 	,	mGearFolderMenu(NULL)
 	,	mGearLandmarkMenu(NULL)
+	,	mSortingMenu(NULL)
+	,	mAddMenu(NULL)
 {
 	mInventoryObserver = new LLLandmarksPanelObserver(this);
 	gInventory.addObserver(mInventoryObserver);
@@ -304,6 +297,12 @@ void LLLandmarksPanel::onTeleport()
 	}
 }
 
+/*virtual*/
+void LLLandmarksPanel::onRemoveSelected()
+{
+    onClipboardAction("delete");
+}
+
 // virtual
 bool LLLandmarksPanel::isSingleItemSelected()
 {
@@ -322,6 +321,37 @@ bool LLLandmarksPanel::isSingleItemSelected()
 	return result;
 }
 
+// virtual
+LLToggleableMenu* LLLandmarksPanel::getSelectionMenu()
+{
+    LLToggleableMenu* menu = mGearFolderMenu;
+
+    if (mCurrentSelectedList)
+    {
+        LLFolderViewModelItemInventory* listenerp = getCurSelectedViewModelItem();
+        if (!listenerp)
+            return menu;
+
+        if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
+        {
+            menu = mGearLandmarkMenu;
+        }
+    }
+    return menu;
+}
+
+// virtual
+LLToggleableMenu* LLLandmarksPanel::getSortingMenu()
+{
+    return mSortingMenu;
+}
+
+// virtual
+LLToggleableMenu* LLLandmarksPanel::getCreateMenu()
+{
+    return mAddMenu;
+}
+
 // virtual
 void LLLandmarksPanel::updateVerbs()
 {
@@ -336,8 +366,6 @@ void LLLandmarksPanel::updateVerbs()
 	// 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(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
@@ -668,40 +696,29 @@ void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory
 	if (inventory_list != mFavoritesInventoryPanel)
 	{
 		mFavoritesInventoryPanel->clearSelection();
+		mFavoritesInventoryPanel->getRootFolder()->clearSelection();
 	}
 
 	if (inventory_list != mLandmarksInventoryPanel)
 	{
 		mLandmarksInventoryPanel->clearSelection();
+		mLandmarksInventoryPanel->getRootFolder()->clearSelection();
 	}
 	if (inventory_list != mMyInventoryPanel)
 	{
 		mMyInventoryPanel->clearSelection();
+		mMyInventoryPanel->getRootFolder()->clearSelection();
 	}
 	if (inventory_list != mLibraryInventoryPanel)
 	{
 		mLibraryInventoryPanel->clearSelection();
+		mLibraryInventoryPanel->getRootFolder()->clearSelection();
 	}
 }
 
 // List Commands Handlers
 void LLLandmarksPanel::initListCommandsHandlers()
 {
-	mListCommands = getChild<LLPanel>("bottom_panel");
-
-	mGearButton = getChild<LLMenuButton>(OPTIONS_BUTTON_NAME);
-	mGearButton->setMouseDownCallback(boost::bind(&LLLandmarksPanel::onActionsButtonClick, this));
-
-	mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this));
-
-	LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>(TRASH_BUTTON_NAME);
-	trash_btn->setDragAndDropHandler(boost::bind(&LLLandmarksPanel::handleDragAndDropToTrash, this
-			,	_4 // BOOL drop
-			,	_5 // EDragAndDropType cargo_type
-			,	_6 // void* cargo_data
-			,	_7 // EAcceptance* accept
-			));
-
 	mCommitCallbackRegistrar.add("Places.LandmarksGear.Add.Action", boost::bind(&LLLandmarksPanel::onAddAction, this, _2));
 	mCommitCallbackRegistrar.add("Places.LandmarksGear.CopyPaste.Action", boost::bind(&LLLandmarksPanel::onClipboardAction, this, _2));
 	mCommitCallbackRegistrar.add("Places.LandmarksGear.Custom.Action", boost::bind(&LLLandmarksPanel::onCustomAction, this, _2));
@@ -710,23 +727,15 @@ void LLLandmarksPanel::initListCommandsHandlers()
 	mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2));
 	mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
-	mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	mSortingMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_places_gear_sorting.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+	mAddMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_place_add_button.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 
 	mGearLandmarkMenu->setVisibilityChangeCallback(boost::bind(&LLLandmarksPanel::onMenuVisibilityChange, this, _1, _2));
 	mGearFolderMenu->setVisibilityChangeCallback(boost::bind(&LLLandmarksPanel::onMenuVisibilityChange, this, _1, _2));
 
-	mListCommands->childSetAction(ADD_BUTTON_NAME, boost::bind(&LLLandmarksPanel::showActionMenu, this, mMenuAdd, ADD_BUTTON_NAME));
-}
-
-
-void LLLandmarksPanel::updateListCommands()
-{
-	bool add_folder_enabled = isActionEnabled("category");
-	bool trash_enabled = isActionEnabled("delete") && (isFolderSelected() || isLandmarkSelected());
-
-	// keep Options & Add Landmark buttons always enabled
-	mListCommands->getChildView(ADD_FOLDER_BUTTON_NAME)->setEnabled(add_folder_enabled);
-	mListCommands->getChildView(TRASH_BUTTON_NAME)->setEnabled(trash_enabled);
+	// show menus even if all items are disabled
+	mGearLandmarkMenu->setAlwaysShowMenu(TRUE);
+	mGearFolderMenu->setAlwaysShowMenu(TRUE);
 }
 
 void LLLandmarksPanel::updateMenuVisibility(LLUICtrl* menu)
@@ -734,43 +743,6 @@ void LLLandmarksPanel::updateMenuVisibility(LLUICtrl* menu)
 	onMenuVisibilityChange(menu, LLSD().with("visibility", true));
 }
 
-void LLLandmarksPanel::onActionsButtonClick()
-{
-	LLToggleableMenu* menu = mGearFolderMenu;
-
-	if(mCurrentSelectedList)
-	{
-		LLFolderViewModelItemInventory* listenerp = getCurSelectedViewModelItem();
-		if(!listenerp)
-			return;
-
-		if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
-		{
-			menu = mGearLandmarkMenu;
-		}
-	}
-
-	mGearButton->setMenu(menu);
-}
-
-void LLLandmarksPanel::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
-{
-	if (menu)
-	{
-		menu->buildDrawLabels();
-		menu->updateParent(LLMenuGL::sMenuContainer);
-		menu->arrangeAndClear();
-
-		LLView* spawning_view = getChild<LLView>(spawning_view_name);
-
-		S32 menu_x, menu_y;
-		//show menu in co-ordinates of panel
-		spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
-		menu_y += menu->getRect().getHeight();
-		LLMenuGL::showPopup(this, menu, menu_x, menu_y);
-	}
-}
-
 void LLLandmarksPanel::onTrashButtonClick() const
 {
 	onClipboardAction("delete");
@@ -782,7 +754,8 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
 	LLFolderViewItem* item = getCurSelectedItem();
 
 	std::string command_name = userdata.asString();
-	if("add_landmark" == command_name)
+	if("add_landmark" == command_name
+        || "add_landmark_root" == command_name)
 	{
 		LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos();
 		if(landmark)
@@ -793,8 +766,8 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
 		{
             LLSD args;
             args["type"] = "create_landmark";
-            if (view_model->getInventoryType()
-                == LLInventoryType::IT_CATEGORY)
+            if ("add_landmark" == command_name
+                && view_model->getInventoryType() == LLInventoryType::IT_CATEGORY)
             {
                 args["dest_folder"] = view_model->getUUID();
             }
@@ -837,6 +810,17 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
 			}
 		}
 	}
+    else if ("category_root" == command_name)
+    {
+        //in case My Landmarks tab is completely empty (thus cannot be determined as being selected)
+        menu_create_inventory_item(mLandmarksInventoryPanel, NULL, LLSD("category"),
+            gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK));
+
+        if (mMyLandmarksAccordionTab)
+        {
+            mMyLandmarksAccordionTab->changeOpenClose(false);
+        }
+    }
 }
 
 void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const
@@ -1031,9 +1015,9 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
 
 			// Disable "Show on Map" if landmark loading is in progress.
 			return !gLandmarkList.isAssetInLoadedCallbackMap(asset_uuid);
-	}
-	else if ("rename" == command_name)
-	{
+		}
+		else if ("rename" == command_name)
+		{
 			LLFolderViewItem* selected_item = getCurSelectedItem();
 			if (!selected_item) return false;
 
@@ -1042,6 +1026,11 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
 
 		return true;
 	}
+    if ("category_root" == command_name)
+    {
+        // Landmarks Accordion
+        return true;
+    }
 	else if("category" == command_name)
 	{
 		// we can add folder only in Landmarks Accordion
@@ -1093,6 +1082,16 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
         }
         return true;
     }
+    else if ("add_landmark_root" == command_name)
+    {
+        LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos();
+        if (landmark)
+        {
+            //already exists
+            return false;
+        }
+        return true;
+    }
     else if ("share" == command_name)
     {
         if (!mCurrentSelectedList)
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index e8fb62e0e8..4db77be50b 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -52,13 +52,23 @@ public:
 	LLLandmarksPanel();
 	virtual ~LLLandmarksPanel();
 
-	/*virtual*/ BOOL postBuild();
-	/*virtual*/ void onSearchEdit(const std::string& string);
-	/*virtual*/ void onShowOnMap();
-	/*virtual*/ void onShowProfile();
-	/*virtual*/ void onTeleport();
-	/*virtual*/ void updateVerbs();
-	/*virtual*/ bool isSingleItemSelected();
+	BOOL postBuild() override;
+	void onSearchEdit(const std::string& string) override;
+	void onShowOnMap() override;
+	void onShowProfile() override;
+	void onTeleport() override;
+	void onRemoveSelected() override;
+	void updateVerbs() override;
+	bool isSingleItemSelected() override;
+
+    LLToggleableMenu* getSelectionMenu() override;
+    LLToggleableMenu* getSortingMenu() override;
+    LLToggleableMenu* getCreateMenu() override;
+
+    /**
+     * Processes drag-n-drop of the Landmarks and folders into trash button.
+     */
+    bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept) override;
 
 	void onSelectionChange(LLPlacesInventoryPanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action);
 	void onSelectorButtonClicked();
@@ -108,9 +118,9 @@ protected:
 	void updateSortOrder(LLInventoryPanel* panel, bool byDate);
 
 	//LLRemoteParcelInfoObserver interface
-	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
-	/*virtual*/ void setParcelID(const LLUUID& parcel_id);
-	/*virtual*/ void setErrorStatus(S32 status, const std::string& reason);
+	void processParcelInfo(const LLParcelData& parcel_data) override;
+	void setParcelID(const LLUUID& parcel_id) override;
+	void setErrorStatus(S32 status, const std::string& reason) override;
 	
 private:
 	void initFavoritesInventoryPanel();
@@ -124,9 +134,6 @@ private:
 
 	// List Commands Handlers
 	void initListCommandsHandlers();
-	void updateListCommands();
-	void onActionsButtonClick();
-	void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);
 	void onTrashButtonClick() const;
 	void onAddAction(const LLSD& command_name) const;
 	void onClipboardAction(const LLSD& command_name) const;
@@ -152,11 +159,6 @@ private:
 	bool canItemBeModified(const std::string& command_name, LLFolderViewItem* item) const;
 	void onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params);
 
-	/**
-	 * Processes drag-n-drop of the Landmarks and folders into trash button.
-	 */
-	bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept);
-
 	/**
 	 * Landmark actions callbacks. Fire when a landmark is loaded from the list.
 	 */
@@ -170,14 +172,12 @@ private:
 	LLPlacesInventoryPanel*		mLandmarksInventoryPanel;
 	LLPlacesInventoryPanel*		mMyInventoryPanel;
 	LLPlacesInventoryPanel*		mLibraryInventoryPanel;
-	LLMenuButton*				mGearButton;
 	LLToggleableMenu*			mGearLandmarkMenu;
 	LLToggleableMenu*			mGearFolderMenu;
-	LLMenuGL*					mMenuAdd;
+	LLToggleableMenu*			mSortingMenu;
+	LLToggleableMenu*			mAddMenu;
 	LLPlacesInventoryPanel*		mCurrentSelectedList;
 	LLInventoryObserver*		mInventoryObserver;
-
-	LLPanel*					mListCommands;
 	
 	typedef	std::vector<LLAccordionCtrlTab*> accordion_tabs_t;
 	accordion_tabs_t			mAccordionTabs;
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 427b3fbf57..00752d5a25 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -53,6 +53,7 @@
 #include "llagentpicksinfo.h"
 #include "llavatarpropertiesprocessor.h"
 #include "llcommandhandler.h"
+#include "lldndbutton.h"
 #include "llfloaterworldmap.h"
 #include "llinventorybridge.h"
 #include "llinventoryobserver.h"
@@ -297,6 +298,26 @@ BOOL LLPanelPlaces::postBuild()
 	mPlaceInfoBtn = getChild<LLButton>("profile_btn");
 	mPlaceInfoBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onProfileButtonClicked, this));
 
+    mGearMenuButton = getChild<LLMenuButton>("options_gear_btn");
+    mGearMenuButton->setMouseDownCallback(boost::bind(&LLPanelPlaces::onGearMenuClick, this));
+
+    mSortingMenuButton = getChild<LLMenuButton>("sorting_menu_btn");
+    mSortingMenuButton->setMouseDownCallback(boost::bind(&LLPanelPlaces::onSortingMenuClick, this));
+
+    mAddMenuButton = getChild<LLMenuButton>("add_menu_btn");
+    mAddMenuButton->setMouseDownCallback(boost::bind(&LLPanelPlaces::onAddMenuClick, this));
+
+    mRemoveSelectedBtn = getChild<LLButton>("trash_btn");
+    mRemoveSelectedBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onRemoveButtonClicked, this));
+
+    LLDragAndDropButton* trash_btn = (LLDragAndDropButton*)mRemoveSelectedBtn;
+    trash_btn->setDragAndDropHandler(boost::bind(&LLPanelPlaces::handleDragAndDropToTrash, this
+        , _4 // BOOL drop
+        , _5 // EDragAndDropType cargo_type
+        , _6 // void* cargo_data
+        , _7 // EAcceptance* accept
+    ));
+
 	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
 	registrar.add("Places.OverflowMenu.Action",  boost::bind(&LLPanelPlaces::onOverflowMenuItemClicked, this, _2));
 	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
@@ -629,6 +650,12 @@ void LLPanelPlaces::onTabSelected()
 
 	onFilterEdit(mActivePanel->getFilterSubString(), true);
 	mActivePanel->updateVerbs();
+
+    // History panel does not support deletion nor creation
+    // Hide menus
+    bool supports_create = mActivePanel->getCreateMenu() != NULL;
+    childSetVisible("add_btn_panel", supports_create);
+    childSetVisible("trash_btn_panel", supports_create);
 }
 
 void LLPanelPlaces::onTeleportButtonClicked()
@@ -998,6 +1025,50 @@ void LLPanelPlaces::onBackButtonClicked()
 	updateVerbs();
 }
 
+void LLPanelPlaces::onGearMenuClick()
+{
+    if (mActivePanel)
+    {
+        LLToggleableMenu* menu = mActivePanel->getSelectionMenu();
+        mGearMenuButton->setMenu(menu, LLMenuButton::MP_BOTTOM_LEFT);
+    }
+}
+
+void LLPanelPlaces::onSortingMenuClick()
+{
+    if (mActivePanel)
+    {
+        LLToggleableMenu* menu = mActivePanel->getSortingMenu();
+        mSortingMenuButton->setMenu(menu, LLMenuButton::MP_BOTTOM_LEFT);
+    }
+}
+
+void LLPanelPlaces::onAddMenuClick()
+{
+    if (mActivePanel)
+    {
+        LLToggleableMenu* menu = mActivePanel->getCreateMenu();
+        mAddMenuButton->setMenu(menu, LLMenuButton::MP_BOTTOM_LEFT);
+    }
+}
+
+void LLPanelPlaces::onRemoveButtonClicked()
+{
+    if (mActivePanel)
+    {
+        mActivePanel->onRemoveSelected();
+    }
+}
+
+bool LLPanelPlaces::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept)
+{
+    if (mActivePanel)
+    {
+        return mActivePanel->handleDragAndDropToTrash(drop, cargo_type, cargo_data, accept);
+    }
+    return false;
+}
+
 void LLPanelPlaces::togglePickPanel(BOOL visible)
 {
 	if (mPickPanel)
@@ -1168,9 +1239,17 @@ void LLPanelPlaces::createTabs()
 
 	mActivePanel = dynamic_cast<LLPanelPlacesTab*>(mTabContainer->getCurrentPanel());
 
-	// Filter applied to show all items.
-	if (mActivePanel)
-		mActivePanel->onSearchEdit(mActivePanel->getFilterSubString());
+    if (mActivePanel)
+    {
+        // Filter applied to show all items.
+        mActivePanel->onSearchEdit(mActivePanel->getFilterSubString());
+
+        // History panel does not support deletion nor creation
+        // Hide menus
+        bool supports_create = mActivePanel->getCreateMenu() != NULL;
+        childSetVisible("add_btn_panel", supports_create);
+        childSetVisible("trash_btn_panel", supports_create);
+    }
 
 	mTabsCreated = true;
 }
diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h
index 978b030b2e..610ee283c8 100644
--- a/indra/newview/llpanelplaces.h
+++ b/indra/newview/llpanelplaces.h
@@ -97,6 +97,12 @@ private:
 	void onCreateLandmarkButtonClicked(const LLUUID& folder_id);
 	void onBackButtonClicked();
 	void onProfileButtonClicked();
+    void onGearMenuClick();
+    void onSortingMenuClick();
+    void onAddMenuClick();
+    void onRemoveButtonClicked();
+    bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept);
+
 
 	void toggleMediaPanel();
 	void togglePickPanel(BOOL visible);
@@ -127,6 +133,12 @@ private:
 	LLMenuButton*				mOverflowBtn;
 	LLButton*					mPlaceInfoBtn;
 
+    // Top menu
+    LLMenuButton*				mGearMenuButton;
+    LLMenuButton*				mSortingMenuButton;
+    LLMenuButton*				mAddMenuButton;
+    LLButton*					mRemoveSelectedBtn;
+
 	LLPlacesInventoryObserver*	mInventoryObserver;
 	LLPlacesParcelObserver*		mParcelObserver;
 	LLRemoteParcelInfoObserver* mRemoteParcelObserver;
diff --git a/indra/newview/llpanelplacestab.h b/indra/newview/llpanelplacestab.h
index 367ce46e2e..6c9a6e9da7 100644
--- a/indra/newview/llpanelplacestab.h
+++ b/indra/newview/llpanelplacestab.h
@@ -30,6 +30,7 @@
 #include "llpanel.h"
 
 class LLPanelPlaces;
+class LLToggleableMenu;
 
 class LLPanelPlacesTab : public LLPanel
 {
@@ -42,8 +43,19 @@ public:
 	virtual void onShowOnMap() = 0;
 	virtual void onShowProfile() = 0;
 	virtual void onTeleport() = 0;
+	virtual void onRemoveSelected() = 0;
 	virtual bool isSingleItemSelected() = 0;
 
+    // returns menu for current selection
+    virtual LLToggleableMenu* getSelectionMenu() = 0;
+    virtual LLToggleableMenu* getSortingMenu() = 0;
+    virtual LLToggleableMenu* getCreateMenu() = 0;
+
+    /**
+    * Processes drag-n-drop of the Landmarks and folders into trash button.
+    */
+    virtual bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept) = 0;
+
 	bool isTabVisible(); // Check if parent TabContainer is visible.
 
 	void setPanelPlacesButtons(LLPanelPlaces* panel);
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 3f5664f431..812ddf874e 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -56,7 +56,7 @@ static const std::string COLLAPSED_BY_USER = "collapsed_by_user";
 class LLTeleportHistoryFlatItem : public LLPanel
 {
 public:
-	LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string &region_name,
+	LLTeleportHistoryFlatItem(S32 index, LLToggleableMenu *menu, const std::string &region_name,
 										 	 LLDate date, const std::string &hl);
 	virtual ~LLTeleportHistoryFlatItem();
 
@@ -86,12 +86,13 @@ public:
 
 private:
 	void onProfileBtnClick();
+    void showMenu(S32 x, S32 y);
 
 	LLButton* mProfileBtn;
 	LLTextBox* mTitle;
 	LLTextBox* mTimeTextBox;
 	
-	LLTeleportHistoryPanel::ContextMenu *mContextMenu;
+	LLToggleableMenu *mMenu;
 
 	S32 mIndex;
 	std::string mRegionName;
@@ -112,7 +113,7 @@ protected:
 
 public:
 	LLTeleportHistoryFlatItem* getFlatItemForPersistentItem (
-		LLTeleportHistoryPanel::ContextMenu *context_menu,
+		LLToggleableMenu *menu,
 		const LLTeleportHistoryPersistentItem& persistent_item,
 		const S32 cur_item_index,
 		const std::string &hl);
@@ -130,16 +131,16 @@ private:
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 
-LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLTeleportHistoryPanel::ContextMenu *context_menu, const std::string &region_name,
+LLTeleportHistoryFlatItem::LLTeleportHistoryFlatItem(S32 index, LLToggleableMenu *menu, const std::string &region_name,
 																LLDate date, const std::string &hl)
 :	LLPanel(),
 	mIndex(index),
-	mContextMenu(context_menu),
+	mMenu(menu),
 	mRegionName(region_name),
 	mDate(date),
 	mHighlight(hl)
 {
-	buildFromFile( "panel_teleport_history_item.xml");
+	buildFromFile("panel_teleport_history_item.xml");
 }
 
 LLTeleportHistoryFlatItem::~LLTeleportHistoryFlatItem()
@@ -266,10 +267,9 @@ void LLTeleportHistoryFlatItem::onMouseLeave(S32 x, S32 y, MASK mask)
 // virtual
 BOOL LLTeleportHistoryFlatItem::handleRightMouseDown(S32 x, S32 y, MASK mask)
 {
-	if (mContextMenu)
-		mContextMenu->show(this, mIndex, x, y);
-
-	return LLPanel::handleRightMouseDown(x, y, mask);
+    LLPanel::handleRightMouseDown(x, y, mask);
+	showMenu(x, y);
+    return TRUE;
 }
 
 void LLTeleportHistoryFlatItem::showPlaceInfoPanel(S32 index)
@@ -286,13 +286,23 @@ void LLTeleportHistoryFlatItem::onProfileBtnClick()
 	LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);
 }
 
+void LLTeleportHistoryFlatItem::showMenu(S32 x, S32 y)
+{
+    mMenu->setButtonRect(this);
+    mMenu->buildDrawLabels();
+    mMenu->arrangeAndClear();
+    mMenu->updateParent(LLMenuGL::sMenuContainer);
+
+    LLMenuGL::showPopup(this, mMenu, x, y);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 
 LLTeleportHistoryFlatItem*
 LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem (
-	LLTeleportHistoryPanel::ContextMenu *context_menu,
+	LLToggleableMenu *menu,
 	const LLTeleportHistoryPersistentItem& persistent_item,
 	const S32 cur_item_index,
 	const std::string &hl)
@@ -321,7 +331,7 @@ LLTeleportHistoryFlatItemStorage::getFlatItemForPersistentItem (
 	if ( !item )
 	{
 		item = new LLTeleportHistoryFlatItem(cur_item_index,
-											 context_menu,
+											 menu,
 											 persistent_item.mTitle,
 											 persistent_item.mDate,
 											 hl);
@@ -365,78 +375,6 @@ void LLTeleportHistoryFlatItemStorage::purge()
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 
-LLTeleportHistoryPanel::ContextMenu::ContextMenu() :
-	mMenu(NULL), mIndex(0)
-{
-}
-
-void LLTeleportHistoryPanel::ContextMenu::show(LLView* spawning_view, S32 index, S32 x, S32 y)
-{
-	if (mMenu)
-	{
-		//preventing parent (menu holder) from deleting already "dead" context menus on exit
-		LLView* parent = mMenu->getParent();
-		if (parent)
-		{
-			parent->removeChild(mMenu);
-		}
-		delete mMenu;
-	}
-
-	mIndex = index;
-	mMenu = createMenu();
-
-	mMenu->show(x, y);
-	LLMenuGL::showPopup(spawning_view, mMenu, x, y);
-}
-
-LLContextMenu* LLTeleportHistoryPanel::ContextMenu::createMenu()
-{
-	// set up the callbacks for all of the avatar menu items
-	// (N.B. callbacks don't take const refs as mID is local scope)
-	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
-
-	registrar.add("TeleportHistory.Action", boost::bind(&LLTeleportHistoryPanel::ContextMenu::onUserAction, this, _2));
-
-	// create the context menu from the XUI
-	llassert(LLMenuGL::sMenuContainer != NULL);
-	return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
-		"menu_teleport_history_item.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
-}
-
-void LLTeleportHistoryPanel::ContextMenu::onUserAction(const LLSD& userdata)
-{
-    std::string command_name = userdata.asString();
-    if ("teleport" == command_name)
-    {
-        confirmTeleport(mIndex);
-    }
-    else if ("view" == command_name)
-    {
-        LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);
-    }
-    else if ("show_on_map" == command_name)
-    {
-        LLTeleportHistoryStorage::getInstance()->showItemOnMap(mIndex);
-    }
-    else if ("copy_slurl" == command_name)
-    {
-        LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[mIndex].mGlobalPos;
-        LLLandmarkActions::getSLURLfromPosGlobal(globalPos,
-            boost::bind(&LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback, _1));
-    }
-}
-
-//static
-void LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback(const std::string& slurl)
-{
-	LLClipboard::instance().copyToClipboard(utf8str_to_wstring(slurl),0,slurl.size());
-
-	LLSD args;
-	args["SLURL"] = slurl;
-
-	LLNotificationsUtil::add("CopySLURL", args);
-}
 
 // Not yet implemented; need to remove buildPanel() from constructor when we switch
 //static LLRegisterPanelClassWrapper<LLTeleportHistoryPanel> t_teleport_history("panel_teleport_history");
@@ -450,7 +388,8 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel()
 		mAccordionTabMenu(NULL),
 		mLastSelectedFlatlList(NULL),
 		mLastSelectedItemIndex(-1),
-		mMenuGearButton(NULL)
+		mGearItemMenu(NULL),
+		mSortingMenu(NULL)
 {
 	buildFromFile( "panel_teleport_history.xml");
 }
@@ -458,12 +397,19 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel()
 LLTeleportHistoryPanel::~LLTeleportHistoryPanel()
 {
 	LLTeleportHistoryFlatItemStorage::instance().purge();
-	if (mGearMenuHandle.get()) mGearMenuHandle.get()->die();
 	mTeleportHistoryChangedConnection.disconnect();
 }
 
 BOOL LLTeleportHistoryPanel::postBuild()
 {
+    mCommitCallbackRegistrar.add("TeleportHistory.GearMenu.Action", boost::bind(&LLTeleportHistoryPanel::onGearMenuAction, this, _2));
+    mEnableCallbackRegistrar.add("TeleportHistory.GearMenu.Enable", boost::bind(&LLTeleportHistoryPanel::isActionEnabled, this, _2));
+
+    // init menus before list, since menus are passed to list
+    mGearItemMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_teleport_history_item.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+    mGearItemMenu->setAlwaysShowMenu(TRUE); // all items can be disabled if nothing is selected, show anyway
+    mSortingMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_teleport_history_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+
 	mTeleportHistory = LLTeleportHistoryStorage::getInstance();
 	if (mTeleportHistory)
 	{
@@ -515,22 +461,6 @@ BOOL LLTeleportHistoryPanel::postBuild()
 		}
 	}
 
-	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
-
-	registrar.add("TeleportHistory.ExpandAllFolders",  boost::bind(&LLTeleportHistoryPanel::onExpandAllFolders,  this));
-	registrar.add("TeleportHistory.CollapseAllFolders",  boost::bind(&LLTeleportHistoryPanel::onCollapseAllFolders,  this));
-	registrar.add("TeleportHistory.ClearTeleportHistory",  boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistory,  this));
-	mEnableCallbackRegistrar.add("TeleportHistory.GearMenu.Enable", boost::bind(&LLTeleportHistoryPanel::isActionEnabled, this, _2));
-
-	mMenuGearButton = getChild<LLMenuButton>("gear_btn");
-
-	LLToggleableMenu* gear_menu  = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_teleport_history_gear.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());;
-	if(gear_menu)
-	{
-		mGearMenuHandle  = gear_menu->getHandle();
-		mMenuGearButton->setMenu(gear_menu);
-	}
-
 	return TRUE;
 }
 
@@ -649,6 +579,24 @@ void LLTeleportHistoryPanel::updateVerbs()
 	mShowOnMapBtn->setEnabled(NULL != itemp);
 }
 
+// virtual
+LLToggleableMenu* LLTeleportHistoryPanel::getSelectionMenu()
+{
+    return mGearItemMenu;
+}
+
+// virtual
+LLToggleableMenu* LLTeleportHistoryPanel::getSortingMenu()
+{
+    return mSortingMenu;
+}
+
+// virtual
+LLToggleableMenu* LLTeleportHistoryPanel::getCreateMenu()
+{
+    return NULL;
+}
+
 void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, LLDate& tab_date)
 {
 	const U32 seconds_in_day = 24 * 60 * 60;
@@ -782,7 +730,7 @@ void LLTeleportHistoryPanel::refresh()
 		{
 			LLTeleportHistoryFlatItem* item =
 				LLTeleportHistoryFlatItemStorage::instance()
-				.getFlatItemForPersistentItem(&mContextMenu,
+				.getFlatItemForPersistentItem(mGearItemMenu,
 											  items[mCurrentItem],
 											  mCurrentItem,
 											  filter_string);
@@ -851,7 +799,7 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index)
 
 	const LLTeleportHistoryStorage::slurl_list_t& history_items = mTeleportHistory->getItems();
 	LLTeleportHistoryFlatItem* item = LLTeleportHistoryFlatItemStorage::instance()
-		.getFlatItemForPersistentItem(&mContextMenu,
+		.getFlatItemForPersistentItem(mGearItemMenu,
 									  history_items[history_items.size() - 1], // Most recent item, it was added instead of removed
 									  history_items.size(), // index will be decremented inside loop below
 									  sFilterSubString);
@@ -1023,38 +971,6 @@ void LLTeleportHistoryPanel::onAccordionTabClose(LLAccordionCtrlTab *tab)
 	mHistoryAccordion->arrange();
 }
 
-void LLTeleportHistoryPanel::onExpandAllFolders()
-{
-	S32 tabs_cnt = mItemContainers.size();
-
-	for (S32 n = 0; n < tabs_cnt; n++)
-	{
-		mItemContainers.at(n)->setDisplayChildren(true);
-	}
-	mHistoryAccordion->arrange();
-}
-
-void LLTeleportHistoryPanel::onCollapseAllFolders()
-{
-	S32 tabs_cnt = mItemContainers.size();
-
-	for (S32 n = 0; n < tabs_cnt; n++)
-	{
-		mItemContainers.at(n)->setDisplayChildren(false);
-	}
-	mHistoryAccordion->arrange();
-
-	if (mLastSelectedFlatlList)
-	{
-		mLastSelectedFlatlList->resetSelection();
-	}
-}
-
-void LLTeleportHistoryPanel::onClearTeleportHistory()
-{
-	LLNotificationsUtil::add("ConfirmClearTeleportHistory", LLSD(), LLSD(), boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistoryDialog, this, _1, _2));
-}
-
 bool LLTeleportHistoryPanel::onClearTeleportHistoryDialog(const LLSD& notification, const LLSD& response)
 {
 
@@ -1086,45 +1002,141 @@ LLFlatListView* LLTeleportHistoryPanel::getFlatListViewFromTab(LLAccordionCtrlTa
 	return NULL;
 }
 
-bool LLTeleportHistoryPanel::isActionEnabled(const LLSD& userdata) const
+void LLTeleportHistoryPanel::gotSLURLCallback(const std::string& slurl)
 {
-	S32 tabs_cnt = mItemContainers.size();
+    LLClipboard::instance().copyToClipboard(utf8str_to_wstring(slurl), 0, slurl.size());
 
-	bool has_expanded_tabs = false;
-	bool has_collapsed_tabs = false;
+    LLSD args;
+    args["SLURL"] = slurl;
 
-	for (S32 n = 0; n < tabs_cnt; n++)
-	{
-		LLAccordionCtrlTab* tab = mItemContainers.at(n);
-		if (!tab->getVisible())
-			continue;
+    LLNotificationsUtil::add("CopySLURL", args);
+}
 
-		if (tab->getDisplayChildren())
-		{
-			has_expanded_tabs = true;
-		}
-		else
-		{
-			has_collapsed_tabs = true;
-		}
+void LLTeleportHistoryPanel::onGearMenuAction(const LLSD& userdata)
+{
+    std::string command_name = userdata.asString();
 
-		if (has_expanded_tabs && has_collapsed_tabs)
-		{
-			break;
-		}
-	}
+    if ("expand_all" == command_name)
+    {
+        S32 tabs_cnt = mItemContainers.size();
 
-	std::string command_name = userdata.asString();
+        for (S32 n = 0; n < tabs_cnt; n++)
+        {
+            mItemContainers.at(n)->setDisplayChildren(true);
+        }
+        mHistoryAccordion->arrange();
+    }
+    else if ("collapse_all" == command_name)
+    {
+        S32 tabs_cnt = mItemContainers.size();
+
+        for (S32 n = 0; n < tabs_cnt; n++)
+        {
+            mItemContainers.at(n)->setDisplayChildren(false);
+        }
+        mHistoryAccordion->arrange();
+
+        if (mLastSelectedFlatlList)
+        {
+            mLastSelectedFlatlList->resetSelection();
+        }
+    }
+    else if ("clear_history" == command_name)
+    {
+        LLNotificationsUtil::add("ConfirmClearTeleportHistory", LLSD(), LLSD(), boost::bind(&LLTeleportHistoryPanel::onClearTeleportHistoryDialog, this, _1, _2));
+    }
 
-	if (has_expanded_tabs && command_name == "collapse_all")
-	{
-		return true;
-	}
+    S32 index = -1;
+    if (mLastSelectedFlatlList)
+    {
+        LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+        if (itemp)
+        {
+            index = itemp->getIndex();
+        }
+    }
 
-	if (has_collapsed_tabs && command_name ==  "expand_all")
-	{
-		return true;
-	}
+    if ("teleport" == command_name)
+    {
+        confirmTeleport(index);
+    }
+    else if ("view" == command_name)
+    {
+        LLTeleportHistoryFlatItem::showPlaceInfoPanel(index);
+    }
+    else if ("show_on_map" == command_name)
+    {
+        LLTeleportHistoryStorage::getInstance()->showItemOnMap(index);
+    }
+    else if ("copy_slurl" == command_name)
+    {
+        LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[index].mGlobalPos;
+        LLLandmarkActions::getSLURLfromPosGlobal(globalPos,
+            boost::bind(&LLTeleportHistoryPanel::gotSLURLCallback, _1));
+    }
+}
+
+bool LLTeleportHistoryPanel::isActionEnabled(const LLSD& userdata) const
+{
+    std::string command_name = userdata.asString();
+
+    if (command_name == "collapse_all"
+        || command_name == "expand_all")
+    {
+        S32 tabs_cnt = mItemContainers.size();
+
+        bool has_expanded_tabs = false;
+        bool has_collapsed_tabs = false;
+
+        for (S32 n = 0; n < tabs_cnt; n++)
+        {
+            LLAccordionCtrlTab* tab = mItemContainers.at(n);
+            if (!tab->getVisible())
+                continue;
+
+            if (tab->getDisplayChildren())
+            {
+                has_expanded_tabs = true;
+            }
+            else
+            {
+                has_collapsed_tabs = true;
+            }
+
+            if (has_expanded_tabs && has_collapsed_tabs)
+            {
+                break;
+            }
+        }
+
+        if (command_name == "collapse_all")
+        {
+            return has_expanded_tabs;
+        }
+
+        if (command_name == "expand_all")
+        {
+            return has_collapsed_tabs;
+        }
+    }
+
+    if (command_name == "clear_history")
+    {
+        return mTeleportHistory->getItems().size() > 0;
+    }
+    
+    if ("teleport" == command_name
+        || "view" == command_name
+        || "show_on_map" == command_name
+        || "copy_slurl" == command_name)
+    {
+        if (!mLastSelectedFlatlList)
+        {
+            return false;
+        }
+        LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+        return itemp != NULL;
+    }
 
 	return false;
 }
diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h
index e0abbc47db..241a2e9509 100644
--- a/indra/newview/llpanelteleporthistory.h
+++ b/indra/newview/llpanelteleporthistory.h
@@ -43,36 +43,26 @@ class LLMenuButton;
 class LLTeleportHistoryPanel : public LLPanelPlacesTab
 {
 public:
-	// *TODO: derive from LLListContextMenu?
-	class ContextMenu
-	{
-	public:
-		ContextMenu();
-		void show(LLView* spawning_view, S32 index, S32 x, S32 y);
-
-	private:
-		LLContextMenu* createMenu();
-		void onUserAction(const LLSD& userdata);
-
-		static void gotSLURLCallback(const std::string& slurl);
-
-		LLContextMenu* mMenu;
-		S32 mIndex;
-	};
-
 	LLTeleportHistoryPanel();
 	virtual ~LLTeleportHistoryPanel();
 
-	/*virtual*/ BOOL postBuild();
-	/*virtual*/ void draw();
+    BOOL postBuild() override;
+    void draw() override;
 
-	/*virtual*/ void onSearchEdit(const std::string& string);
-	/*virtual*/ void onShowOnMap();
-	/*virtual*/ void onShowProfile();
-	/*virtual*/ void onTeleport();
-	///*virtual*/ void onCopySLURL();
-	/*virtual*/ void updateVerbs();
-	/*virtual*/ bool isSingleItemSelected();
+    void onSearchEdit(const std::string& string) override;
+    void onShowOnMap() override;
+    void onShowProfile() override;
+    void onTeleport() override;
+    ///*virtual*/ void onCopySLURL();
+    void onRemoveSelected() override {};
+    void updateVerbs() override;
+    bool isSingleItemSelected() override;
+
+    LLToggleableMenu* getSelectionMenu() override;
+    LLToggleableMenu* getSortingMenu() override;
+    LLToggleableMenu* getCreateMenu() override;
+
+    bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept) override { return false; }
 
 private:
 
@@ -93,6 +83,8 @@ private:
 	void showTeleportHistory();
 	void handleItemSelect(LLFlatListView* );
 	LLFlatListView* getFlatListViewFromTab(LLAccordionCtrlTab *);
+	static void gotSLURLCallback(const std::string& slurl);
+	void onGearMenuAction(const LLSD& userdata);
 	bool isActionEnabled(const LLSD& userdata) const;
 
 	void setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool collapsed);
@@ -113,10 +105,10 @@ private:
 	typedef std::vector<LLAccordionCtrlTab*> item_containers_t;
 	item_containers_t mItemContainers;
 
-	ContextMenu mContextMenu;
 	LLContextMenu*			mAccordionTabMenu;
-	LLHandle<LLView>		mGearMenuHandle;
-	LLMenuButton*			mMenuGearButton;
+
+    LLToggleableMenu*			mGearItemMenu;
+    LLToggleableMenu*			mSortingMenu;
 
 	boost::signals2::connection mTeleportHistoryChangedConnection;
 };
diff --git a/indra/newview/skins/default/xui/en/menu_place_add_button.xml b/indra/newview/skins/default/xui/en/menu_place_add_button.xml
index e3a39a1242..ad49f7c3a8 100644
--- a/indra/newview/skins/default/xui/en/menu_place_add_button.xml
+++ b/indra/newview/skins/default/xui/en/menu_place_add_button.xml
@@ -1,27 +1,30 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu
+<toggleable_menu
  layout="topleft"
  left="0"
  mouse_opaque="false"
- name="menu_folder_gear"
+ name="menu_create"
  visible="false">
     <menu_item_call
-     label="Add Folder"
+     label="Landmark current location"
      layout="topleft"
-     name="add_folder">
+     name="add_landmark">
         <on_click
          function="Places.LandmarksGear.Add.Action"
-         parameter="category" />
+         parameter="add_landmark_root" />
         <on_enable
          function="Places.LandmarksGear.Enable"
-         parameter="category" />
+         parameter="add_landmark_root" />
     </menu_item_call>
     <menu_item_call
-     label="Add Landmark"
+     label="Create folder"
      layout="topleft"
-     name="add_landmark">
+     name="add_folder">
         <on_click
          function="Places.LandmarksGear.Add.Action"
-         parameter="add_landmark" />
+         parameter="category_root" />
+        <on_enable
+         function="Places.LandmarksGear.Enable"
+         parameter="category_root" />
     </menu_item_call>
-</menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
index eb76f58722..df1139c98f 100644
--- a/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
@@ -123,37 +123,4 @@
          function="Places.LandmarksGear.Enable"
          parameter="collapse" />
     </menu_item_call>
-    <menu_item_call
-     label="Expand all folders"
-     layout="topleft"
-     name="expand_all">
-        <on_click
-         function="Places.LandmarksGear.Folding.Action"
-         parameter="expand_all" />
-        <on_enable
-         function="Places.LandmarksGear.Enable"
-         parameter="expand_all" />
-    </menu_item_call>
-    <menu_item_call
-     label="Collapse all folders"
-     layout="topleft"
-     name="collapse_all">
-        <on_click
-         function="Places.LandmarksGear.Folding.Action"
-         parameter="collapse_all" />
-        <on_enable
-         function="Places.LandmarksGear.Enable"
-         parameter="collapse_all" />
-    </menu_item_call>
-    <menu_item_check
-     label="Sort by Date"
-     layout="topleft"
-     name="sort_by_date">
-        <on_check
-         function="Places.LandmarksGear.Check"
-         parameter="sort_by_date" />
-        <on_click
-         function="Places.LandmarksGear.Folding.Action"
-         parameter="sort_by_date" />
-    </menu_item_check>
 </toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
index b8249b621b..7a7edc0ab7 100644
--- a/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml
@@ -134,42 +134,4 @@
          function="Places.LandmarksGear.Enable"
          parameter="delete" />
     </menu_item_call>
-    <menu_item_separator
-     layout="topleft" />
-    <menu_item_call
-     label="Expand all folders"
-     layout="topleft"
-     name="expand_all">
-        <on_click
-         function="Places.LandmarksGear.Folding.Action"
-         parameter="expand_all" />
-        <on_enable
-         function="Places.LandmarksGear.Enable"
-         parameter="expand_all" />
-    </menu_item_call>
-    <menu_item_call
-     label="Collapse all folders"
-     layout="topleft"
-     name="collapse_all">
-        <on_click
-         function="Places.LandmarksGear.Folding.Action"
-         parameter="collapse_all" />
-        <on_enable
-         function="Places.LandmarksGear.Enable"
-         parameter="collapse_all" />
-    </menu_item_call>
-    <menu_item_check
-     label="Sort by Date"
-     layout="topleft"
-     name="sort_by_date">
-        <on_check
-         function="Places.LandmarksGear.Check"
-         parameter="sort_by_date" />
-        <on_click
-         function="Places.LandmarksGear.Folding.Action"
-         parameter="sort_by_date" />
-        <on_enable
-         function="Places.LandmarksGear.Enable"
-         parameter="sort_by_date" />
-    </menu_item_check>
 </toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_places_gear_sorting.xml b/indra/newview/skins/default/xui/en/menu_places_gear_sorting.xml
new file mode 100644
index 0000000000..6548fadfa5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_sorting.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="menu_sorter_gear"
+ visible="false">
+    <menu_item_call
+     label="Expand all folders"
+     layout="topleft"
+     name="expand_all">
+        <on_click
+         function="Places.LandmarksGear.Folding.Action"
+         parameter="expand_all" />
+        <on_enable
+         function="Places.LandmarksGear.Enable"
+         parameter="expand_all" />
+    </menu_item_call>
+    <menu_item_call
+     label="Collapse all folders"
+     layout="topleft"
+     name="collapse_all">
+        <on_click
+         function="Places.LandmarksGear.Folding.Action"
+         parameter="collapse_all" />
+        <on_enable
+         function="Places.LandmarksGear.Enable"
+         parameter="collapse_all" />
+    </menu_item_call>
+    <menu_item_separator
+     layout="topleft" />
+    <menu_item_check
+     label="Sort by Date"
+     layout="topleft"
+     name="sort_by_date">
+        <on_check
+         function="Places.LandmarksGear.Check"
+         parameter="sort_by_date" />
+        <on_click
+         function="Places.LandmarksGear.Folding.Action"
+         parameter="sort_by_date" />
+    </menu_item_check>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml
index bc7d4fe33b..0b75fd781a 100644
--- a/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_teleport_history_gear.xml
@@ -12,7 +12,8 @@
      label="Expand all folders"
      name="Expand all folders">
         <menu_item_call.on_click
-         function="TeleportHistory.ExpandAllFolders" />
+         function="TeleportHistory.GearMenu.Action"
+         parameter="expand_all" />
         <on_enable
          function="TeleportHistory.GearMenu.Enable"
          parameter="expand_all" />
@@ -21,7 +22,8 @@
      label="Collapse all folders"
      name="Collapse all folders">
         <menu_item_call.on_click
-         function="TeleportHistory.CollapseAllFolders" />
+         function="TeleportHistory.GearMenu.Action"
+         parameter="collapse_all" />
         <on_enable
          function="TeleportHistory.GearMenu.Enable"
          parameter="collapse_all" />
@@ -31,6 +33,10 @@
      label="Clear Teleport History"
      name="Clear Teleport History">
         <menu_item_call.on_click
-         function="TeleportHistory.ClearTeleportHistory" />
+         function="TeleportHistory.GearMenu.Action"
+         parameter="clear_history" />
+        <on_enable
+         function="TeleportHistory.GearMenu.Enable"
+         parameter="clear_history" />
     </menu_item_call>    
 </toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
index 52da591e35..153e5a70a9 100644
--- a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
+++ b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
@@ -1,37 +1,52 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<context_menu
+<toggleable_menu
+ name="Teleport History Item Menu"
  layout="topleft"
- name="Teleport History Item Context Menu">
+ left="0"
+ mouse_opaque="false"
+ visible="false">
     <menu_item_call
      label="Teleport"
      layout="topleft"
      name="Teleport">
-        <menu_item_call.on_click
-         function="TeleportHistory.Action"
+        <on_click
+         function="TeleportHistory.GearMenu.Action"
+         parameter="teleport" />
+        <on_enable
+         function="TeleportHistory.GearMenu.Enable"
          parameter="teleport" />
     </menu_item_call>
     <menu_item_call
      label="View"
      layout="topleft"
      name="More Information">
-        <menu_item_call.on_click
-         function="TeleportHistory.Action"
+        <on_click
+         function="TeleportHistory.GearMenu.Action"
+         parameter="view" />
+        <on_enable
+         function="TeleportHistory.GearMenu.Enable"
          parameter="view" />
     </menu_item_call>
     <menu_item_call
      label="Show on map"
      layout="topleft"
      name="show_on_map">
-        <menu_item_call.on_click
-         function="TeleportHistory.Action"
+        <on_click
+         function="TeleportHistory.GearMenu.Action"
+         parameter="show_on_map" />
+        <on_enable
+         function="TeleportHistory.GearMenu.Enable"
          parameter="show_on_map" />
     </menu_item_call>
     <menu_item_call
      label="Copy SLurl"
      layout="topleft"
      name="CopyToClipboard">
-        <menu_item_call.on_click
-         function="TeleportHistory.Action"
+        <on_click
+         function="TeleportHistory.GearMenu.Action"
+         parameter="copy_slurl" />
+        <on_enable
+         function="TeleportHistory.GearMenu.Enable"
          parameter="copy_slurl" />
     </menu_item_call>
-</context_menu>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml
index 67a09949ce..af2115156e 100644
--- a/indra/newview/skins/default/xui/en/panel_landmarks.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml
@@ -16,7 +16,7 @@
      bg_alpha_color="DkGray2"
      bg_opaque_color="DkGray2"
      follows="all"
-     height="373"
+     height="398"
      layout="topleft"
      left="3"
      name="landmarks_accordion"
@@ -95,104 +95,4 @@
              width="313"/>
         </accordion_tab>
     </accordion>
-    <panel
-       background_visible="true"
-     bevel_style="none"
-     bottom="0"
-     follows="left|right|bottom"
-     height="27"
-     layout="bottomleft"
-     left="3"
-     name="bottom_panel"
-     width="313">
-     	
-     	  <layout_stack
-		   animate="false"
-		   border_size="0"
-		   follows="left|right|bottom"
-		   height="25"
-		   layout="topleft"
-		   orientation="horizontal"
-		   top_pad="1"
-		   left="0"
-		   name="bottom_panel"
-		   width="307">
-		      <layout_panel
-		       auto_resize="false"
-		       height="25"
-		       layout="topleft"
-		       name="options_gear_btn_panel"
-		       width="32">
-		          <menu_button
-		           follows="bottom|left"
-		           tool_tip="Show additional options"
-		           height="25"
-		           image_hover_unselected="Toolbar_Left_Over"
-		           image_overlay="OptionsMenu_Off"
-		           image_selected="Toolbar_Left_Selected"
-		           image_unselected="Toolbar_Left_Off"
-		           layout="topleft"
-		           left="0"
-		           name="options_gear_btn"
-		           top="0"
-		           width="31" />
-		      </layout_panel>
-		      <layout_panel
-		       auto_resize="false"
-		       height="25"
-		       layout="topleft"
-		       name="add_btn_panel"
-		       width="32">
-		          <button
-		           follows="bottom|left"
-		           height="25"
-		           image_hover_unselected="Toolbar_Middle_Over"
-		           image_overlay="AddItem_Off"
-		           image_selected="Toolbar_Middle_Selected"
-		           image_unselected="Toolbar_Middle_Off"
-		           layout="topleft"
-		           left="0"
-		           name="add_btn"
-		           tool_tip="Add new landmark"
-		           top="0"
-		           width="31" />
-		      </layout_panel>
-		      <layout_panel
-		       auto_resize="true"
-		       height="25"
-		       layout="topleft"
-		       name="dummy_panel"
-		       width="212">
-		          <icon
-		           follows="bottom|left|right"
-		           height="25"
-		           image_name="Toolbar_Middle_Off"
-		           layout="topleft"
-		           left="0"
-		           top="0"
-		           name="dummy_icon"
-		           width="211" />
-		      </layout_panel>
-		      <layout_panel
-		       auto_resize="false"
-		       height="25"
-		       layout="topleft"
-		       name="trash_btn_panel"
-		       width="31">
-		          <dnd_button
-		           follows="bottom|left"
-		           height="25"
-		           image_hover_unselected="Toolbar_Right_Over"
-		           image_overlay="TrashItem_Off"
-		           image_selected="Toolbar_Right_Selected"
-		           image_unselected="Toolbar_Right_Off"
-		           left="0"
-		           layout="topleft"
-		           name="trash_btn"
-		           tool_tip="Remove selected landmark"
-		           top="0"
-		           width="31"/>
-		      </layout_panel>
-  	</layout_stack>
-   </panel>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml
index 1f32ae53ba..75becf6b15 100644
--- a/indra/newview/skins/default/xui/en/panel_places.xml
+++ b/indra/newview/skins/default/xui/en/panel_places.xml
@@ -17,19 +17,121 @@ background_visible="true"
     <string
      name="teleport_history_tab_title"
      value="TELEPORT HISTORY" />
-    <filter_editor
-     text_pad_left="10"
-     follows="left|top|right"
-     font="SansSerifSmall"
-     height="23"
-     layout="topleft"
-     left="10"
-     label="Filter My Places"
-     max_length_chars="300"
-     name="Filter"
-     tab_group="1"
-     top="3"
-     width="303" />
+    <layout_stack
+      animate="false"
+      border_size="0"
+      follows="left|top|right"
+      height="25"
+      layout="topleft"
+      orientation="horizontal"
+      top_pad="1"
+      left="0"
+      name="bottom_panel"
+      width="320">
+      <layout_panel
+        auto_resize="true"
+        height="25"
+        layout="topleft"
+        name="filter_panel"
+        width="193">
+        <filter_editor
+          text_pad_left="10"
+          follows="left|top|right"
+          font="SansSerifSmall"
+          height="23"
+          layout="topleft"
+          left="10"
+          label="Filter My Places"
+          max_length_chars="300"
+          name="Filter"
+          tab_group="1"
+          top="3"
+          width="181" />
+      </layout_panel>
+      <layout_panel
+        auto_resize="false"
+        height="25"
+        layout="topleft"
+        name="options_gear_btn_panel"
+        width="32">
+        <menu_button
+          follows="bottom|left"
+          tool_tip="Show options"
+          height="25"
+          image_hover_unselected="Toolbar_Middle_Over"
+          image_overlay="OptionsMenu_Off"
+          image_selected="Toolbar_Middle_Selected"
+          image_unselected="Toolbar_Middle_Off"
+          menu_position="bottomleft"
+          layout="topleft"
+          left="0"
+          name="options_gear_btn"
+          top="0"
+          width="31" />
+      </layout_panel>
+      <layout_panel
+        auto_resize="false"
+        height="25"
+        layout="topleft"
+        name="options_sort_btn_panel"
+        width="32">
+        <menu_button
+          follows="bottom|left"
+          tool_tip="Show sorting options"
+          height="25"
+          image_hover_unselected="Toolbar_Middle_Over"
+          image_overlay="Conv_toolbar_sort"
+          image_selected="Toolbar_Middle_Selected"
+          image_unselected="Toolbar_Middle_Off"
+          menu_position="bottomleft"
+          layout="topleft"
+          left="0"
+          name="sorting_menu_btn"
+          top="0"
+          width="31" />
+      </layout_panel>
+      <layout_panel
+        auto_resize="false"
+        height="25"
+        layout="topleft"
+        name="add_btn_panel"
+        width="32">
+        <menu_button
+          follows="bottom|left"
+          height="25"
+          image_hover_unselected="Toolbar_Middle_Over"
+          image_overlay="AddItem_Off"
+          image_selected="Toolbar_Middle_Selected"
+          image_unselected="Toolbar_Middle_Off"
+          menu_position="bottomleft"
+          layout="topleft"
+          left="0"
+          name="add_menu_btn"
+          tool_tip="Add new landmark or folder"
+          top="0"
+          width="31" />
+      </layout_panel>
+      <layout_panel
+        auto_resize="false"
+        height="25"
+        layout="topleft"
+        name="trash_btn_panel"
+        width="31">
+        <dnd_button
+          follows="bottom|left"
+          height="25"
+          image_hover_unselected="Toolbar_Right_Over"
+          image_overlay="TrashItem_Off"
+          image_selected="Toolbar_Right_Selected"
+          image_unselected="Toolbar_Right_Off"
+          left="0"
+          layout="topleft"
+          name="trash_btn"
+          tool_tip="Remove selected landmark or folder"
+          top="0"
+          width="31"/>
+      </layout_panel>
+    </layout_stack>
     <tab_container
      follows="all"
      halign="center"
@@ -265,6 +367,7 @@ background_visible="true"
 		
 		<layout_stack
      	follows="bottom|left|right"
+      animate="false"
 		height="23"
 		layout="topleft"
 		mouse_opaque="false"
diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history.xml b/indra/newview/skins/default/xui/en/panel_teleport_history.xml
index 768efc2f3f..55c47c90a4 100644
--- a/indra/newview/skins/default/xui/en/panel_teleport_history.xml
+++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml
@@ -6,7 +6,7 @@
      bg_alpha_color="DkGray">     
     <accordion
      follows="left|top|right|bottom"
-     height="373"
+     height="400"
      layout="topleft"
      left="3"
      top="0"
@@ -147,37 +147,4 @@
 	        </flat_list_view>
 	    </accordion_tab>
     </accordion>
-    <panel
-     background_visible="true"
-     bevel_style="none"
-     bottom="0"
-     follows="left|right|bottom"
-     height="27"
-     layout="bottomleft"
-     left="3"
-     name="bottom_panel"
-     width="313">
-        <menu_button
-         follows="bottom|left"
-         tool_tip="Show additional options"
-         height="25"
-         image_hover_unselected="Toolbar_Left_Over"
-         image_overlay="OptionsMenu_Off"
-         image_selected="Toolbar_Left_Selected"
-         image_unselected="Toolbar_Left_Off"
-         layout="topleft"
-         left="0"
-         name="gear_btn"
-         top="1"
-         width="31" />
-        <icon
-         follows="bottom|left|right"
-         height="25"
-         image_name="Toolbar_Right_Off"
-         layout="topleft"
-         left_pad="1"
-         name="dummy_icon"
-         width="273"
-        />
-    </panel>
 </panel>
-- 
cgit v1.2.3