diff options
author | James Cook <james@lindenlab.com> | 2010-02-03 14:13:56 -0800 |
---|---|---|
committer | James Cook <james@lindenlab.com> | 2010-02-03 14:13:56 -0800 |
commit | 88350edbcbec615f3b15fc82bd5ce4005621ac6f (patch) | |
tree | c244f41159cf32f3e03c6c311e1453bbd383bad5 /indra/llui | |
parent | d489216b6ef41f0d22f3a9062ba6daacc67bc038 (diff) | |
parent | 0bee31de32cb5999e7ec06d74f55d34ce0ac052b (diff) |
merge
Diffstat (limited to 'indra/llui')
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()); } } |