diff options
author | Loren Shih <seraph@lindenlab.com> | 2010-02-08 14:58:53 -0500 |
---|---|---|
committer | Loren Shih <seraph@lindenlab.com> | 2010-02-08 14:58:53 -0500 |
commit | 399d70eede54dff2ba6d14b33f85fdad4d33a662 (patch) | |
tree | ce922e0963b8d46c236c4320b574916507fa3b65 /indra/llui | |
parent | 7e1932878563e5847335d5dcb66c9b23232c372c (diff) | |
parent | 19f4240f977fc26d97e686c4e3a1f13b063e191c (diff) |
automated merge viewer2.0->viewer2.0
Diffstat (limited to 'indra/llui')
-rw-r--r-- | indra/llui/CMakeLists.txt | 2 | ||||
-rw-r--r-- | indra/llui/llbutton.cpp | 14 | ||||
-rw-r--r-- | indra/llui/llbutton.h | 18 | ||||
-rw-r--r-- | indra/llui/lllayoutstack.cpp | 5 | ||||
-rw-r--r-- | indra/llui/lllineeditor.cpp | 271 | ||||
-rw-r--r-- | indra/llui/lllineeditor.h | 27 | ||||
-rw-r--r-- | indra/llui/llmultifloater.cpp | 8 | ||||
-rw-r--r-- | indra/llui/llmultisliderctrl.cpp | 2 | ||||
-rw-r--r-- | indra/llui/llpanel.cpp | 2 | ||||
-rw-r--r-- | indra/llui/llpanel.h | 2 | ||||
-rw-r--r-- | indra/llui/llsliderctrl.cpp | 2 | ||||
-rw-r--r-- | indra/llui/llspinctrl.cpp | 2 | ||||
-rw-r--r-- | indra/llui/lltabcontainer.cpp | 4 | ||||
-rw-r--r-- | indra/llui/lltextbase.cpp | 18 | ||||
-rw-r--r-- | indra/llui/lltexteditor.cpp | 46 | ||||
-rw-r--r-- | indra/llui/lltexteditor.h | 3 | ||||
-rw-r--r-- | indra/llui/lltextvalidate.cpp | 302 | ||||
-rw-r--r-- | indra/llui/lltextvalidate.h | 63 | ||||
-rw-r--r-- | indra/llui/lltooltip.h | 3 | ||||
-rw-r--r-- | indra/llui/llview.cpp | 2 |
20 files changed, 463 insertions, 333 deletions
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index ce068618e2..853f6f173d 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -90,6 +90,7 @@ set(llui_SOURCE_FILES lltextbox.cpp lltexteditor.cpp lltextparser.cpp + lltextvalidate.cpp lltransutil.cpp lltoggleablemenu.cpp lltooltip.cpp @@ -182,6 +183,7 @@ set(llui_HEADER_FILES lltextbox.h lltexteditor.h lltextparser.h + lltextvalidate.h lltoggleablemenu.h lltooltip.h lltransutil.h diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 14b77925f2..1d4dc35cee 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -81,10 +81,9 @@ 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"), + imgoverlay_label_space("imgoverlay_label_space", 1), label_color("label_color"), label_color_selected("label_color_selected"), // requires is_toggle true label_color_disabled("label_color_disabled"), @@ -144,10 +143,9 @@ 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), + mImgOverlayLabelSpace(p.imgoverlay_label_space), mIsToggle(p.is_toggle), mScaleImage(p.scale_image), mDropShadowedText(p.label_shadow), @@ -783,9 +781,9 @@ void LLButton::draw() switch(mImageOverlayAlignment) { case LLFontGL::LEFT: - text_left += overlay_width + 1; + text_left += overlay_width + mImgOverlayLabelSpace; mImageOverlay->draw( - mImageOverlayLeftPad, + mLeftHPad, center_y - (overlay_height / 2), overlay_width, overlay_height, @@ -800,9 +798,9 @@ void LLButton::draw() overlay_color); break; case LLFontGL::RIGHT: - text_right -= overlay_width + 1; + text_right -= overlay_width + mImgOverlayLabelSpace; mImageOverlay->draw( - getRect().getWidth() - mImageOverlayRightPad - overlay_width, + getRect().getWidth() - mRightHPad - overlay_width, center_y - (overlay_height / 2), overlay_width, overlay_height, diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 8e5f19602f..8f35db1007 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -107,11 +107,14 @@ public: 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; + /** + * Space between image_overlay and label + */ + Optional<S32> imgoverlay_label_space; + // callbacks Optional<CommitCallbackParam> click_callback, // alias -> commit_callback mouse_down_callback, @@ -192,10 +195,6 @@ 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; } @@ -328,11 +327,14 @@ private: S32 mRightHPad; S32 mBottomVPad; // under text label - S32 mImageOverlayLeftPad; - S32 mImageOverlayRightPad; S32 mImageOverlayTopPad; S32 mImageOverlayBottomPad; + /* + * Space between image_overlay and label + */ + S32 mImgOverlayLabelSpace; + F32 mHoverGlowStrength; F32 mCurGlowStrength; diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 1aaba88c49..dc79550eb4 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -816,7 +816,10 @@ void LLLayoutStack::calcMinExtents() //static void LLLayoutStack::updateClass() { - for (LLLayoutStack::instance_iter it = beginInstances(); it != endInstances(); ++it) + LLInstanceTrackerScopedGuard guard; + for (LLLayoutStack::instance_iter it = guard.beginInstances(); + it != guard.endInstances(); + ++it) { it->updateLayout(); } diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 30b09352d8..483a394bbd 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -83,19 +83,6 @@ template class LLLineEditor* LLView::getChild<class LLLineEditor>( // Member functions // -void LLLineEditor::PrevalidateNamedFuncs::declareValues() -{ - declare("ascii", LLLineEditor::prevalidateASCII); - declare("float", LLLineEditor::prevalidateFloat); - declare("int", LLLineEditor::prevalidateInt); - declare("positive_s32", LLLineEditor::prevalidatePositiveS32); - declare("non_negative_s32", LLLineEditor::prevalidateNonNegativeS32); - declare("alpha_num", LLLineEditor::prevalidateAlphaNum); - declare("alpha_num_space", LLLineEditor::prevalidateAlphaNumSpace); - declare("ascii_printable_no_pipe", LLLineEditor::prevalidateASCIIPrintableNoPipe); - declare("ascii_printable_no_space", LLLineEditor::prevalidateASCIIPrintableNoSpace); -} - LLLineEditor::Params::Params() : max_length_bytes("max_length", 254), keystroke_callback("keystroke_callback"), @@ -1984,51 +1971,12 @@ void LLLineEditor::setRect(const LLRect& rect) } } -void LLLineEditor::setPrevalidate(LLLinePrevalidateFunc func) +void LLLineEditor::setPrevalidate(LLTextValidate::validate_func_t func) { mPrevalidateFunc = func; updateAllowingLanguageInput(); } -// Limits what characters can be used to [1234567890.-] with [-] only valid in the first position. -// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for -// the simple reasons that intermediate states may be invalid even if the final result is valid. -// -// static -BOOL LLLineEditor::prevalidateFloat(const LLWString &str) -{ - LLLocale locale(LLLocale::USER_LOCALE); - - BOOL success = TRUE; - LLWString trimmed = str; - LLWStringUtil::trim(trimmed); - S32 len = trimmed.length(); - if( 0 < len ) - { - // May be a comma or period, depending on the locale - llwchar decimal_point = (llwchar)LLResMgr::getInstance()->getDecimalPoint(); - - S32 i = 0; - - // First character can be a negative sign - if( '-' == trimmed[0] ) - { - i++; - } - - for( ; i < len; i++ ) - { - if( (decimal_point != trimmed[i] ) && !LLStringOps::isDigit( trimmed[i] ) ) - { - success = FALSE; - break; - } - } - } - - return success; -} - // static BOOL LLLineEditor::postvalidateFloat(const std::string &str) { @@ -2088,223 +2036,6 @@ BOOL LLLineEditor::postvalidateFloat(const std::string &str) return success; } -// Limits what characters can be used to [1234567890-] with [-] only valid in the first position. -// Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for -// the simple reasons that intermediate states may be invalid even if the final result is valid. -// -// static -BOOL LLLineEditor::prevalidateInt(const LLWString &str) -{ - LLLocale locale(LLLocale::USER_LOCALE); - - BOOL success = TRUE; - LLWString trimmed = str; - LLWStringUtil::trim(trimmed); - S32 len = trimmed.length(); - if( 0 < len ) - { - S32 i = 0; - - // First character can be a negative sign - if( '-' == trimmed[0] ) - { - i++; - } - - for( ; i < len; i++ ) - { - if( !LLStringOps::isDigit( trimmed[i] ) ) - { - success = FALSE; - break; - } - } - } - - return success; -} - -// static -BOOL LLLineEditor::prevalidatePositiveS32(const LLWString &str) -{ - LLLocale locale(LLLocale::USER_LOCALE); - - LLWString trimmed = str; - LLWStringUtil::trim(trimmed); - S32 len = trimmed.length(); - BOOL success = TRUE; - if(0 < len) - { - if(('-' == trimmed[0]) || ('0' == trimmed[0])) - { - success = FALSE; - } - S32 i = 0; - while(success && (i < len)) - { - if(!LLStringOps::isDigit(trimmed[i++])) - { - success = FALSE; - } - } - } - if (success) - { - S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10); - if (val <= 0) - { - success = FALSE; - } - } - return success; -} - -BOOL LLLineEditor::prevalidateNonNegativeS32(const LLWString &str) -{ - LLLocale locale(LLLocale::USER_LOCALE); - - LLWString trimmed = str; - LLWStringUtil::trim(trimmed); - S32 len = trimmed.length(); - BOOL success = TRUE; - if(0 < len) - { - if('-' == trimmed[0]) - { - success = FALSE; - } - S32 i = 0; - while(success && (i < len)) - { - if(!LLStringOps::isDigit(trimmed[i++])) - { - success = FALSE; - } - } - } - if (success) - { - S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10); - if (val < 0) - { - success = FALSE; - } - } - return success; -} - -BOOL LLLineEditor::prevalidateAlphaNum(const LLWString &str) -{ - LLLocale locale(LLLocale::USER_LOCALE); - - BOOL rv = TRUE; - S32 len = str.length(); - if(len == 0) return rv; - while(len--) - { - if( !LLStringOps::isAlnum((char)str[len]) ) - { - rv = FALSE; - break; - } - } - return rv; -} - -// static -BOOL LLLineEditor::prevalidateAlphaNumSpace(const LLWString &str) -{ - LLLocale locale(LLLocale::USER_LOCALE); - - BOOL rv = TRUE; - S32 len = str.length(); - if(len == 0) return rv; - while(len--) - { - if(!(LLStringOps::isAlnum((char)str[len]) || (' ' == str[len]))) - { - rv = FALSE; - break; - } - } - return rv; -} - -// Used for most names of things stored on the server, due to old file-formats -// that used the pipe (|) for multiline text storage. Examples include -// inventory item names, parcel names, object names, etc. -// static -BOOL LLLineEditor::prevalidateASCIIPrintableNoPipe(const LLWString &str) -{ - BOOL rv = TRUE; - S32 len = str.length(); - if(len == 0) return rv; - while(len--) - { - llwchar wc = str[len]; - if (wc < 0x20 - || wc > 0x7f - || wc == '|') - { - rv = FALSE; - break; - } - if(!(wc == ' ' - || LLStringOps::isAlnum((char)wc) - || LLStringOps::isPunct((char)wc) ) ) - { - rv = FALSE; - break; - } - } - return rv; -} - - -// Used for avatar names -// static -BOOL LLLineEditor::prevalidateASCIIPrintableNoSpace(const LLWString &str) -{ - BOOL rv = TRUE; - S32 len = str.length(); - if(len == 0) return rv; - while(len--) - { - llwchar wc = str[len]; - if (wc < 0x20 - || wc > 0x7f - || LLStringOps::isSpace(wc)) - { - rv = FALSE; - break; - } - if( !(LLStringOps::isAlnum((char)str[len]) || - LLStringOps::isPunct((char)str[len]) ) ) - { - rv = FALSE; - break; - } - } - return rv; -} - - -// static -BOOL LLLineEditor::prevalidateASCII(const LLWString &str) -{ - BOOL rv = TRUE; - S32 len = str.length(); - while(len--) - { - if (str[len] < 0x20 || str[len] > 0x7f) - { - rv = FALSE; - break; - } - } - return rv; -} - void LLLineEditor::onMouseCaptureLost() { endSelection(); diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index f275dfc45a..b62138426b 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -51,27 +51,18 @@ #include "llviewborder.h" #include "llpreeditor.h" -#include <boost/function.hpp> +#include "lltextvalidate.h" class LLFontGL; class LLLineEditorRollback; class LLButton; class LLContextMenu; -typedef boost::function<BOOL (const LLWString &wstr)> LLLinePrevalidateFunc; - class LLLineEditor : public LLUICtrl, public LLEditMenuHandler, protected LLPreeditor { public: - struct PrevalidateNamedFuncs - : public LLInitParam::TypeValuesHelper<LLLinePrevalidateFunc, PrevalidateNamedFuncs> - - { - static void declareValues(); - }; - typedef boost::function<void (LLLineEditor* caller)> keystroke_callback_t; struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> @@ -81,7 +72,7 @@ public: Optional<keystroke_callback_t> keystroke_callback; - Optional<LLLinePrevalidateFunc, PrevalidateNamedFuncs> prevalidate_callback; + Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback; Optional<LLViewBorder::Params> border; @@ -236,17 +227,7 @@ public: void setTextPadding(S32 left, S32 right); // Prevalidation controls which keystrokes can affect the editor - void setPrevalidate( LLLinePrevalidateFunc func ); - static BOOL prevalidateFloat(const LLWString &str ); - static BOOL prevalidateInt(const LLWString &str ); - static BOOL prevalidatePositiveS32(const LLWString &str); - static BOOL prevalidateNonNegativeS32(const LLWString &str); - static BOOL prevalidateAlphaNum(const LLWString &str ); - static BOOL prevalidateAlphaNumSpace(const LLWString &str ); - static BOOL prevalidateASCIIPrintableNoPipe(const LLWString &str); - static BOOL prevalidateASCIIPrintableNoSpace(const LLWString &str); - static BOOL prevalidateASCII(const LLWString &str); - + void setPrevalidate( LLTextValidate::validate_func_t func ); static BOOL postvalidateFloat(const std::string &str); // line history support: @@ -326,7 +307,7 @@ protected: S32 mLastSelectionStart; S32 mLastSelectionEnd; - LLLinePrevalidateFunc mPrevalidateFunc; + LLTextValidate::validate_func_t mPrevalidateFunc; LLFrameTimer mKeystrokeTimer; LLTimer mTripleClickTimer; diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp index 78738c826d..33d47a3f0e 100644 --- a/indra/llui/llmultifloater.cpp +++ b/indra/llui/llmultifloater.cpp @@ -92,14 +92,6 @@ void LLMultiFloater::draw() } else { - for (S32 i = 0; i < mTabContainer->getTabCount(); i++) - { - LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(i); - if (floaterp->getShortTitle() != mTabContainer->getPanelTitle(i)) - { - mTabContainer->setPanelTitle(i, floaterp->getShortTitle()); - } - } LLFloater::draw(); } } diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp index f4434a0f78..cb81c39103 100644 --- a/indra/llui/llmultisliderctrl.cpp +++ b/indra/llui/llmultisliderctrl.cpp @@ -138,7 +138,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p) params.font(p.font); params.max_length_bytes(MAX_STRING_LENGTH); params.commit_callback.function(LLMultiSliderCtrl::onEditorCommit); - params.prevalidate_callback(&LLLineEditor::prevalidateFloat); + params.prevalidate_callback(&LLTextValidate::validateFloat); params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); mEditor = LLUICtrlFactory::create<LLLineEditor> (params); mEditor->setFocusReceivedCallback( boost::bind(LLMultiSliderCtrl::onEditorGainFocus, _1, this) ); diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 7f23fe2671..7b406e090a 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -936,7 +936,7 @@ LLPanel *LLPanel::childGetVisiblePanelWithHelp() return ::childGetVisiblePanelWithHelp(this); } -void LLPanel::childSetPrevalidate(const std::string& id, BOOL (*func)(const LLWString &) ) +void LLPanel::childSetPrevalidate(const std::string& id, bool (*func)(const LLWString &) ) { LLLineEditor* child = findChild<LLLineEditor>(id); if (child) diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index 6de83fe3a7..4e53fd7ea3 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -226,7 +226,7 @@ public: std::string childGetText(const std::string& id) const { return childGetValue(id).asString(); } // LLLineEditor - void childSetPrevalidate(const std::string& id, BOOL (*func)(const LLWString &) ); + void childSetPrevalidate(const std::string& id, bool (*func)(const LLWString &) ); // LLButton void childSetAction(const std::string& id, boost::function<void(void*)> function, void* value = NULL); diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp index 01c274bb4e..80ee5d0984 100644 --- a/indra/llui/llsliderctrl.cpp +++ b/indra/llui/llsliderctrl.cpp @@ -141,7 +141,7 @@ LLSliderCtrl::LLSliderCtrl(const LLSliderCtrl::Params& p) line_p.rect.setIfNotProvided(text_rect); line_p.font.setIfNotProvided(p.font); line_p.commit_callback.function(&LLSliderCtrl::onEditorCommit); - line_p.prevalidate_callback(&LLLineEditor::prevalidateFloat); + line_p.prevalidate_callback(&LLTextValidate::validateFloat); mEditor = LLUICtrlFactory::create<LLLineEditor>(line_p); mEditor->setFocusReceivedCallback( boost::bind(&LLSliderCtrl::onEditorGainFocus, _1, this )); diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index 28f3788817..491cd7b6f3 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -127,7 +127,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p) } params.max_length_bytes(MAX_STRING_LENGTH); params.commit_callback.function((boost::bind(&LLSpinCtrl::onEditorCommit, this, _2))); - params.prevalidate_callback(&LLLineEditor::prevalidateFloat); + params.prevalidate_callback(&LLTextValidate::validateFloat); params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); mEditor = LLUICtrlFactory::create<LLLineEditor> (params); mEditor->setFocusReceivedCallback( boost::bind(&LLSpinCtrl::onEditorGainFocus, _1, this )); diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 19408989a5..ef9d195a19 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1628,15 +1628,11 @@ void LLTabContainer::setTabImage(LLPanel* child, LLIconCtrl* icon) void LLTabContainer::reshapeTuple(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); 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); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 2b1e2b8226..b84e6f45fb 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1137,6 +1137,7 @@ void LLTextBase::reflow() line_list_t::iterator iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), start_index, line_end_compare()); line_start_index = iter->mDocIndexStart; line_count = iter->mLineNum; + cur_top = iter->mRect.mTop; getSegmentAndOffset(iter->mDocIndexStart, &seg_iter, &seg_offset); mLineInfoList.erase(iter, mLineInfoList.end()); } @@ -1574,8 +1575,10 @@ void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, c { LLStyle::Params icon; icon.image = image; - // HACK: fix spacing of images and remove the fixed char spacing - appendAndHighlightText(" ", prepend_newline, part, icon); + // Text will be replaced during rendering with the icon, + // but string cannot be empty or the segment won't be + // added (or drawn). + appendAndHighlightText(" ", prepend_newline, part, icon); prepend_newline = false; } } @@ -2296,14 +2299,21 @@ F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selec { if ( mStyle->isImage() && (start >= 0) && (end <= mEnd - mStart)) { + // ...for images, only render the image, not the underlying text, + // which is only a placeholder space LLColor4 color = LLColor4::white % mEditor.getDrawContext().mAlpha; LLUIImagePtr image = mStyle->getImage(); S32 style_image_height = image->getHeight(); S32 style_image_width = image->getWidth(); - // Center the image vertically - S32 image_bottom = draw_rect.getCenterY() - (style_image_height/2); + // Text is drawn from the top of the draw_rect downward + S32 text_center = draw_rect.mTop - (mFontHeight / 2); + // Align image to center of text + S32 image_bottom = text_center - (style_image_height / 2); image->draw(draw_rect.mLeft, image_bottom, style_image_width, style_image_height, color); + + const S32 IMAGE_HPAD = 3; + return draw_rect.mLeft + style_image_width + IMAGE_HPAD; } return drawClippedSegment( getStart() + start, getStart() + end, selection_start, selection_end, draw_rect); diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index ac5a0376fc..ad9f066539 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -237,6 +237,7 @@ private: /////////////////////////////////////////////////////////////////// LLTextEditor::Params::Params() : default_text("default_text"), + prevalidate_callback("prevalidate_callback"), embedded_items("embedded_items", false), ignore_tab("ignore_tab", true), handle_edit_keys_directly("handle_edit_keys_directly", false), @@ -244,7 +245,9 @@ LLTextEditor::Params::Params() default_color("default_color"), commit_on_focus_lost("commit_on_focus_lost", false), show_context_menu("show_context_menu") -{} +{ + addSynonym(prevalidate_callback, "text_type"); +} LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : LLTextBase(p), @@ -259,6 +262,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : mMouseDownX(0), mMouseDownY(0), mTabsToNextField(p.ignore_tab), + mPrevalidateFunc(p.prevalidate_callback()), mContextMenu(NULL), mShowContextMenu(p.show_context_menu) { @@ -320,6 +324,17 @@ LLTextEditor::~LLTextEditor() void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Params& input_params) { + // validate incoming text if necessary + if (mPrevalidateFunc) + { + LLWString test_text = utf8str_to_wstring(utf8str); + if (!mPrevalidateFunc(test_text)) + { + // not valid text, nothing to do + return; + } + } + blockUndo(); deselect(); @@ -911,6 +926,21 @@ S32 LLTextEditor::execute( TextCmd* cmd ) // Push the new command is now on the top (front) of the undo stack. mUndoStack.push_front(cmd); mLastCmd = cmd; + + bool need_to_rollback = mPrevalidateFunc + && !mPrevalidateFunc(getViewModel()->getDisplay()); + if (need_to_rollback) + { + // get rid of this last command and clean up undo stack + undo(); + + // remove any evidence of this command from redo history + mUndoStack.pop_front(); + delete cmd; + + // failure, nothing changed + delta = 0; + } } else { @@ -1034,7 +1064,21 @@ S32 LLTextEditor::addChar(S32 pos, llwchar wc) if (mLastCmd && mLastCmd->canExtend(pos)) { S32 delta = 0; + if (mPrevalidateFunc) + { + // get a copy of current text contents + LLWString test_string(getViewModel()->getDisplay()); + + // modify text contents as if this addChar succeeded + llassert(pos <= (S32)test_string.size()); + test_string.insert(pos, 1, wc); + if (!mPrevalidateFunc( test_string)) + { + return 0; + } + } mLastCmd->extendAndExecute(this, pos, wc, &delta); + return delta; } else diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index d96198d9ce..00c6a8b68a 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -44,6 +44,7 @@ #include "lldarray.h" #include "llviewborder.h" // for params #include "lltextbase.h" +#include "lltextvalidate.h" #include "llpreeditor.h" #include "llcontrol.h" @@ -63,6 +64,7 @@ public: struct Params : public LLInitParam::Block<Params, LLTextBase::Params> { Optional<std::string> default_text; + Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback; Optional<bool> embedded_items, ignore_tab, @@ -334,6 +336,7 @@ private: LLCoordGL mLastIMEPosition; // Last position of the IME editor keystroke_signal_t mKeystrokeSignal; + LLTextValidate::validate_func_t mPrevalidateFunc; LLContextMenu* mContextMenu; }; // end class LLTextEditor diff --git a/indra/llui/lltextvalidate.cpp b/indra/llui/lltextvalidate.cpp new file mode 100644 index 0000000000..8b6bc5bd7d --- /dev/null +++ b/indra/llui/lltextvalidate.cpp @@ -0,0 +1,302 @@ +/** + * @file lltextvalidate.cpp + * @brief Text validation helper functions + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// Text editor widget to let users enter a single line. + +#include "linden_common.h" + +#include "lltextvalidate.h" +#include "llresmgr.h" // for LLLocale + +namespace LLTextValidate +{ + void ValidateTextNamedFuncs::declareValues() + { + declare("ascii", validateASCII); + declare("float", validateFloat); + declare("int", validateInt); + declare("positive_s32", validatePositiveS32); + declare("non_negative_s32", validateNonNegativeS32); + declare("alpha_num", validateAlphaNum); + declare("alpha_num_space", validateAlphaNumSpace); + declare("ascii_printable_no_pipe", validateASCIIPrintableNoPipe); + declare("ascii_printable_no_space", validateASCIIPrintableNoSpace); + } + + // Limits what characters can be used to [1234567890.-] with [-] only valid in the first position. + // Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for + // the simple reasons that intermediate states may be invalid even if the final result is valid. + // + bool validateFloat(const LLWString &str) + { + LLLocale locale(LLLocale::USER_LOCALE); + + bool success = TRUE; + LLWString trimmed = str; + LLWStringUtil::trim(trimmed); + S32 len = trimmed.length(); + if( 0 < len ) + { + // May be a comma or period, depending on the locale + llwchar decimal_point = (llwchar)LLResMgr::getInstance()->getDecimalPoint(); + + S32 i = 0; + + // First character can be a negative sign + if( '-' == trimmed[0] ) + { + i++; + } + + for( ; i < len; i++ ) + { + if( (decimal_point != trimmed[i] ) && !LLStringOps::isDigit( trimmed[i] ) ) + { + success = FALSE; + break; + } + } + } + + return success; + } + + // Limits what characters can be used to [1234567890-] with [-] only valid in the first position. + // Does NOT ensure that the string is a well-formed number--that's the job of post-validation--for + // the simple reasons that intermediate states may be invalid even if the final result is valid. + // + bool validateInt(const LLWString &str) + { + LLLocale locale(LLLocale::USER_LOCALE); + + bool success = TRUE; + LLWString trimmed = str; + LLWStringUtil::trim(trimmed); + S32 len = trimmed.length(); + if( 0 < len ) + { + S32 i = 0; + + // First character can be a negative sign + if( '-' == trimmed[0] ) + { + i++; + } + + for( ; i < len; i++ ) + { + if( !LLStringOps::isDigit( trimmed[i] ) ) + { + success = FALSE; + break; + } + } + } + + return success; + } + + bool validatePositiveS32(const LLWString &str) + { + LLLocale locale(LLLocale::USER_LOCALE); + + LLWString trimmed = str; + LLWStringUtil::trim(trimmed); + S32 len = trimmed.length(); + bool success = TRUE; + if(0 < len) + { + if(('-' == trimmed[0]) || ('0' == trimmed[0])) + { + success = FALSE; + } + S32 i = 0; + while(success && (i < len)) + { + if(!LLStringOps::isDigit(trimmed[i++])) + { + success = FALSE; + } + } + } + if (success) + { + S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10); + if (val <= 0) + { + success = FALSE; + } + } + return success; + } + + bool validateNonNegativeS32(const LLWString &str) + { + LLLocale locale(LLLocale::USER_LOCALE); + + LLWString trimmed = str; + LLWStringUtil::trim(trimmed); + S32 len = trimmed.length(); + bool success = TRUE; + if(0 < len) + { + if('-' == trimmed[0]) + { + success = FALSE; + } + S32 i = 0; + while(success && (i < len)) + { + if(!LLStringOps::isDigit(trimmed[i++])) + { + success = FALSE; + } + } + } + if (success) + { + S32 val = strtol(wstring_to_utf8str(trimmed).c_str(), NULL, 10); + if (val < 0) + { + success = FALSE; + } + } + return success; + } + + bool validateAlphaNum(const LLWString &str) + { + LLLocale locale(LLLocale::USER_LOCALE); + + bool rv = TRUE; + S32 len = str.length(); + if(len == 0) return rv; + while(len--) + { + if( !LLStringOps::isAlnum((char)str[len]) ) + { + rv = FALSE; + break; + } + } + return rv; + } + + bool validateAlphaNumSpace(const LLWString &str) + { + LLLocale locale(LLLocale::USER_LOCALE); + + bool rv = TRUE; + S32 len = str.length(); + if(len == 0) return rv; + while(len--) + { + if(!(LLStringOps::isAlnum((char)str[len]) || (' ' == str[len]))) + { + rv = FALSE; + break; + } + } + return rv; + } + + // Used for most names of things stored on the server, due to old file-formats + // that used the pipe (|) for multiline text storage. Examples include + // inventory item names, parcel names, object names, etc. + bool validateASCIIPrintableNoPipe(const LLWString &str) + { + bool rv = TRUE; + S32 len = str.length(); + if(len == 0) return rv; + while(len--) + { + llwchar wc = str[len]; + if (wc < 0x20 + || wc > 0x7f + || wc == '|') + { + rv = FALSE; + break; + } + if(!(wc == ' ' + || LLStringOps::isAlnum((char)wc) + || LLStringOps::isPunct((char)wc) ) ) + { + rv = FALSE; + break; + } + } + return rv; + } + + + // Used for avatar names + bool validateASCIIPrintableNoSpace(const LLWString &str) + { + bool rv = TRUE; + S32 len = str.length(); + if(len == 0) return rv; + while(len--) + { + llwchar wc = str[len]; + if (wc < 0x20 + || wc > 0x7f + || LLStringOps::isSpace(wc)) + { + rv = FALSE; + break; + } + if( !(LLStringOps::isAlnum((char)str[len]) || + LLStringOps::isPunct((char)str[len]) ) ) + { + rv = FALSE; + break; + } + } + return rv; + } + + bool validateASCII(const LLWString &str) + { + bool rv = TRUE; + S32 len = str.length(); + while(len--) + { + if (str[len] < 0x20 || str[len] > 0x7f) + { + rv = FALSE; + break; + } + } + return rv; + } +} diff --git a/indra/llui/lltextvalidate.h b/indra/llui/lltextvalidate.h new file mode 100644 index 0000000000..ffb4e85e7c --- /dev/null +++ b/indra/llui/lltextvalidate.h @@ -0,0 +1,63 @@ +/** + * @file lltextbase.h + * @author Martin Reddy + * @brief The base class of text box/editor, providing Url handling support + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLTEXTVALIDATE_H +#define LL_LLTEXTVALIDATE_H + +#include "llstring.h" +#include "llinitparam.h" +#include <boost/function.hpp> + +namespace LLTextValidate +{ + typedef boost::function<BOOL (const LLWString &wstr)> validate_func_t; + + struct ValidateTextNamedFuncs + : public LLInitParam::TypeValuesHelper<validate_func_t, ValidateTextNamedFuncs> + { + static void declareValues(); + }; + + bool validateFloat(const LLWString &str ); + bool validateInt(const LLWString &str ); + bool validatePositiveS32(const LLWString &str); + bool validateNonNegativeS32(const LLWString &str); + bool validateAlphaNum(const LLWString &str ); + bool validateAlphaNumSpace(const LLWString &str ); + bool validateASCIIPrintableNoPipe(const LLWString &str); + bool validateASCIIPrintableNoSpace(const LLWString &str); + bool validateASCII(const LLWString &str); +} + + +#endif diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h index 7978b6a583..c0811c56c3 100644 --- a/indra/llui/lltooltip.h +++ b/indra/llui/lltooltip.h @@ -129,7 +129,8 @@ private: class LLInspector : public LLToolTip { public: - struct Params : public LLInitParam::Block<Params, LLToolTip::Params> {}; + struct Params : public LLInitParam::Block<Params, LLToolTip::Params> + {}; }; class LLToolTipMgr : public LLSingleton<LLToolTipMgr> diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index f1b08c380b..63e627ceb5 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1720,6 +1720,7 @@ LLView* LLView::findChildView(const std::string& name, BOOL recurse) const for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it) { LLView* childp = *child_it; + llassert(childp); if (childp->getName() == name) { return childp; @@ -1731,6 +1732,7 @@ LLView* LLView::findChildView(const std::string& name, BOOL recurse) const for ( child_it = mChildList.begin(); child_it != mChildList.end(); ++child_it) { LLView* childp = *child_it; + llassert(childp); LLView* viewp = childp->findChildView(name, recurse); if ( viewp ) { |