diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 2d4301a0ae..713ec2a913 100755 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -43,6 +43,9 @@ #include "llview.h" #include "llwindow.h" #include +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) +#include +// [/SL:KB] #include "fsregistrarutils.h" @@ -165,6 +168,9 @@ LLTextBase::Params::Params() bg_readonly_color("bg_readonly_color"), bg_writeable_color("bg_writeable_color"), bg_focus_color("bg_focus_color"), +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + bg_highlighted_color("bg_highlighted_color"), +// [/SL:KB] text_selected_color("text_selected_color"), bg_selected_color("bg_selected_color"), allow_scroll("allow_scroll", true), @@ -214,6 +220,9 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mWriteableBgColor(p.bg_writeable_color), mReadOnlyBgColor(p.bg_readonly_color), mFocusBgColor(p.bg_focus_color), +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + mHighlightedBGColor(p.bg_highlighted_color), +// [/SL:KB] mTextSelectedColor(p.text_selected_color), mSelectedBGColor(p.bg_selected_color), mReflowIndex(S32_MAX), @@ -372,17 +381,32 @@ void LLTextBase::onValueChange(S32 start, S32 end) { } - // Draws the black box behind the selected text +//void LLTextBase::drawSelectionBackground() +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) void LLTextBase::drawSelectionBackground() { - // Draw selection even if we don't have keyboard focus for search/replace if( hasSelection() && !mLineInfoList.empty()) + { + highlight_list_t highlights; + highlights.push_back(range_pair_t(llmin(mSelectionStart, mSelectionEnd), llmax(mSelectionStart, mSelectionEnd))); + drawHighlightsBackground(highlights, mSelectedBGColor); + } +} + +void LLTextBase::drawHighlightsBackground(const highlight_list_t& highlights, const LLColor4& color) +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) +{ +// // Draw selection even if we don't have keyboard focus for search/replace +// if( hasSelection() && !mLineInfoList.empty()) +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + if (!mLineInfoList.empty()) +// [/SL:KB] { std::vector selection_rects; - S32 selection_left = llmin( mSelectionStart, mSelectionEnd ); - S32 selection_right = llmax( mSelectionStart, mSelectionEnd ); +// S32 selection_left = llmin( mSelectionStart, mSelectionEnd ); +// S32 selection_right = llmax( mSelectionStart, mSelectionEnd ); // Skip through the lines we aren't drawing. LLRect content_display_rect = getVisibleDocumentRect(); @@ -391,73 +415,103 @@ void LLTextBase::drawSelectionBackground() line_list_t::const_iterator line_iter = std::lower_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mTop, compare_bottom()); line_list_t::const_iterator end_iter = std::upper_bound(mLineInfoList.begin(), mLineInfoList.end(), content_display_rect.mBottom, compare_top()); - bool done = false; +// bool done = false; +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + highlight_list_t::const_iterator itHighlight = highlights.begin(); +// [/SL:KB] // Find the coordinates of the selected area - for (;line_iter != end_iter && !done; ++line_iter) +// for (;line_iter != end_iter && !done; ++line_iter) +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + for (; (line_iter != end_iter) && (itHighlight != highlights.end()); ++line_iter) +// [/SL:KB] { - // is selection visible on this line? - if (line_iter->mDocIndexEnd > selection_left && line_iter->mDocIndexStart < selection_right) +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + // Find a highlight range with an end index larger than the start of this line + while ( (itHighlight != highlights.end()) && (line_iter->mDocIndexStart > itHighlight->second) ) + ++itHighlight; + + // Draw all highlights on the current line + while ( (itHighlight != highlights.end()) && (itHighlight->first < line_iter->mDocIndexEnd) ) { - segment_set_t::iterator segment_iter; - S32 segment_offset; - getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset); - - LLRect selection_rect; - selection_rect.mLeft = line_iter->mRect.mLeft; - selection_rect.mRight = line_iter->mRect.mLeft; - selection_rect.mBottom = line_iter->mRect.mBottom; - selection_rect.mTop = line_iter->mRect.mTop; - - for(;segment_iter != mSegments.end(); ++segment_iter, segment_offset = 0) + // Keep the names of these to change fewer lines of LL code + S32 selection_left = llmin(itHighlight->first, itHighlight->second); + S32 selection_right = llmax(itHighlight->first, itHighlight->second) ; +// [/SL:KB] + + // is selection visible on this line? + if (line_iter->mDocIndexEnd > selection_left && line_iter->mDocIndexStart < selection_right) { - LLTextSegmentPtr segmentp = *segment_iter; - - S32 segment_line_start = segmentp->getStart() + segment_offset; - S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd); - - if (segment_line_start > segment_line_end) break; - - S32 segment_width = 0; - S32 segment_height = 0; - - // if selection after beginning of segment - if(selection_left >= segment_line_start) + segment_set_t::iterator segment_iter; + S32 segment_offset; + getSegmentAndOffset(line_iter->mDocIndexStart, &segment_iter, &segment_offset); + + LLRect selection_rect; + selection_rect.mLeft = line_iter->mRect.mLeft; + selection_rect.mRight = line_iter->mRect.mLeft; + selection_rect.mBottom = line_iter->mRect.mBottom; + selection_rect.mTop = line_iter->mRect.mTop; + + for(;segment_iter != mSegments.end(); ++segment_iter, segment_offset = 0) { - S32 num_chars = llmin(selection_left, segment_line_end) - segment_line_start; - segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); - selection_rect.mLeft += segment_width; - } + LLTextSegmentPtr segmentp = *segment_iter; - // if selection_right == segment_line_end then that means we are the first character of the next segment - // or first character of the next line, in either case we want to add the length of the current segment - // to the selection rectangle and continue. - // if selection right > segment_line_end then selection spans end of current segment... - if (selection_right >= segment_line_end) - { - // extend selection slightly beyond end of line - // to indicate selection of newline character (use "n" character to determine width) - S32 num_chars = segment_line_end - segment_line_start; - segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); - selection_rect.mRight += segment_width; - } - // else if selection ends on current segment... - else - { - S32 num_chars = selection_right - segment_line_start; - segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); - selection_rect.mRight += segment_width; + S32 segment_line_start = segmentp->getStart() + segment_offset; + S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd); - break; + if (segment_line_start > segment_line_end) break; + + S32 segment_width = 0; + S32 segment_height = 0; + + // if selection after beginning of segment + if(selection_left >= segment_line_start) + { + S32 num_chars = llmin(selection_left, segment_line_end) - segment_line_start; + segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); + selection_rect.mLeft += segment_width; + } + + // if selection_right == segment_line_end then that means we are the first character of the next segment + // or first character of the next line, in either case we want to add the length of the current segment + // to the selection rectangle and continue. + // if selection right > segment_line_end then selection spans end of current segment... + if (selection_right >= segment_line_end) + { + // extend selection slightly beyond end of line + // to indicate selection of newline character (use "n" character to determine width) + S32 num_chars = segment_line_end - segment_line_start; + segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); + selection_rect.mRight += segment_width; + } + // else if selection ends on current segment... + else + { + S32 num_chars = selection_right - segment_line_start; + segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height); + selection_rect.mRight += segment_width; + +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + continue; +// [/SL:KB] +// break; + } } + selection_rects.push_back(selection_rect); } - selection_rects.push_back(selection_rect); + +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + // Only advance if the highlight ends on the current line + if (itHighlight->second > line_iter->mDocIndexEnd) + break; + ++itHighlight; } +// [/SL:KB] } // Draw the selection box (we're using a box instead of reversing the colors on the selected text). gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - const LLColor4& color = mSelectedBGColor; +// const LLColor4& color = mSelectedBGColor; F32 alpha = hasFocus() ? 0.7f : 0.3f; alpha *= getDrawContext().mAlpha; LLColor4 selection_color(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], alpha); @@ -1270,6 +1324,12 @@ void LLTextBase::draw() drawChild(mDocumentView); } +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + if (mHighlightsDirty) + refreshHighlights(); + if (!mHighlights.empty()) + drawHighlightsBackground(mHighlights, mHighlightedBGColor); +// [/SL:KB] drawSelectionBackground(); drawText(); drawCursor(); @@ -2302,6 +2362,10 @@ void LLTextBase::needsReflow(S32 index) { LL_DEBUGS() << "reflow on object " << (void*)this << " index = " << mReflowIndex << ", new index = " << index << LL_ENDL; mReflowIndex = llmin(mReflowIndex, index); + +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + mHighlightsDirty = true; +// [/SL:KB] } void LLTextBase::appendLineBreakSegment(const LLStyle::Params& style_params) @@ -2818,6 +2882,53 @@ bool LLTextBase::scrolledToEnd() return mScroller->isAtBottom(); } +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) +void LLTextBase::clearHighlights() +{ + mHighlightWord.clear(); + mHighlights.clear(); + mHighlightsDirty = false; +} + +void LLTextBase::refreshHighlights() +{ + if (mHighlightsDirty) + { + mHighlights.clear(); + if (!mHighlightWord.empty()) + { + const LLWString& wstrText = getWText(); + + std::list > highlightRanges; + if (mHighlightCaseInsensitive) + boost::ifind_all(highlightRanges, wstrText, mHighlightWord); + else + boost::find_all(highlightRanges, wstrText, mHighlightWord); + + for (std::list >::const_iterator itRange = highlightRanges.begin(); itRange != highlightRanges.end(); ++itRange) + { + S32 idxStart = itRange->begin() - wstrText.begin(); + mHighlights.push_back(range_pair_t(idxStart, idxStart + itRange->size())); + } + } + mHighlightsDirty = false; + } +} + +void LLTextBase::setHighlightWord(const std::string& strHighlight, bool fCaseInsensitive) +{ + if (strHighlight.empty()) + { + clearHighlights(); + return; + } + + mHighlightWord = utf8str_to_wstring(strHighlight); + mHighlightCaseInsensitive = fCaseInsensitive; + mHighlightsDirty = true; +} +// [/SL:KB] + bool LLTextBase::setCursor(S32 row, S32 column) { if (row < 0 || column < 0) return false; diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index d67ce2d035..bd1425c0e7 100755 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -302,6 +302,9 @@ public: bg_readonly_color, bg_writeable_color, bg_focus_color, +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + bg_highlighted_color, +// [/SL:KB] text_selected_color, bg_selected_color; @@ -468,6 +471,13 @@ public: bool scrolledToStart(); bool scrolledToEnd(); +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + // highlighting + void clearHighlights(); + void refreshHighlights(); + void setHighlightWord(const std::string& strHighlight, bool fCaseInsensitive); +// [/SL:KB] + const LLFontGL* getFont() const { return mFont; } virtual void appendLineBreakSegment(const LLStyle::Params& style_params); @@ -485,6 +495,10 @@ protected: struct compare_top; struct line_end_compare; typedef std::vector segment_vec_t; +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + typedef std::pair range_pair_t; + typedef std::list highlight_list_t; +// [/SL:KB] // Abstract inner base class representing an undoable editor command. // Concrete sub-classes can be defined for operations such as insert, remove, etc. @@ -552,6 +566,9 @@ protected: // draw methods void drawSelectionBackground(); // draws the black box behind the selected text +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + void drawHighlightsBackground(const highlight_list_t& highlights, const LLColor4& color); +// [/SL:KB] void drawCursor(); void drawText(); @@ -638,6 +655,9 @@ protected: LLUIColor mFocusBgColor; LLUIColor mTextSelectedColor; LLUIColor mSelectedBGColor; +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + LLUIColor mHighlightedBGColor; +// [/SL:KB] // cursor S32 mCursorPos; // I-beam is just after the mCursorPos-th character. @@ -659,6 +679,14 @@ protected: std::list > mMisspellRanges; std::vector mSuggestionList; +// [SL:KB] - Patch: Control-TextHighlight | Checked: 2013-12-30 (Catznip-3.6) + // highlighting + LLWString mHighlightWord; + bool mHighlightCaseInsensitive; + highlight_list_t mHighlights; + bool mHighlightsDirty; +// [/SL:KB] + // configuration S32 mHPad; // padding on left of text S32 mVPad; // padding above text diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index c93999f02c..4ebaf78e35 100755 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -342,6 +342,15 @@ void LLTextEditor::setText(const LLStringExplicit &utf8str, const LLStyle::Param resetDirty(); } +// [SL:KB] - Patch: UI-FloaterSearchReplace | Checked: 2013-12-30 (Catznip-3.6) +std::string LLTextEditor::getSelectionString() const +{ + S32 idxSel = 0, lenSel = 0; + getSelectionRange(&idxSel, &lenSel); + return (lenSel > 0) ? wstring_to_utf8str(getWText().substr(idxSel, lenSel)) : LLStringUtil::null; +} +// [/SL:KB] + //void LLTextEditor::selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap) // [SL:KB] - Patch: UI-FloaterSearchReplace | Checked: 2010-10-29 (Catznip-2.3.0a) | Added: Catznip-2.3.0a void LLTextEditor::selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap, BOOL search_up) diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index f21f6d8b93..a6ab3761f6 100755 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -148,6 +148,7 @@ public: // void selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE); // [SL:KB] - Patch: UI-FloaterSearchReplace | Checked: 2010-10-29 (Catznip-2.3.0a) | Added: Catznip-2.3.0a + std::string getSelectionString() const; void selectNext(const std::string& search_text_in, BOOL case_insensitive, BOOL wrap = TRUE, BOOL search_up = FALSE); BOOL replaceText(const std::string& search_text, const std::string& replace_text, BOOL case_insensitive, BOOL wrap = TRUE, BOOL search_up = FALSE); // [/SL:KB] diff --git a/indra/newview/llfloatersearchreplace.cpp b/indra/newview/llfloatersearchreplace.cpp index dc163af781..b0d014a1f6 100644 --- a/indra/newview/llfloatersearchreplace.cpp +++ b/indra/newview/llfloatersearchreplace.cpp @@ -1,39 +1,39 @@ /** - * @file llfloatersearchreplace.cpp - * @brief LLFloaterSearchReplace class implementation * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (c) 2010-2013, Kitty Barnett * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. + * The source code in this file is provided to you under the terms of the + * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt + * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * 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. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" -#include "llfloatersearchreplace.h" - #include "llcheckboxctrl.h" +#include "llfloaterreg.h" +#include "llfloatersearchreplace.h" +#include "lllineeditor.h" #include "llmultifloater.h" #include "lltexteditor.h" +#include "llviewermenu.h" + +// ============================================================================ +// LLFloaterSearchReplace class +// LLFloaterSearchReplace::LLFloaterSearchReplace(const LLSD& sdKey) - : LLFloater(sdKey), mEditor(NULL) + : LLFloater(sdKey) + , m_pSearchEditor(NULL) + , m_pReplaceEditor(NULL) + , m_pCaseInsensitiveCheck(NULL) + , m_pSearchUpCheck(NULL) { } @@ -41,84 +41,63 @@ LLFloaterSearchReplace::~LLFloaterSearchReplace() { } -//static -void LLFloaterSearchReplace::show(LLTextEditor* pEditor) -{ - LLFloaterSearchReplace* pSelf = LLFloaterReg::getTypedInstance("search_replace"); - if (!pSelf) - return; - - pSelf->mEditor = pEditor; - if (pEditor) - { - LLFloater *pDependeeNew = NULL, *pDependeeOld = pSelf->getDependee(); - LLView* pView = pEditor->getParent(); - while (pView) - { - pDependeeNew = dynamic_cast(pView); - if (pDependeeNew) - { - if (pDependeeNew != pDependeeOld) - { - if (pDependeeOld) - pDependeeOld->removeDependentFloater(pSelf); - - if (!pDependeeNew->getHost()) - pDependeeNew->addDependentFloater(pSelf); - else - pDependeeNew->getHost()->addDependentFloater(pSelf); - } - break; - } - pView = pView->getParent(); - } - - pSelf->getChildView("replace_text")->setEnabled(!pEditor->getReadOnly()); - pSelf->getChildView("replace_btn")->setEnabled(!pEditor->getReadOnly()); - pSelf->getChildView("replace_all_btn")->setEnabled(!pEditor->getReadOnly()); - pSelf->getChildView("search_text")->setFocus(TRUE); - - pSelf->openFloater(); - } -} - BOOL LLFloaterSearchReplace::postBuild() { - childSetAction("search_btn", boost::bind(&LLFloaterSearchReplace::onBtnSearch, this)); - childSetAction("replace_btn", boost::bind(&LLFloaterSearchReplace::onBtnReplace, this)); - childSetAction("replace_all_btn", boost::bind(&LLFloaterSearchReplace::onBtnReplaceAll, this)); + m_pSearchEditor = getChild("search_text"); + m_pSearchEditor->setCommitCallback(boost::bind(&LLFloaterSearchReplace::onSearchClick, this)); + m_pSearchEditor->setCommitOnFocusLost(false); + m_pSearchEditor->setKeystrokeCallback(boost::bind(&LLFloaterSearchReplace::refreshHighlight, this), NULL); + m_pReplaceEditor = getChild("replace_text"); - setDefaultBtn("search_btn"); + m_pCaseInsensitiveCheck = getChild("case_text"); + m_pCaseInsensitiveCheck->setCommitCallback(boost::bind(&LLFloaterSearchReplace::refreshHighlight, this)); + m_pSearchUpCheck = getChild("find_previous"); + + LLButton* pSearchBtn = getChild("search_btn"); + pSearchBtn->setCommitCallback(boost::bind(&LLFloaterSearchReplace::onSearchClick, this)); + setDefaultBtn(pSearchBtn); + + LLButton* pReplaceBtn = getChild("replace_btn"); + pReplaceBtn->setCommitCallback(boost::bind(&LLFloaterSearchReplace::onReplaceClick, this)); + + LLButton* pReplaceAllBtn = getChild("replace_all_btn"); + pReplaceAllBtn->setCommitCallback(boost::bind(&LLFloaterSearchReplace::onReplaceAllClick, this)); return TRUE; } -void LLFloaterSearchReplace::onBtnSearch() +void LLFloaterSearchReplace::onOpen(const LLSD& sdKey) { - LLCheckBoxCtrl* caseChk = getChild("case_text"); - LLCheckBoxCtrl* prevChk = getChild("find_previous"); - mEditor->selectNext(getChild("search_text")->getValue().asString(), caseChk->get(), TRUE, prevChk->get()); + LLTextEditor* pEditor = getEditor(); + if (pEditor) + { + // HACK-Catznip: hasSelection() is inaccessible but canCopy() is (currently) a synonym *sighs* + if (pEditor->canCopy()) + { + m_pSearchEditor->setText(pEditor->getSelectionString()); + m_pSearchEditor->setCursorToEnd(); + } + pEditor->setHighlightWord(m_pSearchEditor->getText(), m_pCaseInsensitiveCheck->get()); + + m_pReplaceEditor->setEnabled( (pEditor) && (!pEditor->getReadOnly()) ); + getChild("replace_btn")->setEnabled( (pEditor) && (!pEditor->getReadOnly()) ); + getChild("replace_all_btn")->setEnabled( (pEditor) && (!pEditor->getReadOnly()) ); + } + m_pSearchEditor->setFocus(TRUE); } -void LLFloaterSearchReplace::onBtnReplace() +void LLFloaterSearchReplace::onClose(bool fQuiting) { - LLCheckBoxCtrl* caseChk = getChild("case_text"); - LLCheckBoxCtrl* prevChk = getChild("find_previous"); - mEditor->replaceText( - getChild("search_text")->getValue().asString(), getChild("replace_text")->getValue().asString(), caseChk->get(), TRUE, prevChk->get()); -} - -void LLFloaterSearchReplace::onBtnReplaceAll() -{ - LLCheckBoxCtrl* caseChk = getChild("case_text"); - mEditor->replaceTextAll(getChild("search_text")->getValue().asString(), getChild("replace_text")->getValue().asString(), caseChk->get()); + LLTextEditor* pEditor = getEditor(); + if (pEditor) + { + pEditor->clearHighlights(); + } } bool LLFloaterSearchReplace::hasAccelerators() const { - // Pass this on to the editor we're operating on (or any view up along its hierarchy - // (allows Ctrl-F to work when the floater itself has focus - see changeset 0c8947e5f433) - const LLView* pView = (LLView*)mEditor; + const LLView* pView = dynamic_cast(m_EditorHandle.get()); while (pView) { if (pView->hasAccelerators()) @@ -130,21 +109,108 @@ bool LLFloaterSearchReplace::hasAccelerators() const BOOL LLFloaterSearchReplace::handleKeyHere(KEY key, MASK mask) { - // return mEditorCore->handleKeyHere(key, mask); - // VWR-23608 Satomi Ahn - if ( KEY_RETURN == key ) - { - if (getChild("search_text")->hasFocus()) { onBtnSearch(); return TRUE; } - else if (getChild("replace_text")->hasFocus()) { onBtnReplace(); return TRUE; } - } - // Pass this on to the editor we're operating on (or any view up along its hierarchy + // Pass this on to the editor we're operating on (or any view up along its hierarchy) if we don't handle the key ourselves // (allows Ctrl-F to work when the floater itself has focus - see changeset 0c8947e5f433) - LLView* pView = (LLView*)mEditor; + BOOL handled = LLFloater::handleKeyHere(key, mask); + if (!handled) + { + // Check if one of our children currently has keyboard focus and if so route edit accellerators to it + if (gFocusMgr.childHasKeyboardFocus(this)) + { + LLView* pEditView = dynamic_cast(LLEditMenuHandler::gEditMenuHandler); + if ( (pEditView) && (pEditView->hasAncestor(this)) && (gEditMenu) && (gEditMenu->handleAcceleratorKey(key, mask)) ) + { + return TRUE; + } + } + + LLView* pView = m_EditorHandle.get(); + while (pView) + { + if ( (pView->hasAccelerators()) && (pView->handleKeyHere(key, mask)) ) + return TRUE; + pView = pView->getParent(); + } + } + return handled; +} + +//static +void LLFloaterSearchReplace::show(LLTextEditor* pEditor) +{ + LLFloaterSearchReplace* pSelf = LLFloaterReg::getTypedInstance("search_replace"); + if ( (!pSelf) || (!pEditor) ) + return; + + LLFloater *pDependeeNew = NULL, *pDependeeOld = pSelf->getDependee(); + LLView* pView = pEditor->getParent(); while (pView) { - if (pView->hasAccelerators()) - return pView->handleKeyHere(key, mask); + pDependeeNew = dynamic_cast(pView); + if (pDependeeNew) + { + if (pDependeeNew != pDependeeOld) + { + if (pDependeeOld) + { + if (pSelf->getEditor()) + pSelf->getEditor()->clearHighlights(); + pDependeeOld->removeDependentFloater(pSelf); + } + + if (!pDependeeNew->getHost()) + pDependeeNew->addDependentFloater(pSelf); + else + pDependeeNew->getHost()->addDependentFloater(pSelf); + } + break; + } pView = pView->getParent(); } - return FALSE; + + pSelf->m_EditorHandle = pEditor->getHandle(); + pSelf->openFloater(); } + +LLTextEditor* LLFloaterSearchReplace::getEditor() const +{ + return dynamic_cast(m_EditorHandle.get()); +} + +void LLFloaterSearchReplace::refreshHighlight() +{ + LLTextEditor* pEditor = getEditor(); + if (pEditor) + { + pEditor->setHighlightWord(m_pSearchEditor->getText(), m_pCaseInsensitiveCheck->get()); + } +} + +void LLFloaterSearchReplace::onSearchClick() +{ + LLTextEditor* pEditor = getEditor(); + if (pEditor) + { + pEditor->selectNext(m_pSearchEditor->getText(), m_pCaseInsensitiveCheck->get(), TRUE, m_pSearchUpCheck->get()); + } +} + +void LLFloaterSearchReplace::onReplaceClick() +{ + LLTextEditor* pEditor = getEditor(); + if (pEditor) + { + pEditor->replaceText(m_pSearchEditor->getText(), m_pReplaceEditor->getText(), m_pCaseInsensitiveCheck->get(), TRUE, m_pSearchUpCheck->get()); + } +} + +void LLFloaterSearchReplace::onReplaceAllClick() +{ + LLTextEditor* pEditor = getEditor(); + if (pEditor) + { + pEditor->replaceTextAll(m_pSearchEditor->getText(), m_pReplaceEditor->getText(), m_pCaseInsensitiveCheck->get()); + } +} + +// ============================================================================ diff --git a/indra/newview/llfloatersearchreplace.h b/indra/newview/llfloatersearchreplace.h index 0962219c4f..4a53047b26 100644 --- a/indra/newview/llfloatersearchreplace.h +++ b/indra/newview/llfloatersearchreplace.h @@ -1,60 +1,76 @@ /** - * @file llfloatersearchreplace.h - * @brief LLFloaterSearchReplace class implementation * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (c) 2010-2013, Kitty Barnett * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. + * The source code in this file is provided to you under the terms of the + * GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt + * in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * 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. * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ */ #ifndef LL_FLOATERSEARCHREPLACE_H #define LL_FLOATERSEARCHREPLACE_H #include "llfloater.h" -#include "llfloaterreg.h" +// ============================================================================ +// Forward declarations +// + +class LLCheckBoxCtrl; +class LLLineEditor; class LLTextEditor; +// ============================================================================ +// LLFloaterSearchReplace class +// + class LLFloaterSearchReplace : public LLFloater { public: LLFloaterSearchReplace(const LLSD& sdKey); ~LLFloaterSearchReplace(); - /*virtual*/ bool hasAccelerators() const; - /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); - /*virtual*/ BOOL postBuild(); - + /* + * LLView overrides + */ public: - LLTextEditor* getEditor() { return mEditor; } - - static void show(LLTextEditor* pEditor); + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); + /*virtual*/ bool hasAccelerators() const; + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& sdKey); + /*virtual*/ void onClose(bool fQuiting); + /* + * Member functions + */ +public: + static void show(LLTextEditor* pEditor); protected: - void onBtnSearch(); - void onBtnReplace(); - void onBtnReplaceAll(); + LLTextEditor* getEditor() const; + void refreshHighlight(); + void onSearchClick(); + void onSearchKeystroke(); + void onReplaceClick(); + void onReplaceAllClick(); + /* + * Member variables + */ private: - LLTextEditor* mEditor; + LLLineEditor* m_pSearchEditor; + LLLineEditor* m_pReplaceEditor; + LLCheckBoxCtrl* m_pCaseInsensitiveCheck; + LLCheckBoxCtrl* m_pSearchUpCheck; + LLHandle m_EditorHandle; }; -#endif // LL_FLOATERSEARCHREPLACE_H +// ============================================================================ +#endif // LL_FLOATERSEARCHREPLACE_H diff --git a/indra/newview/skins/ansastorm/colors.xml b/indra/newview/skins/ansastorm/colors.xml index d169f932f8..dc6574e26c 100644 --- a/indra/newview/skins/ansastorm/colors.xml +++ b/indra/newview/skins/ansastorm/colors.xml @@ -1100,6 +1100,9 @@ + diff --git a/indra/newview/skins/ansastorm/themes/blood/colors.xml b/indra/newview/skins/ansastorm/themes/blood/colors.xml index 983f1ce8b9..43e8fae103 100644 --- a/indra/newview/skins/ansastorm/themes/blood/colors.xml +++ b/indra/newview/skins/ansastorm/themes/blood/colors.xml @@ -1063,6 +1063,9 @@ + diff --git a/indra/newview/skins/ansastorm/themes/classic_brown/colors.xml b/indra/newview/skins/ansastorm/themes/classic_brown/colors.xml index e743e9fa5a..dd2cfbd9d3 100644 --- a/indra/newview/skins/ansastorm/themes/classic_brown/colors.xml +++ b/indra/newview/skins/ansastorm/themes/classic_brown/colors.xml @@ -1100,6 +1100,9 @@ + diff --git a/indra/newview/skins/ansastorm/themes/ectoplasma/colors.xml b/indra/newview/skins/ansastorm/themes/ectoplasma/colors.xml index fdbaf8410b..543ad46790 100644 --- a/indra/newview/skins/ansastorm/themes/ectoplasma/colors.xml +++ b/indra/newview/skins/ansastorm/themes/ectoplasma/colors.xml @@ -1054,6 +1054,9 @@ + diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index ded9c5599c..0d0f2a0113 100755 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -1044,6 +1044,9 @@ + diff --git a/indra/newview/skins/default/xui/en/floater_search_replace.xml b/indra/newview/skins/default/xui/en/floater_search_replace.xml index 007603c33c..fa608c9515 100644 --- a/indra/newview/skins/default/xui/en/floater_search_replace.xml +++ b/indra/newview/skins/default/xui/en/floater_search_replace.xml @@ -2,7 +2,7 @@ diff --git a/indra/newview/skins/firestorm/themes/ctrlaltstudio/colors.xml b/indra/newview/skins/firestorm/themes/ctrlaltstudio/colors.xml index c928dad12f..c77a14ca1d 100644 --- a/indra/newview/skins/firestorm/themes/ctrlaltstudio/colors.xml +++ b/indra/newview/skins/firestorm/themes/ctrlaltstudio/colors.xml @@ -30,6 +30,9 @@ + @@ -818,6 +821,9 @@ + diff --git a/indra/newview/skins/firestorm/xui/en/widgets/simple_text_editor.xml b/indra/newview/skins/firestorm/xui/en/widgets/simple_text_editor.xml index c863343a96..b7131a6d5c 100644 --- a/indra/newview/skins/firestorm/xui/en/widgets/simple_text_editor.xml +++ b/indra/newview/skins/firestorm/xui/en/widgets/simple_text_editor.xml @@ -21,6 +21,7 @@ bg_visible="true" bg_readonly_color="TextBgReadOnlyColor" bg_writeable_color="TextBgWriteableColor" + bg_highlighted_color="TextBgHighlightColor" bg_selected_color="simpleeditor_bg_selected" bg_focus_color="TextBgFocusColor"> diff --git a/indra/newview/skins/latency/colors.xml b/indra/newview/skins/latency/colors.xml index 20d0750294..baad37ba3d 100644 --- a/indra/newview/skins/latency/colors.xml +++ b/indra/newview/skins/latency/colors.xml @@ -210,6 +210,9 @@ + diff --git a/indra/newview/skins/latency/xui/en/widgets/simple_text_editor.xml b/indra/newview/skins/latency/xui/en/widgets/simple_text_editor.xml index 9b9550878c..0f1024df65 100644 --- a/indra/newview/skins/latency/xui/en/widgets/simple_text_editor.xml +++ b/indra/newview/skins/latency/xui/en/widgets/simple_text_editor.xml @@ -21,6 +21,7 @@ bg_visible="true" bg_readonly_color="TextBgReadOnlyColor" bg_writeable_color="TextBgWriteableColor" + bg_highlighted_color="TextBgHighlightColor" bg_selected_color="TextBgSelectedColor" bg_focus_color="TextBgFocusColor"> diff --git a/indra/newview/skins/starlight/xui/en/widgets/simple_text_editor.xml b/indra/newview/skins/starlight/xui/en/widgets/simple_text_editor.xml index 2371e041e2..61876ab068 100644 --- a/indra/newview/skins/starlight/xui/en/widgets/simple_text_editor.xml +++ b/indra/newview/skins/starlight/xui/en/widgets/simple_text_editor.xml @@ -21,6 +21,7 @@ bg_visible="true" bg_readonly_color="TextBgReadOnlyColor" bg_writeable_color="TextBgWriteableColor" + bg_highlighted_color="EmphasisColor_35" bg_selected_color="EmphasisColor" bg_focus_color="TextBgFocusColor"> diff --git a/indra/newview/skins/starlightcui/xui/en/widgets/simple_text_editor.xml b/indra/newview/skins/starlightcui/xui/en/widgets/simple_text_editor.xml index 664ccfdad1..f9cf52c8fc 100644 --- a/indra/newview/skins/starlightcui/xui/en/widgets/simple_text_editor.xml +++ b/indra/newview/skins/starlightcui/xui/en/widgets/simple_text_editor.xml @@ -21,6 +21,7 @@ bg_visible="true" bg_readonly_color="TextBgReadOnlyColor" bg_writeable_color="TextBgWriteableColor" + bg_highlighted_color="SL-EmphasisColor" bg_selected_color="SL-EmphasisColor" bg_focus_color="TextBgFocusColor"> diff --git a/indra/newview/skins/vintage/colors.xml b/indra/newview/skins/vintage/colors.xml index b5f49576eb..f81aab44e3 100644 --- a/indra/newview/skins/vintage/colors.xml +++ b/indra/newview/skins/vintage/colors.xml @@ -214,6 +214,9 @@ + diff --git a/indra/newview/skins/vintage/xui/en/widgets/simple_text_editor.xml b/indra/newview/skins/vintage/xui/en/widgets/simple_text_editor.xml index 6ef40625bd..d513c21a38 100644 --- a/indra/newview/skins/vintage/xui/en/widgets/simple_text_editor.xml +++ b/indra/newview/skins/vintage/xui/en/widgets/simple_text_editor.xml @@ -21,6 +21,7 @@ bg_visible="true" bg_readonly_color="TextBgReadOnlyColor" bg_writeable_color="TextBgWriteableColor" + bg_highlighted_color="TextBgHighlightColor" bg_selected_color="TextBgSelectedColor" bg_focus_color="TextBgFocusColor">