LineEdit copy-paste & selection by shift-cursor.
This commit is contained in:
parent
5d5cf9e0e0
commit
6d22d95d97
@ -75,6 +75,5 @@
|
||||
</element>
|
||||
<element type="Text">
|
||||
<font name="Cour.ttf" size="10" />
|
||||
<selectioncolor value="1.0 0.5 0.5" />
|
||||
</element>
|
||||
</elements>
|
@ -172,12 +172,18 @@ static void registerLineEdit(asIScriptEngine* engine)
|
||||
engine->RegisterObjectMethod("LineEdit", "void setMaxLength(uint)", asMETHOD(LineEdit, setMaxLength), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "void setEchoCharacter(uint8)", asMETHOD(LineEdit, setEchoCharacter), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "void setDefocusable(bool)", asMETHOD(LineEdit, setDefocusable), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "void setCursorMovable(bool)", asMETHOD(LineEdit, setCursorMovable), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "void setTextSelectable(bool)", asMETHOD(LineEdit, setTextSelectable), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "void setTextCopyable(bool)", asMETHOD(LineEdit, setTextCopyable), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "const string& getText() const", asMETHOD(LineEdit, getText), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "uint getCursorPosition() const", asMETHOD(LineEdit, getCursorPosition), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "float getCursorBlinkRate() const", asMETHOD(LineEdit, getCursorBlinkRate), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "uint getMaxLength() const", asMETHOD(LineEdit, getMaxLength), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "uint8 getEchoCharacter() const", asMETHOD(LineEdit, getEchoCharacter), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "bool isDefocusable() const", asMETHOD(LineEdit, isDefocusable), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "bool isCursorMovable() const", asMETHOD(LineEdit, isCursorMovable), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "bool isTextSelectable() const", asMETHOD(LineEdit, isTextSelectable), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "bool isTextCopyable() const", asMETHOD(LineEdit, isTextCopyable), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "Text@+ getTextElement() const", asMETHOD(LineEdit, getTextElement), asCALL_THISCALL);
|
||||
engine->RegisterObjectMethod("LineEdit", "BorderImage@+ getCursorElement() const", asMETHOD(LineEdit, getCursorElement), asCALL_THISCALL);
|
||||
registerRefCasts<UIElement, LineEdit>(engine, "UIElement", "LineEdit");
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "Precompiled.h"
|
||||
#include "Input.h"
|
||||
#include "LineEdit.h"
|
||||
#include "Log.h"
|
||||
#include "Text.h"
|
||||
#include "UIEvents.h"
|
||||
|
||||
@ -34,12 +35,15 @@ LineEdit::LineEdit(const std::string& name, const std::string& text) :
|
||||
mLastFont(0),
|
||||
mLastFontSize(0),
|
||||
mCursorPosition(0),
|
||||
mDragStartPosition(0),
|
||||
mDragStartPosition(M_MAX_UNSIGNED),
|
||||
mCursorBlinkRate(1.0f),
|
||||
mCursorBlinkTimer(0.0f),
|
||||
mMaxLength(0),
|
||||
mEchoCharacter(0),
|
||||
mDefocusable(true),
|
||||
mCursorMovable(true),
|
||||
mTextSelectable(true),
|
||||
mTextCopyable(true),
|
||||
mDefocus(false)
|
||||
{
|
||||
mClipChildren = true;
|
||||
@ -65,6 +69,14 @@ void LineEdit::setStyle(const XMLElement& element, ResourceCache* cache)
|
||||
|
||||
if (element.hasChildElement("maxlength"))
|
||||
setMaxLength(element.getChildElement("maxlength").getInt("value"));
|
||||
if (element.hasChildElement("defocusable"))
|
||||
setDefocusable(element.getChildElement("defocusable").getBool("enable"));
|
||||
if (element.hasChildElement("cursormovable"))
|
||||
setCursorMovable(element.getChildElement("cursormovable").getBool("enable"));
|
||||
if (element.hasChildElement("textselectable"))
|
||||
setTextSelectable(element.getChildElement("textselectable").getBool("enable"));
|
||||
if (element.hasChildElement("textcopyable"))
|
||||
setTextCopyable(element.getChildElement("textcopyable").getBool("enable"));
|
||||
|
||||
XMLElement textElem = element.getChildElement("text");
|
||||
if (textElem)
|
||||
@ -119,7 +131,7 @@ void LineEdit::update(float timeStep)
|
||||
|
||||
void LineEdit::onClick(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers)
|
||||
{
|
||||
if (buttons & MOUSEB_LEFT)
|
||||
if ((buttons & MOUSEB_LEFT) && (mCursorMovable))
|
||||
{
|
||||
unsigned pos = getCharIndex(position);
|
||||
if (pos != M_MAX_UNSIGNED)
|
||||
@ -137,20 +149,18 @@ void LineEdit::onDragStart(const IntVector2& position, const IntVector2& screenP
|
||||
|
||||
void LineEdit::onDragMove(const IntVector2& position, const IntVector2& screenPosition, int buttons, int qualifiers)
|
||||
{
|
||||
unsigned start = mDragStartPosition;
|
||||
unsigned current = getCharIndex(position);
|
||||
if ((start != M_MAX_UNSIGNED) && (current != M_MAX_UNSIGNED))
|
||||
if ((mCursorMovable) && (mTextSelectable))
|
||||
{
|
||||
if (start < current)
|
||||
unsigned start = mDragStartPosition;
|
||||
unsigned current = getCharIndex(position);
|
||||
if ((start != M_MAX_UNSIGNED) && (current != M_MAX_UNSIGNED))
|
||||
{
|
||||
mText->setSelection(start, current - start);
|
||||
if (start < current)
|
||||
mText->setSelection(start, current - start);
|
||||
else
|
||||
mText->setSelection(current, start - current);
|
||||
setCursorPosition(current);
|
||||
}
|
||||
else
|
||||
{
|
||||
mText->setSelection(current, start - current);
|
||||
setCursorPosition(start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,21 +171,93 @@ void LineEdit::onKey(int key, int buttons, int qualifiers)
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case KEY_LEFT:
|
||||
mText->setSelection(0, 0);
|
||||
if (mCursorPosition > 0)
|
||||
case 'X':
|
||||
case 'C':
|
||||
if ((mTextCopyable) && (qualifiers & QUAL_CTRL))
|
||||
{
|
||||
--mCursorPosition;
|
||||
unsigned start = mText->getSelectionStart();
|
||||
unsigned length = mText->getSelectionLength();
|
||||
|
||||
if (mText->getSelectionLength())
|
||||
sClipBoard = mLine.substr(start, length);
|
||||
|
||||
if (key == 'X')
|
||||
{
|
||||
if (start + length < mLine.length())
|
||||
mLine = mLine.substr(0, start) + mLine.substr(start + length);
|
||||
else
|
||||
mLine = mLine.substr(0, start);
|
||||
mText->setSelection(0, 0);
|
||||
mCursorPosition = start;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
if ((mTextCopyable) && (qualifiers & QUAL_CTRL))
|
||||
{
|
||||
if (sClipBoard.length())
|
||||
{
|
||||
if (mCursorPosition < mLine.length())
|
||||
mLine = mLine.substr(0, mCursorPosition) + sClipBoard + mLine.substr(mCursorPosition);
|
||||
else
|
||||
mLine += sClipBoard;
|
||||
mCursorPosition += sClipBoard.length();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_LEFT:
|
||||
if (!(qualifiers & QUAL_SHIFT))
|
||||
mText->setSelection(0, 0);
|
||||
if ((mCursorMovable) && (mCursorPosition > 0))
|
||||
{
|
||||
if ((mTextSelectable) && (qualifiers & QUAL_SHIFT) && (!mText->getSelectionLength()))
|
||||
mDragStartPosition = mCursorPosition;
|
||||
|
||||
if (qualifiers & QUAL_CTRL)
|
||||
mCursorPosition = 0;
|
||||
else
|
||||
--mCursorPosition;
|
||||
cursorMoved = true;
|
||||
|
||||
if ((mTextSelectable) && (qualifiers & QUAL_SHIFT))
|
||||
{
|
||||
unsigned start = mDragStartPosition;
|
||||
unsigned current = mCursorPosition;
|
||||
if (start < current)
|
||||
mText->setSelection(start, current - start);
|
||||
else
|
||||
mText->setSelection(current, start - current);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case KEY_RIGHT:
|
||||
mText->setSelection(0, 0);
|
||||
if (mCursorPosition < mLine.length())
|
||||
if (!(qualifiers & QUAL_SHIFT))
|
||||
mText->setSelection(0, 0);
|
||||
if ((mCursorMovable) && (mCursorPosition < mLine.length()))
|
||||
{
|
||||
++mCursorPosition;
|
||||
if ((mTextSelectable) && (qualifiers & QUAL_SHIFT) && (!mText->getSelectionLength()))
|
||||
mDragStartPosition = mCursorPosition;
|
||||
|
||||
if (qualifiers & QUAL_CTRL)
|
||||
mCursorPosition = mLine.length();
|
||||
else
|
||||
++mCursorPosition;
|
||||
cursorMoved = true;
|
||||
|
||||
if ((mTextSelectable) && (qualifiers & QUAL_SHIFT))
|
||||
{
|
||||
unsigned start = mDragStartPosition;
|
||||
unsigned current = mCursorPosition;
|
||||
if (start < current)
|
||||
mText->setSelection(start, current - start);
|
||||
else
|
||||
mText->setSelection(current, start - current);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -223,6 +305,9 @@ void LineEdit::onChar(unsigned char c, int buttons, int qualifiers)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
if (qualifiers & QUAL_CTRL)
|
||||
return;
|
||||
|
||||
if (c == '\b')
|
||||
{
|
||||
if ((mLine.length()) && (mCursorPosition))
|
||||
@ -242,11 +327,16 @@ void LineEdit::onChar(unsigned char c, int buttons, int qualifiers)
|
||||
VariantMap eventData;
|
||||
eventData[P_ELEMENT] = (void*)this;
|
||||
sendEvent(EVENT_TEXTFINISHED, eventData);
|
||||
|
||||
mText->setSelection(0, 0);
|
||||
}
|
||||
else if (c == 27)
|
||||
{
|
||||
if (mDefocusable)
|
||||
{
|
||||
mText->setSelection(0, 0);
|
||||
mDefocus = true;
|
||||
}
|
||||
}
|
||||
else if ((c >= 0x20) && ((!mMaxLength) || (mLine.length() < mMaxLength)))
|
||||
{
|
||||
@ -271,7 +361,6 @@ void LineEdit::onChar(unsigned char c, int buttons, int qualifiers)
|
||||
mLine = mLine.substr(0, start) + charStr + mLine.substr(start + length);
|
||||
else
|
||||
mLine = mLine.substr(0, start) + charStr;
|
||||
mText->setSelection(0, 0);
|
||||
mCursorPosition = start + 1;
|
||||
}
|
||||
changed = true;
|
||||
@ -279,6 +368,7 @@ void LineEdit::onChar(unsigned char c, int buttons, int qualifiers)
|
||||
|
||||
if (changed)
|
||||
{
|
||||
mText->setSelection(0, 0);
|
||||
updateText();
|
||||
updateCursor();
|
||||
|
||||
@ -295,12 +385,15 @@ void LineEdit::setText(const std::string& text)
|
||||
{
|
||||
mLine = text;
|
||||
mText->setText(text);
|
||||
// If cursor is not movable, make sure it's at the text end
|
||||
if (!mCursorMovable)
|
||||
setCursorPosition(mLine.length());
|
||||
updateText();
|
||||
}
|
||||
|
||||
void LineEdit::setCursorPosition(unsigned position)
|
||||
{
|
||||
if (position > mLine.length())
|
||||
if ((position > mLine.length()) || (!mCursorMovable))
|
||||
position = mLine.length();
|
||||
|
||||
if (position != mCursorPosition)
|
||||
@ -331,6 +424,21 @@ void LineEdit::setDefocusable(bool enable)
|
||||
mDefocusable = enable;
|
||||
}
|
||||
|
||||
void LineEdit::setCursorMovable(bool enable)
|
||||
{
|
||||
mCursorMovable = enable;
|
||||
}
|
||||
|
||||
void LineEdit::setTextSelectable(bool enable)
|
||||
{
|
||||
mTextSelectable = enable;
|
||||
}
|
||||
|
||||
void LineEdit::setTextCopyable(bool enable)
|
||||
{
|
||||
mTextCopyable = enable;
|
||||
}
|
||||
|
||||
void LineEdit::updateText()
|
||||
{
|
||||
if (!mEchoCharacter)
|
||||
|
@ -67,6 +67,12 @@ public:
|
||||
void setEchoCharacter(char c);
|
||||
//! Set whether can defocus with ESC, default true
|
||||
void setDefocusable(bool enable);
|
||||
//! Set whether can move cursor with arrows or mouse, default true
|
||||
void setCursorMovable(bool enable);
|
||||
//! Set whether selections are allowed, default true
|
||||
void setTextSelectable(bool enable);
|
||||
//! Set whether copy-paste operations are allowed, default true
|
||||
void setTextCopyable(bool enable);
|
||||
|
||||
//! Return text
|
||||
const std::string& getText() const { return mLine; }
|
||||
@ -80,6 +86,12 @@ public:
|
||||
char getEchoCharacter() const { return mEchoCharacter; }
|
||||
//! Return whether can defocus with ESC
|
||||
bool isDefocusable() const { return mDefocusable; }
|
||||
//! Return whether can move cursor with arrows or mouse
|
||||
bool isCursorMovable() const { return mCursorMovable; }
|
||||
//! Return whether selections are allowed
|
||||
bool isTextSelectable() const { return mTextSelectable; }
|
||||
//! Return whether copy-paste operations are allowed
|
||||
bool isTextCopyable() const { return mTextCopyable; }
|
||||
//! Return text element
|
||||
Text* getTextElement() const { return mText; }
|
||||
//! Return cursor element
|
||||
@ -117,6 +129,12 @@ protected:
|
||||
char mEchoCharacter;
|
||||
//! ESC defocus flag
|
||||
bool mDefocusable;
|
||||
//! Cursor movable flag
|
||||
bool mCursorMovable;
|
||||
//! Text selectable flag
|
||||
bool mTextSelectable;
|
||||
//! Copy-paste enable flag
|
||||
bool mTextCopyable;
|
||||
//! Defocus flag (defocus on next update)
|
||||
bool mDefocus;
|
||||
};
|
||||
|
@ -29,6 +29,8 @@
|
||||
|
||||
#include "DebugNew.h"
|
||||
|
||||
std::string UIElement::sClipBoard;
|
||||
|
||||
UIElement::UIElement(const std::string& name) :
|
||||
mName(name),
|
||||
mParent(0),
|
||||
|
@ -293,6 +293,9 @@ protected:
|
||||
//! Userdata
|
||||
Variant mUserData;
|
||||
|
||||
//! Clipboard data
|
||||
static std::string sClipBoard;
|
||||
|
||||
private:
|
||||
//! Return child elements recursively
|
||||
void getChildrenRecursive(std::vector<UIElement*>& dest) const;
|
||||
|
Loading…
Reference in New Issue
Block a user