Commits

Anonymous committed 29568c3

Merging revisions 2070-2084 of https://svn.aws.productengine.com/secondlife/pe/stable-2 into P:\svn\viewer-2.0.0, respecting ancestry
* Bugs: EXT-792 EXT-1519 EXT-1514 EXT-1245 EXT-1600 EXT-1535 EXT-1174 EXT-1241
* Dev: EXT-1271 EXT-1601 EXT-1154

Comments (0)

Files changed (30)

indra/newview/app_settings/settings.xml

       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>FriendsSortOrder</key>
+    <map>
+      <key>Comment</key>
+      <string>Specifies sort order for friends (0 = by name, 1 = by online status)</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>U32</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>NearbyPeopleSortOrder</key>
+    <map>
+      <key>Comment</key>
+      <string>Specifies sort order for nearby people (0 = by name, 2 = by most recent)</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>U32</string>
+      <key>Value</key>
+      <integer>2</integer>
+    </map>
+    <key>RecentPeopleSortOrder</key>
+    <map>
+      <key>Comment</key>
+      <string>Specifies sort order for recent people (0 = by name, 2 = by most recent)</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>U32</string>
+      <key>Value</key>
+      <integer>2</integer>
+    </map>
     <key>ShowPGSearchAll</key>    
     <map>
       <key>Comment</key>

indra/newview/llcallingcard.cpp

 				if (!notifyMsg.empty())
 				{
 					floater->addHistoryLine(notifyMsg,LLUIColorTable::instance().getColor("SystemChatColor"));
-
-					LLIMModel::getInstance()->addMessage(session_id, SYSTEM_FROM, LLUUID::null, notifyMsg);
 				}
 			}
+
+			//*TODO instead of adding IM message about online/offline status
+			//do something like graying avatar icon on messages from a user that went offline, and  make it colored when online.
 		}
 
 		mModifyMask |= LLFriendObserver::ONLINE;

indra/newview/llpanelgroup.cpp

 	{
 		childSetValue("group_name", gdatap->mName);
 
+		LLButton* btn_join = getChild<LLButton>("btn_join");
+		LLUICtrl* join_text = getChild<LLUICtrl>("join_cost_text");
+
 		LLGroupData agent_gdatap;
 		bool is_member = gAgent.getGroupData(mID,agent_gdatap);
-		LLButton* btn_join = getChild<LLButton>("btn_join");
 		bool join_btn_visible = !is_member && gdatap->mOpenEnrollment;
+		
 		btn_join->setVisible(join_btn_visible);
+		join_text->setVisible(join_btn_visible);
+
 		if(join_btn_visible)
 		{
 			LLStringUtil::format_map_t string_args;
-			string_args["[AMOUNT]"] = llformat("%d", gdatap->mMembershipFee);
-			std::string fee_buff = getString("group_join_btn", string_args);
-			btn_join->setLabelSelected(fee_buff);
-			btn_join->setLabelUnselected(fee_buff);
+			std::string fee_buff;
+			if(gdatap->mMembershipFee)
+			{
+				string_args["[AMOUNT]"] = llformat("%d", gdatap->mMembershipFee);
+				fee_buff = getString("group_join_btn", string_args);
+				
+			}
+			else
+			{
+				fee_buff = getString("group_join_free", string_args);
+			}
+			childSetValue("join_cost_text",fee_buff);
 		}
 	}
 }

indra/newview/llpanellandmarks.cpp

 	// mast be called before any other initXXX methods to init Gear menu
 	initListCommandsHandlers();
 
+	U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER);
+	mSortByDate = sort_order & LLInventoryFilter::SO_DATE;
 	initFavoritesInventroyPanel();
 	initLandmarksInventroyPanel();
 	initMyInventroyPanel();
 	return mCurrentSelectedList ?  mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL;
 }
 
+void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate)
+{
+	if(!panel) return; 
+
+	U32 order = panel->getSortOrder();
+	if (byDate)
+	{
+		panel->setSortOrder( order | LLInventoryFilter::SO_DATE );
+	}
+	else 
+	{
+		panel->setSortOrder( order & ~LLInventoryFilter::SO_DATE );
+	}
+}
+
 // virtual
 void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)
 {
 		LLInventoryItem* inv_item =  mCurrentSelectedList->getModel()->getItem(id);
 		if(landmark)
 		{
-			LLPanelPick* panel_pick = new LLPanelPick(TRUE);
-			LLSD params;
+			LLPanelPickEdit* panel_pick = LLPanelPickEdit::create();
 			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);
+			panel_pick->onOpen(LLSD());
+
+			LLPickData data;
+			data.pos_global = landmark_global_pos;
+			data.name = cur_item->getName();
+			data.desc = inv_item->getDescription();
+			data.snapshot_id = parcel_data.snapshot_id;
+			data.parcel_id = parcel_data.parcel_id;
+			panel_pick->setPickData(&data);
+
+			LLSD params;
 			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, 
 			*/ 
 			panel_pick->setExitCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
 					panel_pick, panel_places,params));
+			panel_pick->setSaveCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
+				panel_pick, panel_places,params));
 		}
 	}
 }
 	inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2));
 
 	inventory_list->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+	updateSortOrder(inventory_list, mSortByDate);
 
 	LLPlacesFolderView* root_folder = dynamic_cast<LLPlacesFolderView*>(inventory_list->getRootFolder());
 	if (root_folder)
 	}
 }
 
-void LLLandmarksPanel::onFoldingAction(const LLSD& userdata) const
+void LLLandmarksPanel::onFoldingAction(const LLSD& userdata)
 {
 	if(!mCurrentSelectedList) return;
 
 	{
 		root_folder->closeAllFolders();
 	}
+	else if ( "sort_by_date" == command_name)
+	{
+		mSortByDate = !mSortByDate;
+		updateSortOrder(mFavoritesInventoryPanel, mSortByDate);
+		updateSortOrder(mLandmarksInventoryPanel, mSortByDate);
+		updateSortOrder(mMyInventoryPanel, mSortByDate);
+		updateSortOrder(mLibraryInventoryPanel, mSortByDate);
+	}
 	else
 	{
 		root_folder->doToSelected(&gInventory, userdata);
 	{
 		return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->canPaste() : false;
 	}
+	else if ( "sort_by_date" == command_name)
+	{
+		return  mSortByDate;
+	}
+	// 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;
+	}
+	// we can add folder, or change item/folder only in Landmarks Accordion
+	else if ("add_folder" == command_name || "rename" == command_name || "delete" == command_name)
+	{
+		return mLandmarksInventoryPanel == mCurrentSelectedList;
+	}
+
 	return true;
 }
 
 	}
 }
 
-void LLLandmarksPanel::onPickPanelExit( LLPanelPick* pick_panel, LLView* owner, const LLSD& params)
+void LLLandmarksPanel::onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params)
 {
 	pick_panel->setVisible(FALSE);
 	owner->removeChild(pick_panel);

indra/newview/llpanellandmarks.h

 	bool isLandmarkSelected() const;
 	LLLandmark* getCurSelectedLandmark() const;
 	LLFolderViewItem* getCurSelectedItem () const;
+	void updateSortOrder(LLInventoryPanel* panel, bool byDate);
 
 	//LLRemoteParcelInfoObserver interface
 	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
 	void onTrashButtonClick() const;
 	void onAddAction(const LLSD& command_name) const;
 	void onCopyPasteAction(const LLSD& command_name) const;
-	void onFoldingAction(const LLSD& command_name) const;
+	void onFoldingAction(const LLSD& command_name);
 	bool isActionEnabled(const LLSD& command_name) const;
 	void onCustomAction(const LLSD& command_name);
-	void onPickPanelExit( LLPanelPick* pick_panel, LLView* owner, const LLSD& params);
+	void onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params);
 
 private:
 	LLInventorySubTreePanel*	mFavoritesInventoryPanel;
 	LLInventorySubTreePanel*	mCurrentSelectedList;
 
 	LLPanel*					mListCommands;
+	bool 						mSortByDate;
 };
 
 #endif //LL_LLPANELLANDMARKS_H

indra/newview/llpanelpeople.cpp

 	}
 };
 
+/** Compares avatar items by online status, then by name */
+class LLAvatarItemStatusComparator : public LLAvatarItemComparator
+{
+public:
+	LLAvatarItemStatusComparator() {};
+
+protected:
+	/**
+	 * @return true if item1 < item2, false otherwise
+	 */
+	virtual bool doCompare(const LLAvatarListItem* item1, const LLAvatarListItem* item2) const
+	{
+		LLAvatarTracker& at = LLAvatarTracker::instance();
+		bool online1 = at.isBuddyOnline(item1->getAvatarId());
+		bool online2 = at.isBuddyOnline(item2->getAvatarId());
+
+		if (online1 == online2)
+		{
+			std::string name1 = item1->getAvatarName();
+			std::string name2 = item2->getAvatarName();
+
+			LLStringUtil::toUpper(name1);
+			LLStringUtil::toUpper(name2);
+
+			return name1 < name2;
+		}
+		
+		return online1 > online2; 
+	}
+};
+
 static const LLAvatarItemRecentComparator RECENT_COMPARATOR;
+static const LLAvatarItemStatusComparator STATUS_COMPARATOR;
 
 static LLRegisterPanelClassWrapper<LLPanelPeople> t_people("panel_people");
 
 	mNearbyList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
 	mRecentList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
 
-	mRecentList->setComparator(&RECENT_COMPARATOR);
+	setSortOrder(mRecentList,		(ESortOrder)gSavedSettings.getU32("RecentPeopleSortOrder"),	false);
+	setSortOrder(mAllFriendList,	(ESortOrder)gSavedSettings.getU32("FriendsSortOrder"),		false);
 
 	LLPanel* groups_panel = getChild<LLPanel>(GROUP_TAB_NAME);
 	groups_panel->childSetAction("activate_btn", boost::bind(&LLPanelPeople::onActivateButtonClicked,	this));
 
 	// Create menus.
 	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
 	
 	registrar.add("People.Group.Plus.Action",  boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked,  this, _2));
 	registrar.add("People.Friends.ViewSort.Action",  boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked,  this, _2));
 	registrar.add("People.Nearby.ViewSort.Action",  boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked,  this, _2));
 	registrar.add("People.Groups.ViewSort.Action",  boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked,  this, _2));
 	registrar.add("People.Recent.ViewSort.Action",  boost::bind(&LLPanelPeople::onRecentViewSortMenuItemClicked,  this, _2));
+
+	enable_registrar.add("People.Friends.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck,	this, _2));
+	enable_registrar.add("People.Recent.ViewSort.CheckItem",	boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck,	this, _2));
 	
 	LLMenuGL* plus_menu  = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_plus.xml",  gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
 	mGroupPlusMenuHandle  = plus_menu->getHandle();
 	LLMenuGL::showPopup(parent_panel, menu, menu_x, menu_y);
 }
 
+void LLPanelPeople::setSortOrder(LLAvatarList* list, ESortOrder order, bool save)
+{
+	switch (order)
+	{
+	case E_SORT_BY_NAME:
+		list->sortByName();
+		break;
+	case E_SORT_BY_STATUS:
+		list->setComparator(&STATUS_COMPARATOR);
+		list->sort();
+		break;
+	case E_SORT_BY_MOST_RECENT:
+		list->setComparator(&RECENT_COMPARATOR);
+		list->sort();
+		break;
+	default:
+		llwarns << "Unrecognized people sort order for " << list->getName() << llendl;
+		return;
+	}
+
+	if (save)
+	{
+		std::string setting;
+
+		if (list == mAllFriendList || list == mOnlineFriendList)
+			setting = "FriendsSortOrder";
+		else if (list == mRecentList)
+			setting = "RecentPeopleSortOrder";
+		else if (list == mNearbyList)
+			setting = "NearbyPeopleSortOrder"; // *TODO: unused by current implementation
+
+		if (!setting.empty())
+			gSavedSettings.setU32(setting, order);
+	}
+}
+
 void LLPanelPeople::onVisibilityChange(const LLSD& new_visibility)
 {
 	if (new_visibility.asBoolean() == FALSE)
 
 	if (chosen_item == "sort_name")
 	{
+		setSortOrder(mAllFriendList, E_SORT_BY_NAME);
 	}
 	else if (chosen_item == "sort_status")
 	{
+		setSortOrder(mAllFriendList, E_SORT_BY_STATUS);
 	}
 	else if (chosen_item == "view_icons")
 	{
 
 	if (chosen_item == "sort_recent")
 	{
-		mRecentList->setComparator(&RECENT_COMPARATOR);
-		mRecentList->sort();
+		setSortOrder(mRecentList, E_SORT_BY_MOST_RECENT);
 	} 
 	else if (chosen_item == "sort_name")
 	{
-		mRecentList->sortByName();
+		setSortOrder(mRecentList, E_SORT_BY_NAME);
 	}
 	else if (chosen_item == "view_icons")
 	{
+		// *TODO: implement showing/hiding icons
 	}
 }
 
+bool LLPanelPeople::onFriendsViewSortMenuItemCheck(const LLSD& userdata) 
+{
+	std::string item = userdata.asString();
+	U32 sort_order = gSavedSettings.getU32("FriendsSortOrder");
+
+	if (item == "sort_name") 
+		return sort_order == E_SORT_BY_NAME;
+	if (item == "sort_status")
+		return sort_order == E_SORT_BY_STATUS;
+
+	return false;
+}
+
+bool LLPanelPeople::onRecentViewSortMenuItemCheck(const LLSD& userdata) 
+{
+	std::string item = userdata.asString();
+	U32 sort_order = gSavedSettings.getU32("RecentPeopleSortOrder");
+
+	if (item == "sort_recent")
+		return sort_order == E_SORT_BY_MOST_RECENT;
+	if (item == "sort_name") 
+		return sort_order == E_SORT_BY_NAME;
+
+	return false;
+}
+
 void LLPanelPeople::onCallButtonClicked()
 {
 	// *TODO: not implemented yet

indra/newview/llpanelpeople.h

 	class Updater;
 
 private:
+
+	typedef enum e_sort_oder {
+		E_SORT_BY_NAME = 0,
+		E_SORT_BY_STATUS = 1,
+		E_SORT_BY_MOST_RECENT = 2,
+	} ESortOrder;
+
 	// methods indirectly called by the updaters
 	void					updateFriendList();
 	void					updateNearbyList();
 	void					buttonSetEnabled(const std::string& btn_name, bool enabled);
 	void					buttonSetAction(const std::string& btn_name, const commit_signal_t::slot_type& cb);
 	void					showGroupMenu(LLMenuGL* menu);
+	void					setSortOrder(LLAvatarList* list, ESortOrder order, bool save = true);
 
 	void					onVisibilityChange( const LLSD& new_visibility);
 
 	void					onGroupsViewSortMenuItemClicked(const LLSD& userdata);
 	void					onRecentViewSortMenuItemClicked(const LLSD& userdata);
 
+	bool					onFriendsViewSortMenuItemCheck(const LLSD& userdata);
+	bool					onRecentViewSortMenuItemCheck(const LLSD& userdata);
+
 	// misc callbacks
 	static void				onAvatarPicked(
 								const std::vector<std::string>& names,

indra/newview/llpanelpick.cpp

 
 std::string SET_LOCATION_NOTICE("(will update after save)");
 
-LLPanelPick::LLPanelPick(BOOL edit_mode/* = FALSE */)
-:	LLPanel(), LLAvatarPropertiesObserver(), LLRemoteParcelInfoObserver(),
-	mEditMode(edit_mode),
-	mSnapshotCtrl(NULL),
-	mPickId(LLUUID::null),
-	mCreatorId(LLUUID::null),
-	mDataReceived(FALSE),
-	mIsPickNew(false),
-	mLocationChanged(false)
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+//static
+LLPanelPickInfo* LLPanelPickInfo::create()
 {
-	if (edit_mode)
+	LLPanelPickInfo* panel = new LLPanelPickInfo();
+	LLUICtrlFactory::getInstance()->buildPanel(panel, XML_PANEL_PICK_INFO);
+	return panel;
+}
+
+LLPanelPickInfo::LLPanelPickInfo()
+ : LLPanel()
+ , LLAvatarPropertiesObserver()
+ , LLRemoteParcelInfoObserver()
+ , mAvatarId(LLUUID::null)
+ , mSnapshotCtrl(NULL)
+ , mPickId(LLUUID::null)
+{
+}
+
+LLPanelPickInfo::~LLPanelPickInfo()
+{
+	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
+}
+
+void LLPanelPickInfo::onOpen(const LLSD& key)
+{
+	LLUUID avatar_id = key["avatar_id"];
+	if(avatar_id.isNull())
 	{
-		LLUICtrlFactory::getInstance()->buildPanel(this, XML_PANEL_EDIT_PICK);
-		LLAvatarPropertiesProcessor::instance().addObserver(gAgentID, this);
-	}
-	else
-	{
-		LLUICtrlFactory::getInstance()->buildPanel(this, XML_PANEL_PICK_INFO);
+		return;
 	}
 
+	if(getAvatarId().notNull())
+	{
+		LLAvatarPropertiesProcessor::getInstance()->removeObserver(
+			getAvatarId(), this);
+	}
+
+	setAvatarId(avatar_id);
+
+	resetData();
+	resetControls();
+
+	setPickId(key["pick_id"]);
+	setPickName(key["pick_name"]);
+	setPickDesc(key["pick_desc"]);
+	setSnapshotId(key["snapshot_id"]);
+
+	LLAvatarPropertiesProcessor::getInstance()->addObserver(
+		getAvatarId(), this);
+	LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(
+		getAvatarId(), getPickId());
 }
 
-LLPanelPick::~LLPanelPick()
-{
-	if (mCreatorId.notNull()) 	LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorId, this);
-}
-
-void LLPanelPick::reset()
-{
-	setEditMode(FALSE);
-	
-	mPickId.setNull();
-	mCreatorId.setNull();
-	mParcelId.setNull();
-	
-	setPickName("");
-	setPickDesc("");
-	setPickLocation("");
-	mSnapshotCtrl->setImageAssetID(LLUUID::null);
-
-	//*HACK just setting asset id to NULL not enough to clear 
-	//the texture controls, w/o setValid(FALSE) it continues to 
-	//draw the previously set image
-	mSnapshotCtrl->setValid(FALSE);
-
-	mDataReceived = FALSE;
-
-	mPosGlobal.clearVec();
-
-	childSetValue("maturity", "");
-}
-
-BOOL LLPanelPick::postBuild()
+BOOL LLPanelPickInfo::postBuild()
 {
 	mSnapshotCtrl = getChild<LLTextureCtrl>(XML_SNAPSHOT);
 
-	if (mEditMode)
-	{
-		enableSaveButton(FALSE);
+	childSetLabelArg(XML_BTN_SAVE, SAVE_BTN_LABEL, std::string("Pick"));
 
-		mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1));
-
-		LLLineEditor* line_edit = getChild<LLLineEditor>("pick_name");
-		line_edit->setKeystrokeCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1), NULL);
-		
-		LLTextEditor* text_edit = getChild<LLTextEditor>("pick_desc");
-		text_edit->setKeystrokeCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1));
-
-		childSetAction("cancel_btn", boost::bind(&LLPanelPick::onClickCancel, this));
-		childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPick::onClickSet, this));
-		childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPick::onClickSave, this));
-
-		mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelPick::childSetVisible, this, "edit_icon", true));
-		mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelPick::childSetVisible, this, "edit_icon", false));
-	}
-	else
-	{
-		childSetAction("edit_btn", boost::bind(&LLPanelPick::onClickEdit, this));
-		childSetAction("teleport_btn", boost::bind(&LLPanelPick::onClickTeleport, this));
-		childSetAction("show_on_map_btn", boost::bind(&LLPanelPick::onClickMap, this));
-
-	}
-
-	// EXT-822. We have to process "Back" button click in both Edit & View Modes
-	if (!mBackCb.empty())
-	{
-		LLButton* button = findChild<LLButton>("back_btn");
-		if (button) button->setClickedCallback(mBackCb);
-	}
+	childSetAction("teleport_btn", boost::bind(&LLPanelPickInfo::onClickTeleport, this));
+	childSetAction("show_on_map_btn", boost::bind(&LLPanelPickInfo::onClickMap, this));
+	childSetAction("back_btn", boost::bind(&LLPanelPickInfo::onClickBack, this));
 
 	return TRUE;
 }
 
-void LLPanelPick::init(LLUUID creator_id, LLUUID pick_id)
+void LLPanelPickInfo::processProperties(void* data, EAvatarProcessorType type)
 {
-	mCreatorId = creator_id;
-	mPickId = pick_id;
+	if(APT_PICK_INFO != type)
+	{
+		return;
+	}
+	LLPickData* pick_info = static_cast<LLPickData*>(data);
+	if(!pick_info 
+		|| pick_info->creator_id != getAvatarId() 
+		|| pick_info->pick_id != getPickId())
+	{
+		return;
+	}
 
-	//*TODO consider removing this, already called by setEditMode()
-	updateButtons();
+	setSnapshotId(pick_info->snapshot_id);
+	setPickName(pick_info->name);
+	setPickDesc(pick_info->desc);
+	setPosGlobal(pick_info->pos_global);
+	setPickLocation(createLocationText(pick_info->user_name, pick_info->original_name, 
+		pick_info->sim_name, pick_info->pos_global));
 
-	requestData();
+	// *NOTE dzaporozhan
+	// We want to keep listening to APT_PICK_INFO because user may 
+	// edit the Pick and we have to update Pick info panel.
+	// revomeObserver is called from onClickBack
 }
 
-void LLPanelPick::requestData()
+void LLPanelPickInfo::setExitCallback(const commit_callback_t& cb)
 {
-	mDataReceived = FALSE;
-	LLAvatarPropertiesProcessor::instance().addObserver(mCreatorId, this);
-	LLAvatarPropertiesProcessor::instance().sendPickInfoRequest(mCreatorId, mPickId);
+	getChild<LLButton>("back_btn")->setClickedCallback(cb);
 }
 
-void LLPanelPick::init(LLPickData *pick_data)
+void LLPanelPickInfo::processParcelInfo(const LLParcelData& parcel_data)
 {
-	mPickId = pick_data->pick_id;
-	mCreatorId = pick_data->creator_id;
+	// HACK: Flag 0x2 == adult region,
+	// Flag 0x1 == mature region, otherwise assume PG
+	std::string rating_icon = "icon_event.tga";
+	if (parcel_data.flags & 0x2)
+	{
+		rating_icon = "icon_event_adult.tga";
+	}
+	else if (parcel_data.flags & 0x1)
+	{
+		rating_icon = "icon_event_mature.tga";
+	}
 
-	setPickName(pick_data->name);
-	setPickDesc(pick_data->desc);
-	
-	mSnapshotCtrl->setImageAssetID(pick_data->snapshot_id);
+	childSetValue("maturity", rating_icon);
 
-	//*HACK see reset() where the texture control was set to FALSE
-	mSnapshotCtrl->setValid(TRUE);
-
-	mPosGlobal = pick_data->pos_global;
-	mSimName = pick_data->sim_name;
-	mParcelId = pick_data->parcel_id;
-
-	setPickLocation(createLocationText(pick_data->user_name, pick_data->original_name,
-		pick_data->sim_name, pick_data->pos_global));
+	//*NOTE we don't removeObserver(...) ourselves cause LLRemoveParcelProcessor does it for us
 }
 
-void LLPanelPick::prepareNewPick(const LLVector3d pos_global,
-								const std::string& name,
-								const std::string& desc,
-								const LLUUID& snapshot_id,
-								const LLUUID& parcel_id)
+void LLPanelPickInfo::setEditPickCallback(const commit_callback_t& cb)
 {
-	mPickId.generate();
-	mCreatorId = gAgent.getID();
-	mPosGlobal = pos_global;
-	setPickName(name);
-	setPickDesc(desc);
-	mSnapshotCtrl->setImageAssetID(snapshot_id);
-	mParcelId = parcel_id;
-
-	setPickLocation(createLocationText(std::string(""), SET_LOCATION_NOTICE, name, pos_global));
-
-	childSetLabelArg(XML_BTN_SAVE, SAVE_BTN_LABEL, std::string("Pick"));
-
-	mIsPickNew = true;
+	getChild<LLButton>("edit_btn")->setClickedCallback(cb);
 }
 
-// Fill in some reasonable defaults for a new pick.
-void LLPanelPick::prepareNewPick()
+// PROTECTED AREA
+
+void LLPanelPickInfo::resetControls()
 {
-	// Try to fill in the current parcel
-	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-	if (parcel)
+	if(getAvatarId() == gAgent.getID())
 	{
-		prepareNewPick(gAgent.getPositionGlobal(),
-					  parcel->getName(),
-					  parcel->getDesc(),
-					  parcel->getSnapshotID(),
-					  parcel->getID());
+		childSetEnabled("edit_btn", TRUE);
+		childSetVisible("edit_btn", TRUE);
+	}
+	else
+	{
+		childSetEnabled("edit_btn", FALSE);
+		childSetVisible("edit_btn", FALSE);
 	}
 }
 
-/*virtual*/ void LLPanelPick::processProperties(void* data, EAvatarProcessorType type)
+void LLPanelPickInfo::resetData()
 {
-	if (APT_PICK_INFO != type) return;
-	if (!data) return;
-
-	LLPickData* pick_data = static_cast<LLPickData *>(data);
-	if (!pick_data) return;
-	if (mPickId != pick_data->pick_id) return;
-
-	init(pick_data);
-	mDataReceived = TRUE;
-	LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorId, this);
-
-	if (!mEditMode) 
-	{
-		LLRemoteParcelInfoProcessor::getInstance()->addObserver(pick_data->parcel_id, this);
-		LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(pick_data->parcel_id);
-	}
+	setPickName(LLStringUtil::null);
+	setPickDesc(LLStringUtil::null);
+	setPickLocation(LLStringUtil::null);
+	setPickId(LLUUID::null);
+	setSnapshotId(LLUUID::null);
+	mPosGlobal.clearVec();
+	childSetValue("maturity", LLStringUtil::null);
 }
 
-
-void LLPanelPick::setEditMode( BOOL edit_mode )
-{
-	if (mEditMode == edit_mode) return;
-	mEditMode = edit_mode;
-
-	// preserve data before killing controls
-	LLUUID snapshot_id = mSnapshotCtrl->getImageAssetID();
-	LLRect old_rect = getRect();
-
-	deleteAllChildren();
-
-	// *WORKAROUND: for EXT-931. Children are created for both XML_PANEL_EDIT_PICK & XML_PANEL_PICK_INFO files
-	// The reason is in LLPanel::initPanelXML called from the LLUICtrlFactory::buildPanel().
-	// It creates children from the xml file stored while previous initializing in the "mXMLFilename" member
-	// and then in creates children from the parameters passed from the LLUICtrlFactory::buildPanel().
-	// Xml filename is stored after LLPanel::initPanelXML is called (added with export-from-ll/viewer-2-0, r1594 into LLUICtrlFactory::buildPanel & LLUICtrlFactory::buildFloater)
-	// In case panel creates children from the different xml files they appear from both files.
-	// So, let clear xml filename related to this instance.
-	setXMLFilename("");
-
-	if (edit_mode)
-	{
-		LLUICtrlFactory::getInstance()->buildPanel(this, XML_PANEL_EDIT_PICK);
-	}
-	else
-	{
-		LLUICtrlFactory::getInstance()->buildPanel(this, XML_PANEL_PICK_INFO);
-	}
-
-	//*NOTE this code is from LLPanelMeProfile.togglePanel()... doubt this is a right way to do things
-	reshape(old_rect.getWidth(), old_rect.getHeight());
-	old_rect.setLeftTopAndSize(0, old_rect.getHeight(), old_rect.getWidth(), old_rect.getHeight());
-	setRect(old_rect);
-
-	// time to restore data
-	setPickName(mName);
-	setPickDesc(mDesc);
-	setPickLocation(mLocation);
-	mSnapshotCtrl->setImageAssetID(snapshot_id);
-
-	updateButtons();
-}
-
-void LLPanelPick::onPickChanged(LLUICtrl* ctrl)
-{
-	if(mLocationChanged)
-	{
-		// Pick was enabled in onClickSet
-		return;
-	}
-
-	if( mSnapshotCtrl->isDirty()
-		|| getChild<LLLineEditor>("pick_name")->isDirty()
-		|| getChild<LLTextEditor>("pick_desc")->isDirty() )
-	{
-		enableSaveButton(TRUE);
-	}
-	else
-	{
-		enableSaveButton(FALSE);
-	}
-}
-
-//////////////////////////////////////////////////////////////////////////
-// PROTECTED AREA
-//////////////////////////////////////////////////////////////////////////
-
-//static
-std::string LLPanelPick::createLocationText(const std::string& owner_name, const std::string& original_name,
-												 const std::string& sim_name, const LLVector3d& pos_global)
+// static
+std::string LLPanelPickInfo::createLocationText(const std::string& owner_name, const std::string& original_name, const std::string& sim_name, const LLVector3d& pos_global)
 {
 	std::string location_text;
 	location_text.append(owner_name);
 	return location_text;
 }
 
-void LLPanelPick::setPickName(std::string name)
+void LLPanelPickInfo::setSnapshotId(const LLUUID& id) 
+{ 
+	mSnapshotCtrl->setImageAssetID(id);
+	mSnapshotCtrl->setValid(TRUE);
+}
+
+void LLPanelPickInfo::setPickName(const std::string& name)
 {
 	childSetValue(XML_NAME, name);
-	
-	//preserving non-wrapped text for info/edit modes switching
-	mName = name;
 }
 
-void LLPanelPick::setPickDesc(std::string desc)
+void LLPanelPickInfo::setPickDesc(const std::string& desc)
 {
 	childSetValue(XML_DESC, desc);
-
-	//preserving non-wrapped text for info/edit modes switching
-	mDesc = desc;
 }
 
-void LLPanelPick::setPickLocation(const std::string& location)
+void LLPanelPickInfo::setPickLocation(const std::string& location)
 {
 	childSetValue(XML_LOCATION, location);
 
 	mLocation = location;
 }
 
-std::string LLPanelPick::getPickName()
+void LLPanelPickInfo::onClickMap()
 {
-	return childGetValue(XML_NAME).asString();
+	LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
+	LLFloaterReg::showInstance("world_map", "center");
 }
 
-std::string LLPanelPick::getPickDesc()
+void LLPanelPickInfo::onClickTeleport()
 {
-	return childGetValue(XML_DESC).asString();
+	if (!getPosGlobal().isExactlyZero())
+	{
+		gAgent.teleportViaLocation(getPosGlobal());
+		LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
+	}
 }
 
-std::string LLPanelPick::getPickLocation()
+void LLPanelPickInfo::onClickBack()
 {
-	return childGetValue(XML_LOCATION).asString();
+	LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
 }
 
-void LLPanelPick::sendUpdate()
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+//static
+LLPanelPickEdit* LLPanelPickEdit::create()
+{
+	LLPanelPickEdit* panel = new LLPanelPickEdit();
+	LLUICtrlFactory::getInstance()->buildPanel(panel, XML_PANEL_EDIT_PICK);
+	return panel;
+}
+
+LLPanelPickEdit::LLPanelPickEdit()
+ : LLPanelPickInfo()
+ , mLocationChanged(false)
+ , mNeedData(true)
+{
+}
+
+LLPanelPickEdit::~LLPanelPickEdit()
+{
+}
+
+void LLPanelPickEdit::onOpen(const LLSD& key)
+{
+	LLUUID pick_id = key["pick_id"];
+	mNeedData = true;
+
+	// creating new Pick
+	if(pick_id.isNull())
+	{
+		setAvatarId(gAgent.getID());
+
+		resetData();
+		resetControls();
+
+		setPosGlobal(gAgent.getPositionGlobal());
+
+		LLUUID parcel_id = LLUUID::null, snapshot_id = LLUUID::null;
+		std::string pick_name, pick_desc;
+
+		LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+		if(parcel)
+		{
+			parcel_id = parcel->getID();
+			pick_name = parcel->getName();
+			pick_desc = parcel->getDesc();
+			snapshot_id = parcel->getSnapshotID();
+		}
+
+		setParcelID(parcel_id);
+		childSetValue("pick_name", pick_name);
+		childSetValue("pick_desc", pick_desc);
+		setSnapshotId(snapshot_id);
+		setPickLocation(createLocationText(LLStringUtil::null, SET_LOCATION_NOTICE, 
+			pick_name, getPosGlobal()));
+
+		enableSaveButton(true);
+	}
+	// editing existing pick
+	else
+	{
+		LLPanelPickInfo::onOpen(key);
+
+		enableSaveButton(false);
+	}
+
+	resetDirty();
+}
+
+void LLPanelPickEdit::setPickData(const LLPickData* pick_data)
+{
+	if(!pick_data)
+	{
+		return;
+	}
+
+	mNeedData = false;
+
+	setParcelID(pick_data->parcel_id);
+	childSetValue("pick_name", pick_data->name);
+	childSetValue("pick_desc", pick_data->desc);
+	setSnapshotId(pick_data->snapshot_id);
+	setPickLocation(createLocationText(pick_data->user_name, pick_data->original_name, /*pick_data->sim_name,*/ 
+		pick_data->name, pick_data->pos_global));
+}
+
+BOOL LLPanelPickEdit::postBuild()
+{
+	LLPanelPickInfo::postBuild();
+
+	mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1));
+	mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelPickEdit::childSetVisible, this, "edit_icon", true));
+	mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelPickEdit::childSetVisible, this, "edit_icon", false));
+
+	LLLineEditor* line_edit = getChild<LLLineEditor>("pick_name");
+	line_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1), NULL);
+
+	LLTextEditor* text_edit = getChild<LLTextEditor>("pick_desc");
+	text_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1));
+
+	childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPickEdit::onClickSave, this));
+	childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPickEdit::onClickSetLocation, this));
+
+	return TRUE;
+}
+
+void LLPanelPickEdit::setSaveCallback(const commit_callback_t& cb)
+{
+	getChild<LLButton>("save_changes_btn")->setClickedCallback(cb);
+}
+
+void LLPanelPickEdit::setCancelCallback(const commit_callback_t& cb)
+{
+	getChild<LLButton>("cancel_btn")->setClickedCallback(cb);
+}
+
+void LLPanelPickEdit::resetDirty()
+{
+	LLPanelPickInfo::resetDirty();
+
+	getChild<LLLineEditor>("pick_name")->resetDirty();
+	getChild<LLTextEditor>("pick_desc")->resetDirty();
+	mSnapshotCtrl->resetDirty();
+	mLocationChanged = false;
+}
+
+BOOL LLPanelPickEdit::isDirty() const
+{
+	if( LLPanelPickInfo::isDirty()
+		|| mLocationChanged
+		|| mSnapshotCtrl->isDirty()
+		|| getChild<LLLineEditor>("pick_name")->isDirty()
+		|| getChild<LLTextEditor>("pick_desc")->isDirty())
+	{
+		return TRUE;
+	}
+	return FALSE;
+}
+
+// PROTECTED AREA
+
+void LLPanelPickEdit::sendUpdate()
 {
 	LLPickData pick_data;
 
 	// If we don't have a pick id yet, we'll need to generate one,
 	// otherwise we'll keep overwriting pick_id 00000 in the database.
-	if (mPickId.isNull()) mPickId.generate();
+	if (getPickId().isNull()) 
+	{
+		getPickId().generate();
+	}
 
 	pick_data.agent_id = gAgent.getID();
 	pick_data.session_id = gAgent.getSessionID();
-	pick_data.pick_id = mPickId;
-	pick_data.creator_id = gAgentID;
+	pick_data.pick_id = getPickId();
+	pick_data.creator_id = gAgent.getID();;
 
 	//legacy var  need to be deleted
 	pick_data.top_pick = FALSE; 
 	pick_data.parcel_id = mParcelId;
-	pick_data.name = getPickName();
-	pick_data.desc = getPickDesc();
+	pick_data.name = childGetValue(XML_NAME).asString();
+	pick_data.desc = childGetValue(XML_DESC).asString();
 	pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID();
-	pick_data.pos_global = mPosGlobal;
+	pick_data.pos_global = getPosGlobal();
 	pick_data.sort_order = 0;
 	pick_data.enabled = TRUE;
 
-	mDataReceived = FALSE;
-	LLAvatarPropertiesProcessor::instance().addObserver(gAgentID, this);
-
 	LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data);
 }
 
-
-//-----------------------------------------
-// "PICK INFO" (VIEW MODE) BUTTON HANDLERS
-//-----------------------------------------
-
-//static
-void LLPanelPick::onClickEdit()
+void LLPanelPickEdit::onPickChanged(LLUICtrl* ctrl)
 {
-	if (mEditMode) return;
-	if (!mDataReceived) return;
-	setEditMode(TRUE);
+	if(isDirty())
+	{
+		enableSaveButton(true);
+	}
+	else
+	{
+		enableSaveButton(false);
+	}
 }
 
-//static
-void LLPanelPick::onClickTeleport()
+void LLPanelPickEdit::resetData()
 {
-	teleport(mPosGlobal);
+	LLPanelPickInfo::resetData();
+	mLocationChanged = false;
 }
 
-//static
-void LLPanelPick::onClickMap()
+void LLPanelPickEdit::enableSaveButton(bool enable)
 {
-	showOnMap(mPosGlobal);
+	childSetEnabled(XML_BTN_SAVE, enable);
 }
 
-
-//-----------------------------------------
-// "EDIT PICK" (EDIT MODE) BUTTON HANDLERS
-//-----------------------------------------
-
-//static
-void LLPanelPick::onClickCancel()
+void LLPanelPickEdit::onClickSetLocation()
 {
-	if (!mEditMode) return;
-	
-	if (mIsPickNew)
-	{
-		mBackCb(this, LLSD());
-		return;
-	}
-
-	LLUUID pick_id = mPickId;
-	LLUUID creator_id = mCreatorId;
-	reset();
-	init(creator_id, pick_id);
-}
-
-// static
-void LLPanelPick::onClickSet()
-{
-	if (!mEditMode) return;
-	if (!mIsPickNew && !mDataReceived) return;
-
-	// Save location for later.
-	mPosGlobal = gAgent.getPositionGlobal();
+	// Save location for later use.
+	setPosGlobal(gAgent.getPositionGlobal());
 
 	LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
 	if (parcel)
 		mParcelId = parcel->getID();
 		mSimName = parcel->getName();
 	}
-	setPickLocation(createLocationText(std::string(""), SET_LOCATION_NOTICE, mSimName, mPosGlobal));
+	setPickLocation(createLocationText(
+		LLStringUtil::null, SET_LOCATION_NOTICE, mSimName, getPosGlobal()));
 
 	mLocationChanged = true;
 	enableSaveButton(TRUE);
 }
 
-// static
-void LLPanelPick::onClickSave()
+void LLPanelPickEdit::onClickSave()
 {
-	if (!mEditMode) return;
-	if (!mIsPickNew && !mDataReceived) return;
+	sendUpdate();
 
-	sendUpdate();
-	
-	if (mIsPickNew)
-	{
-		mBackCb(this, LLSD());
-		return;
-	}
+	mLocationChanged = false;
 
-	setEditMode(FALSE);
+	LLSD params;
+	params["action"] = "save_new_pick";
+	notifyParent(params);
 }
 
-void LLPanelPick::updateButtons()
+void LLPanelPickEdit::processProperties(void* data, EAvatarProcessorType type)
 {
-
-	// on Pick Info panel (for non-Agent picks) edit_btn should be invisible
-	if (mEditMode)
+	if(mNeedData)
 	{
-		childSetLabelArg(XML_BTN_SAVE, SAVE_BTN_LABEL, std::string("Changes"));
-	}
-	else 
-	{
-		if (mCreatorId != gAgentID)
-		{
-			childSetEnabled("edit_btn", FALSE);
-			childSetVisible("edit_btn", FALSE);
-		}
-		else 
-		{
-			childSetEnabled("edit_btn", TRUE);
-			childSetVisible("edit_btn", TRUE);
-		}
+		LLPanelPickInfo::processProperties(data, type);
 	}
 }
-
-void LLPanelPick::setExitCallback(commit_callback_t cb)
-{
-	mBackCb = cb;
-	LLButton* button = findChild<LLButton>("back_btn");
-	if (button) button->setClickedCallback(mBackCb);
-}
-
-//static
-void LLPanelPick::teleport(const LLVector3d& position)
-{
-	if (!position.isExactlyZero())
-	{
-		gAgent.teleportViaLocation(position);
-		LLFloaterWorldMap::getInstance()->trackLocation(position);
-	}
-}
-
-//static
-void LLPanelPick::showOnMap(const LLVector3d& position)
-{
-	LLFloaterWorldMap::getInstance()->trackLocation(position);
-	LLFloaterReg::showInstance("world_map", "center");
-}
-
-void LLPanelPick::processParcelInfo(const LLParcelData& parcel_data)
-{
-	if (mEditMode) return;
-
-	// HACK: Flag 0x2 == adult region,
-	// Flag 0x1 == mature region, otherwise assume PG
-	std::string rating_icon = "icon_event.tga";
-	if (parcel_data.flags & 0x2)
-	{
-		rating_icon = "icon_event_adult.tga";
-	}
-	else if (parcel_data.flags & 0x1)
-	{
-		rating_icon = "icon_event_mature.tga";
-	}
-	
-	childSetValue("maturity", rating_icon);
-
-	//*NOTE we don't removeObserver(...) ourselves cause LLRemoveParcelProcessor does it for us
-}
-
-void LLPanelPick::enableSaveButton(bool enable)
-{
-	if(!mEditMode)
-	{
-		return;
-	}
-	childSetEnabled(XML_BTN_SAVE, enable);
-}

indra/newview/llpanelpick.h

 class LLMessageSystem;
 class LLAvatarPropertiesObserver;
 
-class LLPanelPick : public LLPanel, public LLAvatarPropertiesObserver, LLRemoteParcelInfoObserver
+/**
+ * Panel for displaying Pick Information - snapshot, name, description, etc.
+ */
+class LLPanelPickInfo : public LLPanel, public LLAvatarPropertiesObserver, LLRemoteParcelInfoObserver
 {
-	LOG_CLASS(LLPanelPick);
+	LOG_CLASS(LLPanelPickInfo);
 public:
-	LLPanelPick(BOOL edit_mode = FALSE);
-	/*virtual*/ ~LLPanelPick();
+	
+	// Creates new panel
+	static LLPanelPickInfo* create();
 
-	// switches the panel to the VIEW mode and resets controls
-	void reset();
+	virtual ~LLPanelPickInfo();
+
+	/**
+	 * Initializes panel properties
+	 *
+	 * By default Pick will be created for current Agent location.
+	 * Use setPickData to change Pick properties.
+	 */
+	/*virtual*/ void onOpen(const LLSD& key);
 
 	/*virtual*/ BOOL postBuild();
 
-	// Prepares a new pick, including creating an id, giving a sane
-	// initial position, etc (saved on clicking Save Pick button - onClickSave callback).
-	void prepareNewPick();
-	void prepareNewPick(const LLVector3d pos_global,
-					   const std::string& name,
-					   const std::string& desc,
-					   const LLUUID& snapshot_id,
-					   const LLUUID& parcel_id);
-
-	//initializes the panel with data of the pick with id = pick_id 
-	//owned by the avatar with id = creator_id
-	void init(LLUUID creator_id, LLUUID pick_id);
-
 	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
 
-	// switches the panel to either View or Edit mode
-	void setEditMode(BOOL edit_mode);
+	/**
+	 * Sets "Back" button click callback
+	 */
+	virtual void setExitCallback(const commit_callback_t& cb);
 
-	void onPickChanged(LLUICtrl* ctrl);
-
-	// because this panel works in two modes (edit/view) we are  
-	// free from managing two panel for editing and viewing picks and so
-	// are free from controlling switching between them in the parent panel (e.g. Me Profile)
-	// but that causes such a complication that we cannot set a callback for a "Back" button
-	// from the parent panel only once, so we have to preserve that callback
-	// in the pick panel and set it for the back button everytime postBuild() is called.
-	void setExitCallback(commit_callback_t cb);
-
-	static void teleport(const LLVector3d& position);
-	static void showOnMap(const LLVector3d& position);
+	/**
+	 * Sets "Edit" button click callback
+	 */
+	virtual void setEditPickCallback(const commit_callback_t& cb);
 
 	//This stuff we got from LLRemoteParcelObserver, in the last two we intentionally do nothing
 	/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
 
 protected:
 
+	LLPanelPickInfo();
+	
+	/**
+	 * Resets Pick information
+	 */
+	virtual void resetData();
+
+	/**
+	 * Resets UI controls (visibility, values)
+	 */
+	virtual void resetControls();
+
 	/** 
 	* "Location text" is actually the owner name, the original
 	* name that owner gave the parcel, and the location.
 	*/
-	static std::string createLocationText(const std::string& owner_name, const std::string& original_name,
-		const std::string& sim_name, const LLVector3d& pos_global);
+	static std::string createLocationText(
+		const std::string& owner_name, 
+		const std::string& original_name,
+		const std::string& sim_name, 
+		const LLVector3d& pos_global);
 
-	void setPickName(std::string name);
-	void setPickDesc(std::string desc);
-	void setPickLocation(const std::string& location);
+	virtual void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; }
+	virtual LLUUID& getAvatarId() { return mAvatarId; }
 
-	std::string getPickName();
-	std::string getPickDesc();
-	std::string getPickLocation();
+	/**
+	 * Sets snapshot id.
+	 *
+	 * Will mark snapshot control as valid if id is not null.
+	 * Will mark snapshot control as invalid if id is null. If null id is a valid value,
+	 * you have to manually mark snapshot is valid.
+	 */
+	virtual void setSnapshotId(const LLUUID& id);
+	
+	virtual void setPickId(const LLUUID& id) { mPickId = id; }
+	virtual LLUUID& getPickId() { return mPickId; }
+	
+	virtual void setPickName(const std::string& name);
+	
+	virtual void setPickDesc(const std::string& desc);
+	
+	virtual void setPickLocation(const std::string& location);
+	
+	virtual void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; }
+	virtual LLVector3d& getPosGlobal() { return mPosGlobal; }
 
-	void sendUpdate();
-	void requestData();
-
-	void init(LLPickData *pick_data);
-
-	void updateButtons();
-
-	//-----------------------------------------
-	// "PICK INFO" (VIEW MODE) BUTTON HANDLERS
-	//-----------------------------------------
-	void onClickEdit();
-	void onClickTeleport();
+	/**
+	 * Callback for "Map" button, opens Map
+	 */
 	void onClickMap();
 
-	//-----------------------------------------
-	// "EDIT PICK" (EDIT MODE) BUTTON HANDLERS
-	//-----------------------------------------
-	void onClickSet();
-	void onClickSave();
-	void onClickCancel();
+	/**
+	 * Callback for "Teleport" button, teleports user to Pick location.
+	 */
+	void onClickTeleport();
 
+	void onClickBack();
+
+protected:
+
+	LLTextureCtrl* mSnapshotCtrl;
+
+	LLUUID mAvatarId;
+	LLVector3d mPosGlobal;
+	LLUUID mParcelId;
+	LLUUID mPickId;
+	std::string mSimName;
+	std::string mLocation;
+};
+
+/**
+ * Panel for creating/editing Pick.
+ */
+class LLPanelPickEdit : public LLPanelPickInfo
+{
+	LOG_CLASS(LLPanelPickEdit);
+public:
+
+	/**
+	 * Creates new panel
+	 */
+	static LLPanelPickEdit* create();
+
+	/*virtual*/ ~LLPanelPickEdit();
+
+	/*virtual*/ void onOpen(const LLSD& key);
+
+	virtual void setPickData(const LLPickData* pick_data);
+
+	/*virtual*/ BOOL postBuild();
+
+	/**
+	 * Sets "Save" button click callback
+	 */
+	virtual void setSaveCallback(const commit_callback_t& cb);
+
+	/**
+	 * Sets "Cancel" button click callback
+	 */
+	virtual void setCancelCallback(const commit_callback_t& cb);
+
+	/**
+	 * Resets panel and all cantrols to unedited state
+	 */
+	/*virtual*/ void resetDirty();
+
+	/**
+	 * Returns true if any of Pick properties was changed by user.
+	 */
+	/*virtual*/ BOOL isDirty() const;
+
+	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
+
+protected:
+
+	LLPanelPickEdit();
+
+	/**
+	 * Sends Pick properties to server.
+	 */
+	void sendUpdate();
+
+	/**
+	 * Callback for Pick snapshot, name and description changed event.
+	 */
+	void onPickChanged(LLUICtrl* ctrl);
+
+	/*virtual*/ void resetData();
+
+	/**
+	 * Enables/disables "Save" button
+	 */
 	void enableSaveButton(bool enable);
 
+	/**
+	 * Callback for "Set Location" button click
+	 */
+	void onClickSetLocation();
+
+	/**
+	 * Callback for "Save" button click
+	 */
+	void onClickSave();
+
 protected:
-	BOOL mEditMode;
-	LLTextureCtrl*	mSnapshotCtrl;
-	BOOL mDataReceived;
-	bool mIsPickNew;
 
-	LLUUID mPickId;
-	LLUUID mCreatorId;
-	LLVector3d mPosGlobal;
-	LLUUID mParcelId;
-	std::string mSimName;
-
-	//These strings are used to keep non-wrapped text
-	std::string mName;
-	std::string mDesc;
-	std::string mLocation;
-
-	commit_callback_t mBackCb;
 	bool mLocationChanged;
+	bool mNeedData;
 };
 
 #endif // LL_LLPANELPICK_H

indra/newview/llpanelpicks.cpp

 #include "llagent.h"
 #include "llavatarconstants.h"
 #include "llflatlistview.h"
+#include "llfloaterreg.h"
+#include "llfloaterworldmap.h"
 #include "lltexturectrl.h"
 #include "llviewergenericmessage.h"	// send_generic_message
 #include "llmenugl.h"
 	mProfilePanel(NULL),
 	mPickPanel(NULL),
 	mPicksList(NULL)
+	, mPanelPickInfo(NULL)
+	, mPanelPickEdit(NULL)
 {
 }
 
 		mPopupMenu->setItemVisible("pick_separator", TRUE);
 	}
 
-	if(getAvatarId() != key.asUUID())
+	if(getAvatarId() != id)
 	{
 		mPicksList->goToTop();
 	}
 {
 	LLPickItem* pick_item = getSelectedPickItem();
 	if (!pick_item) return;
-	LLPanelPick::teleport(pick_item->getPosGlobal());
+
+	LLVector3d pos = pick_item->getPosGlobal();
+	if (!pos.isExactlyZero())
+	{
+		gAgent.teleportViaLocation(pos);
+		LLFloaterWorldMap::getInstance()->trackLocation(pos);
+	}
 }
 
 //static
 {
 	LLPickItem* pick_item = getSelectedPickItem();
 	if (!pick_item) return;
-	LLPanelPick::showOnMap(pick_item->getPosGlobal());
+
+	LLFloaterWorldMap::getInstance()->trackLocation(pick_item->getPosGlobal());
+	LLFloaterReg::showInstance("world_map", "center");
 }
 
 
 
 void LLPanelPicks::buildPickPanel()
 {
-	if (mPickPanel == NULL)
-	{
-		mPickPanel = new LLPanelPick();
-		mPickPanel->setExitCallback(boost::bind(&LLPanelPicks::onClickBack, this));
-	}
+// 	if (mPickPanel == NULL)
+// 	{
+// 		mPickPanel = new LLPanelPick();
+// 		mPickPanel->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, NULL));
+// 	}
 }
 
 void LLPanelPicks::onClickNew()
 {
-	buildPickPanel();
-	mPickPanel->setEditMode(TRUE);
-	mPickPanel->prepareNewPick();
-	getProfilePanel()->togglePanel(mPickPanel);
+	createPickEditPanel();
+
+	getProfilePanel()->openPanel(mPanelPickEdit, LLSD());
 }
 
 void LLPanelPicks::onClickInfo()
 	LLSD selected_value = mPicksList->getSelectedValue();
 	if (selected_value.isUndefined()) return;
 
-	buildPickPanel();
-	mPickPanel->reset();
-	mPickPanel->init(selected_value[PICK_CREATOR_ID], selected_value[PICK_ID]);
-	getProfilePanel()->togglePanel(mPickPanel);
+	LLPickItem* pick = (LLPickItem*)mPicksList->getSelectedItem();
+
+	createPickInfoPanel();
+
+	LLSD params;
+	params["pick_id"] = pick->getPickId();
+	params["avatar_id"] = pick->getCreatorId();
+	params["snapshot_id"] = pick->getSnapshotId();
+	params["pick_name"] = pick->getPickName();
+	params["pick_desc"] = pick->getPickDesc();
+
+	getProfilePanel()->openPanel(mPanelPickInfo, params);
 }
 
-void LLPanelPicks::onClickBack()
+void LLPanelPicks::onPanelPickClose(LLPanel* panel)
 {
-	getProfilePanel()->togglePanel(mPickPanel);
+	panel->setVisible(FALSE);
+}
+
+void LLPanelPicks::createPickInfoPanel()
+{
+	if(!mPanelPickInfo)
+	{
+		mPanelPickInfo = LLPanelPickInfo::create();
+		mPanelPickInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickInfo));
+		mPanelPickInfo->setEditPickCallback(boost::bind(&LLPanelPicks::onPanelPickEdit, this));
+		mPanelPickInfo->setVisible(FALSE);
+	}
+}
+
+void LLPanelPicks::createPickEditPanel()
+{
+	if(!mPanelPickEdit)
+	{
+		mPanelPickEdit = LLPanelPickEdit::create();
+		mPanelPickEdit->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickEdit));
+		mPanelPickEdit->setSaveCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickEdit));
+		mPanelPickEdit->setCancelCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickEdit));
+		mPanelPickEdit->setVisible(FALSE);
+	}
+}
+
+// void LLPanelPicks::openPickEditPanel(LLPickItem* pick)
+// {
+// 	if(!pick)
+// 	{
+// 		return;
+// 	}
+// }
+
+// void LLPanelPicks::openPickInfoPanel(LLPickItem* pick)
+// {
+// 	if(!mPanelPickInfo)
+// 	{
+// 		mPanelPickInfo = LLPanelPickInfo::create();
+// 		mPanelPickInfo->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, mPanelPickInfo));
+// 		mPanelPickInfo->setEditPickCallback(boost::bind(&LLPanelPicks::onPanelPickEdit, this));
+// 		mPanelPickInfo->setVisible(FALSE);
+// 	}
+// 
+// 	LLSD params;
+// 	params["pick_id"] = pick->getPickId();
+// 	params["avatar_id"] = pick->getCreatorId();
+// 	params["snapshot_id"] = pick->getSnapshotId();
+// 	params["pick_name"] = pick->getPickName();
+// 	params["pick_desc"] = pick->getPickDesc();
+// 
+// 	getProfilePanel()->openPanel(mPanelPickInfo, params);
+// }
+
+void LLPanelPicks::onPanelPickEdit()
+{
+	LLSD selected_value = mPicksList->getSelectedValue();
+	if (selected_value.isUndefined()) return;
+
+	LLPickItem* pick = dynamic_cast<LLPickItem*>(mPicksList->getSelectedItem());
+	
+	createPickEditPanel();
+
+	LLSD params;
+	params["pick_id"] = pick->getPickId();
+	params["avatar_id"] = pick->getCreatorId();
+	params["snapshot_id"] = pick->getSnapshotId();
+	params["pick_name"] = pick->getPickName();
+	params["pick_desc"] = pick->getPickDesc();
+
+	getProfilePanel()->openPanel(mPanelPickEdit, params);
 }
 
 void LLPanelPicks::onClickMenuEdit()
 {
-	//*TODO, refactor - most of that is similar to onClickInfo
-	LLSD selected_value = mPicksList->getSelectedValue();
-	if (selected_value.isUndefined()) return;
-
-	buildPickPanel();
-	mPickPanel->reset();
-	mPickPanel->init(selected_value[PICK_CREATOR_ID], selected_value[PICK_ID]);
-	mPickPanel->setEditMode(TRUE);
-	getProfilePanel()->togglePanel(mPickPanel);
+	onPanelPickEdit();
 }
 
 inline LLPanelProfile* LLPanelPicks::getProfilePanel()
 	setPickDesc(pick_data->desc);
 	setSnapshotId(pick_data->snapshot_id);
 	mPosGlobal = pick_data->pos_global;
+	mSimName = pick_data->sim_name;
+	mPickDescription = pick_data->desc;
+	mUserName = pick_data->user_name;
+	mOriginalName = pick_data->original_name;
 
 	LLTextureCtrl* picture = getChild<LLTextureCtrl>("picture");
 	picture->setImageAssetID(pick_data->snapshot_id);
 
 void LLPickItem::update()
 {
-	mNeedData = true;
+	setNeedData(true);
 	LLAvatarPropertiesProcessor::instance().sendPickInfoRequest(mCreatorID, mPickID);
-	mNeedData = false;
 }
 
 void LLPickItem::processProperties(void *data, EAvatarProcessorType type)
 {
-	if (APT_PICK_INFO != type) return;
-	if (!data) return;
+	if (APT_PICK_INFO != type) 
+	{
+		return;
+	}
 
 	LLPickData* pick_data = static_cast<LLPickData *>(data);
-	if (!pick_data) return;
-	if (mPickID != pick_data->pick_id) return;
+	if (!pick_data || mPickID != pick_data->pick_id) 
+	{
+		return;
+	}
 
 	init(pick_data);
+	setNeedData(false);
 	LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorID, this);
 }
 
-// virtual
-void LLPanelPicks::onClosePanel()
-{
-	// Toggle off Pick Info panel if it is visible.
-	if(mPickPanel && mPickPanel->getVisible())
-	{
-		getProfilePanel()->togglePanel(mPickPanel);
-	}
-}
-
 BOOL LLPickItem::postBuild()
 {
-	setMouseEnterCallback(boost::bind(&LLPanelPick::childSetVisible, this, "hovered_icon", true));
-	setMouseLeaveCallback(boost::bind(&LLPanelPick::childSetVisible, this, "hovered_icon", false));
+	setMouseEnterCallback(boost::bind(&LLPanelPickInfo::childSetVisible, this, "hovered_icon", true));
+	setMouseLeaveCallback(boost::bind(&LLPanelPickInfo::childSetVisible, this, "hovered_icon", false));
 	return TRUE;
 }
 

indra/newview/llpanelpicks.h

 class LLMessageSystem;
 class LLVector3d;
 class LLPanelProfileTab;
-class LLPanelPick;
 class LLAgent;
 class LLMenuGL;
 class LLPickItem;
 class LLFlatListView;
+class LLPanelPickInfo;
+class LLPanelPickEdit;
 
 class LLPanelPicks 
 	: public LLPanelProfileTab
 	// parent panels failed to work (picks related code was in me profile panel)
 	void setProfilePanel(LLPanelProfile* profile_panel);
 
-	/**
-	 * Closes LLPanelPick if it is visible.
-	 */
-	/*virtual*/ void onClosePanel();
-
 private:
 	void onClickDelete();
 	void onClickTeleport();
 	//------------------------------------------------
 	void onClickNew();
 	void onClickInfo();
-	void onClickBack();
+	void onPanelPickClose(LLPanel* panel);
+	void onPanelPickEdit();
 	void onClickMenuEdit();
 
 	void buildPickPanel();
 
 	LLPanelProfile* getProfilePanel();
 
+	void createPickInfoPanel();
+	void createPickEditPanel();
+// 	void openPickEditPanel(LLPickItem* pick);
+// 	void openPickInfoPanel(LLPickItem* pick);
+
 	LLMenuGL* mPopupMenu;
 	LLPanelProfile* mProfilePanel;
-	LLPanelPick* mPickPanel;
+	LLPanelPickInfo* mPickPanel;
 	LLFlatListView* mPicksList;
+	LLPanelPickInfo* mPanelPickInfo;
+	LLPanelPickEdit* mPanelPickEdit;
 };
 
 class LLPickItem : public LLPanel, public LLAvatarPropertiesObserver
 
 	const std::string getDescription();
 
+	const std::string& getSimName() { return mSimName; }
+
+	const std::string& getUserName() { return mUserName; }
+
+	const std::string& getOriginalName() { return mOriginalName; }
+
+	const std::string& getPickDesc() { return mPickDescription; }
+
 	/*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
 
 	void update();
 	bool mNeedData;
 
 	std::string mPickName;
+	std::string mUserName;
+	std::string mOriginalName;
+	std::string mPickDescription;
+	std::string mSimName;
 };
 
 #endif // LL_LLPANELPICKS_H

indra/newview/llpanelplaceinfo.cpp

 		folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK));
 }
 
-void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPick* pick_panel)
+void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel)
 {
 	std::string name = mParcelName->getText();
 	if (name.empty())
 		name = mRegionName->getText();
 	}
 
-	pick_panel->prepareNewPick(pos_global,
-							  name,
-							  mDescEditor->getText(),
-							  mSnapshotCtrl->getImageAssetID(),
-							  mParcelID);
+	LLPickData data;
+	data.pos_global = pos_global;
+	data.name = name;
+	data.desc = mDescEditor->getText();
+	data.snapshot_id = mSnapshotCtrl->getImageAssetID();
+	data.parcel_id = mParcelID;
+	pick_panel->setPickData(&data);
 }
 
 // virtual

indra/newview/llpanelplaceinfo.h

 class LLComboBox;
 class LLInventoryItem;
 class LLLineEditor;
-class LLPanelPick;
+class LLPanelPickEdit;
 class LLParcel;
 class LLIconCtrl;
 class LLTextBox;
 	
 	// Create a pick for the location specified
 	// by global_pos.
-	void createPick(const LLVector3d& pos_global, LLPanelPick* pick_panel);
+	void createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel);
 
 	BOOL isMediaPanelVisible();
 	void toggleMediaPanel(BOOL visible);

indra/newview/llpanelplaces.cpp

 
 		if (mPickPanel == NULL)
 		{
-			mPickPanel = new LLPanelPick();
+			mPickPanel = LLPanelPickEdit::create();
 			addChild(mPickPanel);
 
 			mPickPanel->setExitCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE));
+			mPickPanel->setCancelCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE));
+			mPickPanel->setSaveCallback(boost::bind(&LLPanelPlaces::togglePickPanel, this, FALSE));
 		}
 
 		togglePickPanel(TRUE);
+		mPickPanel->onOpen(LLSD());
+		mPlaceInfo->createPick(mPosGlobal, mPickPanel);
 
 		LLRect rect = getRect();
 		mPickPanel->reshape(rect.getWidth(), rect.getHeight());
 		mPickPanel->setRect(rect);
-		mPickPanel->setEditMode(TRUE);
-
-		mPlaceInfo->createPick(mPosGlobal, mPickPanel);
 	}
     else if (item == "add_to_favbar")
     {

indra/newview/llpanelplaces.h

 class LLInventoryItem;
 class LLFilterEditor;
 class LLLandmark;
-class LLPanelPick;
+class LLPanelPickEdit;
 class LLPanelPlaceInfo;
 class LLPanelPlacesTab;
 class LLParcelSelection;
 	LLPanelPlacesTab*			mActivePanel;
 	LLTabContainer*				mTabContainer;
 	LLPanelPlaceInfo*			mPlaceInfo;
-	LLPanelPick*				mPickPanel;
+	LLPanelPickEdit*			mPickPanel;
 	LLToggleableMenu*			mPlaceMenu;
 	LLToggleableMenu*			mLandmarkMenu;
 

indra/newview/llpanelprofile.cpp

 void LLPanelProfile::togglePanel(LLPanel* panel)
 {
 	// TRUE - we need to open/expand "panel"
-	bool expand = getChildList()->back() != panel;  // mTabCtrl->getVisible();
+	bool expand = getChildList()->front() != panel;  // mTabCtrl->getVisible();
 
 	if (expand)
 	{
-		//*NOTE on view profile panel along with tabcontainer there is 
-		// a backbutton that will be shown when there will be a panel over it even 
-		//if that panel has visible backgroud
-		setAllChildrenVisible(FALSE);
-		
-		panel->setVisible(TRUE);
 		if (panel->getParent() != this)
 		{
-			addChildInBack(panel);
+			addChild(panel);
 		}
 		else
 		{
-			sendChildToBack(panel);