summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llfloater.cpp22
-rw-r--r--indra/llui/llmenugl.cpp35
-rw-r--r--indra/llui/llradiogroup.cpp68
-rw-r--r--indra/llui/llradiogroup.h9
-rw-r--r--indra/llui/lltabcontainer.cpp9
-rw-r--r--indra/llui/lltextbase.cpp3
-rw-r--r--indra/llui/lltextbox.cpp23
-rw-r--r--indra/llui/lltexteditor.cpp17
-rw-r--r--indra/llui/llui.cpp17
-rw-r--r--indra/llui/llui.h4
-rw-r--r--indra/llui/lluictrl.cpp50
-rw-r--r--indra/llui/lluictrl.h3
-rw-r--r--indra/llui/llurlregistry.cpp28
-rw-r--r--indra/llui/llurlregistry.h6
-rw-r--r--indra/llui/llview.cpp54
-rw-r--r--indra/llui/llview.h1
16 files changed, 207 insertions, 142 deletions
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 4690c54c15..a57913683b 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -592,6 +592,8 @@ void LLFloater::openFloater(const LLSD& key)
mOpenSignal(this, key);
onOpen(key);
+
+ dirtyRect();
}
void LLFloater::closeFloater(bool app_quitting)
@@ -657,7 +659,9 @@ void LLFloater::closeFloater(bool app_quitting)
}
}
}
-
+
+ dirtyRect();
+
// Close callback
mCloseSignal(this, LLSD(app_quitting));
@@ -1923,8 +1927,8 @@ void LLFloaterView::restoreAll()
LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor )
{
LLRect base_rect = reference_floater->getRect();
- S32 width = neighbor->getRect().getWidth();
- S32 height = neighbor->getRect().getHeight();
+ LLRect::tCoordType width = neighbor->getRect().getWidth();
+ LLRect::tCoordType height = neighbor->getRect().getHeight();
LLRect new_rect = neighbor->getRect();
LLRect expanded_base_rect = base_rect;
@@ -1943,10 +1947,10 @@ LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLF
}
}
- S32 left_margin = llmax(0, base_rect.mLeft);
- S32 right_margin = llmax(0, getRect().getWidth() - base_rect.mRight);
- S32 top_margin = llmax(0, getRect().getHeight() - base_rect.mTop);
- S32 bottom_margin = llmax(0, base_rect.mBottom);
+ LLRect::tCoordType left_margin = llmax(0, base_rect.mLeft);
+ LLRect::tCoordType right_margin = llmax(0, getRect().getWidth() - base_rect.mRight);
+ LLRect::tCoordType top_margin = llmax(0, getRect().getHeight() - base_rect.mTop);
+ LLRect::tCoordType bottom_margin = llmax(0, base_rect.mBottom);
// find position for floater in following order
// right->left->bottom->top
@@ -2252,8 +2256,8 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
// floater is hosted elsewhere, so ignore
return;
}
- S32 screen_width = getSnapRect().getWidth();
- S32 screen_height = getSnapRect().getHeight();
+ LLRect::tCoordType screen_width = getSnapRect().getWidth();
+ LLRect::tCoordType screen_height = getSnapRect().getHeight();
// convert to local coordinate frame
LLRect snap_rect_local = getLocalSnapRect();
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index e0bb6bd5d3..f2d147ac39 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -121,6 +121,8 @@ const F32 ACTIVATE_HIGHLIGHT_TIME = 0.3f;
static MenuRegistry::Register<LLMenuItemSeparatorGL> register_separator("menu_item_separator");
static MenuRegistry::Register<LLMenuItemCallGL> register_menu_item_call("menu_item_call");
static MenuRegistry::Register<LLMenuItemCheckGL> register_menu_item_check("menu_item_check");
+// Created programmatically but we need to specify custom colors in xml
+static MenuRegistry::Register<LLMenuItemTearOffGL> register_menu_item_tear_off("menu_item_tear_off");
static MenuRegistry::Register<LLMenuGL> register_menu("menu");
static LLDefaultChildRegistry::Register<LLMenuGL> register_menu_default("menu");
@@ -390,8 +392,10 @@ void LLMenuItemGL::buildDrawLabel( void )
void LLMenuItemGL::onCommit( void )
{
- // close all open menus by default
- // if parent menu is actually visible (and we are not triggering menu item via accelerator)
+ // Check torn-off status to allow left-arrow keyboard navigation back
+ // to parent menu.
+ // Also, don't hide if item triggered by keyboard shortcut (and hence
+ // parent not visible).
if (!getMenu()->getTornOff()
&& getMenu()->getVisible())
{
@@ -408,6 +412,12 @@ void LLMenuItemGL::onCommit( void )
{
getMenu()->clearHoverItem();
}
+
+ if (mHighlight != highlight)
+ {
+ dirtyRect();
+ }
+
mHighlight = highlight;
}
@@ -1233,6 +1243,8 @@ void LLMenuItemBranchGL::openMenu()
branch->translate( delta_x, delta_y );
branch->setVisible( TRUE );
branch->getParent()->sendChildToFront(branch);
+
+ dirtyRect();
}
}
@@ -2334,8 +2346,8 @@ void LLMenuGL::createJumpKeys()
{
char jump_key = uppercase_word[i];
- if (LLStringOps::isDigit(jump_key) || LLStringOps::isUpper(jump_key) &&
- mJumpKeys.find(jump_key) == mJumpKeys.end())
+ if (LLStringOps::isDigit(jump_key) || (LLStringOps::isUpper(jump_key) &&
+ mJumpKeys.find(jump_key) == mJumpKeys.end()))
{
mJumpKeys.insert(std::pair<KEY, LLMenuItemGL*>(jump_key, (*item_it)));
(*item_it)->setJumpKey(jump_key);
@@ -3476,16 +3488,19 @@ LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) :
LLRect rect;
menup->localRectToOtherView(LLRect(-1, menup->getRect().getHeight(), menup->getRect().getWidth() + 3, 0), &rect, gFloaterView);
// make sure this floater is big enough for menu
- mTargetHeight = (F32)(rect.getHeight() + floater_header_size + 5);
+ mTargetHeight = (F32)(rect.getHeight() + floater_header_size);
reshape(rect.getWidth(), rect.getHeight());
setRect(rect);
// attach menu to floater
- menup->setFollowsAll();
+ menup->setFollows( FOLLOWS_LEFT | FOLLOWS_BOTTOM );
mOldParent = menup->getParent();
addChild(menup);
menup->setVisible(TRUE);
- menup->translate(-menup->getRect().mLeft + 1, -menup->getRect().mBottom + 1);
+ LLRect menu_rect = menup->getRect();
+ menu_rect.setOriginAndSize( 1, 1,
+ menu_rect.getWidth(), menu_rect.getHeight());
+ menup->setRect(menu_rect);
menup->setDropShadowed(FALSE);
mMenu = menup;
@@ -3513,12 +3528,6 @@ void LLTearOffMenu::draw()
// animate towards target height
reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), mTargetHeight, LLCriticalDamp::getInterpolant(0.05f))));
}
- else
- {
- // when in stasis, remain big enough to hold menu contents
- mTargetHeight = (F32)(mMenu->getRect().getHeight() + floater_header_size + 4);
- reshape(mMenu->getRect().getWidth() + 3, mMenu->getRect().getHeight() + floater_header_size + 5);
- }
LLFloater::draw();
}
diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp
index c66b9bde2b..d1ea5843eb 100644
--- a/indra/llui/llradiogroup.cpp
+++ b/indra/llui/llradiogroup.cpp
@@ -45,8 +45,6 @@
#include "lluictrlfactory.h"
static LLDefaultChildRegistry::Register<LLRadioGroup> r1("radio_group");
-
-
static RadioGroupRegistry::Register<LLRadioCtrl> register_radio_ctrl("radio_item");
@@ -83,6 +81,10 @@ LLRadioGroup::~LLRadioGroup()
// virtual
BOOL LLRadioGroup::postBuild()
{
+ if (!mRadioButtons.empty())
+ {
+ mRadioButtons[0]->setTabStop(true);
+ }
if (mControlVariable)
{
setSelectedIndex(mControlVariable->getValue().asInteger());
@@ -102,7 +104,7 @@ void LLRadioGroup::setIndexEnabled(S32 index, BOOL enabled)
child->setEnabled(enabled);
if (index == mSelectedIndex && enabled == FALSE)
{
- setSelectedIndex(-1);
+ mSelectedIndex = -1;
}
break;
}
@@ -142,8 +144,28 @@ BOOL LLRadioGroup::setSelectedIndex(S32 index, BOOL from_event)
return FALSE;
}
+ if (mSelectedIndex >= 0)
+ {
+ LLRadioCtrl* old_radio_item = mRadioButtons[mSelectedIndex];
+ old_radio_item->setTabStop(false);
+ old_radio_item->setValue( FALSE );
+ }
+ else
+ {
+ mRadioButtons[0]->setTabStop(false);
+ }
+
mSelectedIndex = index;
+ LLRadioCtrl* radio_item = mRadioButtons[mSelectedIndex];
+ radio_item->setTabStop(true);
+ radio_item->setValue( TRUE );
+
+ if (hasFocus())
+ {
+ mRadioButtons[mSelectedIndex]->focusFirstItem(FALSE, FALSE);
+ }
+
if (!from_event)
{
setControlValue(getSelectedIndex());
@@ -211,33 +233,6 @@ BOOL LLRadioGroup::handleKeyHere(KEY key, MASK mask)
return handled;
}
-void LLRadioGroup::draw()
-{
- S32 current_button = 0;
-
- BOOL take_focus = FALSE;
- if (gFocusMgr.childHasKeyboardFocus(this))
- {
- take_focus = TRUE;
- }
-
- for (button_list_t::iterator iter = mRadioButtons.begin();
- iter != mRadioButtons.end(); ++iter)
- {
- LLRadioCtrl* radio = *iter;
- BOOL selected = (current_button == mSelectedIndex);
- radio->setValue( selected );
- if (take_focus && selected && !gFocusMgr.childHasKeyboardFocus(radio))
- {
- // don't flash keyboard focus when navigating via keyboard
- BOOL DONT_FLASH = FALSE;
- radio->focusFirstItem(FALSE, DONT_FLASH);
- }
- current_button++;
- }
-
- LLView::draw();
-}
// When adding a child button, we need to ensure that the radio
// group gets a message when the button is clicked.
@@ -259,6 +254,19 @@ bool LLRadioGroup::addChild(LLView* view, S32 tab_group)
return res;
}
+BOOL LLRadioGroup::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+ // grab focus preemptively, before child button takes mousecapture
+ //
+ if (hasTabStop())
+ {
+ focusFirstItem(FALSE, FALSE);
+ }
+
+ return LLUICtrl::handleMouseDown(x, y, mask);
+}
+
+
// Handle one button being clicked. All child buttons must have this
// function as their callback function.
diff --git a/indra/llui/llradiogroup.h b/indra/llui/llradiogroup.h
index b5516307fd..914548b6aa 100644
--- a/indra/llui/llradiogroup.h
+++ b/indra/llui/llradiogroup.h
@@ -54,7 +54,10 @@ public:
Params()
: length("length"),
type("type")
- {}
+ {
+ // radio items are not tabbable until they are selected
+ tab_stop = false;
+ }
};
/*virtual*/ ~LLRadioCtrl();
@@ -103,6 +106,7 @@ public:
virtual BOOL postBuild();
virtual bool addChild(LLView* view, S32 tab_group = 0);
+ virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleKeyHere(KEY key, MASK mask);
@@ -117,9 +121,6 @@ public:
virtual void setValue(const LLSD& value );
virtual LLSD getValue() const;
- // Draw the group, but also fix the highlighting based on the control.
- void draw();
-
// Update the control as needed. Userdata must be a pointer to the button.
void onClickButton(LLUICtrl* clicked_radio);
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 720ca692f7..b6eed3ef18 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -329,10 +329,13 @@ void LLTabContainer::draw()
}
// Hide all the buttons
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ if (getTabsHidden())
{
- LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( FALSE );
+ for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
+ {
+ LLTabTuple* tuple = *iter;
+ tuple->mButton->setVisible( FALSE );
+ }
}
LLPanel::draw();
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index cb60b4fe36..0fd6a14187 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -420,8 +420,9 @@ BOOL LLTextBase::handleToolTipForUrl(LLView *view, S32 x, S32 y, std::string& ms
LLToolTipMgr::instance().show(LLToolTipParams()
.message(tooltip_msg)
.sticky_rect(sticky_rect_screen));
+ return TRUE;
}
- return TRUE;
+ return FALSE;
}
LLContextMenu *LLTextBase::createUrlContextMenu(const std::string &in_url)
diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp
index 810626268f..132bef0296 100644
--- a/indra/llui/lltextbox.cpp
+++ b/indra/llui/lltextbox.cpp
@@ -161,7 +161,12 @@ BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask)
BOOL LLTextBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
{
- return handleToolTipForUrl(this, x, y, msg, sticky_rect_screen);
+ if (handleToolTipForUrl(this, x, y, msg, sticky_rect_screen))
+ {
+ return TRUE;
+ }
+
+ return LLUICtrl::handleToolTip(x, y, msg, sticky_rect_screen);
}
void LLTextBox::setText(const LLStringExplicit& text)
@@ -297,7 +302,7 @@ LLWString LLTextBox::getWrappedText(const LLStringExplicit& in_text, F32 max_wid
// find the next Url in the text string
LLUrlMatch match;
- while ( LLUrlRegistry::instance().findUrl(wstring_to_utf8str(wtext), match))
+ while ( LLUrlRegistry::instance().findUrl(wtext, match))
{
S32 start = match.getStart();
S32 end = match.getEnd() + 1;
@@ -573,17 +578,21 @@ void LLTextBox::updateDisplayTextAndSegments()
LLWString text = mText.getWString();
// find the next Url in the text string
- while ( LLUrlRegistry::instance().findUrl(wstring_to_utf8str(text), match,
+ while ( LLUrlRegistry::instance().findUrl(text, match,
boost::bind(&LLTextBox::onUrlLabelUpdated, this, _1, _2)) )
{
// work out the char offset for the start/end of the url
+ S32 url_start = match.getStart();
+ S32 url_end = match.getEnd();
+
+ // and the char offset for the label in the display text
S32 seg_start = mDisplayText.size();
- S32 start = seg_start + match.getStart();
- end = start + match.getLabel().size();
+ S32 start = seg_start + url_start;
+ S32 end = start + match.getLabel().size();
// create a segment for the text before the Url
mSegments.insert(new LLNormalTextSegment(new LLStyle(), seg_start, start, *this));
- mDisplayText += text.substr(0, match.getStart());
+ mDisplayText += text.substr(0, url_start);
// create a segment for the Url text
LLStyleSP html(new LLStyle);
@@ -599,7 +608,7 @@ void LLTextBox::updateDisplayTextAndSegments()
mDisplayText += utf8str_to_wstring(match.getLabel());
// move on to the rest of the text after the Url
- text = text.substr(match.getEnd()+1, text.size() - match.getEnd());
+ text = text.substr(url_end+1, text.size() - url_end);
}
// output a segment for the remaining text
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 983777b747..8d5f277b59 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -1120,21 +1120,12 @@ void LLTextEditor::updateCursorXPos()
}
// constraint cursor to editable segments of document
+// NOTE: index must be within document range
S32 LLTextEditor::getEditableIndex(S32 index, bool increasing_direction)
{
- //// always allow editable position at end of doc
- //if (index == getLength())
- //{
- // return index;
- //}
-
segment_set_t::iterator segment_iter;
S32 offset;
getSegmentAndOffset(index, &segment_iter, &offset);
- if (segment_iter == mSegments.end())
- {
- return 0;
- }
LLTextSegmentPtr segmentp = *segment_iter;
@@ -3194,7 +3185,11 @@ void LLTextEditor::draw()
drawLineNumbers();
{
- LLLocalClipRect clip(mTextRect);
+ // pad clipping rectangle so that cursor can draw at full width
+ // when at left edge of mTextRect
+ LLRect clip_rect(mTextRect);
+ clip_rect.stretch(1);
+ LLLocalClipRect clip(clip_rect);
drawSelectionBackground();
drawPreeditMarker();
drawText();
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 950eaf2ea7..000e85f78c 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -81,7 +81,8 @@ std::list<std::string> gUntranslated;
/*static*/ LLWindow* LLUI::sWindow = NULL;
/*static*/ LLHtmlHelp* LLUI::sHtmlHelp = NULL;
/*static*/ LLView* LLUI::sRootView = NULL;
-
+/*static*/ BOOL LLUI::sDirty = FALSE;
+/*static*/ LLRect LLUI::sDirtyRect;
/*static*/ std::vector<std::string> LLUI::sXUIPaths;
/*static*/ LLFrameTimer LLUI::sMouseIdleTimer;
@@ -1603,6 +1604,20 @@ void LLUI::cleanupClass()
sImageProvider->cleanUp();
}
+//static
+void LLUI::dirtyRect(LLRect rect)
+{
+ if (!sDirty)
+ {
+ sDirtyRect = rect;
+ sDirty = TRUE;
+ }
+ else
+ {
+ sDirtyRect.unionWith(rect);
+ }
+}
+
//static
void LLUI::translate(F32 x, F32 y, F32 z)
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 33338f30f9..fddf8192ad 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -174,6 +174,10 @@ public:
static void loadIdentity();
static void translate(F32 x, F32 y, F32 z = 0.0f);
+ static LLRect sDirtyRect;
+ static BOOL sDirty;
+ static void dirtyRect(LLRect rect);
+
// Return the ISO639 language name ("en", "ko", etc.) for the viewer UI.
// http://www.loc.gov/standards/iso639-2/php/code_list.php
static std::string getLanguage();
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 28cdb1ac27..8807e26f6b 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -506,56 +506,6 @@ void LLUICtrl::setFocus(BOOL b)
}
}
-void LLUICtrl::onFocusReceived()
-{
- // trigger callbacks
- LLFocusableElement::onFocusReceived();
-
- // find first view in hierarchy above new focus that is a LLUICtrl
- LLView* viewp = getParent();
- LLUICtrl* last_focus = dynamic_cast<LLUICtrl*>(gFocusMgr.getLastKeyboardFocus());
-
- while (viewp && !viewp->isCtrl())
- {
- viewp = viewp->getParent();
- }
-
- // and if it has newly gained focus, call onFocusReceived()
- LLUICtrl* ctrlp = static_cast<LLUICtrl*>(viewp);
- if (ctrlp && (!last_focus || !last_focus->hasAncestor(ctrlp)))
- {
- ctrlp->onFocusReceived();
- }
-}
-
-void LLUICtrl::onFocusLost()
-{
- // trigger callbacks
- LLFocusableElement::onFocusLost();
-
- // find first view in hierarchy above old focus that is a LLUICtrl
- LLView* viewp = getParent();
- while (viewp && !viewp->isCtrl())
- {
- viewp = viewp->getParent();
- }
-
- // and if it has just lost focus, call onFocusReceived()
- LLUICtrl* ctrlp = static_cast<LLUICtrl*>(viewp);
- // hasFocus() includes any descendants
- if (ctrlp && !ctrlp->hasFocus())
- {
- ctrlp->onFocusLost();
- }
-}
-
-void LLUICtrl::onTopLost()
-{
- // trigger callbacks
- LLFocusableElement::onTopLost();
-}
-
-
// virtual
void LLUICtrl::setTabStop( BOOL b )
{
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 4030230684..3add9393ea 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -153,9 +153,6 @@ protected:
public:
// LLView interface
/*virtual*/ BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );
- /*virtual*/ void onFocusReceived();
- /*virtual*/ void onFocusLost();
- /*virtual*/ void onTopLost();
/*virtual*/ BOOL isCtrl() const;
/*virtual*/ void setTentative(BOOL b);
/*virtual*/ BOOL getTentative() const;
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index f2d340deb7..6f5c694b1b 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -162,3 +162,31 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
return false;
}
+
+bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)
+{
+ // boost::regex_search() only works on char or wchar_t
+ // types, but wchar_t is only 2-bytes on Win32 (not 4).
+ // So we use UTF-8 to make this work the same everywhere.
+ std::string utf8_text = wstring_to_utf8str(text);
+ if (findUrl(utf8_text, match, cb))
+ {
+ // we cannot blindly return the start/end offsets from
+ // the UTF-8 string because it is a variable-length
+ // character encoding, so we need to update the start
+ // and end values to be correct for the wide string.
+ LLWString wurl = utf8str_to_wstring(match.getUrl());
+ S32 start = text.find(wurl);
+ if (start == std::string::npos)
+ {
+ return false;
+ }
+ S32 end = start + wurl.size() - 1;
+
+ match.setValues(start, end, match.getUrl(), match.getLabel(),
+ match.getTooltip(), match.getIcon(),
+ match.getMenuName(), match.getLocation());
+ return true;
+ }
+ return false;
+}
diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h
index 84b033036c..85e934e4b5 100644
--- a/indra/llui/llurlregistry.h
+++ b/indra/llui/llurlregistry.h
@@ -37,10 +37,10 @@
#include "llurlentry.h"
#include "llurlmatch.h"
#include "llsingleton.h"
+#include "llstring.h"
#include <string>
#include <vector>
-#include <map>
/// This default callback for findUrl() simply ignores any label updates
void LLUrlRegistryNullCallback(const std::string &url, const std::string &label);
@@ -77,6 +77,10 @@ public:
bool findUrl(const std::string &text, LLUrlMatch &match,
const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);
+ /// a slightly less efficient version of findUrl for wide strings
+ bool findUrl(const LLWString &text, LLUrlMatch &match,
+ const LLUrlLabelCallback &cb = &LLUrlRegistryNullCallback);
+
private:
LLUrlRegistry();
friend class LLSingleton<LLUrlRegistry>;
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 46510804f8..256c776293 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -143,6 +143,7 @@ LLView::LLView(const LLView::Params& p)
LLView::~LLView()
{
+ dirtyRect();
//llinfos << "Deleting view " << mName << ":" << (void*) this << llendl;
// llassert(LLView::sIsDrawing == FALSE);
@@ -602,6 +603,7 @@ void LLView::setVisible(BOOL visible)
if (!getParent() || getParent()->isInVisibleChain())
{
// tell all children of this view that the visibility may have changed
+ dirtyRect();
handleVisibilityChange( visible );
}
updateBoundingRect();
@@ -673,9 +675,13 @@ LLView* LLView::childrenHandleToolTip(S32 x, S32 y, std::string& msg, LLRect& st
LLView* viewp = *child_it;
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
- if(viewp->pointInView(local_x, local_y) &&
- viewp->getVisible() &&
- viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen) )
+ if(!viewp->pointInView(local_x, local_y) ||
+ !viewp->getVisible())
+ {
+ continue;
+ }
+
+ if(viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen) )
{
if (sDebugMouseHandling)
{
@@ -685,17 +691,22 @@ LLView* LLView::childrenHandleToolTip(S32 x, S32 y, std::string& msg, LLRect& st
handled_view = viewp;
break;
}
+
+ if( viewp->blockMouseEvent(x, y) )
+ {
+ handled_view = viewp;
+ }
}
return handled_view;
}
BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_screen)
{
- LLView* child_handler = childrenHandleToolTip(x, y, msg, sticky_rect_screen);
- BOOL handled = child_handler != NULL;
+ BOOL handled = FALSE;
- // child widgets get priority on tooltips
- if (!handled && !mToolTipMsg.empty())
+ // parents provide tooltips first, which are optionally
+ // overridden by children
+ if (!mToolTipMsg.empty())
{
// allow "scrubbing" over ui by showing next tooltip immediately
// if previous one was still visible
@@ -710,7 +721,9 @@ BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect& sticky_rect_s
handled = TRUE;
}
- if( blockMouseEvent(x, y) )
+ // child tooltips will override our own
+ LLView* child_handler = childrenHandleToolTip(x, y, msg, sticky_rect_screen);
+ if (child_handler)
{
handled = TRUE;
}
@@ -1297,7 +1310,7 @@ void LLView::drawChildren()
{
// Only draw views that are within the root view
localRectToScreen(viewp->getRect(),&screenRect);
- if ( rootRect.overlaps(screenRect) )
+ if ( rootRect.overlaps(screenRect) && LLUI::sDirtyRect.overlaps(screenRect))
{
glMatrixMode(GL_MODELVIEW);
LLUI::pushMatrix();
@@ -1316,6 +1329,21 @@ void LLView::drawChildren()
gGL.getTexUnit(0)->disable();
}
+void LLView::dirtyRect()
+{
+ LLView* child = getParent();
+ LLView* parent = child ? child->getParent() : NULL;
+ LLView* cur = this;
+ while (child && parent && parent->getParent())
+ { //find third to top-most view
+ cur = child;
+ child = parent;
+ parent = parent->getParent();
+ }
+
+ LLUI::dirtyRect(cur->calcScreenRect());
+}
+
//Draw a box for debugging.
void LLView::drawDebugRect()
{
@@ -1529,6 +1557,8 @@ void LLView::updateBoundingRect()
{
if (isDead()) return;
+ LLRect cur_rect = mBoundingRect;
+
if (mUseBoundingRect)
{
mBoundingRect = calcBoundingRect();
@@ -1543,6 +1573,12 @@ void LLView::updateBoundingRect()
{
getParent()->updateBoundingRect();
}
+
+ if (mBoundingRect != cur_rect)
+ {
+ dirtyRect();
+ }
+
}
LLRect LLView::calcScreenRect() const
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 1f7e5afaae..bf3b5d0614 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -519,6 +519,7 @@ public:
virtual BOOL handleUnicodeCharHere(llwchar uni_char);
virtual void handleReshape(const LLRect& rect, bool by_user);
+ virtual void dirtyRect();
virtual void notifyParent(const LLSD& info);
virtual void notifyChildren(const LLSD& info);