Textbox now inherits from Label - gets all the fancy text selection features

This commit is contained in:
Simon Robertshaw 2012-06-26 22:55:52 +01:00
parent 7c259c0123
commit 5a71068ba0
4 changed files with 312 additions and 8 deletions

View File

@ -125,20 +125,58 @@ void Label::Tick(float dt)
{ {
if(!this->IsFocused() && (selecting || (selectionIndex0 != -1 && selectionIndex1 != -1))) if(!this->IsFocused() && (selecting || (selectionIndex0 != -1 && selectionIndex1 != -1)))
{ {
ClearSelection();
}
}
int Label::getLowerSelectionBound()
{
return (selectionIndex0 > selectionIndex1) ? selectionIndex1 : selectionIndex0;
}
int Label::getHigherSelectionBound()
{
return (selectionIndex0 > selectionIndex1) ? selectionIndex0 : selectionIndex1;
}
bool Label::HasSelection()
{
if(selectionIndex0 != -1 && selectionIndex1 != -1 && selectionIndex0 != selectionIndex1)
return true;
return false;
}
void Label::ClearSelection()
{
selecting = false; selecting = false;
selectionIndex0 = -1; selectionIndex0 = -1;
selectionIndex1 = -1; selectionIndex1 = -1;
updateSelection(); updateSelection();
}
} }
void Label::updateSelection() void Label::updateSelection()
{ {
std::string currentText; std::string currentText;
if(selectionIndex0 < 0) selectionIndex0 = 0;
if(selectionIndex0 > text.length()) selectionIndex0 = text.length();
if(selectionIndex1 < 0) selectionIndex1 = 0;
if(selectionIndex1 > text.length()) selectionIndex1 = text.length();
if(selectionIndex0 == -1 || selectionIndex1 == -1)
{
selectionXH = -1;
selectionXL = -1;
textFragments = std::string(currentText);
return;
}
if(multiline) if(multiline)
currentText = textLines; currentText = textLines;
else else
currentText = text; currentText = text;
if(selectionIndex1 > selectionIndex0) { if(selectionIndex1 > selectionIndex0) {
selectionLineH = Graphics::PositionAtCharIndex((char*)currentText.c_str(), selectionIndex1, selectionXH, selectionYH); selectionLineH = Graphics::PositionAtCharIndex((char*)currentText.c_str(), selectionIndex1, selectionXH, selectionYH);
selectionLineL = Graphics::PositionAtCharIndex((char*)currentText.c_str(), selectionIndex0, selectionXL, selectionYL); selectionLineL = Graphics::PositionAtCharIndex((char*)currentText.c_str(), selectionIndex0, selectionXL, selectionYL);

View File

@ -34,6 +34,9 @@ namespace ui
void updateMultiline(); void updateMultiline();
void updateSelection(); void updateSelection();
int getLowerSelectionBound();
int getHigherSelectionBound();
public: public:
//Label(Window* parent_state, std::string labelText); //Label(Window* parent_state, std::string labelText);
Label(Point position, Point size, std::string labelText); Label(Point position, Point size, std::string labelText);
@ -41,11 +44,14 @@ namespace ui
virtual ~Label(); virtual ~Label();
virtual void SetMultiline(bool status); virtual void SetMultiline(bool status);
virtual void SetText(std::string text); virtual void SetText(std::string text);
virtual std::string GetText(); virtual std::string GetText();
void SetTextColour(Colour textColour) { this->textColour = textColour; } virtual bool HasSelection();
virtual void ClearSelection();
void SetTextColour(Colour textColour) { this->textColour = textColour; }
virtual void OnMouseClick(int x, int y, unsigned button); virtual void OnMouseClick(int x, int y, unsigned button);
virtual void OnMouseUp(int x, int y, unsigned button); virtual void OnMouseUp(int x, int y, unsigned button);

View File

@ -8,6 +8,234 @@
using namespace ui; using namespace ui;
Textbox::Textbox(Point position, Point size, std::string textboxText):
Label(position, size, ""),
actionCallback(NULL),
masked(false),
border(true),
mouseDown(false)
{
SetText(textboxText);
cursor = text.length();
}
Textbox::~Textbox()
{
if(actionCallback)
delete actionCallback;
}
void Textbox::SetText(std::string newText)
{
backingText = newText;
if(masked)
{
std::string maskedText = std::string(newText);
std::fill(maskedText.begin(), maskedText.end(), '\x8D');
Label::SetText(maskedText);
}
else
Label::SetText(newText);
if(cursor)
{
cursorPosition = Graphics::textnwidth((char *)text.c_str(), cursor);
}
else
{
cursorPosition = 0;
}
}
void Textbox::SetDisplayText(std::string newText)
{
Label::SetText(text);
}
std::string Textbox::GetText()
{
return backingText;
}
void Textbox::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt)
{
bool changed = false;
try
{
switch(key)
{
case KEY_HOME:
cursor = 0;
break;
case KEY_END:
cursor = backingText.length();
break;
case KEY_LEFT:
if(cursor > 0)
cursor--;
break;
case KEY_RIGHT:
if(cursor < backingText.length())
cursor++;
break;
case KEY_DELETE:
if(HasSelection())
{
if(getLowerSelectionBound() < 0 || getHigherSelectionBound() > backingText.length())
return;
backingText.erase(backingText.begin()+getLowerSelectionBound(), backingText.begin()+getHigherSelectionBound());
cursor = getLowerSelectionBound();
changed = true;
}
else if(backingText.length() && cursor < backingText.length())
{
if(ctrl)
backingText.erase(cursor, backingText.length()-cursor);
else
backingText.erase(cursor, 1);
changed = true;
}
break;
case KEY_BACKSPACE:
if(HasSelection())
{
if(getLowerSelectionBound() < 0 || getHigherSelectionBound() > backingText.length())
return;
backingText.erase(backingText.begin()+getLowerSelectionBound(), backingText.begin()+getHigherSelectionBound());
cursor = getLowerSelectionBound();
changed = true;
}
else if(backingText.length() && cursor > 0)
{
if(ctrl)
{
backingText.erase(0, cursor);
cursor = 0;
}
else
{
backingText.erase(cursor-1, 1);
cursor--;
}
changed = true;
}
break;
}
if(character >= ' ' && character < 127)
{
if(HasSelection())
{
if(getLowerSelectionBound() < 0 || getHigherSelectionBound() > backingText.length())
return;
backingText.erase(backingText.begin()+getLowerSelectionBound(), backingText.begin()+getHigherSelectionBound());
cursor = getLowerSelectionBound();
}
if(cursor == backingText.length())
{
backingText += character;
}
else
{
backingText.insert(cursor, 1, (char)character);
}
cursor++;
changed = true;
}
ClearSelection();
}
catch(std::out_of_range &e)
{
cursor = 0;
backingText = "";
}
if(changed)
{
if(masked)
{
std::string maskedText = std::string(backingText);
std::fill(maskedText.begin(), maskedText.end(), '\x8D');
Label::SetText(maskedText);
}
else
{
text = backingText;
}
if(actionCallback)
actionCallback->TextChangedCallback(this);
}
if(multiline)
updateMultiline();
updateSelection();
TextPosition(text);
if(cursor)
{
cursorPosition = Graphics::textnwidth((char *)text.c_str(), cursor);
}
else
{
cursorPosition = 0;
}
}
void Textbox::OnMouseClick(int x, int y, unsigned button)
{
mouseDown = true;
cursor = Graphics::CharIndexAtPosition((char*)text.c_str(), x-textPosition.X, y-textPosition.Y);
if(cursor)
{
cursorPosition = Graphics::textnwidth((char *)text.c_str(), cursor);
}
else
{
cursorPosition = 0;
}
Label::OnMouseClick(x, y, button);
}
void Textbox::OnMouseUp(int x, int y, unsigned button)
{
mouseDown = false;
Label::OnMouseUp(x, y, button);
}
void Textbox::OnMouseMoved(int localx, int localy, int dx, int dy)
{
if(mouseDown)
{
cursor = Graphics::CharIndexAtPosition((char*)text.c_str(), localx-textPosition.X, localy-textPosition.Y);
if(cursor)
{
cursorPosition = Graphics::textnwidth((char *)text.c_str(), cursor);
}
else
{
cursorPosition = 0;
}
}
Label::OnMouseMoved(localx, localy, dx, dy);
}
void Textbox::Draw(const Point& screenPos)
{
Label::Draw(screenPos);
Graphics * g = Engine::Ref().g;
if(IsFocused())
{
if(border) g->drawrect(screenPos.X, screenPos.Y, Size.X, Size.Y, 255, 255, 255, 255);
g->draw_line(screenPos.X+textPosition.X+cursorPosition, screenPos.Y+3, screenPos.X+textPosition.X+cursorPosition, screenPos.Y+12, 255, 255, 255, XRES+BARSIZE);
}
else
{
if(border) g->drawrect(screenPos.X, screenPos.Y, Size.X, Size.Y, 160, 160, 160, 255);
}
}
/*
Textbox::Textbox(Point position, Point size, std::string textboxText): Textbox::Textbox(Point position, Point size, std::string textboxText):
Component(position, size), Component(position, size),
text(textboxText), text(textboxText),
@ -165,4 +393,4 @@ void Textbox::Draw(const Point& screenPos)
g->drawtext(screenPos.X+textPosition.X, screenPos.Y+textPosition.Y, displayText, 255, 255, 255, 255); g->drawtext(screenPos.X+textPosition.X, screenPos.Y+textPosition.Y, displayText, 255, 255, 255, 255);
if(Appearance.icon) if(Appearance.icon)
g->draw_icon(screenPos.X+iconPosition.X, screenPos.Y+iconPosition.Y, Appearance.icon); g->draw_icon(screenPos.X+iconPosition.X, screenPos.Y+iconPosition.Y, Appearance.icon);
} }*/

View File

@ -3,7 +3,7 @@
#include <string> #include <string>
#include "Component.h" #include "Label.h"
#include "Misc.h" #include "Misc.h"
namespace ui namespace ui
@ -15,7 +15,37 @@ public:
virtual void TextChangedCallback(ui::Textbox * sender) {} virtual void TextChangedCallback(ui::Textbox * sender) {}
virtual ~TextboxAction() {} virtual ~TextboxAction() {}
}; };
class Textbox : public Component
class Textbox : public Label
{
friend class TextboxAction;
protected:
bool mouseDown;
bool masked, border;
int cursor, cursorPosition;
TextboxAction *actionCallback;
std::string backingText;
public:
Textbox(Point position, Point size, std::string textboxText);
virtual ~Textbox();
virtual void SetDisplayText(std::string text);
virtual void SetText(std::string text);
virtual std::string GetText();
void SetBorder(bool border) { this->border = border; };
void SetHidden(bool hidden) { masked = hidden; }
bool GetHidden() { return masked; }
void SetActionCallback(TextboxAction * action) { actionCallback = action; }
virtual void OnMouseClick(int x, int y, unsigned button);
virtual void OnMouseUp(int x, int y, unsigned button);
virtual void OnMouseMoved(int localx, int localy, int dx, int dy);
virtual void OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool alt);
virtual void Draw(const Point& screenPos);
};
/*class Textbox : public Component
{ {
friend class TextboxAction; friend class TextboxAction;
protected: protected:
@ -44,6 +74,8 @@ public:
virtual void Draw(const Point& screenPos); virtual void Draw(const Point& screenPos);
}; };
}*/
} }
#endif // TEXTBOX_H #endif // TEXTBOX_H