summaryrefslogtreecommitdiff
path: root/indra/llui/lllineeditor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui/lllineeditor.cpp')
-rw-r--r--indra/llui/lllineeditor.cpp200
1 files changed, 158 insertions, 42 deletions
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 3eb58e1aec..d0fbf4b913 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -37,6 +37,7 @@
#include "llgl.h"
#include "lltimer.h"
+#include "llcalc.h"
//#include "llclipboard.h"
#include "llcontrol.h"
#include "llbutton.h"
@@ -81,6 +82,7 @@ LLLineEditor::Params::Params()
: max_length(""),
keystroke_callback("keystroke_callback"),
prevalidate_callback("prevalidate_callback"),
+ prevalidate_input_callback("prevalidate_input_callback"),
background_image("background_image"),
background_image_disabled("background_image_disabled"),
background_image_focused("background_image_focused"),
@@ -88,6 +90,7 @@ LLLineEditor::Params::Params()
revert_on_esc("revert_on_esc", true),
commit_on_focus_lost("commit_on_focus_lost", true),
ignore_tab("ignore_tab", true),
+ is_password("is_password", false),
cursor_color("cursor_color"),
text_color("text_color"),
text_readonly_color("text_readonly_color"),
@@ -100,10 +103,11 @@ LLLineEditor::Params::Params()
text_pad_right("text_pad_right"),
default_text("default_text")
{
- mouse_opaque = true;
+ changeDefault(mouse_opaque, true);
addSynonym(select_on_focus, "select_all_on_focus_received");
addSynonym(border, "border");
addSynonym(label, "watermark_text");
+ addSynonym(max_length.chars, "max_length");
}
LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
@@ -129,8 +133,9 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mBorderThickness( 0 ),
mIgnoreArrowKeys( FALSE ),
mIgnoreTab( p.ignore_tab ),
- mDrawAsterixes( FALSE ),
+ mDrawAsterixes( p.is_password ),
mSelectAllonFocusReceived( p.select_on_focus ),
+ mSelectAllonCommit( TRUE ),
mPassDelete(FALSE),
mReadOnly(FALSE),
mBgImage( p.background_image ),
@@ -172,6 +177,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
updateTextPadding();
setCursor(mText.length());
+ setPrevalidateInput(p.prevalidate_input_callback());
setPrevalidate(p.prevalidate_callback());
LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>
@@ -192,6 +198,7 @@ LLLineEditor::~LLLineEditor()
void LLLineEditor::onFocusReceived()
{
+ gEditMenuHandler = this;
LLUICtrl::onFocusReceived();
updateAllowingLanguageInput();
}
@@ -227,7 +234,10 @@ void LLLineEditor::onCommit()
setControlValue(getValue());
LLUICtrl::onCommit();
- selectAll();
+
+ // Selection on commit needs to be turned off when evaluating maths
+ // expressions, to allow indication of the error position
+ if (mSelectAllonCommit) selectAll();
}
// Returns TRUE if user changed value at all
@@ -388,7 +398,11 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
setCursor(llmin((S32)mText.length(), getCursor()));
// Set current history line to end of history.
- if(mLineHistory.end() != mLineHistory.begin())
+ if (mLineHistory.empty())
+ {
+ mCurrentHistoryLine = mLineHistory.end();
+ }
+ else
{
mCurrentHistoryLine = mLineHistory.end() - 1;
}
@@ -400,23 +414,15 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
// Picks a new cursor position based on the actual screen size of text being drawn.
void LLLineEditor::setCursorAtLocalPos( S32 local_mouse_x )
{
- const llwchar* wtext = mText.getWString().c_str();
- LLWString asterix_text;
- if (mDrawAsterixes)
- {
- for (S32 i = 0; i < mText.length(); i++)
- {
- asterix_text += utf8str_to_wstring(PASSWORD_ASTERISK);
- }
- wtext = asterix_text.c_str();
- }
+ S32 cursor_pos = calcCursorPos(local_mouse_x);
+
+ S32 left_pos = llmin( mSelectionStart, cursor_pos );
+ S32 length = llabs( mSelectionStart - cursor_pos );
+ const LLWString& substr = mText.getWString().substr(left_pos, length);
+
+ if (mIsSelecting && !prevalidateInput(substr))
+ return;
- S32 cursor_pos =
- mScrollHPos +
- mGLFont->charFromPixelOffset(
- wtext, mScrollHPos,
- (F32)(local_mouse_x - mTextLeftEdge),
- (F32)(mTextRightEdge - mTextLeftEdge + 1)); // min-max range is inclusive
setCursor(cursor_pos);
}
@@ -500,6 +506,11 @@ BOOL LLLineEditor::canSelectAll() const
void LLLineEditor::selectAll()
{
+ if (!prevalidateInput(mText.getWString()))
+ {
+ return;
+ }
+
mSelectionStart = mText.length();
mSelectionEnd = 0;
setCursor(mSelectionEnd);
@@ -585,6 +596,9 @@ BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask)
if (mask & MASK_SHIFT)
{
+ // assume we're starting a drag select
+ mIsSelecting = TRUE;
+
// Handle selection extension
S32 old_cursor_pos = getCursor();
setCursorAtLocalPos(x);
@@ -619,8 +633,6 @@ BOOL LLLineEditor::handleMouseDown(S32 x, S32 y, MASK mask)
mSelectionStart = old_cursor_pos;
mSelectionEnd = getCursor();
}
- // assume we're starting a drag select
- mIsSelecting = TRUE;
}
else
{
@@ -791,6 +803,9 @@ void LLLineEditor::removeChar()
{
if( getCursor() > 0 )
{
+ if (!prevalidateInput(mText.getWString().substr(getCursor()-1, 1)))
+ return;
+
mText.erase(getCursor() - 1, 1);
setCursor(getCursor() - 1);
@@ -811,6 +826,9 @@ void LLLineEditor::addChar(const llwchar uni_char)
}
else if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode())
{
+ if (!prevalidateInput(mText.getWString().substr(getCursor(), 1)))
+ return;
+
mText.erase(getCursor(), 1);
}
@@ -859,6 +877,13 @@ void LLLineEditor::extendSelection( S32 new_cursor_pos )
startSelection();
}
+ S32 left_pos = llmin( mSelectionStart, new_cursor_pos );
+ S32 selection_length = llabs( mSelectionStart - new_cursor_pos );
+ const LLWString& selection = mText.getWString().substr(left_pos, selection_length);
+
+ if (!prevalidateInput(selection))
+ return;
+
setCursor(new_cursor_pos);
mSelectionEnd = getCursor();
}
@@ -989,8 +1014,12 @@ void LLLineEditor::deleteSelection()
{
if( !mReadOnly && hasSelection() )
{
- S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
- S32 selection_length = llabs( mSelectionStart - mSelectionEnd );
+ S32 left_pos, selection_length;
+ getSelectionRange(&left_pos, &selection_length);
+ const LLWString& selection = mText.getWString().substr(left_pos, selection_length);
+
+ if (!prevalidateInput(selection))
+ return;
mText.erase(left_pos, selection_length);
deselect();
@@ -1008,13 +1037,17 @@ void LLLineEditor::cut()
{
if( canCut() )
{
+ S32 left_pos, length;
+ getSelectionRange(&left_pos, &length);
+ const LLWString& selection = mText.getWString().substr(left_pos, length);
+
+ if (!prevalidateInput(selection))
+ return;
+
// Prepare for possible rollback
LLLineEditorRollback rollback( this );
-
- S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
- S32 length = llabs( mSelectionStart - mSelectionEnd );
- gClipboard.copyFromSubstring( mText.getWString(), left_pos, length );
+ LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length );
deleteSelection();
// Validate new string and rollback the if needed.
@@ -1045,13 +1078,13 @@ void LLLineEditor::copy()
{
S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
S32 length = llabs( mSelectionStart - mSelectionEnd );
- gClipboard.copyFromSubstring( mText.getWString(), left_pos, length );
+ LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length );
}
}
BOOL LLLineEditor::canPaste() const
{
- return !mReadOnly && gClipboard.canPasteString();
+ return !mReadOnly && LLClipboard::instance().isTextAvailable();
}
void LLLineEditor::paste()
@@ -1082,17 +1115,13 @@ void LLLineEditor::pasteHelper(bool is_primary)
if (can_paste_it)
{
LLWString paste;
- if (is_primary)
- {
- paste = gClipboard.getPastePrimaryWString();
- }
- else
- {
- paste = gClipboard.getPasteWString();
- }
+ LLClipboard::instance().pasteFromClipboard(paste, is_primary);
if (!paste.empty())
{
+ if (!prevalidateInput(paste))
+ return;
+
// Prepare for possible rollback
LLLineEditorRollback rollback(this);
@@ -1173,13 +1202,13 @@ void LLLineEditor::copyPrimary()
{
S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
S32 length = llabs( mSelectionStart - mSelectionEnd );
- gClipboard.copyFromPrimarySubstring( mText.getWString(), left_pos, length );
+ LLClipboard::instance().copyToClipboard( mText.getWString(), left_pos, length, true);
}
}
BOOL LLLineEditor::canPastePrimary() const
{
- return !mReadOnly && gClipboard.canPastePrimaryString();
+ return !mReadOnly && LLClipboard::instance().isTextAvailable(true);
}
void LLLineEditor::updatePrimary()
@@ -1440,6 +1469,13 @@ BOOL LLLineEditor::handleUnicodeCharHere(llwchar uni_char)
LLLineEditorRollback rollback( this );
+ {
+ LLWString u_char;
+ u_char.assign(1, uni_char);
+ if (!prevalidateInput(u_char))
+ return handled;
+ }
+
addChar(uni_char);
mKeystrokeTimer.reset();
@@ -1491,6 +1527,15 @@ void LLLineEditor::doDelete()
}
else if ( getCursor() < mText.length())
{
+ const LLWString& text_to_delete = mText.getWString().substr(getCursor(), 1);
+
+ if (!prevalidateInput(text_to_delete))
+ {
+ if( mKeystrokeCallback )
+ mKeystrokeCallback( this );
+
+ return;
+ }
setCursor(getCursor() + 1);
removeChar();
}
@@ -1529,8 +1574,11 @@ void LLLineEditor::drawBackground()
{
image = mBgImage;
}
+
+ if (!image) return;
- F32 alpha = getDrawContext().mAlpha;
+ F32 alpha = getCurrentTransparency();
+
// optionally draw programmatic border
if (has_focus)
{
@@ -1575,7 +1623,7 @@ void LLLineEditor::draw()
LLRect background( 0, getRect().getHeight(), getRect().getWidth(), 0 );
background.stretch( -mBorderThickness );
- S32 lineeditor_v_pad = llround((background.getHeight() - mGLFont->getLineHeight())/2);
+ S32 lineeditor_v_pad = (background.getHeight() - mGLFont->getLineHeight()) / 2;
drawBackground();
@@ -1835,6 +1883,27 @@ S32 LLLineEditor::findPixelNearestPos(const S32 cursor_offset) const
return result;
}
+S32 LLLineEditor::calcCursorPos(S32 mouse_x)
+{
+ const llwchar* wtext = mText.getWString().c_str();
+ LLWString asterix_text;
+ if (mDrawAsterixes)
+ {
+ for (S32 i = 0; i < mText.length(); i++)
+ {
+ asterix_text += utf8str_to_wstring(PASSWORD_ASTERISK);
+ }
+ wtext = asterix_text.c_str();
+ }
+
+ S32 cur_pos = mScrollHPos +
+ mGLFont->charFromPixelOffset(
+ wtext, mScrollHPos,
+ (F32)(mouse_x - mTextLeftEdge),
+ (F32)(mTextRightEdge - mTextLeftEdge + 1)); // min-max range is inclusive
+
+ return cur_pos;
+}
//virtual
void LLLineEditor::clear()
{
@@ -1928,6 +1997,22 @@ void LLLineEditor::setPrevalidate(LLTextValidate::validate_func_t func)
updateAllowingLanguageInput();
}
+void LLLineEditor::setPrevalidateInput(LLTextValidate::validate_func_t func)
+{
+ mPrevalidateInputFunc = func;
+ updateAllowingLanguageInput();
+}
+
+bool LLLineEditor::prevalidateInput(const LLWString& wstr)
+{
+ if (mPrevalidateInputFunc && !mPrevalidateInputFunc(wstr))
+ {
+ return false;
+ }
+
+ return true;
+}
+
// static
BOOL LLLineEditor::postvalidateFloat(const std::string &str)
{
@@ -1987,6 +2072,32 @@ BOOL LLLineEditor::postvalidateFloat(const std::string &str)
return success;
}
+BOOL LLLineEditor::evaluateFloat()
+{
+ bool success;
+ F32 result = 0.f;
+ std::string expr = getText();
+ LLStringUtil::toUpper(expr);
+
+ success = LLCalc::getInstance()->evalString(expr, result);
+
+ if (!success)
+ {
+ // Move the cursor to near the error on failure
+ setCursor(LLCalc::getInstance()->getLastErrorPos());
+ // *TODO: Translated error message indicating the type of error? Select error text?
+ }
+ else
+ {
+ // Replace the expression with the result
+ std::string result_str = llformat("%f",result);
+ setText(result_str);
+ selectAll();
+ }
+
+ return success;
+}
+
void LLLineEditor::onMouseCaptureLost()
{
endSelection();
@@ -2286,3 +2397,8 @@ void LLLineEditor::setContextMenu(LLContextMenu* new_context_menu)
else
mContextMenuHandle.markDead();
}
+
+void LLLineEditor::setFont(const LLFontGL* font)
+{
+ mGLFont = font;
+}