From c5fc945f33e441705d8518077468184dda6b3599 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Mon, 20 May 2013 00:36:34 -0500 Subject: [PATCH] Updated LLResizeBar and LLResizeHandle to use LLView::Param based ctors. Cleaned up LLKeyWords Cleaned up LLStatBar Added per-account setting access to ui library Added LLUICachedControl Updated LLUIString --- indra/llui/llcallbackmap.h | 11 +- indra/llui/llfloater.cpp | 211 ++++++++++-------------- indra/llui/llfloater.h | 2 + indra/llui/llkeywords.cpp | 186 ++++++++++++++------- indra/llui/llkeywords.h | 59 ++++++- indra/llui/llpanel.cpp | 8 +- indra/llui/llresizebar.cpp | 74 +++++++-- indra/llui/llresizebar.h | 26 ++- indra/llui/llresizehandle.cpp | 92 ++++++++--- indra/llui/llresizehandle.h | 14 +- indra/llui/llscrolllistctrl.cpp | 13 +- indra/llui/llstatbar.cpp | 34 ++-- indra/llui/llstatbar.h | 4 +- indra/llui/lltexteditor.cpp | 16 +- indra/llui/lltexteditor.h | 10 +- indra/llui/llui.cpp | 18 ++ indra/llui/llui.h | 22 +++ indra/llui/lluistring.cpp | 89 +++++++--- indra/llui/lluistring.h | 52 +++--- indra/newview/app_settings/keywords.ini | 6 +- indra/newview/llappviewer.cpp | 1 + indra/newview/llfloaterstats.cpp | 3 - indra/newview/llpreviewscript.cpp | 4 +- indra/newview/llviewertexteditor.cpp | 2 +- 24 files changed, 628 insertions(+), 329 deletions(-) diff --git a/indra/llui/llcallbackmap.h b/indra/llui/llcallbackmap.h index eadb9c98f..2ad6d54c5 100644 --- a/indra/llui/llcallbackmap.h +++ b/indra/llui/llcallbackmap.h @@ -30,24 +30,25 @@ * $/LicenseInfo$ */ -#ifndef LL_CALLBACK_MAP_H -#define LL_CALLBACK_MAP_H +#ifndef LLCALLBACKMAP_H +#define LLCALLBACKMAP_H #include -#include "llstring.h" +#include +#include class LLCallbackMap { public: // callback definition. - typedef void* (*callback_t)(void* data); + typedef boost::function callback_t; typedef std::map map_t; typedef map_t::iterator map_iter_t; typedef map_t::const_iterator map_const_iter_t; LLCallbackMap() : mCallback(NULL), mData(NULL) { } - LLCallbackMap(callback_t callback, void* data) : mCallback(callback), mData(data) { } + LLCallbackMap(callback_t callback, void* data = NULL) : mCallback(callback), mData(data) { } callback_t mCallback; void* mData; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index dd421eb6e..348e5e383 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -314,67 +314,7 @@ void LLFloater::initFloater(const std::string& title, if( mResizable ) { - // Resize bars (sides) - const S32 RESIZE_BAR_THICKNESS = 3; - mResizeBar[LLResizeBar::LEFT] = new LLResizeBar( - std::string("resizebar_left"), - this, - LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0), - min_width, S32_MAX, LLResizeBar::LEFT ); - addChild( mResizeBar[0] ); - - mResizeBar[LLResizeBar::TOP] = new LLResizeBar( - std::string("resizebar_top"), - this, - LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS), - min_height, S32_MAX, LLResizeBar::TOP ); - addChild( mResizeBar[1] ); - - mResizeBar[LLResizeBar::RIGHT] = new LLResizeBar( - std::string("resizebar_right"), - this, - LLRect( getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0), - min_width, S32_MAX, LLResizeBar::RIGHT ); - addChild( mResizeBar[2] ); - - mResizeBar[LLResizeBar::BOTTOM] = new LLResizeBar( - std::string("resizebar_bottom"), - this, - LLRect( 0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0), - min_height, S32_MAX, LLResizeBar::BOTTOM ); - addChild( mResizeBar[3] ); - - - // Resize handles (corners) - mResizeHandle[0] = new LLResizeHandle( - std::string("Resize Handle"), - LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0), - min_width, - min_height, - LLResizeHandle::RIGHT_BOTTOM); - addChild(mResizeHandle[0]); - - mResizeHandle[1] = new LLResizeHandle( - std::string("resize"), - LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT), - min_width, - min_height, - LLResizeHandle::RIGHT_TOP ); - addChild(mResizeHandle[1]); - - mResizeHandle[2] = new LLResizeHandle( std::string("resize"), - LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ), - min_width, - min_height, - LLResizeHandle::LEFT_BOTTOM ); - addChild(mResizeHandle[2]); - - mResizeHandle[3] = new LLResizeHandle( std::string("resize"), - LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ), - min_width, - min_height, - LLResizeHandle::LEFT_TOP ); - addChild(mResizeHandle[3]); + addResizeCtrls(); } // Close button. @@ -414,6 +354,94 @@ void LLFloater::initFloater(const std::string& title, } } +void LLFloater::addResizeCtrls() +{ + // Resize bars (sides) + LLResizeBar::Params p; + p.name("resizebar_left"); + p.resizing_view(this); + p.min_size(mMinWidth); + p.side(LLResizeBar::LEFT); + mResizeBar[LLResizeBar::LEFT] = LLUICtrlFactory::create(p); + addChild( mResizeBar[LLResizeBar::LEFT] ); + + p.name("resizebar_top"); + p.min_size(mMinHeight); + p.side(LLResizeBar::TOP); + + mResizeBar[LLResizeBar::TOP] = LLUICtrlFactory::create(p); + addChild( mResizeBar[LLResizeBar::TOP] ); + + p.name("resizebar_right"); + p.min_size(mMinWidth); + p.side(LLResizeBar::RIGHT); + mResizeBar[LLResizeBar::RIGHT] = LLUICtrlFactory::create(p); + addChild( mResizeBar[LLResizeBar::RIGHT] ); + + p.name("resizebar_bottom"); + p.min_size(mMinHeight); + p.side(LLResizeBar::BOTTOM); + mResizeBar[LLResizeBar::BOTTOM] = LLUICtrlFactory::create(p); + addChild( mResizeBar[LLResizeBar::BOTTOM] ); + + // Resize handles (corners) + LLResizeHandle::Params handle_p; + // handles must not be mouse-opaque, otherwise they block hover events + // to other buttons like the close box. JC + handle_p.mouse_opaque(false); + handle_p.min_width(mMinWidth); + handle_p.min_height(mMinHeight); + handle_p.corner(LLResizeHandle::RIGHT_BOTTOM); + mResizeHandle[0] = LLUICtrlFactory::create(handle_p); + addChild(mResizeHandle[0]); + + handle_p.corner(LLResizeHandle::RIGHT_TOP); + mResizeHandle[1] = LLUICtrlFactory::create(handle_p); + addChild(mResizeHandle[1]); + + handle_p.corner(LLResizeHandle::LEFT_BOTTOM); + mResizeHandle[2] = LLUICtrlFactory::create(handle_p); + addChild(mResizeHandle[2]); + + handle_p.corner(LLResizeHandle::LEFT_TOP); + mResizeHandle[3] = LLUICtrlFactory::create(handle_p); + addChild(mResizeHandle[3]); + + layoutResizeCtrls(); +} + +void LLFloater::layoutResizeCtrls() +{ + LLRect rect; + + // Resize bars (sides) + const S32 RESIZE_BAR_THICKNESS = 3; + rect = LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0); + mResizeBar[LLResizeBar::LEFT]->setRect(rect); + + rect = LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS); + mResizeBar[LLResizeBar::TOP]->setRect(rect); + + rect = LLRect(getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0); + mResizeBar[LLResizeBar::RIGHT]->setRect(rect); + + rect = LLRect(0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0); + mResizeBar[LLResizeBar::BOTTOM]->setRect(rect); + + // Resize handles (corners) + rect = LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0); + mResizeHandle[0]->setRect(rect); + + rect = LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT); + mResizeHandle[1]->setRect(rect); + + rect = LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ); + mResizeHandle[2]->setRect(rect); + + rect = LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ); + mResizeHandle[3]->setRect(rect); +} + void LLFloater::enableResizeCtrls(bool enable, bool width, bool height) { mResizeBar[LLResizeBar::LEFT]->setVisible(enable && width); @@ -1547,66 +1575,7 @@ void LLFloater::setCanResize(BOOL can_resize) } else if (!mResizable && can_resize) { - // Resize bars (sides) - const S32 RESIZE_BAR_THICKNESS = 3; - mResizeBar[0] = new LLResizeBar( - std::string("resizebar_left"), - this, - LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0), - mMinWidth, S32_MAX, LLResizeBar::LEFT ); - addChild( mResizeBar[0] ); - - mResizeBar[1] = new LLResizeBar( - std::string("resizebar_top"), - this, - LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS), - mMinHeight, S32_MAX, LLResizeBar::TOP ); - addChild( mResizeBar[1] ); - - mResizeBar[2] = new LLResizeBar( - std::string("resizebar_right"), - this, - LLRect( getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0), - mMinWidth, S32_MAX, LLResizeBar::RIGHT ); - addChild( mResizeBar[2] ); - - mResizeBar[3] = new LLResizeBar( - std::string("resizebar_bottom"), - this, - LLRect( 0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0), - mMinHeight, S32_MAX, LLResizeBar::BOTTOM ); - addChild( mResizeBar[3] ); - - - // Resize handles (corners) - mResizeHandle[0] = new LLResizeHandle( - std::string("Resize Handle"), - LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0), - mMinWidth, - mMinHeight, - LLResizeHandle::RIGHT_BOTTOM); - addChild(mResizeHandle[0]); - - mResizeHandle[1] = new LLResizeHandle( std::string("resize"), - LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT), - mMinWidth, - mMinHeight, - LLResizeHandle::RIGHT_TOP ); - addChild(mResizeHandle[1]); - - mResizeHandle[2] = new LLResizeHandle( std::string("resize"), - LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ), - mMinWidth, - mMinHeight, - LLResizeHandle::LEFT_BOTTOM ); - addChild(mResizeHandle[2]); - - mResizeHandle[3] = new LLResizeHandle( std::string("resize"), - LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ), - mMinWidth, - mMinHeight, - LLResizeHandle::LEFT_TOP ); - addChild(mResizeHandle[3]); + addResizeCtrls(); enableResizeCtrls(can_resize); } mResizable = can_resize; diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index aadb2c811..9a9fa9d19 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -269,6 +269,8 @@ private: void updateButtons(); void buildButtons(); BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index); + void addResizeCtrls(); + void layoutResizeCtrls(); LLRect mExpandedRect; LLDragHandle* mDragHandle; diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index 547ff4088..972209859 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -42,31 +42,25 @@ const U32 KEYWORD_FILE_CURRENT_VERSION = 2; -inline BOOL LLKeywordToken::isHead(const llwchar* s, bool search_end_c_comment) const +inline BOOL LLKeywordToken::isHead(const llwchar* s) const { // strncmp is much faster than string compare + BOOL res = TRUE; const llwchar* t = mToken.c_str(); S32 len = mToken.size(); - if (search_end_c_comment && len == 2 && t[0] == '/' && t[1] == '*') - { - // Special case for C-like */ end comment token - if (s[0] == '*' && s[1] == '/') - { - return TRUE; - } - else - { - return FALSE; - } - } - for (S32 i = 0; i < len; i++) + for (S32 i=0; i= other_end) + { + // We've hit the end of other. + // This covers two cases: other being shorter than self, or the strings being equal. + // In either case, we want to return false. + result = false; + break; + } + else if(self_iter >= self_end) + { + // self is shorter than other. + result = true; + break; + } + else if(*self_iter != *other_iter) + { + // The current character differs. The strings are not equal. + result = *self_iter < *other_iter; + break; + } + + self_iter++; + other_iter++; + } + + return result; +} LLColor3 LLKeywords::readColor( const std::string& s ) { F32 r, g, b; r = g = b = 0.0f; - S32 read = sscanf(s.c_str(), "%f, %f, %f]", &r, &g, &b ); - if( read != 3 ) /* Flawfinder: ignore */ + S32 values_read = sscanf(s.c_str(), "%f, %f, %f]", &r, &g, &b ); + if( values_read != 3 ) { llinfos << " poorly formed color in keyword file" << llendl; } return LLColor3( r, g, b ); } +LLFastTimer::DeclareTimer FTM_SYNTAX_COLORING("Syntax Coloring"); + // Walk through a string, applying the rules specified by the keyword token list and // create a list of color segments. -void LLKeywords::findSegments(std::vector* seg_list, const LLWString& wtext, const LLColor4 &defaultColor) +void LLKeywords::findSegments(std::vector* seg_list, const LLWString& wtext, const LLColor4 &defaultColor) { - std::for_each(seg_list->begin(), seg_list->end(), DeletePointer()); + LLFastTimer ft(FTM_SYNTAX_COLORING); seg_list->clear(); if( wtext.empty() ) @@ -290,7 +367,7 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS return; } - S32 text_len = wtext.size(); + S32 text_len = wtext.size() + 1; seg_list->push_back( new LLTextSegment( LLColor3(defaultColor), 0, text_len ) ); @@ -343,9 +420,9 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS } S32 seg_end = cur - base; - LLTextSegment* text_segment = new LLTextSegment( cur_token->getColor(), seg_start, seg_end ); + LLTextSegmentPtr text_segment = new LLTextSegment( cur_token->getColor(), seg_start, seg_end ); text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, defaultColor); + insertSegment( *seg_list, text_segment, text_len, defaultColor); line_done = TRUE; // to break out of second loop. break; } @@ -387,17 +464,15 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS S32 seg_end = 0; seg_start = cur - base; - cur += cur_delimiter->getLength(); + cur += cur_delimiter->getLengthHead(); - //if( cur_delimiter->getType() == LLKeywordToken::TWO_SIDED_DELIMITER ) LLKeywordToken::TOKEN_TYPE type = cur_delimiter->getType(); - if( type == LLKeywordToken::TWO_SIDED_DELIMITER || type == LLKeywordToken::TWO_SIDED_DELIMITER_ESC ) + if( type == LLKeywordToken::TWO_SIDED_DELIMITER || type == LLKeywordToken::DOUBLE_QUOTATION_MARKS ) { - //llassert( cur_delimiter->getDelimiter() != NULL ); - while( *cur && !cur_delimiter->isTail(cur) ) + while( *cur && !cur_delimiter->isTail(cur)) { // Check for an escape sequence. - if (type == LLKeywordToken::TWO_SIDED_DELIMITER_ESC && *cur == '\\') + if (type == LLKeywordToken::DOUBLE_QUOTATION_MARKS && *cur == '\\') { // Count the number of backslashes. S32 num_backslashes = 0; @@ -433,13 +508,13 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS if( *cur ) { - cur += cur_delimiter->getLength(); - seg_end = seg_start + between_delimiters + cur_delimiter->getLength() + cur_delimiter->getLength2(); + cur += cur_delimiter->getLengthHead(); + seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead() + cur_delimiter->getLengthTail(); } else { // eof - seg_end = seg_start + between_delimiters + cur_delimiter->getLength(); + seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead(); } } else @@ -451,13 +526,13 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS between_delimiters++; cur++; } - seg_end = seg_start + between_delimiters + cur_delimiter->getLength(); + seg_end = seg_start + between_delimiters + cur_delimiter->getLengthHead(); } - LLTextSegment* text_segment = new LLTextSegment( cur_delimiter->getColor(), seg_start, seg_end ); + LLTextSegmentPtr text_segment = new LLTextSegment( cur_delimiter->getColor(), seg_start, seg_end ); text_segment->setToken( cur_delimiter ); - insertSegment( seg_list, text_segment, text_len, defaultColor); + insertSegment( *seg_list, text_segment, text_len, defaultColor); // Note: we don't increment cur, since the end of one delimited seg may be immediately // followed by the start of another one. @@ -477,7 +552,7 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS S32 seg_len = p - cur; if( seg_len > 0 ) { - LLWString word( cur, 0, seg_len ); + WStringMapIndex word( cur, seg_len ); word_token_map_t::iterator map_iter = mWordTokenMap.find(word); if( map_iter != mWordTokenMap.end() ) { @@ -488,9 +563,9 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS // llinfos << "Seg: [" << word.c_str() << "]" << llendl; - LLTextSegment* text_segment = new LLTextSegment( cur_token->getColor(), seg_start, seg_end ); + LLTextSegmentPtr text_segment = new LLTextSegment( cur_token->getColor(), seg_start, seg_end ); text_segment->setToken( cur_token ); - insertSegment( seg_list, text_segment, text_len, defaultColor); + insertSegment( *seg_list, text_segment, text_len, defaultColor); } cur += seg_len; continue; @@ -505,25 +580,24 @@ void LLKeywords::findSegments(std::vector* seg_list, const LLWS } } -void LLKeywords::insertSegment(std::vector* seg_list, LLTextSegment* new_segment, S32 text_len, const LLColor4 &defaultColor ) +void LLKeywords::insertSegment(std::vector& seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor ) { - LLTextSegment* last = seg_list->back(); + LLTextSegmentPtr last = seg_list.back(); S32 new_seg_end = new_segment->getEnd(); if( new_segment->getStart() == last->getStart() ) { - *last = *new_segment; - delete new_segment; + seg_list.pop_back(); } else { last->setEnd( new_segment->getStart() ); - seg_list->push_back( new_segment ); } + seg_list.push_back( new_segment ); if( new_seg_end < text_len ) { - seg_list->push_back( new LLTextSegment( defaultColor, new_seg_end, text_len ) ); + seg_list.push_back( new LLTextSegment( defaultColor, new_seg_end, text_len ) ); } } diff --git a/indra/llui/llkeywords.h b/indra/llui/llkeywords.h index 5c55157ac..b6b7a9fdd 100644 --- a/indra/llui/llkeywords.h +++ b/indra/llui/llkeywords.h @@ -39,14 +39,32 @@ #include #include #include +#include "llpointer.h" class LLTextSegment; - +typedef LLPointer LLTextSegmentPtr; class LLKeywordToken { public: - enum TOKEN_TYPE { WORD, LINE, TWO_SIDED_DELIMITER, ONE_SIDED_DELIMITER, TWO_SIDED_DELIMITER_ESC }; + /** + * @brief Types of tokens/delimters being parsed. + * + * @desc Tokens/delimiters that need to be identified/highlighted. All are terminated if an EOF is encountered. + * - WORD are keywords in the normal sense, i.e. constants, events, etc. + * - LINE are for entire lines (currently only flow control labels use this). + * - ONE_SIDED_DELIMITER are for open-ended delimiters which are terminated by EOL. + * - TWO_SIDED_DELIMITER are for delimiters that end with a different delimiter than they open with. + * - DOUBLE_QUOTATION_MARKS are for delimiting areas using the same delimiter to open and close. + */ + enum TOKEN_TYPE + { + WORD, + LINE, + TWO_SIDED_DELIMITER, + ONE_SIDED_DELIMITER, + DOUBLE_QUOTATION_MARKS + }; LLKeywordToken( TOKEN_TYPE type, const LLColor3& color, const LLWString& token, const LLWString& tool_tip, const LLWString& delimiter ) : @@ -58,9 +76,9 @@ public: { } - S32 getLength() const { return mToken.size(); } - S32 getLength2() const { return mDelimiter.size(); } - BOOL isHead(const llwchar* s, bool search_end_c_comment = false) const; + S32 getLengthHead() const { return mToken.size(); } + S32 getLengthTail() const { return mDelimiter.size(); } + BOOL isHead(const llwchar* s) const; BOOL isTail(const llwchar* s) const; const LLWString& getToken() const { return mToken; } const LLColor3& getColor() const { return mColor; } @@ -89,7 +107,7 @@ public: BOOL loadFromFile(const std::string& filename); BOOL isLoaded() const { return mLoaded; } - void findSegments(std::vector *seg_list, const LLWString& text, const LLColor4 &defaultColor ); + void findSegments(std::vector *seg_list, const LLWString& text, const LLColor4 &defaultColor ); // Add the token as described void addToken(LLKeywordToken::TOKEN_TYPE type, @@ -97,8 +115,33 @@ public: const LLColor3& color, const std::string& tool_tip = LLStringUtil::null, const std::string& delimiter = LLStringUtil::null); + + // This class is here as a performance optimization. + // The word token map used to be defined as std::map. + // This worked, but caused a performance bottleneck due to memory allocation and string copies + // because it's not possible to search such a map without creating an LLWString. + // Using this class as the map index instead allows us to search using segments of an existing + // text run without copying them first, which greatly reduces overhead in LLKeywords::findSegments(). + class WStringMapIndex + { + public: + // copy constructor + WStringMapIndex(const WStringMapIndex& other); + // constructor from a string (copies the string's data into the new object) + WStringMapIndex(const LLWString& str); + // constructor from pointer and length + // NOTE: does NOT copy data, caller must ensure that the lifetime of the pointer exceeds that of the new object! + WStringMapIndex(const llwchar *start, size_t length); + ~WStringMapIndex(); + bool operator<(const WStringMapIndex &other) const; + private: + void copyData(const llwchar *start, size_t length); + const llwchar *mData; + size_t mLength; + bool mOwner; + }; - typedef std::map word_token_map_t; + typedef std::map word_token_map_t; typedef word_token_map_t::const_iterator keyword_iterator_t; keyword_iterator_t begin() const { return mWordTokenMap.begin(); } keyword_iterator_t end() const { return mWordTokenMap.end(); } @@ -109,7 +152,7 @@ public: private: LLColor3 readColor(const std::string& s); - void insertSegment(std::vector *seg_list, LLTextSegment* new_segment, S32 text_len, const LLColor4 &defaultColor); + void insertSegment(std::vector& seg_list, LLTextSegmentPtr new_segment, S32 text_len, const LLColor4 &defaultColor); BOOL mLoaded; word_token_map_t mWordTokenMap; diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 896be0c4e..27d0111fc 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -1053,7 +1053,13 @@ struct LLLayoutStack::LLEmbeddedPanel { min_dim = mMinWidth; } - mResizeBar = new LLResizeBar(std::string("resizer"), mPanel, LLRect(), min_dim, S32_MAX, side); + LLResizeBar::Params p; + p.name = "resizer"; + p.resizing_view = mPanel; + p.min_size = min_dim; + p.max_size = S32_MAX; + p.side = side; + mResizeBar = LLUICtrlFactory::create(p); mResizeBar->setEnableSnapping(FALSE); // panels initialized as hidden should not start out partially visible if (!mPanel->getVisible()) diff --git a/indra/llui/llresizebar.cpp b/indra/llui/llresizebar.cpp index bd99e6c73..95c8068fd 100644 --- a/indra/llui/llresizebar.cpp +++ b/indra/llui/llresizebar.cpp @@ -40,23 +40,22 @@ #include "llfocusmgr.h" #include "llwindow.h" -LLResizeBar::LLResizeBar( const std::string& name, LLView* resizing_view, const LLRect& rect, S32 min_size, S32 max_size, Side side ) - : - LLView( name, rect, TRUE ), +LLResizeBar::LLResizeBar(const LLResizeBar::Params& p) +: LLView(p), mDragLastScreenX( 0 ), mDragLastScreenY( 0 ), mLastMouseScreenX( 0 ), mLastMouseScreenY( 0 ), - mMinSize( min_size ), - mMaxSize( max_size ), - mSide( side ), - mSnappingEnabled(TRUE), - mAllowDoubleClickSnapping(TRUE), - mResizingView(resizing_view) + mMinSize( p.min_size ), + mMaxSize( p.max_size ), + mSide( p.side ), + mSnappingEnabled(p.snapping_enabled), + mAllowDoubleClickSnapping(p.allow_double_click_snapping), + mResizingView(p.resizing_view) { setFollowsNone(); // set up some generically good follow code. - switch( side ) + switch( mSide ) { case LEFT: setFollowsLeft(); @@ -180,6 +179,11 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask) break; } + notifyParent(LLSD().with("action", "resize") + .with("view_name", mResizingView->getName()) + .with("new_height", new_height) + .with("new_width", new_width)); + scaled_rect.mTop = scaled_rect.mBottom + new_height; scaled_rect.mRight = scaled_rect.mLeft + new_width; mResizingView->setRect(scaled_rect); @@ -188,8 +192,7 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask) if (mSnappingEnabled) { - //static LLCachedControl snap_margin (*LLUI::sConfigGroup,"SnapMargin", 0); - S32 snap_margin = LLUI::sConfigGroup->getS32("SnapMargin"); + static LLUICachedControl snap_margin ("SnapMargin", 0); switch( mSide ) { case LEFT: @@ -220,17 +223,62 @@ BOOL LLResizeBar::handleHover(S32 x, S32 y, MASK mask) switch(mSide) { case LEFT: - mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft; + { + S32 actual_delta_x = new_rect.mLeft - orig_rect.mLeft; + if (actual_delta_x != delta_x) + { + // restore everything by left + new_rect.mBottom = orig_rect.mBottom; + new_rect.mTop = orig_rect.mTop; + new_rect.mRight = orig_rect.mRight; + mResizingView->setShape(new_rect, true); + } + mDragLastScreenX += actual_delta_x; + break; + } case RIGHT: + { + S32 actual_delta_x = new_rect.mRight - orig_rect.mRight; + if (actual_delta_x != delta_x) + { + // restore everything by left + new_rect.mBottom = orig_rect.mBottom; + new_rect.mTop = orig_rect.mTop; + new_rect.mLeft = orig_rect.mLeft; + mResizingView->setShape(new_rect, true); + } mDragLastScreenX += new_rect.mRight - orig_rect.mRight; break; + } case TOP: + { + S32 actual_delta_y = new_rect.mTop - orig_rect.mTop; + if (actual_delta_y != delta_y) + { + // restore everything by left + new_rect.mBottom = orig_rect.mBottom; + new_rect.mLeft = orig_rect.mLeft; + new_rect.mRight = orig_rect.mRight; + mResizingView->setShape(new_rect, true); + } mDragLastScreenY += new_rect.mTop - orig_rect.mTop; break; + } case BOTTOM: + { + S32 actual_delta_y = new_rect.mBottom - orig_rect.mBottom; + if (actual_delta_y != delta_y) + { + // restore everything by left + new_rect.mTop = orig_rect.mTop; + new_rect.mLeft = orig_rect.mLeft; + new_rect.mRight = orig_rect.mRight; + mResizingView->setShape(new_rect, true); + } mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom; break; + } default: break; } diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h index 14bdd8d16..b2c34d93d 100644 --- a/indra/llui/llresizebar.h +++ b/indra/llui/llresizebar.h @@ -41,7 +41,31 @@ class LLResizeBar : public LLView public: enum Side { LEFT, TOP, RIGHT, BOTTOM }; - LLResizeBar(const std::string& name, LLView* resizing_view, const LLRect& rect, S32 min_size, S32 max_size, Side side ); + struct Params : public LLInitParam::Block + { + Mandatory resizing_view; + Mandatory side; + + Optional min_size; + Optional max_size; + Optional snapping_enabled; + Optional allow_double_click_snapping; + + Params() + : max_size("max_size", S32_MAX), + snapping_enabled("snapping_enabled", true), + resizing_view("resizing_view"), + side("side"), + allow_double_click_snapping("allow_double_click_snapping", true) + { + name = "resize_bar"; + } + }; + +protected: + LLResizeBar(const LLResizeBar::Params& p); + friend class LLUICtrlFactory; +public: // virtual void draw(); No appearance virtual BOOL handleHover(S32 x, S32 y, MASK mask); diff --git a/indra/llui/llresizehandle.cpp b/indra/llui/llresizehandle.cpp index 690f12b42..3eb25907d 100644 --- a/indra/llui/llresizehandle.cpp +++ b/indra/llui/llresizehandle.cpp @@ -44,31 +44,36 @@ const S32 RESIZE_BORDER_WIDTH = 3; -LLResizeHandle::LLResizeHandle( const std::string& name, const LLRect& rect, S32 min_width, S32 min_height, ECorner corner ) - : - LLView( name, rect, FALSE ), +LLResizeHandle::Params::Params() +: corner("corner"), + min_width("min_width"), + min_height("min_height") +{ + name = "resize_handle"; +} + +LLResizeHandle::LLResizeHandle(const LLResizeHandle::Params& p) +: LLView(p), mDragLastScreenX( 0 ), mDragLastScreenY( 0 ), mLastMouseScreenX( 0 ), mLastMouseScreenY( 0 ), mImage( NULL ), - mMinWidth( min_width ), - mMinHeight( min_height ), - mCorner( corner ) + mMinWidth( p.min_width ), + mMinHeight( p.min_height ), + mCorner( p.corner ) { - setSaveToXML(false); - if( RIGHT_BOTTOM == mCorner) { mImage = LLUI::getUIImage("UIImgResizeBottomRightUUID"); } - switch( mCorner ) + switch( p.corner ) { - case LEFT_TOP: setFollows( FOLLOWS_LEFT | FOLLOWS_TOP ); break; - case LEFT_BOTTOM: setFollows( FOLLOWS_LEFT | FOLLOWS_BOTTOM ); break; - case RIGHT_TOP: setFollows( FOLLOWS_RIGHT | FOLLOWS_TOP ); break; - case RIGHT_BOTTOM: setFollows( FOLLOWS_RIGHT | FOLLOWS_BOTTOM ); break; + case LEFT_TOP: setFollows( FOLLOWS_LEFT | FOLLOWS_TOP ); break; + case LEFT_BOTTOM: setFollows( FOLLOWS_LEFT | FOLLOWS_BOTTOM ); break; + case RIGHT_TOP: setFollows( FOLLOWS_RIGHT | FOLLOWS_TOP ); break; + case RIGHT_BOTTOM: setFollows( FOLLOWS_RIGHT | FOLLOWS_BOTTOM ); break; } // decorator object, don't serialize @@ -205,8 +210,7 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask) LLView* snap_view = NULL; LLView* test_view = NULL; - //static LLCachedControl snap_margin (*LLUI::sConfigGroup,"SnapMargin", 0); - S32 snap_margin = LLUI::sConfigGroup->getS32("SnapMargin"); + static LLUICachedControl snap_margin ("SnapMargin", 0); // now do snapping switch(mCorner) { @@ -255,23 +259,65 @@ BOOL LLResizeHandle::handleHover(S32 x, S32 y, MASK mask) // update last valid mouse cursor position based on resized view's actual size LLRect new_rect = resizing_view->getRect(); + S32 actual_delta_x = 0; + S32 actual_delta_y = 0; switch(mCorner) { case LEFT_TOP: - mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft; - mDragLastScreenY += new_rect.mTop - orig_rect.mTop; + actual_delta_x = new_rect.mLeft - orig_rect.mLeft; + actual_delta_y = new_rect.mTop - orig_rect.mTop; + if (actual_delta_x != delta_x + || actual_delta_y != delta_y) + { + new_rect.mRight = orig_rect.mRight; + new_rect.mBottom = orig_rect.mBottom; + resizing_view->setShape(new_rect, true); + } + + mDragLastScreenX += actual_delta_x; + mDragLastScreenY += actual_delta_y; break; case LEFT_BOTTOM: - mDragLastScreenX += new_rect.mLeft - orig_rect.mLeft; - mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom; + actual_delta_x = new_rect.mLeft - orig_rect.mLeft; + actual_delta_y = new_rect.mBottom - orig_rect.mBottom; + if (actual_delta_x != delta_x + || actual_delta_y != delta_y) + { + new_rect.mRight = orig_rect.mRight; + new_rect.mTop = orig_rect.mTop; + resizing_view->setShape(new_rect, true); + } + + mDragLastScreenX += actual_delta_x; + mDragLastScreenY += actual_delta_y; break; case RIGHT_TOP: - mDragLastScreenX += new_rect.mRight - orig_rect.mRight; - mDragLastScreenY += new_rect.mTop - orig_rect.mTop; + actual_delta_x = new_rect.mRight - orig_rect.mRight; + actual_delta_y = new_rect.mTop - orig_rect.mTop; + if (actual_delta_x != delta_x + || actual_delta_y != delta_y) + { + new_rect.mLeft = orig_rect.mLeft; + new_rect.mBottom = orig_rect.mBottom; + resizing_view->setShape(new_rect, true); + } + + mDragLastScreenX += actual_delta_x; + mDragLastScreenY += actual_delta_y; break; case RIGHT_BOTTOM: - mDragLastScreenX += new_rect.mRight - orig_rect.mRight; - mDragLastScreenY += new_rect.mBottom- orig_rect.mBottom; + actual_delta_x = new_rect.mRight - orig_rect.mRight; + actual_delta_y = new_rect.mBottom - orig_rect.mBottom; + if (actual_delta_x != delta_x + || actual_delta_y != delta_y) + { + new_rect.mLeft = orig_rect.mLeft; + new_rect.mTop = orig_rect.mTop; + resizing_view->setShape(new_rect, true); + } + + mDragLastScreenX += actual_delta_x; + mDragLastScreenY += actual_delta_y; break; default: break; diff --git a/indra/llui/llresizehandle.h b/indra/llui/llresizehandle.h index 0e23d526f..1560a0379 100644 --- a/indra/llui/llresizehandle.h +++ b/indra/llui/llresizehandle.h @@ -35,7 +35,6 @@ #include "stdtypes.h" #include "llview.h" -#include "llimagegl.h" #include "llcoord.h" @@ -44,9 +43,18 @@ class LLResizeHandle : public LLView public: enum ECorner { LEFT_TOP, LEFT_BOTTOM, RIGHT_TOP, RIGHT_BOTTOM }; - - LLResizeHandle(const std::string& name, const LLRect& rect, S32 min_width, S32 min_height, ECorner corner = RIGHT_BOTTOM ); + struct Params : public LLInitParam::Block + { + Mandatory corner; + Optional min_width; + Optional min_height; + Params(); + }; +protected: + LLResizeHandle(const LLResizeHandle::Params&); + friend class LLUICtrlFactory; +public: virtual void draw(); virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 5e9fc95df..a5bbc9b90 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -3888,11 +3888,14 @@ LLScrollColumnHeader::LLScrollColumnHeader(const std::string& label, const LLRec // resize handles on left and right const S32 RESIZE_BAR_THICKNESS = 3; - mResizeBar = new LLResizeBar( - std::string("resizebar"), - this, - LLRect( getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0), - MIN_COLUMN_WIDTH, S32_MAX, LLResizeBar::RIGHT ); + LLResizeBar::Params p; + p.name = "resizebar"; + p.resizing_view = this; + p.rect = LLRect( getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0); + p.min_size = MIN_COLUMN_WIDTH; + p.max_size = S32_MAX; + p.side = LLResizeBar::RIGHT; + mResizeBar = LLUICtrlFactory::create(p); addChild(mResizeBar); mResizeBar->setEnabled(FALSE); diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp index 9b4a98f93..bed37f2c0 100644 --- a/indra/llui/llstatbar.cpp +++ b/indra/llui/llstatbar.cpp @@ -48,19 +48,19 @@ LLStatBar::LLStatBar(const std::string& name, const LLRect& rect, const std::string& setting, BOOL default_bar, BOOL default_history) : LLView(name, rect, TRUE), - mSetting(setting) + mSetting(setting), + mLabel(name), + mMinBar(0.f), + mMaxBar(50.f), + mStatp(NULL), + mTickSpacing(10.f), + mLabelSpacing(10.f), + mPrecision(0), + mUpdatesPerSec(5), + mPerSec(true), + mDisplayMean(true) { - mMinBar = 0.f; - mMaxBar = 50.f; - mStatp = NULL; - mTickSpacing = 10.f; - mLabelSpacing = 10.f; - mPrecision = 0; - mUpdatesPerSec = 5; - mLabel = name; - mPerSec = TRUE; mValue = 0.f; - mDisplayMean = TRUE; S32 mode = -1; if (mSetting.length() > 0) @@ -296,16 +296,6 @@ void LLStatBar::draw() LLView::draw(); } -const std::string& LLStatBar::getLabel() const -{ - return mLabel; -} - -void LLStatBar::setLabel(const std::string& label) -{ - mLabel = label; -} - void LLStatBar::setUnitLabel(const std::string& unit_label) { mUnitLabel = unit_label; @@ -319,7 +309,7 @@ LLRect LLStatBar::getRequiredRect() { if (mDisplayHistory) { - rect.mTop = 67; + rect.mTop = 35 + mStatp->getNumBins(); } else { diff --git a/indra/llui/llstatbar.h b/indra/llui/llstatbar.h index 53640af2b..8c1ef3ecd 100644 --- a/indra/llui/llstatbar.h +++ b/indra/llui/llstatbar.h @@ -53,8 +53,6 @@ public: virtual void draw(); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - const std::string& getLabel() const; - void setLabel(const std::string& label); void setUnitLabel(const std::string& unit_label); /*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options. @@ -72,7 +70,7 @@ public: LLStat *mStatp; private: LLFrameTimer mUpdateTimer; - std::string mLabel; + LLUIString mLabel; std::string mUnitLabel; F32 mValue; std::string mSetting; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 1166be5ee..0fb44aa19 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -373,8 +373,6 @@ LLTextEditor::~LLTextEditor() gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit() // Scrollbar is deleted by LLView - mHoverSegment = NULL; - std::for_each(mSegments.begin(), mSegments.end(), DeletePointer()); std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); //LLView::deleteViewByHandle(mPopupMenuHandle); @@ -949,7 +947,7 @@ const LLTextSegment* LLTextEditor::getPreviousSegment() const return idx >= 0 ? mSegments[idx] : NULL; } -void LLTextEditor::getSelectedSegments(std::vector& segments) const +void LLTextEditor::getSelectedSegments(std::vector& segments) const { S32 left = hasSelection() ? llmin(mSelectionStart, mSelectionEnd) : mCursorPos; S32 right = hasSelection() ? llmax(mSelectionStart, mSelectionEnd) : mCursorPos; @@ -1527,7 +1525,7 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask) // Check to see if we're over an HTML-style link if( !mSegments.empty() ) { - const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); + LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); if( cur_segment ) { if(cur_segment->getStyle()->isLink()) @@ -3647,7 +3645,6 @@ void LLTextEditor::onTabInto() void LLTextEditor::clear() { setText(LLStringUtil::null); - std::for_each(mSegments.begin(), mSegments.end(), DeletePointer()); mSegments.clear(); } @@ -4165,7 +4162,7 @@ void LLTextEditor::appendText(const std::string &new_text, bool allow_undo, bool { S32 segment_start = old_length; S32 segment_end = getLength(); - LLTextSegment* segment = new LLTextSegment(stylep, segment_start, segment_end ); + LLTextSegmentPtr segment = new LLTextSegment(stylep, segment_start, segment_end ); mSegments.push_back(segment); } @@ -4383,13 +4380,12 @@ void LLTextEditor::updateSegments() // Make sure we have at least one segment if (mSegments.size() == 1 && mSegments[0]->getIsDefault()) { - delete mSegments[0]; mSegments.clear(); // create default segment } if (mSegments.empty()) { LLColor4& text_color = ( mReadOnly ? mReadOnlyFgColor : mFgColor ); - LLTextSegment* default_segment = new LLTextSegment( text_color, 0, mWText.length() ); + LLTextSegmentPtr default_segment = new LLTextSegment( text_color, 0, mWText.length() ); default_segment->setIsDefault(TRUE); mSegments.push_back(default_segment); } @@ -4420,7 +4416,6 @@ void LLTextEditor::pruneSegments() { // erase invalid segments ++iter; - std::for_each(iter, mSegments.end(), DeletePointer()); mSegments.erase(iter, mSegments.end()); } else @@ -4432,7 +4427,6 @@ void LLTextEditor::pruneSegments() void LLTextEditor::findEmbeddedItemSegments() { mHoverSegment = NULL; - std::for_each(mSegments.begin(), mSegments.end(), DeletePointer()); mSegments.clear(); BOOL found_embedded_items = FALSE; @@ -4513,7 +4507,7 @@ BOOL LLTextEditor::handleMouseUpOverSegment(S32 x, S32 y, MASK mask) // Finds the text segment (if any) at the give local screen position -const LLTextSegment* LLTextEditor::getSegmentAtLocalPos( S32 x, S32 y ) const +LLTextSegment* LLTextEditor::getSegmentAtLocalPos( S32 x, S32 y ) const { // Find the cursor position at the requested local screen position S32 offset = getCursorPosFromLocalCoord( x, y, FALSE ); diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index b4001cf48..0a0fc2bd5 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -293,7 +293,7 @@ public: const LLTextSegment* getCurrentSegment() const { return getSegmentAtOffset(mCursorPos); } const LLTextSegment* getPreviousSegment() const; - void getSelectedSegments(std::vector& segments) const; + void getSelectedSegments(std::vector& segments) const; static bool isPartOfWord(llwchar c) { return ( (c == '_') || (c == '\'') || LLStringOps::isAlnum((char)c)); } @@ -327,7 +327,7 @@ protected: void unindentLineBeforeCloseBrace(); S32 getSegmentIdxAtOffset(S32 offset) const; - const LLTextSegment* getSegmentAtLocalPos(S32 x, S32 y) const; + LLTextSegment* getSegmentAtLocalPos(S32 x, S32 y) const; const LLTextSegment* getSegmentAtOffset(S32 offset) const; void reportBadKeystroke() { make_ui_sound("UISndBadKeystroke"); } @@ -462,9 +462,9 @@ protected: BOOL mParseHighlights; std::string mHTML; - typedef std::vector segment_list_t; + typedef std::vector segment_list_t; segment_list_t mSegments; - const LLTextSegment* mHoverSegment; + LLTextSegmentPtr mHoverSegment; // Scrollbar data class LLScrollbar* mScrollbar; @@ -613,7 +613,7 @@ private: -class LLTextSegment +class LLTextSegment : public LLRefCount { public: // for creating a compare value diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 056a21a6c..40f43bf54 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -61,6 +61,7 @@ std::map gTranslation; std::list gUntranslated; /*static*/ LLControlGroup* LLUI::sConfigGroup = NULL; +/*static*/ LLControlGroup* LLUI::sAccountGroup = NULL; /*static*/ LLControlGroup* LLUI::sIgnoresGroup = NULL; /*static*/ LLControlGroup* LLUI::sColorsGroup = NULL; /*static*/ LLUIAudioCallback LLUI::sAudioCallback = NULL; @@ -116,6 +117,7 @@ bool handleShowXUINamesChanged(const LLSD& newvalue) } void LLUI::initClass(LLControlGroup* config, + LLControlGroup* account, LLControlGroup* ignores, LLControlGroup* colors, LLImageProviderInterface* image_provider, @@ -126,10 +128,12 @@ void LLUI::initClass(LLControlGroup* config, { LLRender2D::initClass(image_provider, scale_factor); sConfigGroup = config; + sAccountGroup = account; sIgnoresGroup = ignores; sColorsGroup = colors; if (sConfigGroup == NULL + || sAccountGroup == NULL || sIgnoresGroup == NULL || sColorsGroup == NULL) { @@ -287,6 +291,20 @@ void LLUI::glRectToScreen(const LLRect& gl, LLRect *screen) glPointToScreen(gl.mRight, gl.mBottom, &screen->mRight, &screen->mBottom); } + +LLControlGroup& LLUI::getControlControlGroup (const std::string& controlname) +{ + if(sConfigGroup->controlExists(controlname)) + return *sConfigGroup; + if(sAccountGroup->controlExists(controlname)) + return *sAccountGroup; + //if(sIgnoresGroup->controlExists(controlname)) //Identical to sConfigGroup currently. + // return *sIgnoresGroup; + if(sColorsGroup->controlExists(controlname)) + return *sColorsGroup; + return *sConfigGroup; +} + // static void LLUI::setHtmlHelp(LLHtmlHelp* html_help) { diff --git a/indra/llui/llui.h b/indra/llui/llui.h index a24159e2c..44cb0d820 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -62,6 +62,7 @@ public: // Methods // static void initClass(LLControlGroup* config, + LLControlGroup* account, LLControlGroup* ignores, LLControlGroup* colors, LLImageProviderInterface* image_provider, @@ -99,12 +100,15 @@ public: static void glPointToScreen(S32 gl_x, S32 gl_y, S32 *screen_x, S32 *screen_y); static void screenRectToGL(const LLRect& screen, LLRect *gl); static void glRectToScreen(const LLRect& gl, LLRect *screen); + // Returns the control group containing the control name, or the default group + static LLControlGroup& getControlControlGroup (const std::string& controlname); static void setHtmlHelp(LLHtmlHelp* html_help); // // Data // static LLControlGroup* sConfigGroup; + static LLControlGroup* sAccountGroup; static LLControlGroup* sIgnoresGroup; static LLControlGroup* sColorsGroup; static LLUIAudioCallback sAudioCallback; @@ -392,6 +396,24 @@ template LLRegisterWith LLInitClass::sRegister( template LLRegisterWith LLDestroyClass::sRegister(&T::destroyClass); +template +class LLUICachedControl : public LLCachedControl +{ +public: + // This constructor will declare a control if it doesn't exist in the contol group + LLUICachedControl(const std::string& name, + const T& default_value, + const std::string& comment = "Declared In Code") + : LLCachedControl(LLUI::getControlControlGroup(name), name, default_value, comment) + {} + + // This constructor will signal an error if the control doesn't exist in the control group + LLUICachedControl(const std::string& name) + : LLCachedControl(LLUI::getControlControlGroup(name), name) + {} +}; + + template class LLParamBlock { diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp index 0b76b8e81..0332765f1 100644 --- a/indra/llui/lluistring.cpp +++ b/indra/llui/lluistring.cpp @@ -33,31 +33,35 @@ #include "linden_common.h" #include "lluistring.h" #include "llsd.h" +#include "lltrans.h" -const LLStringUtil::format_map_t LLUIString::sNullArgs; +LLFastTimer::DeclareTimer FTM_UI_STRING("UI String"); LLUIString::LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args) - : mOrig(instring), - mArgs(args) +: mOrig(instring), + mArgs(new LLStringUtil::format_map_t(args)) { - format(); + dirty(); } void LLUIString::assign(const std::string& s) { mOrig = s; - format(); + dirty(); } void LLUIString::setArgList(const LLStringUtil::format_map_t& args) + { - mArgs = args; - format(); + getArgs() = args; + dirty(); } void LLUIString::setArgs(const LLSD& sd) { + LLFastTimer timer(FTM_UI_STRING); + if (!sd.isMap()) return; for(LLSD::map_const_iterator sd_it = sd.beginMap(); sd_it != sd.endMap(); @@ -65,40 +69,40 @@ void LLUIString::setArgs(const LLSD& sd) { setArg(sd_it->first, sd_it->second.asString()); } - format(); + dirty(); } void LLUIString::setArg(const std::string& key, const std::string& replacement) { - mArgs[key] = replacement; - format(); + getArgs()[key] = replacement; + dirty(); } void LLUIString::truncate(S32 maxchars) { - if (mWResult.size() > (size_t)maxchars) + if (getUpdatedWResult().size() > (size_t)maxchars) { - LLWStringUtil::truncate(mWResult, maxchars); - mResult = wstring_to_utf8str(mWResult); + LLWStringUtil::truncate(getUpdatedWResult(), maxchars); + mResult = wstring_to_utf8str(getUpdatedWResult()); } } void LLUIString::erase(S32 charidx, S32 len) { - mWResult.erase(charidx, len); - mResult = wstring_to_utf8str(mWResult); + getUpdatedWResult().erase(charidx, len); + mResult = wstring_to_utf8str(getUpdatedWResult()); } void LLUIString::insert(S32 charidx, const LLWString& wchars) { - mWResult.insert(charidx, wchars); - mResult = wstring_to_utf8str(mWResult); + getUpdatedWResult().insert(charidx, wchars); + mResult = wstring_to_utf8str(getUpdatedWResult()); } void LLUIString::replace(S32 charidx, llwchar wc) { - mWResult[charidx] = wc; - mResult = wstring_to_utf8str(mWResult); + getUpdatedWResult()[charidx] = wc; + mResult = wstring_to_utf8str(getUpdatedWResult()); } void LLUIString::clear() @@ -109,9 +113,48 @@ void LLUIString::clear() mWResult.clear(); } -void LLUIString::format() +void LLUIString::dirty() { - mResult = mOrig; - LLStringUtil::format(mResult, mArgs); - mWResult = utf8str_to_wstring(mResult); + mNeedsResult = true; + mNeedsWResult = true; +} + +void LLUIString::updateResult() const +{ + mNeedsResult = false; + + LLFastTimer timer(FTM_UI_STRING); + + // optimize for empty strings (don't attempt string replacement) + if (mOrig.empty()) + { + mResult.clear(); + mWResult.clear(); + return; + } + mResult = mOrig; + + // get the default args + local args + LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs(); + if (mArgs && !mArgs->empty()) + { + combined_args.insert(mArgs->begin(), mArgs->end()); + } + LLStringUtil::format(mResult, combined_args); +} + +void LLUIString::updateWResult() const +{ + mNeedsWResult = false; + + mWResult = utf8str_to_wstring(getUpdatedResult()); +} + +LLStringUtil::format_map_t& LLUIString::getArgs() +{ + if (!mArgs) + { + mArgs = new LLStringUtil::format_map_t; + } + return *mArgs; } diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h index aedeca27c..d88c3cd66 100644 --- a/indra/llui/lluistring.h +++ b/indra/llui/lluistring.h @@ -51,9 +51,9 @@ // llinfos << mMessage.getString() << llendl; // outputs "Welcome Steve to Second Life" // mMessage.setArg("[USERNAME]", "Joe"); // llinfos << mMessage.getString() << llendl; // outputs "Welcome Joe to Second Life" -// mMessage = "Recepci￳n a la [SECONDLIFE] [USERNAME]" +// mMessage = "Bienvenido a la [SECONDLIFE] [USERNAME]" // mMessage.setArg("[SECONDLIFE]", "Segunda Vida"); -// llinfos << mMessage.getString() << llendl; // outputs "Recepci￳n a la Segunda Vida Joe" +// llinfos << mMessage.getString() << llendl; // outputs "Bienvenido a la Segunda Vida Joe" // Implementation Notes: // Attempting to have operator[](const std::string& s) return mArgs[s] fails because we have @@ -64,9 +64,10 @@ class LLUIString public: // These methods all perform appropriate argument substitution // and modify mOrig where appropriate - LLUIString() {} + LLUIString() : mArgs(NULL), mNeedsResult(false), mNeedsWResult(false) {} LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args); - LLUIString(const std::string& instring) { assign(instring); } + LLUIString(const std::string& instring) : mArgs(NULL) { assign(instring); } + ~LLUIString() { delete mArgs; } void assign(const std::string& instring); LLUIString& operator=(const std::string& s) { assign(s); return *this; } @@ -76,34 +77,45 @@ public: void setArgs(const class LLSD& sd); void setArg(const std::string& key, const std::string& replacement); - const std::string& getString() const { return mResult; } - operator std::string() const { return mResult; } + const std::string& getString() const { return getUpdatedResult(); } + operator std::string() const { return getUpdatedResult(); } - const LLWString& getWString() const { return mWResult; } - operator LLWString() const { return mWResult; } + const LLWString& getWString() const { return getUpdatedWResult(); } + operator LLWString() const { return getUpdatedWResult(); } - bool empty() const { return mWResult.empty(); } - S32 length() const { return mWResult.size(); } + bool empty() const { return getUpdatedResult().empty(); } + S32 length() const { return getUpdatedWResult().size(); } void clear(); - void clearArgs() { mArgs.clear(); } - - // These utuilty functions are included for text editing. + void clearArgs() { if (mArgs) mArgs->clear(); } + + // These utility functions are included for text editing. // They do not affect mOrig and do not perform argument substitution void truncate(S32 maxchars); void erase(S32 charidx, S32 len); void insert(S32 charidx, const LLWString& wchars); void replace(S32 charidx, llwchar wc); - - static const LLStringUtil::format_map_t sNullArgs; private: - void format(); - + // something changed, requiring reformatting of strings + void dirty(); + + std::string& getUpdatedResult() const { if (mNeedsResult) { updateResult(); } return mResult; } + LLWString& getUpdatedWResult() const{ if (mNeedsWResult) { updateWResult(); } return mWResult; } + + // do actual work of updating strings (non-inlined) + void updateResult() const; + void updateWResult() const; + LLStringUtil::format_map_t& getArgs(); + std::string mOrig; - std::string mResult; - LLWString mWResult; // for displaying - LLStringUtil::format_map_t mArgs; + mutable std::string mResult; + mutable LLWString mWResult; // for displaying + LLStringUtil::format_map_t* mArgs; + + // controls lazy evaluation + mutable bool mNeedsResult; + mutable bool mNeedsWResult; }; #endif // LL_LLUISTRING_H diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini index d43e54989..e9cd38814 100644 --- a/indra/newview/app_settings/keywords.ini +++ b/indra/newview/app_settings/keywords.ini @@ -885,11 +885,11 @@ return Leave current function or event handler # Comment [one_sided_delimiter .8, .3, .15] // Comment:Non-functional commentary or disabled code -[two_sided_delimiter_esc .8, .3, .15] +[two_sided_delimiter .8, .3, .15] /* */ Comment:Non-functional commentary or disabled code # String literals -[two_sided_delimiter_esc 0, .2, 0] -" " String literal +[double_quotation_marks 0, .2, 0] +" String literal #functions are supplied by the program now diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0a8e23bbe..6cc328c4f 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -689,6 +689,7 @@ bool LLAppViewer::init() // Widget construction depends on LLUI being initialized LLUI::initClass(&gSavedSettings, + &gSavedPerAccountSettings, &gSavedSettings, &gColors, LLUIImageList::getInstance(), diff --git a/indra/newview/llfloaterstats.cpp b/indra/newview/llfloaterstats.cpp index eac963a3f..23cab8efe 100644 --- a/indra/newview/llfloaterstats.cpp +++ b/indra/newview/llfloaterstats.cpp @@ -160,7 +160,6 @@ void LLFloaterStats::buildStats() stat_barp->mPerSec = FALSE; stat_barp = render_statviewp->addStat("New Objs", &(LLViewerStats::getInstance()->mNumNewObjectsStat), "DebugStatModeNewObjs"); - stat_barp->setLabel("New Objs"); stat_barp->setUnitLabel("/sec"); stat_barp->mMinBar = 0.f; stat_barp->mMaxBar = 1000.f; @@ -169,7 +168,6 @@ void LLFloaterStats::buildStats() stat_barp->mPerSec = TRUE; stat_barp = render_statviewp->addStat("Object Cache Hit Rate", &(LLViewerStats::getInstance()->mNumNewObjectsStat), std::string(), false, true); - stat_barp->setLabel("Object Cache Hit Rate"); stat_barp->setUnitLabel("%"); stat_barp->mMinBar = 0.f; stat_barp->mMaxBar = 100.f; @@ -186,7 +184,6 @@ void LLFloaterStats::buildStats() LLStatView *texture_statviewp = render_statviewp->addStatView(params); stat_barp = texture_statviewp->addStat("Cache Hit Rate", &(LLTextureFetch::sCacheHitRate), std::string(), false, true); - stat_barp->setLabel("Cache Hit Rate"); stat_barp->setUnitLabel("%"); stat_barp->mMinBar = 0.f; stat_barp->mMaxBar = 100.f; diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index e34a8d724..503628f6c 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -597,11 +597,11 @@ void LLScriptEdCore::updateDynamicHelp(BOOL immediate) } const LLTextSegment* segment = NULL; - std::vector selected_segments; + std::vector selected_segments; mEditor->getSelectedSegments(selected_segments); // try segments in selection range first - std::vector::iterator segment_iter; + std::vector::iterator segment_iter; for (segment_iter = selected_segments.begin(); segment_iter != selected_segments.end(); ++segment_iter) { if((*segment_iter)->getToken() && (*segment_iter)->getToken()->getType() == LLKeywordToken::WORD) diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index 72bf54c21..d12b63997 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -869,7 +869,7 @@ BOOL LLViewerTextEditor::handleHover(S32 x, S32 y, MASK mask) // Check to see if we're over an HTML-style link if( !mSegments.empty() ) { - const LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); + LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y ); if( cur_segment ) { if(cur_segment->getStyle()->isLink())