Anonymous avatar Anonymous committed d55f276

merge -r 1586-1593 https://svn.aws.productengine.com/secondlife/pe/stable-2 -> viewer-2.0.0-3
Fixes: EXT-839 EXT-859 EXT-868 EXT-795 EXT-861 EXT-678 EXT-848 EXT-873

Comments (0)

Files changed (24)

indra/llui/llcombobox.cpp

 
 LLComboBox::Params::Params()
 :	allow_text_entry("allow_text_entry", false),
+	allow_new_values("allow_new_values", false),
 	show_text_as_tentative("show_text_as_tentative", true),
 	max_chars("max_chars", 20),
 	list_position("list_position", BELOW),
 	mTextEntryTentative(p.show_text_as_tentative),
 	mHasAutocompletedText(false),
 	mAllowTextEntry(p.allow_text_entry),
+	mAllowNewValues(p.allow_new_values),
 	mMaxChars(p.max_chars),
 	mPrearrangeCallback(p.prearrange_callback()),
 	mTextEntryCallback(p.text_entry_callback()),
 	if (mList->getVisible())
 	{
 		// assert selection in list
-		mList->selectNthItem(mLastSelectedIndex);
+		if(mAllowNewValues)
+		{
+			// mLastSelectedIndex = -1 means that we entered a new value, don't select
+			// any of existing items in this case.
+			if(mLastSelectedIndex >= 0)
+				mList->selectNthItem(mLastSelectedIndex);
+		}
+		else
+			mList->selectNthItem(mLastSelectedIndex);
 
 		mButton->setToggleState(FALSE);
 		mList->setVisible(FALSE);

indra/llui/llcombobox.h

 	:	public LLInitParam::Block<Params, LLUICtrl::Params>
 	{
 		Optional<bool>						allow_text_entry,
-											show_text_as_tentative;
+											show_text_as_tentative,
+											allow_new_values;
 		Optional<S32>						max_chars;
 		Optional<commit_callback_t> 		prearrange_callback,
 											text_entry_callback,
 
 private:
 	BOOL				mAllowTextEntry;
+	BOOL				mAllowNewValues;
 	S32					mMaxChars;
 	BOOL				mTextEntryTentative;
 	commit_callback_t	mPrearrangeCallback;

indra/llui/lldockablefloater.cpp

 
 #include "lldockablefloater.h"
 
+//static
+LLDockableFloater* LLDockableFloater::instance = NULL;
+
 LLDockableFloater::LLDockableFloater(LLDockControl* dockControl,
 		const LLSD& key, const Params& params) :
 	LLFloater(key, params), mDockControl(dockControl)
 {
+	resetInstance();
 }
 
 LLDockableFloater::~LLDockableFloater()
 	return LLView::postBuild();
 }
 
+void LLDockableFloater::resetInstance()
+{
+	if (instance != this)
+	{
+		if (instance != NULL && instance->isDocked())
+		{
+			//closeFloater() is not virtual
+			if (instance->canClose())
+			{
+				instance->closeFloater();
+			}
+			else
+			{
+				instance->setVisible(FALSE);
+			}
+		}
+		instance = this;
+	}
+}
+
+void LLDockableFloater::setVisible(BOOL visible)
+{
+	if(visible && isDocked())
+	{
+		resetInstance();
+	}
+	LLFloater::setVisible(visible);
+}
+
 void LLDockableFloater::setDocked(bool docked, bool pop_on_undock)
 {
 	if (mDockControl.get() != NULL)
 	{
 		if (docked)
 		{
+			resetInstance();
 			mDockControl.get()->on();
 		}
 		else

indra/llui/lldockablefloater.h

 	/* virtula */BOOL postBuild();
 	/* virtual */void setDocked(bool docked, bool pop_on_undock = true);
 	/* virtual */void draw();
+	/*virtual*/ void setVisible(BOOL visible);
+
+private:
+	/**
+	 * Provides unique of dockable floater.
+	 * If dockable floater already exists it should  be closed.
+	 */
+	void resetInstance();
 
 protected:
 	void setDockControl(LLDockControl* dockControl);
 private:
 	std::auto_ptr<LLDockControl> mDockControl;
 	LLUIImagePtr mDockTongue;
+	static LLDockableFloater* instance;
 };
 
 #endif /* LL_DOCKABLEFLOATER_H */

indra/llui/llfiltereditor.cpp

 	line_editor_p.rect(getLocalRect());
 	line_editor_p.follows.flags(FOLLOWS_ALL);
 	line_editor_p.text_pad_right(getRect().getHeight());
+	line_editor_p.revert_on_esc(false);
 	line_editor_p.keystroke_callback(boost::bind(&LLUICtrl::onCommit, this));
 
 	mFilterEditor = LLUICtrlFactory::create<LLLineEditor>(line_editor_p);

indra/llui/lllineeditor.cpp

 	background_image_focused("background_image_focused"),
 	select_on_focus("select_on_focus", false),
 	handle_edit_keys_directly("handle_edit_keys_directly", false),
+	revert_on_esc("revert_on_esc", true),
 	commit_on_focus_lost("commit_on_focus_lost", true),
 	ignore_tab("ignore_tab", true),
 	cursor_color("cursor_color"),
 	mMinHPixels(0),		// computed in updateTextPadding() below
 	mMaxHPixels(0),		// computed in updateTextPadding() below
 	mCommitOnFocusLost( p.commit_on_focus_lost ),
-	mRevertOnEsc( TRUE ),
+	mRevertOnEsc( p.revert_on_esc ),
 	mKeystrokeCallback( p.keystroke_callback() ),
 	mIsSelecting( FALSE ),
 	mSelectionStart( 0 ),

indra/llui/lllineeditor.h

 
 		Optional<bool>					select_on_focus,
 										handle_edit_keys_directly,
+										revert_on_esc,
 										commit_on_focus_lost,
 										ignore_tab;
 

indra/llui/llmenugl.cpp

 	return handled;
 }
 
+BOOL LLMenuHolderGL::handleKey(KEY key, MASK mask, BOOL called_from_parent)
+{
+	BOOL handled =  false;
+	LLMenuGL* const  pMenu  = dynamic_cast<LLMenuGL*>(getVisibleMenu());
+			
+	if (pMenu)
+	{
+		//handle ESCAPE and RETURN key
+		handled = LLPanel::handleKey(key, mask, called_from_parent);
+		if (!handled)
+		{
+			if (pMenu->getHighlightedItem())
+			{
+				handled = pMenu->handleKey(key, mask, TRUE);
+			}
+			else
+			{
+				//highlight first enabled one
+				pMenu->highlightNextItem(NULL);
+				handled = true;
+			}
+		}
+	}
+	
+	return handled;
+	
+}
+
 void LLMenuHolderGL::reshape(S32 width, S32 height, BOOL called_from_parent)
 {
 	if (width != getRect().getWidth() || height != getRect().getHeight())
 	LLView::reshape(width, height, called_from_parent);
 }
 
-BOOL LLMenuHolderGL::hasVisibleMenu() const
+LLView* const LLMenuHolderGL::getVisibleMenu() const
 {
 	for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it)
 	{
 		LLView* viewp = *child_it;
 		if (viewp->getVisible() && dynamic_cast<LLMenuBarGL*>(viewp) == NULL)
 		{
-			return TRUE;
+			return viewp;
 		}
 	}
-	return FALSE;
+	return NULL;
 }
 
 

indra/llui/llmenugl.h

 	// Close context menus on right mouse up not handled by menus.
 	/*virtual*/ BOOL handleRightMouseUp( S32 x, S32 y, MASK mask );
 
+	virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
 	virtual const LLRect getMenuRect() const { return getLocalRect(); }
-	virtual BOOL hasVisibleMenu() const;
+	LLView*const getVisibleMenu() const;
+	virtual BOOL hasVisibleMenu() const {return getVisibleMenu() != NULL;}
 
 	static void setActivatedItem(LLMenuItemGL* item);
 

indra/llui/llscrolllistctrl.h

 	void			sortOnce(S32 column, BOOL ascending);
 
 	// manually call this whenever editing list items in place to flag need for resorting
-	void			setNeedsSort() { mSorted = false; }
+	void			setNeedsSort(bool val = true) { mSorted = !val; }
 	void			dirtyColumns(); // some operation has potentially affected column layout or ordering
 
 protected:

indra/newview/llbottomtray.cpp

 #include "llchiclet.h"
 #include "llfloaterreg.h"
 #include "llflyoutbutton.h"
+#include "llimpanel.h" // for LLIMFloater
 #include "lllayoutstack.h"
 #include "llnearbychatbar.h"
 #include "llsplitbutton.h"
 #include "llsyswellwindow.h"
 #include "llfloatercamera.h"
-#include "llimpanel.h"
 
 LLBottomTray::LLBottomTray(const LLSD&)
 :	mChicletPanel(NULL),
 	}
 }
 
+// *TODO Vadim: why void* ?
 void* LLBottomTray::createNearbyChatBar(void* userdata)
 {
 	return new LLNearbyChatBar();
 
 LLIMChiclet* LLBottomTray::createIMChiclet(const LLUUID& session_id)
 {
-	if(session_id.isNull())
+	LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(session_id);
+
+	switch (im_chiclet_type)
 	{
-		return NULL;
+	case LLIMChiclet::TYPE_IM:
+		return getChicletPanel()->createChiclet<LLIMP2PChiclet>(session_id);
+	case LLIMChiclet::TYPE_GROUP:
+		return getChicletPanel()->createChiclet<LLIMGroupChiclet>(session_id);
+	case LLIMChiclet::TYPE_UNKNOWN:
+		break;
 	}
 
-	LLFloaterIMPanel* im = LLIMMgr::getInstance()->findFloaterBySession(session_id);
-	if (!im) 
-	{
-		return NULL; //should never happen
-	}
-
-	switch(im->getDialogType())
-	{
-	case IM_NOTHING_SPECIAL:
-		return getChicletPanel()->createChiclet<LLIMP2PChiclet>(session_id);
-		break;
-	case IM_SESSION_GROUP_START:
-	case IM_SESSION_INVITE:
-		return getChicletPanel()->createChiclet<LLIMGroupChiclet>(session_id);
-		break;
-	default:
-		return NULL;
-		break;
-	}
+	return NULL;
 }
 
 //virtual
 {
 	mCamPanel->setVisible(visible);
 	mMovementPanel->setVisible(visible);
+
+	if (!visible)
+	{
+		LLFloaterReg::hideFloaterInstance("moveview");
+		LLFloaterReg::hideFloaterInstance("camera");
+	}
 }

indra/newview/llchiclet.cpp

 	gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.0f,0.0f,0.0f,1.f), FALSE);
 }
 
+// static
+LLIMChiclet::EType LLIMChiclet::getIMSessionType(const LLUUID& session_id)
+{
+	EType				type	= TYPE_UNKNOWN;
+	LLFloaterIMPanel*	im		= NULL;
+
+	if(session_id.isNull())
+		return type;
+
+	if (!(im = LLIMMgr::getInstance()->findFloaterBySession(session_id)))
+	{
+		llassert_always(0 && "IM session not found"); // should never happen
+		return type;
+	}
+
+	switch(im->getDialogType())
+	{
+	case IM_NOTHING_SPECIAL:
+		type = TYPE_IM;
+		break;
+	case IM_SESSION_GROUP_START:
+	case IM_SESSION_INVITE:
+		type = TYPE_GROUP;
+		break;
+	default:
+		break;
+	}
+
+	return type;
+}
+
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 , speaker("speaker")
 , show_speaker("show_speaker")
 {
+	// *TODO Vadim: Get rid of hardcoded values.
 	rect(LLRect(0, 25, 45, 0));
 
 	avatar_icon.name("avatar_icon");
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 
+// *TODO Vadim: Move this out of llchiclet.cpp.
+
 LLTalkButton::Params::Params()
  : speak_button("speak_button")
  , show_button("show_button")
  , monitor("monitor")
 {
+	// *TODO Vadim: move hardcoded labels (!) and other params to XUI.
 	speak_button.name("left");
 	speak_button.label("Speak");
 	speak_button.label_selected("Speak");

indra/newview/llchiclet.h

 class LLIMChiclet : public LLChiclet
 {
 public:
+	enum EType {
+		TYPE_UNKNOWN,
+		TYPE_IM,
+		TYPE_GROUP
+	};
 	
 	/*virtual*/ ~LLIMChiclet() {};
 
 	/*virtual*/ void draw();
 
 	/**
+	 * Determine whether given ID refers to a group or an IM chat session.
+	 * 
+	 * This is used when we need to chose what IM chiclet (P2P/group)
+	 * class to instantiate.
+	 * 
+	 * @param session_id session ID.
+	 * @return TYPE_GROUP in case of group chat session,
+	 *         TYPE_IM in case of P2P session,
+	 *         TYPE_UNKNOWN otherwise.
+	 */
+	static EType getIMSessionType(const LLUUID& session_id);
+
+	/**
 	 * The action taken on mouse down event.
 	 * 
 	 * Made public so that it can be triggered from outside
 		Params();
 	};
 
-	void setOtherParticipantId(const LLUUID& other_participant_id);
+	/* virtual */ void setOtherParticipantId(const LLUUID& other_participant_id);
 
 	/*virtual*/ void setShowSpeaker(bool show);
 

indra/newview/llgrouplist.cpp

 		const LLGroupData& group_data = gAgent.mGroups.get(i);
 		if (name_filter != LLStringUtil::null && !findInsensitive(group_data.mName, name_filter))
 			continue;
-		addItem(id, group_data.mName, highlight_id == id, ADD_BOTTOM);
+		addItem(id, group_data.mName, highlight_id == id, ADD_BOTTOM); // ADD_SORTED can only sort by first column anyway
 	}
 
+	// Force sorting the list.
+	updateSort();
+
 	// add "none" to list at top
 	{
 		std::string loc_none = LLTrans::getString("GroupsNone");
 		if (name_filter == LLStringUtil::null || findInsensitive(loc_none, name_filter))
 			addItem(LLUUID::null, loc_none, highlight_id.isNull(), ADD_TOP);
+
+		// Prevent the "none" item from being sorted.
+		setNeedsSort(false);
 	}
 
 	group_list->selectByValue(highlight_id);

indra/newview/lllocationinputctrl.cpp

 {
 	BOOL result = LLComboBox::handleKeyHere(key, mask);
 
-	if (key == KEY_DOWN && hasFocus() && mList->getItemCount() != 0)
+	if (key == KEY_DOWN && hasFocus() && mList->getItemCount() != 0 && !mList->getVisible())
 	{
 		showList();
 	}

indra/newview/llnavigationbar.cpp

 	if(!search_query.empty())
 	{
 		LLSearchHistory::getInstance()->addEntry(search_query);
-		invokeSearch(mSearchComboBox->getValue().asString());	
 	}
+	invokeSearch(search_query);	
 }
 
 void LLNavigationBar::onTeleportHistoryMenuItemClicked(const LLSD& userdata)

indra/newview/llsearchcombobox.cpp

 {
 	std::string search_query = getSimple();
 	LLStringUtil::trim(search_query);
-	if(search_query.empty())
-	{
-		mTextEntry->setText(search_query);
-		setControlValue(search_query);
 
-		return;
-	}
-
-	remove(search_query);
-	add(search_query, ADD_TOP);
 	mTextEntry->setText(search_query);
 	setControlValue(search_query);
 
+	if(!search_query.empty())
+	{
+		remove(search_query);
+		add(search_query, ADD_TOP);
+	}
+
 	LLUICtrl::onCommit();
 }
 

indra/newview/llsyswellwindow.cpp

 	if(mChannel)
 		mChannel->setShowToasts(!visible);
 
-	LLFloater::setVisible(visible);
+	LLDockableFloater::setVisible(visible);
 }
 
 //---------------------------------------------------------------------------------
 //---------------------------------------------------------------------------------
 LLSysWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID& sessionId,
 		S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId) :
-		LLScrollingPanel(LLPanel::Params()), mParent(parent)
+		LLScrollingPanel(LLPanel::Params()), mChiclet(NULL), mParent(parent)
 {
 	LLUICtrlFactory::getInstance()->buildPanel(this, "panel_activeim_row.xml", NULL);
 
-	mChiclet = getChild<LLIMChiclet>("chiclet");
+	// Choose which of the pre-created chiclets (IM/group) to use.
+	// The other one gets hidden.
+
+	LLIMChiclet::EType im_chiclet_type = LLIMChiclet::getIMSessionType(sessionId);
+	switch (im_chiclet_type)
+	{
+	case LLIMChiclet::TYPE_GROUP:
+		mChiclet = getChild<LLIMChiclet>("group_chiclet");
+		childSetVisible("p2p_chiclet", false);
+		break;
+	case LLIMChiclet::TYPE_UNKNOWN: // assign mChiclet a non-null value anyway
+	case LLIMChiclet::TYPE_IM:
+		mChiclet = getChild<LLIMChiclet>("p2p_chiclet");
+		childSetVisible("group_chiclet", false);
+		break;
+	}
+
+	// Initialize chiclet.
 	mChiclet->setCounter(chicletCounter);
 	mChiclet->setSessionId(sessionId);
 	mChiclet->setIMSessionName(name);

indra/newview/llsyswellwindow.h

 	virtual void setVisible(BOOL visible);
 	void adjustWindowPosition();
 	void toggleWindow();
+	/*virtua*/BOOL	canClose() { return FALSE; }
 
 	// Handlers
 	void onItemClick(LLSysWellItem* item);

indra/newview/llviewerwindow.cpp

 	{
 		return TRUE;
 	}
+	//some of context menus use this container, let context menu handle navigation keys
+	if(gMenuHolder && gMenuHolder->handleKey(key, mask, TRUE))
+	{
+		return TRUE;
+	}
 
 	// Traverses up the hierarchy
 	LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();

indra/newview/skins/default/xui/en/panel_activeim_row.xml

 	bevel_style="in"
 	bg_alpha_color="0 0 0 0">
   <chiclet_im_p2p
-		name="chiclet"
+		name="p2p_chiclet"
 		layout="topleft"
 		follows="left"
 		top="5"
 		height="25"
 		width="45">
   </chiclet_im_p2p>
+  <chiclet_im_group
+		name="group_chiclet"
+		layout="topleft"
+		follows="left"
+		top="5"
+		left="5"
+		height="25"
+		width="45">
+  </chiclet_im_group>
 	<text
 		type="string"
 		name="contact_name"

indra/newview/skins/default/xui/en/panel_bottomtray.xml

          top="0"
          width="5"/>
         <layout_panel
+         auto_resize="false"
          follows="left|right"
          height="28"
          layout="topleft"
          left="5"
          min_height="28"
-         width="500"
+         width="600"
          top="0"
          min_width="305"
          name="chat_bar"

indra/newview/skins/default/xui/en/widgets/location_input.xml

       	        show_text_as_tentative="false"
                 max_chars="20"
                 follows="left|top"
+                allow_new_values="true"
                 >
   <info_button name="Place Information"
                           label=""

indra/newview/skins/default/xui/en/widgets/search_combo_box.xml

  show_text_as_tentative="false"
  dropdown_button_visible="false"
  max_chars="256"
+ allow_new_values="true"
  background_image="TextField_Search_Off"
  background_image_disabled="TextField_Search_Disabled"
  background_image_focused="TextField_Search_Active">
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.