summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rwxr-xr-xindra/llui/llcombobox.cpp1
-rwxr-xr-xindra/llui/lldockablefloater.cpp2
-rw-r--r--indra/llui/llfolderviewitem.cpp45
-rwxr-xr-xindra/llui/llfolderviewitem.h4
-rwxr-xr-xindra/llui/llfolderviewmodel.h2
-rwxr-xr-xindra/llui/llmenugl.cpp53
-rwxr-xr-xindra/llui/llmenugl.h4
-rwxr-xr-xindra/llui/llsearcheditor.cpp13
-rwxr-xr-xindra/llui/llsearcheditor.h2
-rwxr-xr-xindra/llui/lltabcontainer.cpp20
-rwxr-xr-xindra/llui/llurlentry.cpp46
-rwxr-xr-xindra/llui/llurlentry.h11
-rwxr-xr-xindra/llui/llurlregistry.cpp15
13 files changed, 177 insertions, 41 deletions
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index b32aea5ffa..559895da1a 100755
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -443,6 +443,7 @@ void LLComboBox::onFocusLost()
{
mTextEntry->selectAll();
}
+ mButton->setForcePressedState(false);
LLUICtrl::onFocusLost();
}
diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp
index 3396213f1c..c937d190c6 100755
--- a/indra/llui/lldockablefloater.cpp
+++ b/indra/llui/lldockablefloater.cpp
@@ -153,7 +153,7 @@ void LLDockableFloater::setVisible(BOOL visible)
mDockControl.get()->repositionDockable();
}
- if (visible)
+ if (visible && !isMinimized())
{
LLFloater::setFrontmost(getAutoFocus());
}
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 747b472ac2..f16cd8e124 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -128,6 +128,7 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p)
mSelectPending(FALSE),
mLabelStyle( LLFontGL::NORMAL ),
mHasVisibleChildren(FALSE),
+ mIsFolderComplete(true),
mLocalIndentation(p.folder_indentation),
mIndentation(0),
mItemHeight(p.item_height),
@@ -672,7 +673,7 @@ void LLFolderViewItem::drawOpenFolderArrow(const Params& default_params, const L
//
const S32 TOP_PAD = default_params.item_top_pad;
- if (hasVisibleChildren())
+ if (hasVisibleChildren() || !isFolderComplete())
{
LLUIImage* arrow_image = default_params.folder_arrow_image;
gl_draw_scaled_rotated_image(
@@ -932,6 +933,8 @@ LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ):
mLastArrangeGeneration( -1 ),
mLastCalculatedWidth(0)
{
+ // folder might have children that are not loaded yet. Mark it as incomplete until chance to check it.
+ mIsFolderComplete = false;
}
void LLFolderViewFolder::updateLabelRotation()
@@ -1014,6 +1017,12 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height )
mHasVisibleChildren = found;
}
+ if (!mIsFolderComplete)
+ {
+ mIsFolderComplete = getFolderViewModel()->isFolderComplete(this);
+ }
+
+
// calculate height as a single item (without any children), and reshapes rectangle to match
LLFolderViewItem::arrange( width, height );
@@ -1461,31 +1470,37 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection)
LLFolderView* root = getRoot();
- for (std::vector<LLFolderViewItem*>::iterator it = items_to_select_forward.begin(), end_it = items_to_select_forward.end();
+ BOOL selection_reverse = new_selection->isSelected(); //indication that some elements are being deselected
+
+ // array always go from 'will be selected' to ' will be unselected', iterate
+ // in opposite direction to simplify identification of 'point of origin' in
+ // case it is in the list we are working with
+ for (std::vector<LLFolderViewItem*>::reverse_iterator it = items_to_select_forward.rbegin(), end_it = items_to_select_forward.rend();
it != end_it;
++it)
{
LLFolderViewItem* item = *it;
- if (item->isSelected())
+ BOOL selected = item->isSelected();
+ if (!selection_reverse && selected)
{
- root->removeFromSelectionList(item);
+ // it is our 'point of origin' where we shift/expand from
+ // don't deselect it
+ selection_reverse = TRUE;
}
else
{
- item->selectItem();
+ root->changeSelection(item, !selected);
}
- root->addToSelectionList(item);
}
- if (new_selection->isSelected())
+ if (selection_reverse)
{
- root->removeFromSelectionList(new_selection);
+ // at some point we reversed selection, first element should be deselected
+ root->changeSelection(last_selected_item_from_cur, FALSE);
}
- else
- {
- new_selection->selectItem();
- }
- root->addToSelectionList(new_selection);
+
+ // element we expand to should always be selected
+ root->changeSelection(new_selection, TRUE);
}
@@ -1673,7 +1688,9 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r
mIsOpen = openitem;
if(!was_open && openitem)
{
- getViewModelItem()->openItem();
+ getViewModelItem()->openItem();
+ // openItem() will request content, it won't be incomplete
+ mIsFolderComplete = true;
}
else if(was_open && !openitem)
{
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index 5ad5731cad..f77d676f46 100755
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -114,6 +114,7 @@ protected:
F32 mControlLabelRotation;
LLFolderView* mRoot;
bool mHasVisibleChildren,
+ mIsFolderComplete, // indicates that some children were not loaded/added yet
mIsCurSelection,
mDragAndDropTarget,
mIsMouseOverTitle,
@@ -210,6 +211,9 @@ public:
BOOL hasVisibleChildren() { return mHasVisibleChildren; }
+ // true if object can't have children
+ BOOL isFolderComplete() { return mIsFolderComplete; }
+
// Call through to the viewed object and return true if it can be
// removed. Returns true if it's removed.
//virtual BOOL removeRecursively(BOOL single_item);
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index f6550eae42..8e780c6752 100755
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -122,6 +122,7 @@ public:
virtual void filter() = 0;
virtual bool contentsReady() = 0;
+ virtual bool isFolderComplete(class LLFolderViewFolder*) = 0;
virtual void setFolderView(LLFolderView* folder_view) = 0;
virtual LLFolderViewFilter& getFilter() = 0;
virtual const LLFolderViewFilter& getFilter() const = 0;
@@ -442,6 +443,7 @@ public:
// By default, we assume the content is available. If a network fetch mechanism is implemented for the model,
// this method needs to be overloaded and return the relevant fetch status.
virtual bool contentsReady() { return true; }
+ virtual bool isFolderComplete(LLFolderViewFolder* folder) { return true; }
struct ViewModelCompare
{
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 7cdbcb0621..3b8d282445 100755
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -225,7 +225,6 @@ BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask)
BOOL LLMenuItemGL::handleHover(S32 x, S32 y, MASK mask)
{
- setHover(TRUE);
getWindow()->setCursor(UI_CURSOR_ARROW);
return TRUE;
}
@@ -236,6 +235,18 @@ BOOL LLMenuItemGL::handleRightMouseDown(S32 x, S32 y, MASK mask)
return LLUICtrl::handleRightMouseDown(x,y,mask);
}
+void LLMenuItemGL::onMouseEnter(S32 x, S32 y, MASK mask)
+{
+ setHover(TRUE);
+ LLUICtrl::onMouseEnter(x,y,mask);
+}
+
+void LLMenuItemGL::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+ setHover(FALSE);
+ LLUICtrl::onMouseLeave(x,y,mask);
+}
+
//virtual
BOOL LLMenuItemGL::handleRightMouseUp(S32 x, S32 y, MASK mask)
{
@@ -533,9 +544,6 @@ void LLMenuItemGL::draw( void )
gl_line_2d(x_begin, (MENU_ITEM_PADDING / 2) + 1, x_end, (MENU_ITEM_PADDING / 2) + 1);
}
}
-
- // clear got hover every frame
- setHover(FALSE);
}
BOOL LLMenuItemGL::setLabelArg( const std::string& key, const LLStringExplicit& text )
@@ -1043,7 +1051,7 @@ void LLMenuItemBranchGL::onCommit( void )
// keyboard navigation automatically propagates highlight to sub-menu
// to facilitate fast menu control via jump keys
- if (LLMenuGL::getKeyboardMode() && getBranch()&& !getBranch()->getHighlightedItem())
+ if (LLMenuGL::getKeyboardMode() && getBranch() && !getBranch()->getHighlightedItem())
{
getBranch()->highlightNextItem(NULL);
}
@@ -1456,7 +1464,16 @@ BOOL LLMenuItemBranchDownGL::handleMouseDown( S32 x, S32 y, MASK mask )
{
// switch to mouse control mode
LLMenuGL::setKeyboardMode(FALSE);
- onCommit();
+
+ if (getVisible() && isOpen())
+ {
+ LLMenuGL::sMenuContainer->hideMenus();
+ }
+ else
+ {
+ onCommit();
+ }
+
make_ui_sound("UISndClick");
return TRUE;
}
@@ -1588,10 +1605,6 @@ void LLMenuItemBranchDownGL::draw( void )
gl_line_2d(x_begin, LABEL_BOTTOM_PAD_PIXELS, x_end, LABEL_BOTTOM_PAD_PIXELS);
}
}
-
- // reset every frame so that we only show highlight
- // when we get hover events on that frame
- setHover(FALSE);
}
@@ -3625,8 +3638,24 @@ BOOL LLMenuHolderGL::handleMouseDown( S32 x, S32 y, MASK mask )
BOOL handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL;
if (!handled)
{
- // clicked off of menu, hide them all
- hideMenus();
+ LLMenuGL* visible_menu = (LLMenuGL*)getVisibleMenu();
+ LLMenuItemGL* parent_menu = visible_menu ? visible_menu->getParentMenuItem() : NULL;
+ if (parent_menu && parent_menu->getVisible())
+ {
+ // don't hide menu if parent was hit
+ LLRect parent_rect;
+ parent_menu->localRectToOtherView(parent_menu->getLocalRect(), &parent_rect, this);
+ if (!parent_rect.pointInRect(x, y))
+ {
+ // clicked off of menu and parent, hide them all
+ hideMenus();
+ }
+ }
+ else
+ {
+ // no visible parent, clicked off of menu, hide them all
+ hideMenus();
+ }
}
return handled;
}
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index ae9b169691..28f9e3b6e9 100755
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -158,6 +158,10 @@ public:
virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask );
virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
+
+ virtual void onMouseEnter(S32 x, S32 y, MASK mask);
+ virtual void onMouseLeave(S32 x, S32 y, MASK mask);
+
virtual void draw( void );
BOOL getHover() const { return mGotHover; }
diff --git a/indra/llui/llsearcheditor.cpp b/indra/llui/llsearcheditor.cpp
index ea96fc573d..1fdd05a11c 100755
--- a/indra/llui/llsearcheditor.cpp
+++ b/indra/llui/llsearcheditor.cpp
@@ -29,6 +29,7 @@
#include "linden_common.h"
#include "llsearcheditor.h"
+#include "llkeyboard.h"
LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
: LLUICtrl(p),
@@ -166,4 +167,16 @@ void LLSearchEditor::handleKeystroke()
{
mKeystrokeCallback(this, getValue());
}
+
+ KEY key = gKeyboard->currentKey();
+ if (key == KEY_LEFT ||
+ key == KEY_RIGHT)
+ {
+ return;
+ }
+
+ if (mTextChangedCallback)
+ {
+ mTextChangedCallback(this, getValue());
+ }
}
diff --git a/indra/llui/llsearcheditor.h b/indra/llui/llsearcheditor.h
index c2d7916938..3b12868225 100755
--- a/indra/llui/llsearcheditor.h
+++ b/indra/llui/llsearcheditor.h
@@ -82,12 +82,14 @@ public:
virtual void setFocus( BOOL b );
void setKeystrokeCallback( commit_callback_t cb ) { mKeystrokeCallback = cb; }
+ void setTextChangedCallback( commit_callback_t cb ) { mTextChangedCallback = cb; }
protected:
void onClearButtonClick(const LLSD& data);
virtual void handleKeystroke();
commit_callback_t mKeystrokeCallback;
+ commit_callback_t mTextChangedCallback;
LLLineEditor* mSearchEditor;
LLButton* mSearchButton;
LLButton* mClearButton;
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 4b08798892..701a06a085 100755
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -1775,6 +1775,11 @@ void LLTabContainer::onNextBtn( const LLSD& data )
scrollNext();
}
mScrolled = FALSE;
+
+ if(mCurrentTabIdx < mTabList.size()-1)
+ {
+ selectNextTab();
+ }
}
void LLTabContainer::onNextBtnHeld( const LLSD& data )
@@ -1783,6 +1788,11 @@ void LLTabContainer::onNextBtnHeld( const LLSD& data )
{
mScrollTimer.reset();
scrollNext();
+
+ if(mCurrentTabIdx < mTabList.size()-1)
+ {
+ selectNextTab();
+ }
mScrolled = TRUE;
}
}
@@ -1794,6 +1804,11 @@ void LLTabContainer::onPrevBtn( const LLSD& data )
scrollPrev();
}
mScrolled = FALSE;
+
+ if(mCurrentTabIdx > 0)
+ {
+ selectPrevTab();
+ }
}
void LLTabContainer::onJumpFirstBtn( const LLSD& data )
@@ -1812,6 +1827,11 @@ void LLTabContainer::onPrevBtnHeld( const LLSD& data )
{
mScrollTimer.reset();
scrollPrev();
+
+ if(mCurrentTabIdx > 0)
+ {
+ selectPrevTab();
+ }
mScrolled = TRUE;
}
}
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 6db0d88998..95f931de0a 100755
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -203,10 +203,10 @@ std::string LLUrlEntryBase::urlToGreyQuery(const std::string &url) const
{
LLUriParser up(unescapeUrl(url));
- std::string query;
+ std::string label;
up.extractParts();
- up.glueSecond(query);
-
+ up.glueFirst(label);
+ std::string query = url.substr(label.size());
return query;
}
@@ -293,11 +293,7 @@ std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string) const
LLUrlEntryHTTPNoProtocol::LLUrlEntryHTTPNoProtocol()
: LLUrlEntryBase()
{
- mPattern = boost::regex("("
- "\\bwww\\.\\S+\\.\\S+" // i.e. www.FOO.BAR
- "|" // or
- "(?<!@)\\b[^[:space:]:@/>]+\\.(?:com|net|edu|org)([/:][^[:space:]<]*)?\\b" // i.e. FOO.net
- ")",
+ mPattern = boost::regex("\\bwww\\.\\S+\\.\\S+", // i.e. www.FOO.BAR
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_http.xml";
mTooltip = LLTrans::getString("TooltipHttpUrl");
@@ -1401,6 +1397,40 @@ std::string LLUrlEntryIcon::getIcon(const std::string &url)
return mIcon;
}
+//
+// LLUrlEntryEmail Describes a generic mailto: Urls
+//
+LLUrlEntryEmail::LLUrlEntryEmail()
+ : LLUrlEntryBase()
+{
+ mPattern = boost::regex("(mailto:)?[\\w\\.\\-]+@[\\w\\.\\-]+\\.[a-z]{2,6}",
+ boost::regex::perl | boost::regex::icase);
+ mMenuName = "menu_url_email.xml";
+ mTooltip = LLTrans::getString("TooltipEmail");
+}
+
+std::string LLUrlEntryEmail::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ int pos = url.find("mailto:");
+
+ if (pos == std::string::npos)
+ {
+ return escapeUrl(url);
+ }
+
+ std::string ret = escapeUrl(url.substr(pos + 7, url.length() - pos + 8));
+ return ret;
+}
+
+std::string LLUrlEntryEmail::getUrl(const std::string &string) const
+{
+ if (string.find("mailto:") == std::string::npos)
+ {
+ return "mailto:" + escapeUrl(string);
+ }
+ return escapeUrl(string);
+}
+
LLUrlEntryExperienceProfile::LLUrlEntryExperienceProfile()
{
mPattern = boost::regex(APP_HEADER_REGEX "/experience/[\\da-f-]+/\\w+\\S*",
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index dd1f257a3d..4d5e77c3bd 100755
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -506,5 +506,16 @@ public:
/*virtual*/ std::string getIcon(const std::string &url);
};
+///
+/// LLUrlEntryEmail Describes a generic mailto: Urls
+///
+class LLUrlEntryEmail : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryEmail();
+ /*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
+ /*virtual*/ std::string getUrl(const std::string &string) const;
+};
+
#endif
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 2085505947..fcdb5b19d4 100755
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -76,9 +76,10 @@ LLUrlRegistry::LLUrlRegistry()
registerUrl(new LLUrlEntrySL());
mUrlEntrySLLabel = new LLUrlEntrySLLabel();
registerUrl(mUrlEntrySLLabel);
- // most common pattern is a URL without any protocol,
- // e.g., "secondlife.com"
+ // most common pattern is a URL without any protocol starting with "www",
+ // e.g., "www.secondlife.com"
registerUrl(new LLUrlEntryHTTPNoProtocol());
+ registerUrl(new LLUrlEntryEmail());
}
LLUrlRegistry::~LLUrlRegistry()
@@ -155,11 +156,9 @@ static bool stringHasUrl(const std::string &text)
return (text.find("://") != std::string::npos ||
text.find("www.") != std::string::npos ||
text.find(".com") != std::string::npos ||
- text.find(".net") != std::string::npos ||
- text.find(".edu") != std::string::npos ||
- text.find(".org") != std::string::npos ||
text.find("<nolink>") != std::string::npos ||
- text.find("<icon") != std::string::npos);
+ text.find("<icon") != std::string::npos ||
+ text.find("@") != std::string::npos);
}
bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb, bool is_content_trusted)
@@ -218,6 +217,10 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
// did we find a match? if so, return its details in the match object
if (match_entry)
{
+ // Skip if link is an email with an empty username (starting with @). See MAINT-5371.
+ if (match_start > 0 && text.substr(match_start - 1, 1) == "@")
+ return false;
+
// fill in the LLUrlMatch object and return it
std::string url = text.substr(match_start, match_end - match_start + 1);