summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
authorJames Cook <james@lindenlab.com>2010-02-03 14:13:56 -0800
committerJames Cook <james@lindenlab.com>2010-02-03 14:13:56 -0800
commit88350edbcbec615f3b15fc82bd5ce4005621ac6f (patch)
treec244f41159cf32f3e03c6c311e1453bbd383bad5 /indra/llui
parentd489216b6ef41f0d22f3a9062ba6daacc67bc038 (diff)
parent0bee31de32cb5999e7ec06d74f55d34ce0ac052b (diff)
merge
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/llaccordionctrl.cpp75
-rw-r--r--indra/llui/llaccordionctrl.h9
-rw-r--r--indra/llui/llaccordionctrltab.cpp34
-rw-r--r--indra/llui/llaccordionctrltab.h1
-rw-r--r--indra/llui/llbutton.cpp22
-rw-r--r--indra/llui/llbutton.h20
-rw-r--r--indra/llui/llcombobox.cpp9
-rw-r--r--indra/llui/llconsole.cpp4
-rw-r--r--indra/llui/llconsole.h2
-rw-r--r--indra/llui/lldockablefloater.cpp2
-rw-r--r--indra/llui/lldockcontrol.cpp6
-rw-r--r--indra/llui/lldraghandle.cpp1
-rw-r--r--indra/llui/llflatlistview.cpp35
-rw-r--r--indra/llui/llflatlistview.h2
-rw-r--r--indra/llui/llfloater.cpp25
-rw-r--r--indra/llui/llfloater.h4
-rw-r--r--indra/llui/llfloaterreg.cpp4
-rw-r--r--indra/llui/llfloaterreg.h3
-rw-r--r--indra/llui/lllineeditor.cpp6
-rw-r--r--indra/llui/llmenugl.cpp25
-rw-r--r--indra/llui/llmenugl.h2
-rw-r--r--indra/llui/llnotifications.cpp5
-rw-r--r--indra/llui/llnotifications.h4
-rw-r--r--indra/llui/llnotificationsutil.cpp5
-rw-r--r--indra/llui/llnotificationsutil.h2
-rw-r--r--indra/llui/llscrolllistctrl.cpp12
-rw-r--r--indra/llui/llscrolllistctrl.h1
-rw-r--r--indra/llui/llscrolllistitem.h2
-rw-r--r--indra/llui/llspinctrl.cpp16
-rw-r--r--indra/llui/llspinctrl.h5
-rw-r--r--indra/llui/llstyle.cpp5
-rw-r--r--indra/llui/llstyle.h4
-rw-r--r--indra/llui/lltabcontainer.cpp80
-rw-r--r--indra/llui/lltabcontainer.h1
-rw-r--r--indra/llui/lltextbase.cpp138
-rw-r--r--indra/llui/lltextbase.h29
-rw-r--r--indra/llui/lltexteditor.cpp90
-rw-r--r--indra/llui/lltexteditor.h1
-rw-r--r--indra/llui/lltooltip.cpp3
-rw-r--r--indra/llui/llui.cpp18
-rw-r--r--indra/llui/lluicolortable.h2
-rw-r--r--indra/llui/lluiimage.cpp4
-rw-r--r--indra/llui/lluistring.h2
-rw-r--r--indra/llui/llurlentry.cpp42
-rw-r--r--indra/llui/llurlentry.h27
-rw-r--r--indra/llui/llurlmatch.cpp8
-rw-r--r--indra/llui/llurlmatch.h6
-rw-r--r--indra/llui/llurlregistry.cpp17
-rw-r--r--indra/llui/llviewmodel.h3
-rw-r--r--indra/llui/tests/llurlentry_test.cpp307
-rw-r--r--indra/llui/tests/llurlmatch_test.cpp31
51 files changed, 687 insertions, 474 deletions
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp
index b5e870228a..d0c73fbfbc 100644
--- a/indra/llui/llaccordionctrl.cpp
+++ b/indra/llui/llaccordionctrl.cpp
@@ -63,6 +63,8 @@ static LLDefaultChildRegistry::Register<LLAccordionCtrl> t2("accordion");
LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params)
, mFitParent(params.fit_parent)
+ , mAutoScrolling( false )
+ , mAutoScrollRate( 0.f )
{
mSingleExpansion = params.single_expansion;
if(mFitParent && !mSingleExpansion)
@@ -72,6 +74,8 @@ LLAccordionCtrl::LLAccordionCtrl(const Params& params):LLPanel(params)
}
LLAccordionCtrl::LLAccordionCtrl() : LLPanel()
+ , mAutoScrolling( false )
+ , mAutoScrollRate( 0.f )
{
mSingleExpansion = false;
mFitParent = false;
@@ -81,6 +85,19 @@ LLAccordionCtrl::LLAccordionCtrl() : LLPanel()
//---------------------------------------------------------------------------------
void LLAccordionCtrl::draw()
{
+ if (mAutoScrolling)
+ {
+ // add acceleration to autoscroll
+ mAutoScrollRate = llmin(mAutoScrollRate + (LLFrameTimer::getFrameDeltaTimeF32() * AUTO_SCROLL_RATE_ACCEL), MAX_AUTO_SCROLL_RATE);
+ }
+ else
+ {
+ // reset to minimum for next time
+ mAutoScrollRate = MIN_AUTO_SCROLL_RATE;
+ }
+ // clear this flag to be set on next call to autoScroll
+ mAutoScrolling = false;
+
LLRect local_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
LLLocalClipRect clip(local_rect);
@@ -420,6 +437,64 @@ BOOL LLAccordionCtrl::handleKeyHere (KEY key, MASK mask)
return LLPanel::handleKeyHere(key,mask);
}
+BOOL LLAccordionCtrl::handleDragAndDrop (S32 x, S32 y, MASK mask,
+ BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+{
+ // Scroll folder view if needed. Never accepts a drag or drop.
+ *accept = ACCEPT_NO;
+ BOOL handled = autoScroll(x, y);
+
+ if( !handled )
+ {
+ handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type,
+ cargo_data, accept, tooltip_msg) != NULL;
+ }
+ return TRUE;
+}
+
+BOOL LLAccordionCtrl::autoScroll (S32 x, S32 y)
+{
+ static LLUICachedControl<S32> scrollbar_size ("UIScrollbarSize", 0);
+
+ bool scrolling = false;
+ if( mScrollbar->getVisible() )
+ {
+ LLRect rect_local( 0, getRect().getHeight(), getRect().getWidth() - scrollbar_size, 0 );
+ LLRect screen_local_extents;
+
+ // clip rect against root view
+ screenRectToLocal(getRootView()->getLocalRect(), &screen_local_extents);
+ rect_local.intersectWith(screen_local_extents);
+
+ // autoscroll region should take up no more than one third of visible scroller area
+ S32 auto_scroll_region_height = llmin(rect_local.getHeight() / 3, 10);
+ S32 auto_scroll_speed = llround(mAutoScrollRate * LLFrameTimer::getFrameDeltaTimeF32());
+
+ LLRect bottom_scroll_rect = screen_local_extents;
+ bottom_scroll_rect.mTop = rect_local.mBottom + auto_scroll_region_height;
+ if( bottom_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() < mScrollbar->getDocPosMax()) )
+ {
+ mScrollbar->setDocPos( mScrollbar->getDocPos() + auto_scroll_speed );
+ mAutoScrolling = true;
+ scrolling = true;
+ }
+
+ LLRect top_scroll_rect = screen_local_extents;
+ top_scroll_rect.mBottom = rect_local.mTop - auto_scroll_region_height;
+ if( top_scroll_rect.pointInRect( x, y ) && (mScrollbar->getDocPos() > 0) )
+ {
+ mScrollbar->setDocPos( mScrollbar->getDocPos() - auto_scroll_speed );
+ mAutoScrolling = true;
+ scrolling = true;
+ }
+ }
+ return scrolling;
+}
+
void LLAccordionCtrl::updateLayout (S32 width, S32 height)
{
S32 panel_top = height - BORDER_MARGIN ;
diff --git a/indra/llui/llaccordionctrl.h b/indra/llui/llaccordionctrl.h
index 4cb0f38281..d57a42df32 100644
--- a/indra/llui/llaccordionctrl.h
+++ b/indra/llui/llaccordionctrl.h
@@ -81,6 +81,11 @@ public:
virtual BOOL handleRightMouseDown ( S32 x, S32 y, MASK mask);
virtual BOOL handleScrollWheel ( S32 x, S32 y, S32 clicks );
virtual BOOL handleKeyHere (KEY key, MASK mask);
+ virtual BOOL handleDragAndDrop (S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg);
//
// Call reshape after changing splitter's size
@@ -112,11 +117,15 @@ private:
void showScrollbar (S32 width, S32 height);
void hideScrollbar (S32 width, S32 height);
+ BOOL autoScroll (S32 x, S32 y);
+
private:
LLRect mInnerRect;
LLScrollbar* mScrollbar;
bool mSingleExpansion;
bool mFitParent;
+ bool mAutoScrolling;
+ F32 mAutoScrollRate;
};
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 4bfe44135a..daa9e08f14 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -45,6 +45,7 @@ static const std::string DD_HEADER_NAME = "dd_header";
static const S32 HEADER_HEIGHT = 20;
static const S32 HEADER_IMAGE_LEFT_OFFSET = 5;
static const S32 HEADER_TEXT_LEFT_OFFSET = 30;
+static const F32 AUTO_OPEN_TIME = 1.f;
static LLDefaultChildRegistry::Register<LLAccordionCtrlTab> t1("accordion_tab");
@@ -73,6 +74,11 @@ public:
virtual void onMouseEnter(S32 x, S32 y, MASK mask);
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
+ virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg);
private:
LLTextBox* mHeaderTextbox;
@@ -92,6 +98,8 @@ private:
LLUIColor mHeaderBGColor;
bool mNeedsHighlight;
+
+ LLFrameTimer mAutoOpenTimer;
};
LLAccordionCtrlTab::LLAccordionCtrlTabHeader::Params::Params()
@@ -209,6 +217,7 @@ void LLAccordionCtrlTab::LLAccordionCtrlTabHeader::onMouseLeave(S32 x, S32 y, MA
{
LLUICtrl::onMouseLeave(x, y, mask);
mNeedsHighlight = false;
+ mAutoOpenTimer.stop();
}
BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask, BOOL called_from_parent)
{
@@ -218,8 +227,33 @@ BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleKey(KEY key, MASK mask,
}
return LLUICtrl::handleKey(key, mask, called_from_parent);
}
+BOOL LLAccordionCtrlTab::LLAccordionCtrlTabHeader::handleDragAndDrop(S32 x, S32 y, MASK mask,
+ BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+{
+ LLAccordionCtrlTab* parent = dynamic_cast<LLAccordionCtrlTab*>(getParent());
+ if ( parent && !parent->getDisplayChildren() && parent->getCollapsible() && parent->canOpenClose() )
+ {
+ if (mAutoOpenTimer.getStarted())
+ {
+ if (mAutoOpenTimer.getElapsedTimeF32() > AUTO_OPEN_TIME)
+ {
+ parent->changeOpenClose(false);
+ mAutoOpenTimer.stop();
+ return TRUE;
+ }
+ }
+ else
+ mAutoOpenTimer.start();
+ }
+ return LLUICtrl::handleDragAndDrop(x, y, mask, drop, cargo_type,
+ cargo_data, accept, tooltip_msg);
+}
LLAccordionCtrlTab::Params::Params()
: title("title")
,display_children("expanded", true)
diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h
index b200d43438..2e0260ab16 100644
--- a/indra/llui/llaccordionctrltab.h
+++ b/indra/llui/llaccordionctrltab.h
@@ -115,6 +115,7 @@ public:
void changeOpenClose(bool is_open);
void canOpenClose(bool can_open_close) { mCanOpenClose = can_open_close;};
+ bool canOpenClose() const { return mCanOpenClose; };
virtual BOOL postBuild();
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index 9ce8ce8d55..4944ed4fe7 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -81,6 +81,10 @@ LLButton::Params::Params()
image_pressed_selected("image_pressed_selected"),
image_overlay("image_overlay"),
image_overlay_alignment("image_overlay_alignment", std::string("center")),
+ image_left_pad("image_left_pad"),
+ image_right_pad("image_right_pad"),
+ image_top_pad("image_top_pad"),
+ image_bottom_pad("image_bottom_pad"),
label_color("label_color"),
label_color_selected("label_color_selected"), // requires is_toggle true
label_color_disabled("label_color_disabled"),
@@ -140,6 +144,10 @@ LLButton::LLButton(const LLButton::Params& p)
mImageOverlay(p.image_overlay()),
mImageOverlayColor(p.image_overlay_color()),
mImageOverlayAlignment(LLFontGL::hAlignFromName(p.image_overlay_alignment)),
+ mImageOverlayLeftPad(p.image_left_pad),
+ mImageOverlayRightPad(p.image_right_pad),
+ mImageOverlayTopPad(p.image_top_pad),
+ mImageOverlayBottomPad(p.image_bottom_pad),
mIsToggle(p.is_toggle),
mScaleImage(p.scale_image),
mDropShadowedText(p.label_shadow),
@@ -763,6 +771,12 @@ void LLButton::draw()
center_x++;
}
+ S32 text_width_delta = overlay_width + 1;
+ // if image paddings set, they should participate in scaling process
+ S32 image_size_delta = mImageOverlayTopPad + mImageOverlayBottomPad;
+ overlay_width = overlay_width - image_size_delta;
+ overlay_height = overlay_height - image_size_delta;
+
// fade out overlay images on disabled buttons
LLColor4 overlay_color = mImageOverlayColor.get();
if (!enabled)
@@ -774,8 +788,8 @@ void LLButton::draw()
switch(mImageOverlayAlignment)
{
case LLFontGL::LEFT:
- text_left += overlay_width + 1;
- text_width -= overlay_width + 1;
+ text_left += overlay_width + mImageOverlayRightPad + 1;
+ text_width -= text_width_delta;
mImageOverlay->draw(
mLeftHPad,
center_y - (overlay_height / 2),
@@ -792,8 +806,8 @@ void LLButton::draw()
overlay_color);
break;
case LLFontGL::RIGHT:
- text_right -= overlay_width + 1;
- text_width -= overlay_width + 1;
+ text_right -= overlay_width + mImageOverlayLeftPad+ 1;
+ text_width -= text_width_delta;
mImageOverlay->draw(
getRect().getWidth() - mRightHPad - overlay_width,
center_y - (overlay_height / 2),
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index cd149e3113..8e5f19602f 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -106,6 +106,12 @@ public:
Optional<S32> pad_left;
Optional<S32> pad_bottom; // under text label
+ //image overlay paddings
+ Optional<S32> image_left_pad;
+ Optional<S32> image_right_pad;
+ Optional<S32> image_top_pad;
+ Optional<S32> image_bottom_pad;
+
// callbacks
Optional<CommitCallbackParam> click_callback, // alias -> commit_callback
mouse_down_callback,
@@ -186,6 +192,15 @@ public:
void setLeftHPad( S32 pad ) { mLeftHPad = pad; }
void setRightHPad( S32 pad ) { mRightHPad = pad; }
+ void setImageOverlayLeftPad( S32 pad ) { mImageOverlayLeftPad = pad; }
+ S32 getImageOverlayLeftPad() const { return mImageOverlayLeftPad; }
+ void setImageOverlayRightPad( S32 pad ) { mImageOverlayRightPad = pad; }
+ S32 getImageOverlayRightPad() const { return mImageOverlayRightPad; }
+ void setImageOverlayTopPad( S32 pad ) { mImageOverlayTopPad = pad; }
+ S32 getImageOverlayTopPad() const { return mImageOverlayTopPad; }
+ void setImageOverlayBottomPad( S32 pad ) { mImageOverlayBottomPad = pad; }
+ S32 getImageOverlayBottomPad() const { return mImageOverlayBottomPad; }
+
const std::string getLabelUnselected() const { return wstring_to_utf8str(mUnselectedLabel); }
const std::string getLabelSelected() const { return wstring_to_utf8str(mSelectedLabel); }
@@ -313,6 +328,11 @@ private:
S32 mRightHPad;
S32 mBottomVPad; // under text label
+ S32 mImageOverlayLeftPad;
+ S32 mImageOverlayRightPad;
+ S32 mImageOverlayTopPad;
+ S32 mImageOverlayBottomPad;
+
F32 mHoverGlowStrength;
F32 mCurGlowStrength;
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index f29e8785eb..9d23daf56d 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -103,7 +103,8 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p)
mPrearrangeCallback(p.prearrange_callback()),
mTextEntryCallback(p.text_entry_callback()),
mListPosition(p.list_position),
- mLastSelectedIndex(-1)
+ mLastSelectedIndex(-1),
+ mLabel(p.label)
{
// Text label button
@@ -490,6 +491,7 @@ void LLComboBox::createLineEditor(const LLComboBox::Params& p)
params.handle_edit_keys_directly(true);
params.commit_on_focus_lost(false);
params.follows.flags(FOLLOWS_ALL);
+ params.label(mLabel);
mTextEntry = LLUICtrlFactory::create<LLLineEditor> (params);
mTextEntry->setText(cur_label);
mTextEntry->setIgnoreTab(TRUE);
@@ -505,7 +507,8 @@ void LLComboBox::createLineEditor(const LLComboBox::Params& p)
mButton->setRect(rect);
mButton->setTabStop(TRUE);
mButton->setHAlign(LLFontGL::LEFT);
-
+ mButton->setLabel(mLabel.getString());
+
if (mTextEntry)
{
mTextEntry->setVisible(FALSE);
@@ -633,7 +636,7 @@ void LLComboBox::hideList()
if(mLastSelectedIndex >= 0)
mList->selectNthItem(mLastSelectedIndex);
}
- else
+ else if(mLastSelectedIndex >= 0)
mList->selectNthItem(mLastSelectedIndex);
mButton->setToggleState(FALSE);
diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp
index 59499f987b..0237c80efa 100644
--- a/indra/llui/llconsole.cpp
+++ b/indra/llui/llconsole.cpp
@@ -66,7 +66,9 @@ LLConsole::LLConsole(const LLConsole::Params& p)
: LLUICtrl(p),
LLFixedBuffer(p.max_lines),
mLinePersistTime(p.persist_time), // seconds
- mFont(p.font)
+ mFont(p.font),
+ mConsoleWidth(0),
+ mConsoleHeight(0)
{
if (p.font_size_index.isProvided())
{
diff --git a/indra/llui/llconsole.h b/indra/llui/llconsole.h
index 5800a82922..4719950f28 100644
--- a/indra/llui/llconsole.h
+++ b/indra/llui/llconsole.h
@@ -150,8 +150,6 @@ private:
F32 mLinePersistTime; // Age at which to stop drawing.
F32 mFadeTime; // Age at which to start fading
const LLFontGL* mFont;
- S32 mLastBoxHeight;
- S32 mLastBoxWidth;
S32 mConsoleWidth;
S32 mConsoleHeight;
diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp
index 74438b184a..57baf28dab 100644
--- a/indra/llui/lldockablefloater.cpp
+++ b/indra/llui/lldockablefloater.cpp
@@ -146,7 +146,7 @@ void LLDockableFloater::setVisible(BOOL visible)
if (visible)
{
- LLFloater::setFrontmost(TRUE);
+ LLFloater::setFrontmost(getAutoFocus());
}
LLFloater::setVisible(visible);
}
diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp
index 0d8e54aa48..d836a5f4cd 100644
--- a/indra/llui/lldockcontrol.cpp
+++ b/indra/llui/lldockcontrol.cpp
@@ -37,7 +37,11 @@
LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
const LLUIImagePtr& dockTongue, DocAt dockAt, get_allowed_rect_callback_t get_allowed_rect_callback) :
- mDockWidget(dockWidget), mDockableFloater(dockableFloater), mDockTongue(dockTongue)
+ mDockWidget(dockWidget),
+ mDockableFloater(dockableFloater),
+ mDockTongue(dockTongue),
+ mDockTongueX(0),
+ mDockTongueY(0)
{
mDockAt = dockAt;
diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp
index a93c666648..832f148902 100644
--- a/indra/llui/lldraghandle.cpp
+++ b/indra/llui/lldraghandle.cpp
@@ -113,6 +113,7 @@ void LLDragHandleTop::setTitle(const std::string& title)
params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT);
params.font_shadow(LLFontGL::DROP_SHADOW_SOFT);
params.use_ellipses = true;
+ params.allow_html = false; //cancel URL replacement in floater title
mTitleBox = LLUICtrlFactory::create<LLTextBox> (params);
addChild( mTitleBox );
}
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 3694ecd4f4..92993650a7 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -289,8 +289,8 @@ void LLFlatListView::resetSelection(bool no_commit_on_deselection /*= false*/)
onCommit();
}
- // Stretch selected items rect to ensure it won't be clipped
- mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1));
+ // Stretch selected item rect to ensure it won't be clipped
+ mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1));
}
void LLFlatListView::setNoItemsCommentText(const std::string& comment_text)
@@ -393,7 +393,7 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p)
LLViewBorder::Params params;
params.name("scroll border");
- params.rect(getSelectedItemsRect());
+ params.rect(getLastSelectedItemRect());
params.visible(false);
params.bevel_style(LLViewBorder::BEVEL_IN);
mSelectedItemsBorder = LLUICtrlFactory::create<LLViewBorder> (params);
@@ -480,8 +480,8 @@ void LLFlatListView::rearrangeItems()
item_new_top -= (rc.getHeight() + mItemPad);
}
- // Stretch selected items rect to ensure it won't be clipped
- mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1));
+ // Stretch selected item rect to ensure it won't be clipped
+ mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1));
}
void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)
@@ -664,8 +664,8 @@ bool LLFlatListView::selectItemPair(item_pair_t* item_pair, bool select)
onCommit();
}
- // Stretch selected items rect to ensure it won't be clipped
- mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1));
+ // Stretch selected item rect to ensure it won't be clipped
+ mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1));
return true;
}
@@ -680,23 +680,6 @@ LLRect LLFlatListView::getLastSelectedItemRect()
return mSelectedItemPairs.back()->first->getRect();
}
-LLRect LLFlatListView::getSelectedItemsRect()
-{
- if (!mSelectedItemPairs.size())
- {
- return LLRect::null;
- }
- LLRect rc = getLastSelectedItemRect();
- for ( pairs_const_iterator_t
- it = mSelectedItemPairs.begin(),
- it_end = mSelectedItemPairs.end();
- it != it_end; ++it )
- {
- rc.unionWith((*it)->first->getRect());
- }
- return rc;
-}
-
void LLFlatListView::selectFirstItem ()
{
selectItemPair(mItemPairs.front(), true);
@@ -819,8 +802,8 @@ bool LLFlatListView::selectAll()
onCommit();
}
- // Stretch selected items rect to ensure it won't be clipped
- mSelectedItemsBorder->setRect(getSelectedItemsRect().stretch(-1));
+ // Stretch selected item rect to ensure it won't be clipped
+ mSelectedItemsBorder->setRect(getLastSelectedItemRect().stretch(-1));
return true;
}
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
index 5999e79f61..949a731507 100644
--- a/indra/llui/llflatlistview.h
+++ b/indra/llui/llflatlistview.h
@@ -368,8 +368,6 @@ protected:
LLRect getLastSelectedItemRect();
- LLRect getSelectedItemsRect();
-
void ensureSelectedVisible();
private:
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 79d8f90fec..a55915af35 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -1650,24 +1650,8 @@ void LLFloater::draw()
}
else
{
- //FIXME: get rid of this hack
- // draw children
- LLView* focused_child = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus());
- BOOL focused_child_visible = FALSE;
- if (focused_child && focused_child->getParent() == this)
- {
- focused_child_visible = focused_child->getVisible();
- focused_child->setVisible(FALSE);
- }
-
// don't call LLPanel::draw() since we've implemented custom background rendering
LLView::draw();
-
- if (focused_child_visible)
- {
- focused_child->setVisible(TRUE);
- }
- drawChild(focused_child);
}
// update tearoff button for torn off floaters
@@ -1916,9 +1900,10 @@ static LLDefaultChildRegistry::Register<LLFloaterView> r("floater_view");
LLFloaterView::LLFloaterView (const Params& p)
: LLUICtrl (p),
+
mFocusCycleMode(FALSE),
- mSnapOffsetBottom(0)
- ,mSnapOffsetRight(0)
+ mSnapOffsetBottom(0),
+ mSnapOffsetRight(0)
{
}
@@ -2578,6 +2563,8 @@ void LLFloaterView::pushVisibleAll(BOOL visible, const skip_list_t& skip_list)
view->pushVisible(visible);
}
}
+
+ LLFloaterReg::blockShowFloaters(true);
}
void LLFloaterView::popVisibleAll(const skip_list_t& skip_list)
@@ -2595,6 +2582,8 @@ void LLFloaterView::popVisibleAll(const skip_list_t& skip_list)
view->popVisible();
}
}
+
+ LLFloaterReg::blockShowFloaters(false);
}
void LLFloater::setInstanceName(const std::string& name)
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index f70495c0f0..2166d8db8a 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -301,6 +301,7 @@ protected:
const LLRect& getExpandedRect() const { return mExpandedRect; }
void setAutoFocus(BOOL focus) { mAutoFocus = focus; } // whether to automatically take focus when opened
+ BOOL getAutoFocus() const { return mAutoFocus; }
LLDragHandle* getDragHandle() const { return mDragHandle; }
void destroy() { die(); } // Don't call this directly. You probably want to call closeFloater()
@@ -468,9 +469,6 @@ public:
void setSnapOffsetRight(S32 offset) { mSnapOffsetRight = offset; }
private:
- S32 mColumn;
- S32 mNextLeft;
- S32 mNextTop;
BOOL mFocusCycleMode;
S32 mSnapOffsetBottom;
S32 mSnapOffsetRight;
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index eb67e3a561..5de3934c8a 100644
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -34,6 +34,7 @@
#include "llfloaterreg.h"
+//#include "llagent.h"
#include "llfloater.h"
#include "llmultifloater.h"
#include "llfloaterreglistener.h"
@@ -45,6 +46,7 @@ LLFloaterReg::instance_list_t LLFloaterReg::sNullInstanceList;
LLFloaterReg::instance_map_t LLFloaterReg::sInstanceMap;
LLFloaterReg::build_map_t LLFloaterReg::sBuildMap;
std::map<std::string,std::string> LLFloaterReg::sGroupMap;
+bool LLFloaterReg::sBlockShowFloaters = false;
static LLFloaterRegListener sFloaterRegListener;
@@ -217,6 +219,8 @@ LLFloaterReg::const_instance_list_t& LLFloaterReg::getFloaterList(const std::str
//static
LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus)
{
+ if( sBlockShowFloaters )
+ return 0;//
LLFloater* instance = getInstance(name, key);
if (instance)
{
diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h
index 634a235926..8a11d5c3f2 100644
--- a/indra/llui/llfloaterreg.h
+++ b/indra/llui/llfloaterreg.h
@@ -75,6 +75,7 @@ private:
static instance_map_t sInstanceMap;
static build_map_t sBuildMap;
static std::map<std::string,std::string> sGroupMap;
+ static bool sBlockShowFloaters;
public:
// Registration
@@ -152,6 +153,8 @@ public:
{
return dynamic_cast<T*>(showInstance(name, key, focus));
}
+
+ static void blockShowFloaters(bool value) { sBlockShowFloaters = value;}
};
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 73e4d126f3..eb2b4f7705 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -70,6 +70,8 @@ const S32 SCROLL_INCREMENT_DEL = 4; // make space for baskspacing
const F32 AUTO_SCROLL_TIME = 0.05f;
const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click. *TODO: make this equal to the double click interval?
+const std::string PASSWORD_ASTERISK( "\xE2\x80\xA2" ); // U+2022 BULLET
+
static LLDefaultChildRegistry::Register<LLLineEditor> r1("line_editor");
// Compiler optimization, generate extern template
@@ -401,7 +403,7 @@ void LLLineEditor::setCursorAtLocalPos( S32 local_mouse_x )
{
for (S32 i = 0; i < mText.length(); i++)
{
- asterix_text += '*';
+ asterix_text += utf8str_to_wstring(PASSWORD_ASTERISK);
}
wtext = asterix_text.c_str();
}
@@ -1599,7 +1601,7 @@ void LLLineEditor::draw()
std::string text;
for (S32 i = 0; i < mText.length(); i++)
{
- text += '*';
+ text += PASSWORD_ASTERISK;
}
mText = text;
}
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index c172a2b714..7fa9a88059 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -1651,6 +1651,7 @@ LLMenuGL::LLMenuGL(const LLMenuGL::Params& p)
mBackgroundColor( p.bg_color() ),
mBgVisible( p.bg_visible ),
mDropShadowed( p.drop_shadow ),
+ mHasSelection(false),
mHorizontalLayout( p.horizontal_layout ),
mScrollable(mHorizontalLayout ? FALSE : p.scrollable), // Scrolling is supported only for vertical layout
mMaxScrollableItems(p.max_scrollable_items),
@@ -1875,17 +1876,21 @@ void LLMenuGL::scrollItemsDown()
item_list_t::iterator next_item_iter;
- for (next_item_iter = ++cur_item_iter; next_item_iter != mItems.end(); next_item_iter++)
+ if (cur_item_iter != mItems.end())
{
- if( (*next_item_iter)->getVisible())
+ for (next_item_iter = ++cur_item_iter; next_item_iter != mItems.end(); next_item_iter++)
{
- break;
+ if( (*next_item_iter)->getVisible())
+ {
+ break;
+ }
+ }
+
+ if (next_item_iter != mItems.end() &&
+ (*next_item_iter)->getVisible())
+ {
+ mFirstVisibleItem = *next_item_iter;
}
- }
-
- if ((*next_item_iter)->getVisible())
- {
- mFirstVisibleItem = *next_item_iter;
}
mNeedsArrange = TRUE;
@@ -2809,7 +2814,7 @@ BOOL LLMenuGL::handleHover( S32 x, S32 y, MASK mask )
((LLMenuItemGL*)viewp)->setHighlight(TRUE);
LLMenuGL::setKeyboardMode(FALSE);
}
- mHasSelection = TRUE;
+ mHasSelection = true;
}
}
}
@@ -2888,7 +2893,7 @@ void LLMenuGL::setVisible(BOOL visible)
}
else
{
- mHasSelection = FALSE;
+ mHasSelection = true;
mFadeTimer.stop();
}
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 61e06f9e5f..8441aaadd4 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -546,7 +546,7 @@ private:
LLHandle<LLView> mParentMenuItem;
LLUIString mLabel;
BOOL mDropShadowed; // Whether to drop shadow
- BOOL mHasSelection;
+ bool mHasSelection;
LLFrameTimer mFadeTimer;
LLTimer mScrollItemsTimer;
BOOL mTornOff;
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 86989012ee..5816cef6af 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -283,6 +283,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLXMLNodeP
}
LLNotificationForm::LLNotificationForm(const LLSD& sd)
+ : mIgnore(IGNORE_NO)
{
if (sd.isArray())
{
@@ -384,7 +385,8 @@ LLNotificationTemplate::LLNotificationTemplate() :
mExpireSeconds(0),
mExpireOption(-1),
mURLOption(-1),
- mURLOpenExternally(-1),
+ mURLOpenExternally(-1),
+ mPersist(false),
mUnique(false),
mPriority(NOTIFICATION_PRIORITY_NORMAL)
{
@@ -1058,6 +1060,7 @@ LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelN
if(p == mChannels.end())
{
llerrs << "Did not find channel named " << channelName << llendl;
+ return LLNotificationChannelPtr();
}
return p->second;
}
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index aeb4cebf1b..8d993b71d7 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -371,7 +371,7 @@ private:
// this is just for making it easy to look things up in a set organized by UUID -- DON'T USE IT
// for anything real!
- LLNotification(LLUUID uuid) : mId(uuid) {}
+ LLNotification(LLUUID uuid) : mId(uuid), mCancelled(false), mRespondedTo(false), mIgnored(false), mPriority(NOTIFICATION_PRIORITY_UNSPECIFIED), mTemporaryResponder(false) {}
void cancel();
@@ -621,7 +621,7 @@ namespace LLNotificationComparators
struct orderBy
{
typedef boost::function<T (LLNotificationPtr)> field_t;
- orderBy(field_t field, EDirection = ORDER_INCREASING) : mField(field) {}
+ orderBy(field_t field, EDirection direction = ORDER_INCREASING) : mField(field), mDirection(direction) {}
bool operator()(LLNotificationPtr lhs, LLNotificationPtr rhs)
{
if (mDirection == ORDER_DECREASING)
diff --git a/indra/llui/llnotificationsutil.cpp b/indra/llui/llnotificationsutil.cpp
index f343d27cb4..54bdb4bd66 100644
--- a/indra/llui/llnotificationsutil.cpp
+++ b/indra/llui/llnotificationsutil.cpp
@@ -94,3 +94,8 @@ void LLNotificationsUtil::cancel(LLNotificationPtr pNotif)
{
LLNotifications::instance().cancel(pNotif);
}
+
+LLNotificationPtr LLNotificationsUtil::find(LLUUID uuid)
+{
+ return LLNotifications::instance().find(uuid);
+}
diff --git a/indra/llui/llnotificationsutil.h b/indra/llui/llnotificationsutil.h
index d552fa915b..338204924a 100644
--- a/indra/llui/llnotificationsutil.h
+++ b/indra/llui/llnotificationsutil.h
@@ -65,6 +65,8 @@ namespace LLNotificationsUtil
S32 getSelectedOption(const LLSD& notification, const LLSD& response);
void cancel(LLNotificationPtr pNotif);
+
+ LLNotificationPtr find(LLUUID uuid);
}
#endif
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 4e84013db0..478e270c98 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -498,7 +498,7 @@ void LLScrollListCtrl::fitContents(S32 max_width, S32 max_height)
{
S32 height = llmin( getRequiredRect().getHeight(), max_height );
if(mPageLines)
- height = llmin( mPageLines * mLineHeight + (mDisplayColumnHeaders ? mHeadingHeight : 0), height );
+ height = llmin( mPageLines * mLineHeight + 2*mBorderThickness + (mDisplayColumnHeaders ? mHeadingHeight : 0), height );
S32 width = getRect().getWidth();
@@ -1534,7 +1534,7 @@ LLRect LLScrollListCtrl::getCellRect(S32 row_index, S32 column_index)
S32 rect_bottom = getRowOffsetFromIndex(row_index);
LLScrollListColumn* columnp = getColumn(column_index);
cell_rect.setOriginAndSize(rect_left, rect_bottom,
- rect_left + columnp->getWidth(), mLineHeight);
+ /*rect_left + */columnp->getWidth(), mLineHeight);
return cell_rect;
}
@@ -2760,9 +2760,13 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& element, EAddPosition
LLScrollListItem* LLScrollListCtrl::addRow(const LLScrollListItem::Params& item_p, EAddPosition pos)
{
- if (!item_p.validateBlock()) return NULL;
-
LLScrollListItem *new_item = new LLScrollListItem(item_p);
+ return addRow(new_item, item_p, pos);
+}
+
+LLScrollListItem* LLScrollListCtrl::addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& item_p, EAddPosition pos)
+{
+ if (!item_p.validateBlock() || !new_item) return NULL;
new_item->setNumColumns(mColumns.size());
// Add any columns we don't already have
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 907dc90bea..d2d2379328 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -148,6 +148,7 @@ public:
// "columns" => [ "column" => column name, "value" => value, "type" => type, "font" => font, "font-style" => style ], "id" => uuid
// Creates missing columns automatically.
virtual LLScrollListItem* addElement(const LLSD& element, EAddPosition pos = ADD_BOTTOM, void* userdata = NULL);
+ virtual LLScrollListItem* addRow(LLScrollListItem *new_item, const LLScrollListItem::Params& value, EAddPosition pos = ADD_BOTTOM);
virtual LLScrollListItem* addRow(const LLScrollListItem::Params& value, EAddPosition pos = ADD_BOTTOM);
// Simple add element. Takes a single array of:
// [ "value" => value, "font" => font, "font-style" => style ]
diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h
index 15b86cc945..25ce846d90 100644
--- a/indra/llui/llscrolllistitem.h
+++ b/indra/llui/llscrolllistitem.h
@@ -95,7 +95,7 @@ public:
void setUserdata( void* userdata ) { mUserdata = userdata; }
void* getUserdata() const { return mUserdata; }
- LLUUID getUUID() const { return mItemValue.asUUID(); }
+ virtual LLUUID getUUID() const { return mItemValue.asUUID(); }
LLSD getValue() const { return mItemValue; }
void setRect(LLRect rect) { mRectangle = rect; }
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index 20a1ab7af3..28f3788817 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -270,13 +270,19 @@ void LLSpinCtrl::clear()
mbHasBeenSet = FALSE;
}
-
+void LLSpinCtrl::updateLabelColor()
+{
+ if( mLabelBox )
+ {
+ mLabelBox->setColor( getEnabled() ? mTextEnabledColor.get() : mTextDisabledColor.get() );
+ }
+}
void LLSpinCtrl::updateEditor()
{
LLLocale locale(LLLocale::USER_LOCALE);
- // Don't display very small negative values as -0.000
+ // Don't display very small negative valu es as -0.000
F32 displayed_value = clamp_precision((F32)getValue().asReal(), mPrecision);
// if( S32( displayed_value * pow( 10, mPrecision ) ) == 0 )
@@ -339,10 +345,7 @@ void LLSpinCtrl::setEnabled(BOOL b)
{
LLView::setEnabled( b );
mEditor->setEnabled( b );
- if( mLabelBox )
- {
- mLabelBox->setColor( b ? mTextEnabledColor.get() : mTextDisabledColor.get() );
- }
+ updateLabelColor();
}
@@ -390,6 +393,7 @@ void LLSpinCtrl::setLabel(const LLStringExplicit& label)
{
llwarns << "Attempting to set label on LLSpinCtrl constructed without one " << getName() << llendl;
}
+ updateLabelColor();
}
void LLSpinCtrl::setAllowEdit(BOOL allow_edit)
diff --git a/indra/llui/llspinctrl.h b/indra/llui/llspinctrl.h
index 0e610b7741..00d6f86f83 100644
--- a/indra/llui/llspinctrl.h
+++ b/indra/llui/llspinctrl.h
@@ -81,8 +81,8 @@ public:
virtual void setPrecision(S32 precision);
void setLabel(const LLStringExplicit& label);
- void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; }
- void setDisabledLabelColor(const LLColor4& c) { mTextDisabledColor = c; }
+ void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; updateLabelColor(); }
+ void setDisabledLabelColor(const LLColor4& c) { mTextDisabledColor = c; updateLabelColor();}
void setAllowEdit(BOOL allow_edit);
virtual void onTabInto();
@@ -103,6 +103,7 @@ public:
void onDownBtn(const LLSD& data);
private:
+ void updateLabelColor();
void updateEditor();
void reportInvalidData();
diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp
index 71511f69a4..b8f93b6a0e 100644
--- a/indra/llui/llstyle.cpp
+++ b/indra/llui/llstyle.cpp
@@ -49,7 +49,10 @@ LLStyle::Params::Params()
LLStyle::LLStyle(const LLStyle::Params& p)
-: mVisible(p.visible),
+: mItalic(FALSE),
+ mBold(FALSE),
+ mUnderline(FALSE),
+ mVisible(p.visible),
mColor(p.color()),
mReadOnlyColor(p.readonly_color()),
mFont(p.font()),
diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h
index ee9ca730e9..2067e8e8be 100644
--- a/indra/llui/llstyle.h
+++ b/indra/llui/llstyle.h
@@ -59,11 +59,12 @@ public:
void setColor(const LLColor4 &color) { mColor = color; }
const LLColor4& getReadOnlyColor() const { return mReadOnlyColor; }
+ void setReadOnlyColor(const LLColor4& color) { mReadOnlyColor = color; }
BOOL isVisible() const;
void setVisible(BOOL is_visible);
- LLFontGL::ShadowType getShadowType() { return mDropShadow; }
+ LLFontGL::ShadowType getShadowType() const { return mDropShadow; }
void setFont(const LLFontGL* font);
const LLFontGL* getFont() const;
@@ -116,5 +117,6 @@ private:
};
typedef LLPointer<LLStyle> LLStyleSP;
+typedef LLPointer<const LLStyle> LLStyleConstSP;
#endif // LL_LLSTYLE_H
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index 43c44f2253..6be76605fd 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -1373,6 +1373,8 @@ BOOL LLTabContainer::setTab(S32 which)
{
LLTabTuple* tuple = *iter;
BOOL is_selected = ( tuple == selected_tuple );
+ tuple->mButton->setUseEllipses(TRUE);
+ tuple->mButton->setHAlign(LLFontGL::LEFT);
tuple->mTabPanel->setVisible( is_selected );
// tuple->mTabPanel->setFocus(is_selected); // not clear that we want to do this here.
tuple->mButton->setToggleState( is_selected );
@@ -1478,63 +1480,54 @@ void LLTabContainer::setTabPanelFlashing(LLPanel* child, BOOL state )
void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const LLColor4& color)
{
- static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
LLTabTuple* tuple = getTabByPanel(child);
if( tuple )
{
- tuple->mButton->setImageOverlay(image_name, LLFontGL::RIGHT, color);
-
- if (!mIsVertical)
- {
- // remove current width from total tab strip width
- mTotalTabWidth -= tuple->mButton->getRect().getWidth();
-
- S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
- tuple->mButton->getImageOverlay()->getImage()->getWidth(0) :
- 0;
-
- tuple->mPadding = image_overlay_width;
-
- tuple->mButton->setRightHPad(6);
- tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
- tuple->mButton->getRect().getHeight());
- // add back in button width to total tab strip width
- mTotalTabWidth += tuple->mButton->getRect().getWidth();
-
- // tabs have changed size, might need to scroll to see current tab
- updateMaxScrollPos();
- }
+ tuple->mButton->setImageOverlay(image_name, LLFontGL::LEFT, color);
+ reshape_tuple(tuple);
}
}
void LLTabContainer::setTabImage(LLPanel* child, const LLUUID& image_id, const LLColor4& color)
{
- static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
LLTabTuple* tuple = getTabByPanel(child);
if( tuple )
{
- tuple->mButton->setImageOverlay(image_id, LLFontGL::RIGHT, color);
+ tuple->mButton->setImageOverlay(image_id, LLFontGL::LEFT, color);
+ reshape_tuple(tuple);
+ }
+}
- if (!mIsVertical)
- {
- // remove current width from total tab strip width
- mTotalTabWidth -= tuple->mButton->getRect().getWidth();
+void LLTabContainer::reshape_tuple(LLTabTuple* tuple)
+{
+ static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
+ static LLUICachedControl<S32> image_left_padding ("UIButtonImageLeftPadding", 4);
+ static LLUICachedControl<S32> image_right_padding ("UIButtonImageRightPadding", 4);
+ static LLUICachedControl<S32> image_top_padding ("UIButtonImageTopPadding", 2);
+ static LLUICachedControl<S32> image_bottom_padding ("UIButtonImageBottomPadding", 2);
- S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
- tuple->mButton->getImageOverlay()->getImage()->getWidth(0) :
- 0;
+ if (!mIsVertical)
+ {
+ tuple->mButton->setImageOverlayLeftPad(image_left_padding);
+ tuple->mButton->setImageOverlayRightPad(image_right_padding);
+ tuple->mButton->setImageOverlayTopPad(image_top_padding);
+ tuple->mButton->setImageOverlayBottomPad(image_bottom_padding);
- tuple->mPadding = image_overlay_width;
+ // remove current width from total tab strip width
+ mTotalTabWidth -= tuple->mButton->getRect().getWidth();
- tuple->mButton->setRightHPad(6);
- tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
- tuple->mButton->getRect().getHeight());
- // add back in button width to total tab strip width
- mTotalTabWidth += tuple->mButton->getRect().getWidth();
+ S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
+ tuple->mButton->getImageOverlay()->getImage()->getWidth(0) : 0;
- // tabs have changed size, might need to scroll to see current tab
- updateMaxScrollPos();
- }
+ tuple->mPadding = image_overlay_width;
+
+ tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
+ tuple->mButton->getRect().getHeight());
+ // add back in button width to total tab strip width
+ mTotalTabWidth += tuple->mButton->getRect().getWidth();
+
+ // tabs have changed size, might need to scroll to see current tab
+ updateMaxScrollPos();
}
}
@@ -1597,7 +1590,10 @@ void LLTabContainer::onTabBtn( const LLSD& data, LLPanel* panel )
LLTabTuple* tuple = getTabByPanel(panel);
selectTabPanel( panel );
- tuple->mTabPanel->setFocus(TRUE);
+ if (tuple)
+ {
+ tuple->mTabPanel->setFocus(TRUE);
+ }
}
void LLTabContainer::onNextBtn( const LLSD& data )
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index 33c49e0d6f..2a55877d3c 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -228,6 +228,7 @@ private:
// updates tab button images given the tuple, tab position and the corresponding params
void update_images(LLTabTuple* tuple, TabParams params, LLTabContainer::TabPosition pos);
+ void reshape_tuple(LLTabTuple* tuple);
// Variables
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 790240ab48..2b1e2b8226 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -185,7 +185,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mWriteableBgColor(p.bg_writeable_color),
mReadOnlyBgColor(p.bg_readonly_color),
mFocusBgColor(p.bg_focus_color),
- mReflowNeeded(FALSE),
+ mReflowIndex(S32_MAX),
mCursorPos( 0 ),
mScrollNeeded(FALSE),
mDesiredXPixel(-1),
@@ -244,7 +244,8 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
LLTextBase::~LLTextBase()
{
- delete mPopupMenu;
+ // Menu, like any other LLUICtrl, is deleted by its parent - gMenuHolder
+
clearSegments();
}
@@ -291,9 +292,13 @@ bool LLTextBase::truncate()
return did_truncate;
}
-LLStyle::Params LLTextBase::getDefaultStyle()
+LLStyle::Params LLTextBase::getDefaultStyleParams()
{
- return LLStyle::Params().color(mFgColor.get()).readonly_color(mReadOnlyFgColor.get()).font(mDefaultFont).drop_shadow(mFontShadow);
+ return LLStyle::Params()
+ .color(LLUIColor(&mFgColor))
+ .readonly_color(LLUIColor(&mReadOnlyFgColor))
+ .font(mDefaultFont)
+ .drop_shadow(mFontShadow);
}
void LLTextBase::onValueChange(S32 start, S32 end)
@@ -307,7 +312,6 @@ void LLTextBase::drawSelectionBackground()
// Draw selection even if we don't have keyboard focus for search/replace
if( hasSelection() && !mLineInfoList.empty())
{
- LLWString text = getWText();
std::vector<LLRect> selection_rects;
S32 selection_left = llmin( mSelectionStart, mSelectionEnd );
@@ -406,7 +410,7 @@ void LLTextBase::drawCursor()
&& gFocusMgr.getAppHasFocus()
&& !mReadOnly)
{
- LLWString wtext = getWText();
+ const LLWString &wtext = getWText();
const llwchar* text = wtext.c_str();
LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos);
@@ -492,7 +496,6 @@ void LLTextBase::drawCursor()
void LLTextBase::drawText()
{
- LLWString text = getWText();
const S32 text_len = getLength();
if( text_len <= 0 )
{
@@ -619,7 +622,8 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
else
{
// create default editable segment to hold new text
- default_segment = new LLNormalTextSegment( new LLStyle(getDefaultStyle()), pos, pos + insert_len, *this);
+ LLStyleConstSP sp(new LLStyle(getDefaultStyleParams()));
+ default_segment = new LLNormalTextSegment( sp, pos, pos + insert_len, *this);
}
// shift remaining segments to right
@@ -656,7 +660,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s
}
onValueChange(pos, pos + insert_len);
- needsReflow();
+ needsReflow(pos);
return insert_len;
}
@@ -716,7 +720,7 @@ S32 LLTextBase::removeStringNoUndo(S32 pos, S32 length)
createDefaultSegment();
onValueChange(pos, pos);
- needsReflow();
+ needsReflow(pos);
return -length; // This will be wrong if someone calls removeStringNoUndo with an excessive length
}
@@ -732,7 +736,7 @@ S32 LLTextBase::overwriteCharNoUndo(S32 pos, llwchar wc)
getViewModel()->setDisplay(text);
onValueChange(pos, pos + 1);
- needsReflow();
+ needsReflow(pos);
return 1;
}
@@ -743,7 +747,8 @@ void LLTextBase::createDefaultSegment()
// ensures that there is always at least one segment
if (mSegments.empty())
{
- LLTextSegmentPtr default_segment = new LLNormalTextSegment( new LLStyle(getDefaultStyle()), 0, getLength() + 1, *this);
+ LLStyleConstSP sp(new LLStyle(getDefaultStyleParams()));
+ LLTextSegmentPtr default_segment = new LLNormalTextSegment( sp, 0, getLength() + 1, *this);
mSegments.insert(default_segment);
default_segment->linkToDocument(this);
}
@@ -757,15 +762,18 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert)
}
segment_set_t::iterator cur_seg_iter = getSegIterContaining(segment_to_insert->getStart());
+ S32 reflow_start_index = 0;
if (cur_seg_iter == mSegments.end())
{
mSegments.insert(segment_to_insert);
segment_to_insert->linkToDocument(this);
+ reflow_start_index = segment_to_insert->getStart();
}
else
{
LLTextSegmentPtr cur_segmentp = *cur_seg_iter;
+ reflow_start_index = cur_segmentp->getStart();
if (cur_segmentp->getStart() < segment_to_insert->getStart())
{
S32 old_segment_end = cur_segmentp->getEnd();
@@ -773,7 +781,8 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert)
cur_segmentp->setEnd(segment_to_insert->getStart());
// advance to next segment
// insert remainder of old segment
- LLTextSegmentPtr remainder_segment = new LLNormalTextSegment( cur_segmentp->getStyle(), segment_to_insert->getStart(), old_segment_end, *this);
+ LLStyleConstSP sp = cur_segmentp->getStyle();
+ LLTextSegmentPtr remainder_segment = new LLNormalTextSegment( sp, segment_to_insert->getStart(), old_segment_end, *this);
mSegments.insert(cur_seg_iter, remainder_segment);
remainder_segment->linkToDocument(this);
// insert new segment before remainder of old segment
@@ -823,7 +832,7 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert)
}
// layout potentially changed
- needsReflow();
+ needsReflow(reflow_start_index);
}
BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)
@@ -1018,6 +1027,16 @@ void LLTextBase::setReadOnlyColor(const LLColor4 &c)
}
//virtual
+void LLTextBase::handleVisibilityChange( BOOL new_visibility )
+{
+ if(!new_visibility && mPopupMenu)
+ {
+ mPopupMenu->hide();
+ }
+ LLUICtrl::handleVisibilityChange(new_visibility);
+}
+
+//virtual
void LLTextBase::setValue(const LLSD& value )
{
setText(value.asString());
@@ -1068,15 +1087,16 @@ S32 LLTextBase::getLeftOffset(S32 width)
static LLFastTimer::DeclareTimer FTM_TEXT_REFLOW ("Text Reflow");
-void LLTextBase::reflow(S32 start_index)
+void LLTextBase::reflow()
{
LLFastTimer ft(FTM_TEXT_REFLOW);
updateSegments();
- while(mReflowNeeded)
+ while(mReflowIndex < S32_MAX)
{
- mReflowNeeded = false;
+ S32 start_index = mReflowIndex;
+ mReflowIndex = S32_MAX;
// shrink document to minimum size (visible portion of text widget)
// to force inlined widgets with follows set to shrink
@@ -1108,7 +1128,6 @@ void LLTextBase::reflow(S32 start_index)
S32 line_start_index = 0;
const S32 text_available_width = mVisibleTextRect.getWidth() - mHPad; // reserve room for margin
S32 remaining_pixels = text_available_width;
- LLWString text(getWText());
S32 line_count = 0;
// find and erase line info structs starting at start_index and going to end of document
@@ -1510,16 +1529,7 @@ std::string LLTextBase::getText() const
void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params)
{
LLStyle::Params style_params(input_params);
- style_params.fillFrom(getDefaultStyle());
-
- if (!style_params.font.isProvided())
- {
- style_params.font = mDefaultFont;
- }
- if (!style_params.drop_shadow.isProvided())
- {
- style_params.drop_shadow = mFontShadow;
- }
+ style_params.fillFrom(getDefaultStyleParams());
S32 part = (S32)LLTextParser::WHOLE;
if(mParseHTML)
@@ -1536,13 +1546,7 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c
LLStyle::Params link_params = style_params;
link_params.color = match.getColor();
link_params.readonly_color = match.getColor();
- // apply font name from requested style_params
- std::string font_name = LLFontGL::nameFromFont(style_params.font());
- std::string font_size = LLFontGL::sizeFromFont(style_params.font());
- link_params.font.name(font_name);
- link_params.font.size(font_size);
link_params.font.style("UNDERLINE");
-
link_params.link_href = match.getUrl();
// output the text before the Url
@@ -1575,20 +1579,28 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c
prepend_newline = false;
}
}
- // output the styled Url
- appendAndHighlightText(match.getLabel(), prepend_newline, part, link_params);
- prepend_newline = false;
- // set the tooltip for the Url label
- if (! match.getTooltip().empty())
+ // output the styled Url (unless we've been asked to suppress hyperlinking)
+ if (match.isLinkDisabled())
{
- segment_set_t::iterator it = getSegIterContaining(getLength()-1);
- if (it != mSegments.end())
+ appendAndHighlightText(match.getLabel(), prepend_newline, part, style_params);
+ }
+ else
+ {
+ appendAndHighlightText(match.getLabel(), prepend_newline, part, link_params);
+
+ // set the tooltip for the Url label
+ if (! match.getTooltip().empty())
{
- LLTextSegmentPtr segment = *it;
- segment->setToolTip(match.getTooltip());
+ segment_set_t::iterator it = getSegIterContaining(getLength()-1);
+ if (it != mSegments.end())
+ {
+ LLTextSegmentPtr segment = *it;
+ segment->setToolTip(match.getTooltip());
+ }
}
}
+ prepend_newline = false;
// move on to the rest of the text after the Url
if (end < (S32)text.length())
@@ -1611,9 +1623,15 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c
}
}
-void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepend_newline, S32 highlight_part, const LLStyle::Params& stylep)
+void LLTextBase::needsReflow(S32 index)
{
- if (new_text.empty()) return;
+ lldebugs << "reflow on object " << (void*)this << " index = " << mReflowIndex << ", new index = " << index << llendl;
+ mReflowIndex = llmin(mReflowIndex, index);
+}
+
+void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepend_newline, S32 highlight_part, const LLStyle::Params& style_params)
+{
+ if (new_text.empty()) return;
// Save old state
S32 selection_start = mSelectionStart;
@@ -1631,7 +1649,7 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen
if (mParseHighlights && highlight)
{
- LLStyle::Params highlight_params = stylep;
+ LLStyle::Params highlight_params(style_params);
LLSD pieces = highlight->parsePartialLineHighlights(new_text, highlight_params.color(), (LLTextParser::EHighlightPosition)highlight_part);
for (S32 i = 0; i < pieces.size(); i++)
@@ -1651,7 +1669,8 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen
wide_text = utf8str_to_wstring(pieces[i]["text"].asString());
}
S32 cur_length = getLength();
- LLTextSegmentPtr segmentp = new LLNormalTextSegment(new LLStyle(highlight_params), cur_length, cur_length + wide_text.size(), *this);
+ LLStyleConstSP sp(new LLStyle(highlight_params));
+ LLTextSegmentPtr segmentp = new LLNormalTextSegment(sp, cur_length, cur_length + wide_text.size(), *this);
segment_vec_t segments;
segments.push_back(segmentp);
insertStringNoUndo(cur_length, wide_text, &segments);
@@ -1675,7 +1694,8 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen
segment_vec_t segments;
S32 segment_start = old_length;
S32 segment_end = old_length + wide_text.size();
- segments.push_back(new LLNormalTextSegment(new LLStyle(stylep), segment_start, segment_end, *this ));
+ LLStyleConstSP sp(new LLStyle(style_params));
+ segments.push_back(new LLNormalTextSegment(sp, segment_start, segment_end, *this ));
insertStringNoUndo(getLength(), wide_text, &segments);
}
@@ -1719,7 +1739,7 @@ void LLTextBase::replaceUrlLabel(const std::string &url,
for (it = mSegments.begin(); it != mSegments.end(); ++it)
{
LLTextSegment *seg = *it;
- const LLStyleSP style = seg->getStyle();
+ LLStyleConstSP style = seg->getStyle();
// update segment start/end length in case we replaced text earlier
S32 seg_length = seg->getEnd() - seg->getStart();
@@ -1756,7 +1776,7 @@ void LLTextBase::setWText(const LLWString& text)
setText(wstring_to_utf8str(text));
}
-LLWString LLTextBase::getWText() const
+const LLWString& LLTextBase::getWText() const
{
return getViewModel()->getDisplay();
}
@@ -2212,9 +2232,9 @@ bool LLTextSegment::canEdit() const { return false; }
void LLTextSegment::unlinkFromDocument(LLTextBase*) {}
void LLTextSegment::linkToDocument(LLTextBase*) {}
const LLColor4& LLTextSegment::getColor() const { return LLColor4::white; }
-void LLTextSegment::setColor(const LLColor4 &color) {}
-const LLStyleSP LLTextSegment::getStyle() const {static LLStyleSP sp(new LLStyle()); return sp; }
-void LLTextSegment::setStyle(const LLStyleSP &style) {}
+//void LLTextSegment::setColor(const LLColor4 &color) {}
+LLStyleConstSP LLTextSegment::getStyle() const {static LLStyleConstSP sp(new LLStyle()); return sp; }
+void LLTextSegment::setStyle(LLStyleConstSP style) {}
void LLTextSegment::setToken( LLKeywordToken* token ) {}
LLKeywordToken* LLTextSegment::getToken() const { return NULL; }
void LLTextSegment::setToolTip( const std::string &msg ) {}
@@ -2239,7 +2259,7 @@ BOOL LLTextSegment::hasMouseCapture() { return FALSE; }
// LLNormalTextSegment
//
-LLNormalTextSegment::LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 end, LLTextBase& editor )
+LLNormalTextSegment::LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor )
: LLTextSegment(start, end),
mStyle( style ),
mToken(NULL),
@@ -2250,7 +2270,7 @@ LLNormalTextSegment::LLNormalTextSegment( const LLStyleSP& style, S32 start, S32
LLUIImagePtr image = mStyle->getImage();
if (image.notNull())
{
- mImageLoadedConnection = image->addLoadedCallback(boost::bind(&LLTextBase::needsReflow, &mEditor));
+ mImageLoadedConnection = image->addLoadedCallback(boost::bind(&LLTextBase::needsReflow, &mEditor, start));
}
}
@@ -2313,8 +2333,6 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
LLColor4 color = (mEditor.getReadOnly() ? mStyle->getReadOnlyColor() : mStyle->getColor()) % alpha;
- font = mStyle->getFont();
-
if( selection_start > seg_start )
{
// Draw normally
@@ -2451,7 +2469,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
if (num_chars > 0)
{
height = mFontHeight;
- LLWString text = mEditor.getWText();
+ const LLWString &text = mEditor.getWText();
// if last character is a newline, then return true, forcing line break
llwchar last_char = text[mStart + first_char + num_chars - 1];
if (last_char == '\n')
@@ -2478,7 +2496,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const
{
- LLWString text = mEditor.getWText();
+ const LLWString &text = mEditor.getWText();
return mStyle->getFont()->charFromPixelOffset(text.c_str(), mStart + start_offset,
(F32)segment_local_x_coord,
F32_MAX,
@@ -2488,7 +2506,7 @@ S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset,
S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
{
- LLWString text = mEditor.getWText();
+ const LLWString &text = mEditor.getWText();
LLUIImagePtr image = mStyle->getImage();
if( image.notNull())
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 038b9eaa62..3dda6f4cc8 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -41,6 +41,7 @@
#include "llpanel.h"
#include <string>
+#include <vector>
#include <set>
#include <boost/signals2.hpp>
@@ -121,6 +122,7 @@ public:
/*virtual*/ BOOL acceptsTextInput() const { return !mReadOnly; }
/*virtual*/ void setColor( const LLColor4& c );
virtual void setReadOnlyColor(const LLColor4 &c);
+ virtual void handleVisibilityChange( BOOL new_visibility );
/*virtual*/ void setValue(const LLSD& value );
/*virtual*/ LLTextViewModel* getViewModel() const;
@@ -144,11 +146,11 @@ public:
// wide-char versions
void setWText(const LLWString& text);
- LLWString getWText() const;
+ const LLWString& getWText() const;
void appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params = LLStyle::Params());
// force reflow of text
- void needsReflow() { mReflowNeeded = TRUE; }
+ void needsReflow(S32 index = 0);
S32 getLength() const { return getWText().length(); }
S32 getLineCount() const { return mLineInfoList.size(); }
@@ -184,7 +186,6 @@ public:
bool scrolledToEnd();
const LLFontGL* getDefaultFont() const { return mDefaultFont; }
- LLStyle::Params getDefaultStyle();
public:
// Fired when a URL link is clicked
@@ -281,7 +282,8 @@ protected:
void createDefaultSegment();
virtual void updateSegments();
void insertSegment(LLTextSegmentPtr segment_to_insert);
-
+ LLStyle::Params getDefaultStyleParams();
+
// manage lines
S32 getLineStart( S32 line ) const;
S32 getLineEnd( S32 line ) const;
@@ -290,7 +292,7 @@ protected:
S32 getFirstVisibleLine() const;
std::pair<S32, S32> getVisibleLines(bool fully_visible = false);
S32 getLeftOffset(S32 width);
- void reflow(S32 start_index = 0);
+ void reflow();
// cursor
void updateCursorXPos();
@@ -360,7 +362,7 @@ protected:
class LLScrollContainer* mScroller;
// transient state
- bool mReflowNeeded; // need to reflow text because of change to text contents or display region
+ S32 mReflowIndex; // index at which to start reflow. S32_MAX indicates no reflow needed.
bool mScrollNeeded; // need to change scroll region because of change to cursor position
S32 mScrollIndex; // index of first character to keep visible in scroll region
@@ -388,9 +390,9 @@ public:
virtual void linkToDocument(class LLTextBase* editor);
virtual const LLColor4& getColor() const;
- virtual void setColor(const LLColor4 &color);
- virtual const LLStyleSP getStyle() const;
- virtual void setStyle(const LLStyleSP &style);
+ //virtual void setColor(const LLColor4 &color);
+ virtual LLStyleConstSP getStyle() const;
+ virtual void setStyle(LLStyleConstSP style);
virtual void setToken( LLKeywordToken* token );
virtual LLKeywordToken* getToken() const;
virtual void setToolTip(const std::string& tooltip);
@@ -426,7 +428,7 @@ protected:
class LLNormalTextSegment : public LLTextSegment
{
public:
- LLNormalTextSegment( const LLStyleSP& style, S32 start, S32 end, LLTextBase& editor );
+ LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 end, LLTextBase& editor );
LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible = TRUE);
~LLNormalTextSegment();
@@ -436,9 +438,8 @@ public:
/*virtual*/ F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
/*virtual*/ bool canEdit() const { return true; }
/*virtual*/ const LLColor4& getColor() const { return mStyle->getColor(); }
- /*virtual*/ void setColor(const LLColor4 &color) { mStyle->setColor(color); }
- /*virtual*/ const LLStyleSP getStyle() const { return mStyle; }
- /*virtual*/ void setStyle(const LLStyleSP &style) { mStyle = style; }
+ /*virtual*/ LLStyleConstSP getStyle() const { return mStyle; }
+ /*virtual*/ void setStyle(LLStyleConstSP style) { mStyle = style; }
/*virtual*/ void setToken( LLKeywordToken* token ) { mToken = token; }
/*virtual*/ LLKeywordToken* getToken() const { return mToken; }
/*virtual*/ BOOL getToolTip( std::string& msg ) const;
@@ -456,7 +457,7 @@ protected:
protected:
class LLTextBase& mEditor;
- LLStyleSP mStyle;
+ LLStyleConstSP mStyle;
S32 mFontHeight;
LLKeywordToken* mToken;
std::string mTooltip;
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index f2c3879a6c..62aeb50011 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -1285,8 +1285,6 @@ void LLTextEditor::cut()
gClipboard.copyFromSubstring( getWText(), left_pos, length, mSourceID );
deleteSelection( FALSE );
- needsReflow();
-
onKeyStroke();
}
@@ -1391,8 +1389,6 @@ void LLTextEditor::pasteHelper(bool is_primary)
setCursorPos(mCursorPos + insert(mCursorPos, clean_string, FALSE, LLTextSegmentPtr()));
deselect();
- needsReflow();
-
onKeyStroke();
}
@@ -1787,8 +1783,6 @@ BOOL LLTextEditor::handleKeyHere(KEY key, MASK mask )
if(text_may_have_changed)
{
- needsReflow();
-
onKeyStroke();
}
needsScroll();
@@ -1831,8 +1825,6 @@ BOOL LLTextEditor::handleUnicodeCharHere(llwchar uni_char)
// Most keystrokes will make the selection box go away, but not all will.
deselect();
- needsReflow();
-
onKeyStroke();
}
@@ -1891,8 +1883,6 @@ void LLTextEditor::doDelete()
}
onKeyStroke();
-
- needsReflow();
}
//----------------------------------------------------------------------------
@@ -1935,8 +1925,6 @@ void LLTextEditor::undo()
setCursorPos(pos);
- needsReflow();
-
onKeyStroke();
}
@@ -1979,8 +1967,6 @@ void LLTextEditor::redo()
setCursorPos(pos);
- needsReflow();
-
onKeyStroke();
}
@@ -2040,6 +2026,20 @@ void LLTextEditor::showContextMenu(S32 x, S32 y)
LLMenuHolderGL::child_registry_t::instance());
}
+ // Route menu to this class
+ // previously this was done in ::handleRightMoseDown:
+ //if(hasTabStop())
+ // setFocus(TRUE) - why? weird...
+ // and then inside setFocus
+ // ....
+ // gEditMenuHandler = this;
+ // ....
+ // but this didn't work in all cases and just weird...
+ //why not here?
+ // (all this was done for EXT-4443)
+
+ gEditMenuHandler = this;
+
S32 screen_x, screen_y;
localPointToScreen(x, y, &screen_x, &screen_y);
mContextMenu->show(screen_x, screen_y);
@@ -2325,8 +2325,6 @@ void LLTextEditor::insertText(const std::string &new_text)
setCursorPos(mCursorPos + insert( mCursorPos, utf8str_to_wstring(new_text), FALSE, LLTextSegmentPtr() ));
- needsReflow();
-
setEnabled( enabled );
}
@@ -2349,8 +2347,6 @@ void LLTextEditor::appendWidget(const LLInlineViewSegment::Params& params, const
LLTextSegmentPtr segment = new LLInlineViewSegment(params, old_length, old_length + widget_wide_text.size());
insert(getLength(), widget_wide_text, FALSE, segment);
- needsReflow();
-
// Set the cursor and scroll position
if( selection_start != selection_end )
{
@@ -2375,52 +2371,6 @@ void LLTextEditor::appendWidget(const LLInlineViewSegment::Params& params, const
}
}
-
-void LLTextEditor::replaceUrlLabel(const std::string &url,
- const std::string &label)
-{
- // get the full (wide) text for the editor so we can change it
- LLWString text = getWText();
- LLWString wlabel = utf8str_to_wstring(label);
- bool modified = false;
- S32 seg_start = 0;
-
- // iterate through each segment looking for ones styled as links
- segment_set_t::iterator it;
- for (it = mSegments.begin(); it != mSegments.end(); ++it)
- {
- LLTextSegment *seg = *it;
- const LLStyleSP style = seg->getStyle();
-
- // update segment start/end length in case we replaced text earlier
- S32 seg_length = seg->getEnd() - seg->getStart();
- seg->setStart(seg_start);
- seg->setEnd(seg_start + seg_length);
-
- // if we find a link with our Url, then replace the label
- if (style->isLink() && style->getLinkHREF() == url)
- {
- S32 start = seg->getStart();
- S32 end = seg->getEnd();
- text = text.substr(0, start) + wlabel + text.substr(end, text.size() - end + 1);
- seg->setEnd(start + wlabel.size());
- modified = true;
- }
-
- // work out the character offset for the next segment
- seg_start = seg->getEnd();
- }
-
- // update the editor with the new (wide) text string
- if (modified)
- {
- getViewModel()->setDisplay(text);
- deselect();
- setCursorPos(mCursorPos);
- needsReflow();
- }
-}
-
void LLTextEditor::removeTextFromEnd(S32 num_chars)
{
if (num_chars <= 0) return;
@@ -2432,7 +2382,6 @@ void LLTextEditor::removeTextFromEnd(S32 num_chars)
mSelectionStart = llclamp(mSelectionStart, 0, len);
mSelectionEnd = llclamp(mSelectionEnd, 0, len);
- needsReflow();
needsScroll();
}
@@ -2491,8 +2440,6 @@ BOOL LLTextEditor::tryToRevertToPristineState()
i--;
}
}
-
- needsReflow();
}
return isPristine(); // TRUE => success
@@ -2559,13 +2506,16 @@ void LLTextEditor::updateLinkSegments()
// if the link's label (what the user can edit) is a valid Url,
// then update the link's HREF to be the same as the label text.
// This lets users edit Urls in-place.
- LLStyleSP style = static_cast<LLStyleSP>(segment->getStyle());
+ LLStyleConstSP style = segment->getStyle();
+ LLStyleSP new_style(new LLStyle(*style));
LLWString url_label = wtext.substr(segment->getStart(), segment->getEnd()-segment->getStart());
if (LLUrlRegistry::instance().hasUrl(url_label))
{
std::string new_url = wstring_to_utf8str(url_label);
LLStringUtil::trim(new_url);
- style->setLinkHREF(new_url);
+ new_style->setLinkHREF(new_url);
+ LLStyleConstSP sp(new_style);
+ segment->setStyle(sp);
}
}
}
@@ -2664,7 +2614,6 @@ BOOL LLTextEditor::importBuffer(const char* buffer, S32 length )
startOfDoc();
deselect();
- needsReflow();
return success;
}
@@ -2768,7 +2717,6 @@ void LLTextEditor::updatePreedit(const LLWString &preedit_string,
mPreeditStandouts = preedit_standouts;
- needsReflow();
setCursorPos(insert_preedit_at + caret_position);
// Update of the preedit should be caused by some key strokes.
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index 043dda8fa6..a136f9ccce 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -149,7 +149,6 @@ public:
void selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE);
BOOL replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE);
void replaceTextAll(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive);
- void replaceUrlLabel(const std::string &url, const std::string &label);
// Undo/redo stack
void blockUndo();
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index 01c7a81309..173fde8e76 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -400,7 +400,8 @@ bool LLToolTip::hasClickCallback()
//
LLToolTipMgr::LLToolTipMgr()
-: mToolTip(NULL),
+: mToolTipsBlocked(false),
+ mToolTip(NULL),
mNeedsToolTip(false)
{}
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index d0ed3b6fca..76f07373b4 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -1911,10 +1911,10 @@ namespace LLInitParam
void TypedParam<LLUIColor>::setBlockFromValue()
{
LLColor4 color = mData.mValue.get();
- red = color.mV[VRED];
- green = color.mV[VGREEN];
- blue = color.mV[VBLUE];
- alpha = color.mV[VALPHA];
+ red.set(color.mV[VRED], false);
+ green.set(color.mV[VGREEN], false);
+ blue.set(color.mV[VBLUE], false);
+ alpha.set(color.mV[VALPHA], false);
control.set("", false);
}
@@ -1965,9 +1965,9 @@ namespace LLInitParam
{
if (mData.mValue)
{
- name = LLFontGL::nameFromFont(mData.mValue);
- size = LLFontGL::sizeFromFont(mData.mValue);
- style = LLFontGL::getStringFromStyle(mData.mValue->getFontDesc().getStyle());
+ name.set(LLFontGL::nameFromFont(mData.mValue), false);
+ size.set(LLFontGL::sizeFromFont(mData.mValue), false);
+ style.set(LLFontGL::getStringFromStyle(mData.mValue->getFontDesc().getStyle()), false);
}
}
@@ -2073,8 +2073,8 @@ namespace LLInitParam
void TypedParam<LLCoordGL>::setBlockFromValue()
{
- x = mData.mValue.mX;
- y = mData.mValue.mY;
+ x.set(mData.mValue.mX, false);
+ y.set(mData.mValue.mY, false);
}
diff --git a/indra/llui/lluicolortable.h b/indra/llui/lluicolortable.h
index 59be0c4f9a..c87695f456 100644
--- a/indra/llui/lluicolortable.h
+++ b/indra/llui/lluicolortable.h
@@ -94,7 +94,7 @@ private:
bool loadFromFilename(const std::string& filename);
// consider using sorted vector, can be much faster
- typedef std::map<std::string, LLColor4> string_color_map_t;
+ typedef std::map<std::string, LLUIColor> string_color_map_t;
void clearTable(string_color_map_t& table);
void setColor(const std::string& name, const LLColor4& color, string_color_map_t& table);
diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp
index 966d919dc7..8cd6460b66 100644
--- a/indra/llui/lluiimage.cpp
+++ b/indra/llui/lluiimage.cpp
@@ -182,11 +182,11 @@ namespace LLInitParam
{
if (mData.mValue == NULL)
{
- name = "none";
+ name.set("none", false);
}
else
{
- name = mData.mValue->getName();
+ name.set(mData.mValue->getName(), false);
}
}
diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h
index 7ec0fd603a..32cfc0d9cd 100644
--- a/indra/llui/lluistring.h
+++ b/indra/llui/lluistring.h
@@ -64,7 +64,7 @@ class LLUIString
public:
// These methods all perform appropriate argument substitution
// and modify mOrig where appropriate
- LLUIString() {}
+ LLUIString() : mNeedsResult(false), mNeedsWResult(false) {}
LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args);
LLUIString(const std::string& instring) { assign(instring); }
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 7a62ca5098..0bbf1fe084 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -39,8 +39,9 @@
#include "lltrans.h"
#include "lluicolortable.h"
-LLUrlEntryBase::LLUrlEntryBase()
-: mColor(LLUIColorTable::instance().getColor("HTMLLinkColor"))
+LLUrlEntryBase::LLUrlEntryBase() :
+ mColor(LLUIColorTable::instance().getColor("HTMLLinkColor")),
+ mDisabledLink(false)
{
}
@@ -48,7 +49,7 @@ LLUrlEntryBase::~LLUrlEntryBase()
{
}
-std::string LLUrlEntryBase::getUrl(const std::string &string)
+std::string LLUrlEntryBase::getUrl(const std::string &string) const
{
return escapeUrl(string);
}
@@ -88,7 +89,7 @@ std::string LLUrlEntryBase::escapeUrl(const std::string &url) const
return LLURI::escape(url, no_escape_chars, true);
}
-std::string LLUrlEntryBase::getLabelFromWikiLink(const std::string &url)
+std::string LLUrlEntryBase::getLabelFromWikiLink(const std::string &url) const
{
// return the label part from [http://www.example.org Label]
const char *text = url.c_str();
@@ -104,7 +105,7 @@ std::string LLUrlEntryBase::getLabelFromWikiLink(const std::string &url)
return unescapeUrl(url.substr(start, url.size()-start-1));
}
-std::string LLUrlEntryBase::getUrlFromWikiLink(const std::string &string)
+std::string LLUrlEntryBase::getUrlFromWikiLink(const std::string &string) const
{
// return the url part from [http://www.example.org Label]
const char *text = string.c_str();
@@ -191,7 +192,7 @@ std::string LLUrlEntryHTTPLabel::getLabel(const std::string &url, const LLUrlLab
return getLabelFromWikiLink(url);
}
-std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string)
+std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string) const
{
return getUrlFromWikiLink(string);
}
@@ -204,7 +205,7 @@ LLUrlEntryHTTPNoProtocol::LLUrlEntryHTTPNoProtocol()
mPattern = boost::regex("("
"\\bwww\\.\\S+\\.\\S+" // i.e. www.FOO.BAR
"|" // or
- "(?<!@)\\b[^[:space:]:@/]+\\.(?:com|net|edu|org)([/:]\\S*)?\\b" // i.e. FOO.net
+ "(?<!@)\\b[^[:space:]:@/>]+\\.(?:com|net|edu|org)([/:][^[:space:]<]*)?\\b" // i.e. FOO.net
")",
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_http.xml";
@@ -216,7 +217,7 @@ std::string LLUrlEntryHTTPNoProtocol::getLabel(const std::string &url, const LLU
return unescapeUrl(url);
}
-std::string LLUrlEntryHTTPNoProtocol::getUrl(const std::string &string)
+std::string LLUrlEntryHTTPNoProtocol::getUrl(const std::string &string) const
{
if (string.find("://") == std::string::npos)
{
@@ -231,7 +232,7 @@ std::string LLUrlEntryHTTPNoProtocol::getUrl(const std::string &string)
LLUrlEntrySLURL::LLUrlEntrySLURL()
{
// see http://slurl.com/about.php for details on the SLURL format
- mPattern = boost::regex("http://slurl.com/secondlife/\\S+/?(\\d+)?/?(\\d+)?/?(\\d+)?/?\\S*",
+ mPattern = boost::regex("http://(maps.secondlife.com|slurl.com)/secondlife/\\S+/?(\\d+)?/?(\\d+)?/?(\\d+)?/?\\S*",
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_slurl.xml";
mTooltip = LLTrans::getString("TooltipSLURL");
@@ -665,7 +666,7 @@ std::string LLUrlEntrySLLabel::getLabel(const std::string &url, const LLUrlLabel
return getLabelFromWikiLink(url);
}
-std::string LLUrlEntrySLLabel::getUrl(const std::string &string)
+std::string LLUrlEntrySLLabel::getUrl(const std::string &string) const
{
return getUrlFromWikiLink(string);
}
@@ -710,3 +711,24 @@ std::string LLUrlEntryWorldMap::getLocation(const std::string &url) const
// return the part of the Url after secondlife:///app/worldmap/ part
return ::getStringAfterToken(url, "app/worldmap/");
}
+
+//
+// LLUrlEntryNoLink lets us turn of URL detection with <nolink>...</nolink> tags
+//
+LLUrlEntryNoLink::LLUrlEntryNoLink()
+{
+ mPattern = boost::regex("<nolink>[^<]*</nolink>",
+ boost::regex::perl|boost::regex::icase);
+ mDisabledLink = true;
+}
+
+std::string LLUrlEntryNoLink::getUrl(const std::string &url) const
+{
+ // return the text between the <nolink> and </nolink> tags
+ return url.substr(8, url.size()-8-9);
+}
+
+std::string LLUrlEntryNoLink::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
+{
+ return getUrl(url);
+}
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index 4fc2eb5e05..e6844b595c 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -71,7 +71,7 @@ public:
boost::regex getPattern() const { return mPattern; }
/// Return the url from a string that matched the regex
- virtual std::string getUrl(const std::string &string);
+ virtual std::string getUrl(const std::string &string) const;
/// Given a matched Url, return a label for the Url
virtual std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) { return url; }
@@ -91,12 +91,15 @@ public:
/// Return the name of a SL location described by this Url, if any
virtual std::string getLocation(const std::string &url) const { return ""; }
+ /// is this a match for a URL that should not be hyperlinked?
+ bool isLinkDisabled() const { return mDisabledLink; }
+
protected:
std::string getIDStringFromUrl(const std::string &url) const;
std::string escapeUrl(const std::string &url) const;
std::string unescapeUrl(const std::string &url) const;
- std::string getLabelFromWikiLink(const std::string &url);
- std::string getUrlFromWikiLink(const std::string &string);
+ std::string getLabelFromWikiLink(const std::string &url) const;
+ std::string getUrlFromWikiLink(const std::string &string) const;
void addObserver(const std::string &id, const std::string &url, const LLUrlLabelCallback &cb);
void callObservers(const std::string &id, const std::string &label);
@@ -111,6 +114,7 @@ protected:
std::string mTooltip;
LLUIColor mColor;
std::multimap<std::string, LLUrlEntryObserver> mObservers;
+ bool mDisabledLink;
};
///
@@ -131,7 +135,7 @@ class LLUrlEntryHTTPLabel : public LLUrlEntryBase
public:
LLUrlEntryHTTPLabel();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
- /*virtual*/ std::string getUrl(const std::string &string);
+ /*virtual*/ std::string getUrl(const std::string &string) const;
};
///
@@ -142,7 +146,7 @@ class LLUrlEntryHTTPNoProtocol : public LLUrlEntryBase
public:
LLUrlEntryHTTPNoProtocol();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
- /*virtual*/ std::string getUrl(const std::string &string);
+ /*virtual*/ std::string getUrl(const std::string &string) const;
};
///
@@ -249,7 +253,7 @@ class LLUrlEntrySLLabel : public LLUrlEntryBase
public:
LLUrlEntrySLLabel();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
- /*virtual*/ std::string getUrl(const std::string &string);
+ /*virtual*/ std::string getUrl(const std::string &string) const;
};
///
@@ -264,4 +268,15 @@ public:
/*virtual*/ std::string getLocation(const std::string &url) const;
};
+///
+/// LLUrlEntryNoLink lets us turn of URL detection with <nolink>...</nolink> tags
+///
+class LLUrlEntryNoLink : public LLUrlEntryBase
+{
+public:
+ LLUrlEntryNoLink();
+ /*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/llurlmatch.cpp b/indra/llui/llurlmatch.cpp
index 3b47145a22..72a199c220 100644
--- a/indra/llui/llurlmatch.cpp
+++ b/indra/llui/llurlmatch.cpp
@@ -41,14 +41,17 @@ LLUrlMatch::LLUrlMatch() :
mLabel(""),
mTooltip(""),
mIcon(""),
- mMenuName("")
+ mMenuName(""),
+ mLocation(""),
+ mDisabledLink(false)
{
}
void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
const std::string &label, const std::string &tooltip,
const std::string &icon, const LLUIColor& color,
- const std::string &menu, const std::string &location)
+ const std::string &menu, const std::string &location,
+ bool disabled_link)
{
mStart = start;
mEnd = end;
@@ -59,4 +62,5 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
mColor = color;
mMenuName = menu;
mLocation = location;
+ mDisabledLink = disabled_link;
}
diff --git a/indra/llui/llurlmatch.h b/indra/llui/llurlmatch.h
index 7f5767923a..e86762548b 100644
--- a/indra/llui/llurlmatch.h
+++ b/indra/llui/llurlmatch.h
@@ -83,11 +83,14 @@ public:
/// return the SL location that this Url describes, or "" if none.
std::string getLocation() const { return mLocation; }
+ /// is this a match for a URL that should not be hyperlinked?
+ bool isLinkDisabled() const { return mDisabledLink; }
+
/// Change the contents of this match object (used by LLUrlRegistry)
void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
const std::string &tooltip, const std::string &icon,
const LLUIColor& color, const std::string &menu,
- const std::string &location);
+ const std::string &location, bool disabled_link);
private:
U32 mStart;
@@ -99,6 +102,7 @@ private:
std::string mMenuName;
std::string mLocation;
LLUIColor mColor;
+ bool mDisabledLink;
};
#endif
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 419d2322f9..5db1f46b8d 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -46,6 +46,7 @@ LLUrlRegistry::LLUrlRegistry()
mUrlEntry.reserve(16);
// Urls are matched in the order that they were registered
+ registerUrl(new LLUrlEntryNoLink());
registerUrl(new LLUrlEntrySLURL());
registerUrl(new LLUrlEntryHTTP());
registerUrl(new LLUrlEntryHTTPLabel());
@@ -136,7 +137,8 @@ static bool stringHasUrl(const std::string &text)
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(".org") != std::string::npos ||
+ text.find("<nolink>") != std::string::npos);
}
bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LLUrlLabelCallback &cb)
@@ -181,7 +183,8 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
match_entry->getIcon(),
match_entry->getColor(),
match_entry->getMenuName(),
- match_entry->getLocation(url));
+ match_entry->getLocation(url),
+ match_entry->isLinkDisabled());
return true;
}
@@ -209,9 +212,13 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr
S32 end = start + wurl.size() - 1;
match.setValues(start, end, match.getUrl(),
- match.getLabel(), match.getTooltip(),
- match.getIcon(), match.getColor(),
- match.getMenuName(), match.getLocation());
+ match.getLabel(),
+ match.getTooltip(),
+ match.getIcon(),
+ match.getColor(),
+ match.getMenuName(),
+ match.getLocation(),
+ match.isLinkDisabled());
return true;
}
return false;
diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h
index c8a9b52cca..992365d44d 100644
--- a/indra/llui/llviewmodel.h
+++ b/indra/llui/llviewmodel.h
@@ -107,7 +107,8 @@ public:
// New functions
/// Get the stored value in string form
- LLWString getDisplay() const { return mDisplay; }
+ const LLWString& getDisplay() const { return mDisplay; }
+
/**
* Set the display string directly (see LLTextEditor). What the user is
* editing is actually the LLWString value rather than the underlying
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 30b59859d3..bcb1e65092 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -33,7 +33,7 @@ LLUIColor LLUIColorTable::getColor(const std::string& name, const LLColor4& defa
return LLUIColor();
}
-LLUIColor::LLUIColor() {}
+LLUIColor::LLUIColor() : mColorPtr(NULL) {}
namespace tut
{
@@ -52,9 +52,10 @@ namespace
namespace tut
{
- void testRegex(const std::string &testname, boost::regex regex,
+ void testRegex(const std::string &testname, LLUrlEntryBase &entry,
const char *text, const std::string &expected)
{
+ boost::regex regex = entry.getPattern();
std::string url = "";
boost::cmatch result;
bool found = boost::regex_search(text, result, regex);
@@ -62,7 +63,7 @@ namespace tut
{
S32 start = static_cast<U32>(result[0].first - text);
S32 end = static_cast<U32>(result[0].second - text);
- url = std::string(text+start, end-start);
+ url = entry.getUrl(std::string(text+start, end-start));
}
ensure_equals(testname, url, expected);
}
@@ -74,74 +75,73 @@ namespace tut
// test LLUrlEntryHTTP - standard http Urls
//
LLUrlEntryHTTP url;
- boost::regex r = url.getPattern();
- testRegex("no valid url", r,
+ testRegex("no valid url", url,
"htp://slurl.com/",
"");
- testRegex("simple http (1)", r,
+ testRegex("simple http (1)", url,
"http://slurl.com/",
"http://slurl.com/");
- testRegex("simple http (2)", r,
+ testRegex("simple http (2)", url,
"http://slurl.com",
"http://slurl.com");
- testRegex("simple http (3)", r,
+ testRegex("simple http (3)", url,
"http://slurl.com/about.php",
"http://slurl.com/about.php");
- testRegex("simple https", r,
+ testRegex("simple https", url,
"https://slurl.com/about.php",
"https://slurl.com/about.php");
- testRegex("http in text (1)", r,
+ testRegex("http in text (1)", url,
"XX http://slurl.com/ XX",
"http://slurl.com/");
- testRegex("http in text (2)", r,
+ testRegex("http in text (2)", url,
"XX http://slurl.com/about.php XX",
"http://slurl.com/about.php");
- testRegex("https in text", r,
+ testRegex("https in text", url,
"XX https://slurl.com/about.php XX",
"https://slurl.com/about.php");
- testRegex("two http urls", r,
+ testRegex("two http urls", url,
"XX http://slurl.com/about.php http://secondlife.com/ XX",
"http://slurl.com/about.php");
- testRegex("http url with port and username", r,
+ testRegex("http url with port and username", url,
"XX http://nobody@slurl.com:80/about.php http://secondlife.com/ XX",
"http://nobody@slurl.com:80/about.php");
- testRegex("http url with port, username, and query string", r,
+ testRegex("http url with port, username, and query string", url,
"XX http://nobody@slurl.com:80/about.php?title=hi%20there http://secondlife.com/ XX",
"http://nobody@slurl.com:80/about.php?title=hi%20there");
// note: terminating commas will be removed by LLUrlRegistry:findUrl()
- testRegex("http url with commas in middle and terminating", r,
+ testRegex("http url with commas in middle and terminating", url,
"XX http://slurl.com/?title=Hi,There, XX",
"http://slurl.com/?title=Hi,There,");
// note: terminating periods will be removed by LLUrlRegistry:findUrl()
- testRegex("http url with periods in middle and terminating", r,
+ testRegex("http url with periods in middle and terminating", url,
"XX http://slurl.com/index.php. XX",
"http://slurl.com/index.php.");
// DEV-19842: Closing parenthesis ")" breaks urls
- testRegex("http url with brackets (1)", r,
+ testRegex("http url with brackets (1)", url,
"XX http://en.wikipedia.org/wiki/JIRA_(software) XX",
"http://en.wikipedia.org/wiki/JIRA_(software)");
// DEV-19842: Closing parenthesis ")" breaks urls
- testRegex("http url with brackets (2)", r,
+ testRegex("http url with brackets (2)", url,
"XX http://jira.secondlife.com/secure/attachment/17990/eggy+avs+in+1.21.0+(93713)+public+nightly.jpg XX",
"http://jira.secondlife.com/secure/attachment/17990/eggy+avs+in+1.21.0+(93713)+public+nightly.jpg");
// DEV-10353: URLs in chat log terminated incorrectly when newline in chat
- testRegex("http url with newlines", r,
+ testRegex("http url with newlines", url,
"XX\nhttp://www.secondlife.com/\nXX",
"http://www.secondlife.com/");
}
@@ -153,39 +153,38 @@ namespace tut
// test LLUrlEntryHTTPLabel - wiki-style http Urls with labels
//
LLUrlEntryHTTPLabel url;
- boost::regex r = url.getPattern();
- testRegex("invalid wiki url [1]", r,
+ testRegex("invalid wiki url [1]", url,
"[http://www.example.org]",
"");
- testRegex("invalid wiki url [2]", r,
+ testRegex("invalid wiki url [2]", url,
"[http://www.example.org",
"");
- testRegex("invalid wiki url [3]", r,
+ testRegex("invalid wiki url [3]", url,
"[http://www.example.org Label",
"");
- testRegex("example.org with label (spaces)", r,
+ testRegex("example.org with label (spaces)", url,
"[http://www.example.org Text]",
- "[http://www.example.org Text]");
+ "http://www.example.org");
- testRegex("example.org with label (tabs)", r,
+ testRegex("example.org with label (tabs)", url,
"[http://www.example.org\t Text]",
- "[http://www.example.org\t Text]");
+ "http://www.example.org");
- testRegex("SL http URL with label", r,
+ testRegex("SL http URL with label", url,
"[http://www.secondlife.com/ Second Life]",
- "[http://www.secondlife.com/ Second Life]");
+ "http://www.secondlife.com/");
- testRegex("SL https URL with label", r,
+ testRegex("SL https URL with label", url,
"XXX [https://www.secondlife.com/ Second Life] YYY",
- "[https://www.secondlife.com/ Second Life]");
+ "https://www.secondlife.com/");
- testRegex("SL http URL with label", r,
+ testRegex("SL http URL with label", url,
"[http://www.secondlife.com/?test=Hi%20There Second Life]",
- "[http://www.secondlife.com/?test=Hi%20There Second Life]");
+ "http://www.secondlife.com/?test=Hi%20There");
}
template<> template<>
@@ -195,69 +194,68 @@ namespace tut
// test LLUrlEntrySLURL - second life URLs
//
LLUrlEntrySLURL url;
- boost::regex r = url.getPattern();
- testRegex("no valid slurl [1]", r,
+ testRegex("no valid slurl [1]", url,
"htp://slurl.com/secondlife/Ahern/50/50/50/",
"");
- testRegex("no valid slurl [2]", r,
+ testRegex("no valid slurl [2]", url,
"http://slurl.com/secondlife/",
"");
- testRegex("no valid slurl [3]", r,
+ testRegex("no valid slurl [3]", url,
"hhtp://slurl.com/secondlife/Ahern/50/FOO/50/",
"");
- testRegex("Ahern (50,50,50) [1]", r,
+ testRegex("Ahern (50,50,50) [1]", url,
"http://slurl.com/secondlife/Ahern/50/50/50/",
"http://slurl.com/secondlife/Ahern/50/50/50/");
- testRegex("Ahern (50,50,50) [2]", r,
+ testRegex("Ahern (50,50,50) [2]", url,
"XXX http://slurl.com/secondlife/Ahern/50/50/50/ XXX",
"http://slurl.com/secondlife/Ahern/50/50/50/");
- testRegex("Ahern (50,50,50) [3]", r,
+ testRegex("Ahern (50,50,50) [3]", url,
"XXX http://slurl.com/secondlife/Ahern/50/50/50 XXX",
"http://slurl.com/secondlife/Ahern/50/50/50");
- testRegex("Ahern (50,50,50) multicase", r,
+ testRegex("Ahern (50,50,50) multicase", url,
"XXX http://SLUrl.com/SecondLife/Ahern/50/50/50/ XXX",
"http://SLUrl.com/SecondLife/Ahern/50/50/50/");
- testRegex("Ahern (50,50) [1]", r,
+ testRegex("Ahern (50,50) [1]", url,
"XXX http://slurl.com/secondlife/Ahern/50/50/ XXX",
"http://slurl.com/secondlife/Ahern/50/50/");
- testRegex("Ahern (50,50) [2]", r,
+ testRegex("Ahern (50,50) [2]", url,
"XXX http://slurl.com/secondlife/Ahern/50/50 XXX",
"http://slurl.com/secondlife/Ahern/50/50");
- testRegex("Ahern (50)", r,
+ testRegex("Ahern (50)", url,
"XXX http://slurl.com/secondlife/Ahern/50 XXX",
"http://slurl.com/secondlife/Ahern/50");
- testRegex("Ahern", r,
+ testRegex("Ahern", url,
"XXX http://slurl.com/secondlife/Ahern/ XXX",
"http://slurl.com/secondlife/Ahern/");
- testRegex("Ahern SLURL with title", r,
+ testRegex("Ahern SLURL with title", url,
"XXX http://slurl.com/secondlife/Ahern/50/50/50/?title=YOUR%20TITLE%20HERE! XXX",
"http://slurl.com/secondlife/Ahern/50/50/50/?title=YOUR%20TITLE%20HERE!");
- testRegex("Ahern SLURL with msg", r,
+ testRegex("Ahern SLURL with msg", url,
"XXX http://slurl.com/secondlife/Ahern/50/50/50/?msg=Your%20text%20here. XXX",
"http://slurl.com/secondlife/Ahern/50/50/50/?msg=Your%20text%20here.");
// DEV-21577: In-world SLURLs containing "(" or ")" are not treated as a hyperlink in chat
- testRegex("SLURL with brackets", r,
+ testRegex("SLURL with brackets", url,
"XXX http://slurl.com/secondlife/Burning%20Life%20(Hyper)/27/210/30 XXX",
"http://slurl.com/secondlife/Burning%20Life%20(Hyper)/27/210/30");
// DEV-35459: SLURLs and teleport Links not parsed properly
- testRegex("SLURL with quote", r,
+ testRegex("SLURL with quote", url,
"XXX http://slurl.com/secondlife/A'ksha%20Oasis/41/166/701 XXX",
- "http://slurl.com/secondlife/A'ksha%20Oasis/41/166/701");
+ "http://slurl.com/secondlife/A%27ksha%20Oasis/41/166/701");
}
template<> template<>
@@ -267,25 +265,24 @@ namespace tut
// test LLUrlEntryAgent - secondlife://app/agent Urls
//
LLUrlEntryAgent url;
- boost::regex r = url.getPattern();
- testRegex("Invalid Agent Url", r,
+ testRegex("Invalid Agent Url", url,
"secondlife:///app/agent/0e346d8b-4433-4d66-XXXX-fd37083abc4c/about",
"");
- testRegex("Agent Url ", r,
+ testRegex("Agent Url ", url,
"secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about",
"secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about");
- testRegex("Agent Url in text", r,
+ testRegex("Agent Url in text", url,
"XXX secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about XXX",
"secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about");
- testRegex("Agent Url multicase", r,
+ testRegex("Agent Url multicase", url,
"XXX secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/About XXX",
"secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/About");
- testRegex("Agent Url alternate command", r,
+ testRegex("Agent Url alternate command", url,
"XXX secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/foobar",
"secondlife:///App/AGENT/0E346D8B-4433-4d66-a6b0-fd37083abc4c/foobar");
}
@@ -297,25 +294,24 @@ namespace tut
// test LLUrlEntryGroup - secondlife://app/group Urls
//
LLUrlEntryGroup url;
- boost::regex r = url.getPattern();
- testRegex("Invalid Group Url", r,
+ testRegex("Invalid Group Url", url,
"secondlife:///app/group/00005ff3-4044-c79f-XXXX-fb28ae0df991/about",
"");
- testRegex("Group Url ", r,
+ testRegex("Group Url ", url,
"secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about",
"secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about");
- testRegex("Group Url ", r,
+ testRegex("Group Url ", url,
"secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/inspect",
"secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/inspect");
- testRegex("Group Url in text", r,
+ testRegex("Group Url in text", url,
"XXX secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about XXX",
"secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about");
- testRegex("Group Url multicase", r,
+ testRegex("Group Url multicase", url,
"XXX secondlife:///APP/Group/00005FF3-4044-c79f-9de8-fb28ae0df991/About XXX",
"secondlife:///APP/Group/00005FF3-4044-c79f-9de8-fb28ae0df991/About");
}
@@ -327,45 +323,44 @@ namespace tut
// test LLUrlEntryPlace - secondlife://<location> URLs
//
LLUrlEntryPlace url;
- boost::regex r = url.getPattern();
- testRegex("no valid slurl [1]", r,
+ testRegex("no valid slurl [1]", url,
"secondlife://Ahern/FOO/50/",
"");
- testRegex("Ahern (50,50,50) [1]", r,
+ testRegex("Ahern (50,50,50) [1]", url,
"secondlife://Ahern/50/50/50/",
"secondlife://Ahern/50/50/50/");
- testRegex("Ahern (50,50,50) [2]", r,
+ testRegex("Ahern (50,50,50) [2]", url,
"XXX secondlife://Ahern/50/50/50/ XXX",
"secondlife://Ahern/50/50/50/");
- testRegex("Ahern (50,50,50) [3]", r,
+ testRegex("Ahern (50,50,50) [3]", url,
"XXX secondlife://Ahern/50/50/50 XXX",
"secondlife://Ahern/50/50/50");
- testRegex("Ahern (50,50,50) multicase", r,
+ testRegex("Ahern (50,50,50) multicase", url,
"XXX SecondLife://Ahern/50/50/50/ XXX",
"SecondLife://Ahern/50/50/50/");
- testRegex("Ahern (50,50) [1]", r,
+ testRegex("Ahern (50,50) [1]", url,
"XXX secondlife://Ahern/50/50/ XXX",
"secondlife://Ahern/50/50/");
- testRegex("Ahern (50,50) [2]", r,
+ testRegex("Ahern (50,50) [2]", url,
"XXX secondlife://Ahern/50/50 XXX",
"secondlife://Ahern/50/50");
// DEV-21577: In-world SLURLs containing "(" or ")" are not treated as a hyperlink in chat
- testRegex("SLURL with brackets", r,
+ testRegex("SLURL with brackets", url,
"XXX secondlife://Burning%20Life%20(Hyper)/27/210/30 XXX",
"secondlife://Burning%20Life%20(Hyper)/27/210/30");
// DEV-35459: SLURLs and teleport Links not parsed properly
- testRegex("SLURL with quote", r,
+ testRegex("SLURL with quote", url,
"XXX secondlife://A'ksha%20Oasis/41/166/701 XXX",
- "secondlife://A'ksha%20Oasis/41/166/701");
+ "secondlife://A%27ksha%20Oasis/41/166/701");
}
template<> template<>
@@ -375,21 +370,20 @@ namespace tut
// test LLUrlEntryParcel - secondlife://app/parcel Urls
//
LLUrlEntryParcel url;
- boost::regex r = url.getPattern();
- testRegex("Invalid Classified Url", r,
+ testRegex("Invalid Classified Url", url,
"secondlife:///app/parcel/0000060e-4b39-e00b-XXXX-d98b1934e3a8/about",
"");
- testRegex("Classified Url ", r,
+ testRegex("Classified Url ", url,
"secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about",
"secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about");
- testRegex("Classified Url in text", r,
+ testRegex("Classified Url in text", url,
"XXX secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about XXX",
"secondlife:///app/parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/about");
- testRegex("Classified Url multicase", r,
+ testRegex("Classified Url multicase", url,
"XXX secondlife:///APP/Parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/About XXX",
"secondlife:///APP/Parcel/0000060e-4b39-e00b-d0c3-d98b1934e3a8/About");
}
@@ -400,73 +394,72 @@ namespace tut
// test LLUrlEntryTeleport - secondlife://app/teleport URLs
//
LLUrlEntryTeleport url;
- boost::regex r = url.getPattern();
- testRegex("no valid teleport [1]", r,
+ testRegex("no valid teleport [1]", url,
"http://slurl.com/secondlife/Ahern/50/50/50/",
"");
- testRegex("no valid teleport [2]", r,
+ testRegex("no valid teleport [2]", url,
"secondlife:///app/teleport/",
"");
- testRegex("no valid teleport [3]", r,
+ testRegex("no valid teleport [3]", url,
"second-life:///app/teleport/Ahern/50/50/50/",
"");
- testRegex("no valid teleport [3]", r,
+ testRegex("no valid teleport [3]", url,
"hhtp://slurl.com/secondlife/Ahern/50/FOO/50/",
"");
- testRegex("Ahern (50,50,50) [1]", r,
+ testRegex("Ahern (50,50,50) [1]", url,
"secondlife:///app/teleport/Ahern/50/50/50/",
"secondlife:///app/teleport/Ahern/50/50/50/");
- testRegex("Ahern (50,50,50) [2]", r,
+ testRegex("Ahern (50,50,50) [2]", url,
"XXX secondlife:///app/teleport/Ahern/50/50/50/ XXX",
"secondlife:///app/teleport/Ahern/50/50/50/");
- testRegex("Ahern (50,50,50) [3]", r,
+ testRegex("Ahern (50,50,50) [3]", url,
"XXX secondlife:///app/teleport/Ahern/50/50/50 XXX",
"secondlife:///app/teleport/Ahern/50/50/50");
- testRegex("Ahern (50,50,50) multicase", r,
+ testRegex("Ahern (50,50,50) multicase", url,
"XXX secondlife:///app/teleport/Ahern/50/50/50/ XXX",
"secondlife:///app/teleport/Ahern/50/50/50/");
- testRegex("Ahern (50,50) [1]", r,
+ testRegex("Ahern (50,50) [1]", url,
"XXX secondlife:///app/teleport/Ahern/50/50/ XXX",
"secondlife:///app/teleport/Ahern/50/50/");
- testRegex("Ahern (50,50) [2]", r,
+ testRegex("Ahern (50,50) [2]", url,
"XXX secondlife:///app/teleport/Ahern/50/50 XXX",
"secondlife:///app/teleport/Ahern/50/50");
- testRegex("Ahern (50)", r,
+ testRegex("Ahern (50)", url,
"XXX secondlife:///app/teleport/Ahern/50 XXX",
"secondlife:///app/teleport/Ahern/50");
- testRegex("Ahern", r,
+ testRegex("Ahern", url,
"XXX secondlife:///app/teleport/Ahern/ XXX",
"secondlife:///app/teleport/Ahern/");
- testRegex("Ahern teleport with title", r,
+ testRegex("Ahern teleport with title", url,
"XXX secondlife:///app/teleport/Ahern/50/50/50/?title=YOUR%20TITLE%20HERE! XXX",
"secondlife:///app/teleport/Ahern/50/50/50/?title=YOUR%20TITLE%20HERE!");
- testRegex("Ahern teleport with msg", r,
+ testRegex("Ahern teleport with msg", url,
"XXX secondlife:///app/teleport/Ahern/50/50/50/?msg=Your%20text%20here. XXX",
"secondlife:///app/teleport/Ahern/50/50/50/?msg=Your%20text%20here.");
// DEV-21577: In-world SLURLs containing "(" or ")" are not treated as a hyperlink in chat
- testRegex("Teleport with brackets", r,
+ testRegex("Teleport with brackets", url,
"XXX secondlife:///app/teleport/Burning%20Life%20(Hyper)/27/210/30 XXX",
"secondlife:///app/teleport/Burning%20Life%20(Hyper)/27/210/30");
// DEV-35459: SLURLs and teleport Links not parsed properly
- testRegex("Teleport url with quote", r,
+ testRegex("Teleport url with quote", url,
"XXX secondlife:///app/teleport/A'ksha%20Oasis/41/166/701 XXX",
- "secondlife:///app/teleport/A'ksha%20Oasis/41/166/701");
+ "secondlife:///app/teleport/A%27ksha%20Oasis/41/166/701");
}
template<> template<>
@@ -476,33 +469,32 @@ namespace tut
// test LLUrlEntrySL - general secondlife:// URLs
//
LLUrlEntrySL url;
- boost::regex r = url.getPattern();
- testRegex("no valid slapp [1]", r,
+ testRegex("no valid slapp [1]", url,
"http:///app/",
"");
- testRegex("valid slapp [1]", r,
+ testRegex("valid slapp [1]", url,
"secondlife:///app/",
"secondlife:///app/");
- testRegex("valid slapp [2]", r,
+ testRegex("valid slapp [2]", url,
"secondlife:///app/teleport/Ahern/50/50/50/",
"secondlife:///app/teleport/Ahern/50/50/50/");
- testRegex("valid slapp [3]", r,
+ testRegex("valid slapp [3]", url,
"secondlife:///app/foo",
"secondlife:///app/foo");
- testRegex("valid slapp [4]", r,
+ testRegex("valid slapp [4]", url,
"secondlife:///APP/foo?title=Hi%20There",
"secondlife:///APP/foo?title=Hi%20There");
- testRegex("valid slapp [5]", r,
+ testRegex("valid slapp [5]", url,
"secondlife://host/app/",
"secondlife://host/app/");
- testRegex("valid slapp [6]", r,
+ testRegex("valid slapp [6]", url,
"secondlife://host:8080/foo/bar",
"secondlife://host:8080/foo/bar");
}
@@ -514,35 +506,34 @@ namespace tut
// test LLUrlEntrySLLabel - general secondlife:// URLs with labels
//
LLUrlEntrySLLabel url;
- boost::regex r = url.getPattern();
- testRegex("invalid wiki url [1]", r,
+ testRegex("invalid wiki url [1]", url,
"[secondlife:///app/]",
"");
- testRegex("invalid wiki url [2]", r,
+ testRegex("invalid wiki url [2]", url,
"[secondlife:///app/",
"");
- testRegex("invalid wiki url [3]", r,
+ testRegex("invalid wiki url [3]", url,
"[secondlife:///app/ Label",
"");
- testRegex("agent slurl with label (spaces)", r,
+ testRegex("agent slurl with label (spaces)", url,
"[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about Text]",
- "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about Text]");
+ "secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about");
- testRegex("agent slurl with label (tabs)", r,
+ testRegex("agent slurl with label (tabs)", url,
"[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about\t Text]",
- "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about\t Text]");
+ "secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about");
- testRegex("agent slurl with label", r,
+ testRegex("agent slurl with label", url,
"[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about FirstName LastName]",
- "[secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about FirstName LastName]");
+ "secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about");
- testRegex("teleport slurl with label", r,
+ testRegex("teleport slurl with label", url,
"XXX [secondlife:///app/teleport/Ahern/50/50/50/ Teleport to Ahern] YYY",
- "[secondlife:///app/teleport/Ahern/50/50/50/ Teleport to Ahern]");
+ "secondlife:///app/teleport/Ahern/50/50/50/");
}
template<> template<>
@@ -552,62 +543,98 @@ namespace tut
// test LLUrlEntryHTTPNoProtocol - general URLs without a protocol
//
LLUrlEntryHTTPNoProtocol url;
- boost::regex r = url.getPattern();
- testRegex("naked .com URL", r,
+ testRegex("naked .com URL", url,
"see google.com",
- "google.com");
+ "http://google.com");
- testRegex("naked .org URL", r,
+ testRegex("naked .org URL", url,
"see en.wikipedia.org for details",
- "en.wikipedia.org");
+ "http://en.wikipedia.org");
- testRegex("naked .net URL", r,
+ testRegex("naked .net URL", url,
"example.net",
- "example.net");
+ "http://example.net");
- testRegex("naked .edu URL (2 instances)", r,
+ testRegex("naked .edu URL (2 instances)", url,
"MIT web site is at web.mit.edu and also www.mit.edu",
- "web.mit.edu");
+ "http://web.mit.edu");
- testRegex("don't match e-mail addresses", r,
+ testRegex("don't match e-mail addresses", url,
"test@lindenlab.com",
"");
- testRegex(".com URL with path", r,
+ testRegex(".com URL with path", url,
"see secondlife.com/status for grid status",
- "secondlife.com/status");
+ "http://secondlife.com/status");
- testRegex(".com URL with port", r,
+ testRegex(".com URL with port", url,
"secondlife.com:80",
- "secondlife.com:80");
+ "http://secondlife.com:80");
- testRegex(".com URL with port and path", r,
+ testRegex(".com URL with port and path", url,
"see secondlife.com:80/status",
- "secondlife.com:80/status");
+ "http://secondlife.com:80/status");
- testRegex("www.*.com URL with port and path", r,
+ testRegex("www.*.com URL with port and path", url,
"see www.secondlife.com:80/status",
- "www.secondlife.com:80/status");
+ "http://www.secondlife.com:80/status");
- testRegex("invalid .com URL [1]", r,
+ testRegex("invalid .com URL [1]", url,
"..com",
"");
- testRegex("invalid .com URL [2]", r,
+ testRegex("invalid .com URL [2]", url,
"you.come",
"");
- testRegex("invalid .com URL [3]", r,
+ testRegex("invalid .com URL [3]", url,
"recommended",
"");
- testRegex("invalid .edu URL", r,
+ testRegex("invalid .edu URL", url,
"hi there scheduled maitenance has begun",
"");
- testRegex("invalid .net URL", r,
+ testRegex("invalid .net URL", url,
"foo.netty",
"");
+
+ testRegex("XML tags around URL [1]", url,
+ "<foo>secondlife.com</foo>",
+ "http://secondlife.com");
+
+ testRegex("XML tags around URL [2]", url,
+ "<foo>secondlife.com/status?bar=1</foo>",
+ "http://secondlife.com/status?bar=1");
+ }
+
+ template<> template<>
+ void object::test<12>()
+ {
+ //
+ // test LLUrlEntryNoLink - turn off hyperlinking
+ //
+ LLUrlEntryNoLink url;
+
+ testRegex("<nolink> [1]", url,
+ "<nolink>google.com</nolink>",
+ "google.com");
+
+ testRegex("<nolink> [2]", url,
+ "<nolink>google.com",
+ "");
+
+ testRegex("<nolink> [3]", url,
+ "google.com</nolink>",
+ "");
+
+ testRegex("<nolink> [4]", url,
+ "<nolink>Hello World</nolink>",
+ "Hello World");
+
+ testRegex("<nolink> [5]", url,
+ "<nolink>My Object</nolink>",
+ "My Object");
}
}
diff --git a/indra/llui/tests/llurlmatch_test.cpp b/indra/llui/tests/llurlmatch_test.cpp
index e8cf135346..24a32de268 100644
--- a/indra/llui/tests/llurlmatch_test.cpp
+++ b/indra/llui/tests/llurlmatch_test.cpp
@@ -25,6 +25,7 @@
// link seam
LLUIColor::LLUIColor()
+ : mColorPtr(NULL)
{}
namespace tut
@@ -53,7 +54,7 @@ namespace tut
LLUrlMatch match;
ensure("empty()", match.empty());
- match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLUIColor(), "", "");
+ match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLUIColor(), "", "", false);
ensure("! empty()", ! match.empty());
}
@@ -66,7 +67,7 @@ namespace tut
LLUrlMatch match;
ensure_equals("getStart() == 0", match.getStart(), 0);
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
ensure_equals("getStart() == 10", match.getStart(), 10);
}
@@ -79,7 +80,7 @@ namespace tut
LLUrlMatch match;
ensure_equals("getEnd() == 0", match.getEnd(), 0);
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
ensure_equals("getEnd() == 20", match.getEnd(), 20);
}
@@ -92,10 +93,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getUrl() == ''", match.getUrl(), "");
- match.setValues(10, 20, "http://slurl.com/", "", "", "", LLUIColor(), "", "");
+ match.setValues(10, 20, "http://slurl.com/", "", "", "", LLUIColor(), "", "", false);
ensure_equals("getUrl() == 'http://slurl.com/'", match.getUrl(), "http://slurl.com/");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
ensure_equals("getUrl() == '' (2)", match.getUrl(), "");
}
@@ -108,10 +109,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getLabel() == ''", match.getLabel(), "");
- match.setValues(10, 20, "", "Label", "", "", LLUIColor(), "", "");
+ match.setValues(10, 20, "", "Label", "", "", LLUIColor(), "", "", false);
ensure_equals("getLabel() == 'Label'", match.getLabel(), "Label");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
ensure_equals("getLabel() == '' (2)", match.getLabel(), "");
}
@@ -124,10 +125,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getTooltip() == ''", match.getTooltip(), "");
- match.setValues(10, 20, "", "", "Info", "", LLUIColor(), "", "");
+ match.setValues(10, 20, "", "", "Info", "", LLUIColor(), "", "", false);
ensure_equals("getTooltip() == 'Info'", match.getTooltip(), "Info");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
ensure_equals("getTooltip() == '' (2)", match.getTooltip(), "");
}
@@ -140,10 +141,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getIcon() == ''", match.getIcon(), "");
- match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "", "");
+ match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "", "", false);
ensure_equals("getIcon() == 'Icon'", match.getIcon(), "Icon");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
ensure_equals("getIcon() == '' (2)", match.getIcon(), "");
}
@@ -156,10 +157,10 @@ namespace tut
LLUrlMatch match;
ensure("getMenuName() empty", match.getMenuName().empty());
- match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "");
+ match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "", false);
ensure_equals("getMenuName() == \"xui_file.xml\"", match.getMenuName(), "xui_file.xml");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
ensure("getMenuName() empty (2)", match.getMenuName().empty());
}
@@ -172,10 +173,10 @@ namespace tut
LLUrlMatch match;
ensure("getLocation() empty", match.getLocation().empty());
- match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "Paris");
+ match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "Paris", false);
ensure_equals("getLocation() == \"Paris\"", match.getLocation(), "Paris");
- match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "");
+ match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false);
ensure("getLocation() empty (2)", match.getLocation().empty());
}
}