231 lines
7.4 KiB
C++
231 lines
7.4 KiB
C++
/**
|
|
*
|
|
* Copyright (c) 2010-2013, Kitty Barnett
|
|
*
|
|
* 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
|
|
*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
#include "llviewerprecompiledheaders.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)
|
|
, m_pSearchEditor(NULL)
|
|
, m_pReplaceEditor(NULL)
|
|
, m_pCaseInsensitiveCheck(NULL)
|
|
, m_pSearchUpCheck(NULL)
|
|
{
|
|
}
|
|
|
|
LLFloaterSearchReplace::~LLFloaterSearchReplace()
|
|
{
|
|
}
|
|
|
|
bool LLFloaterSearchReplace::postBuild()
|
|
{
|
|
m_pSearchEditor = getChild<LLLineEditor>("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<LLLineEditor>("replace_text");
|
|
|
|
m_pCaseInsensitiveCheck = getChild<LLCheckBoxCtrl>("case_text");
|
|
m_pCaseInsensitiveCheck->setCommitCallback(boost::bind(&LLFloaterSearchReplace::refreshHighlight, this));
|
|
m_pSearchUpCheck = getChild<LLCheckBoxCtrl>("find_previous");
|
|
|
|
LLButton* pSearchBtn = getChild<LLButton>("search_btn");
|
|
pSearchBtn->setCommitCallback(boost::bind(&LLFloaterSearchReplace::onSearchClick, this));
|
|
setDefaultBtn(pSearchBtn);
|
|
|
|
LLButton* pReplaceBtn = getChild<LLButton>("replace_btn");
|
|
pReplaceBtn->setCommitCallback(boost::bind(&LLFloaterSearchReplace::onReplaceClick, this));
|
|
|
|
LLButton* pReplaceAllBtn = getChild<LLButton>("replace_all_btn");
|
|
pReplaceAllBtn->setCommitCallback(boost::bind(&LLFloaterSearchReplace::onReplaceAllClick, this));
|
|
|
|
return true;
|
|
}
|
|
|
|
void LLFloaterSearchReplace::onOpen(const LLSD& sdKey)
|
|
{
|
|
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<LLButton>("replace_btn")->setEnabled( (pEditor) && (!pEditor->getReadOnly()) );
|
|
getChild<LLButton>("replace_all_btn")->setEnabled( (pEditor) && (!pEditor->getReadOnly()) );
|
|
}
|
|
m_pSearchEditor->setFocus(true);
|
|
}
|
|
|
|
void LLFloaterSearchReplace::onClose(bool fQuiting)
|
|
{
|
|
LLTextEditor* pEditor = getEditor();
|
|
if (pEditor)
|
|
{
|
|
pEditor->clearHighlights();
|
|
}
|
|
}
|
|
|
|
bool LLFloaterSearchReplace::hasAccelerators() const
|
|
{
|
|
const LLView* pView = dynamic_cast<LLTextEditor*>(m_EditorHandle.get());
|
|
while (pView)
|
|
{
|
|
if (pView->hasAccelerators())
|
|
return true;
|
|
pView = pView->getParent();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool LLFloaterSearchReplace::handleKeyHere(KEY key, MASK mask)
|
|
{
|
|
// 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)
|
|
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<LLView*>(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
|
|
LLFloaterSearchReplace* LLFloaterSearchReplace::show(LLTextEditor* pEditor)
|
|
{
|
|
LLFloaterSearchReplace* pSelf = LLFloaterReg::getTypedInstance<LLFloaterSearchReplace>("search_replace");
|
|
if ( (!pSelf) || (!pEditor) )
|
|
return NULL;
|
|
|
|
LLFloater *pDependeeNew = NULL, *pDependeeOld = pSelf->getDependee();
|
|
LLView* pView = pEditor->getParent();
|
|
while (pView)
|
|
{
|
|
pDependeeNew = dynamic_cast<LLFloater*>(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();
|
|
}
|
|
|
|
pSelf->m_EditorHandle = pEditor->getHandle();
|
|
pSelf->openFloater();
|
|
|
|
return pSelf;
|
|
}
|
|
|
|
//static
|
|
LLFloaterSearchReplace* LLFloaterSearchReplace::findInstance()
|
|
{
|
|
return LLFloaterReg::findTypedInstance<LLFloaterSearchReplace>("search_replace");
|
|
}
|
|
|
|
LLTextEditor* LLFloaterSearchReplace::getEditor() const
|
|
{
|
|
return dynamic_cast<LLTextEditor*>(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());
|
|
}
|
|
}
|
|
|
|
void LLFloaterSearchReplace::setCanReplace(bool can_replace)
|
|
{
|
|
m_pReplaceEditor->setEnabled(can_replace);
|
|
getChild<LLButton>("replace_btn")->setEnabled(can_replace);
|
|
getChild<LLButton>("replace_all_btn")->setEnabled(can_replace);
|
|
}
|
|
// ============================================================================
|