From Jean-Sebastien Guay, "osgWidget::WindowManager did nothing in its keyUp event, and in particular didn't call any callbacks. Since I wanted to have callbacks on keyUp, I copied what it does on keyDown, which works for me. I could have just used keyDown and saved myself the trouble, but you know me... :-)

osgWidget::Input:

[Functional changes]
- Previously, the field would be filled with spaces up to its max length, and typing would just replace the spaces. Also, there was a _textLength variable that kept track of the real length of text in the field, since the osgText::Text's length just reflected the length of spaces+text entered. This was not great, as you could still select the spaces with the mouse and it just feels hacky. So I changed it to only contain the text entered, no spaces, and _textLength was removed since it's now redundant (the osgText::Text's length is used instead).
- Fixed the selection size which (visually only) showed one more character selected than what was really selected.
- Fixed selection by dragging the mouse, it would sometimes not select the last character of the string.
- Cursor will now accurately reflect whether insert mode is activated (block cursor) or we're in normal mode (line cursor) like in most editors.
- Implemented Ctrl-X (cut)
- Added a new clear() method that allows the field to be emptied correctly. Useful for a command line interface, for example (hint, hint).
- Mouse and keyboard event handler methods would always return false, which meant selecting with the mouse would also rotate the trackball, and typing an 's' would turn on stats.

[Code cleanup]
- Renamed the (local) _selectionMin and _selectionMax variables which are used in a lot of places, as the underscores would lead to think they were members. Either I called them selection{Min|Max} or delete{Min|Max} where it made more sense.
- Fixed some indenting which was at 3 spaces (inconsistently), I'm sure I didn't catch all the lines where this was the case though.
- Put spaces between variable, operator and value where missing, especially in for()s. Again I only did this where I made changes, there are probably others left.

The result is that delete, backspace, Ctrl-X, Ctrl-C, Ctrl-V, and typing behaviour should now be consistent with text editor conventions, whether insert mode is enabled or not. I hope. :-)

Note, there's a nasty const_cast in there. Why isn't osgText::Font::getGlyph() declared const?

Also, as a note, the current implementation of cut, copy and paste (in addition to being Windows only, yuck) gets and puts the data into an std::string, thus if the osgText::String in the field contains unicode characters I think it won't work correctly. Perhaps someone could implement a proper clipboard class that would be cross-platform and support osgText::String (more precisely other languages like Chinese) correctly? Cut, copy and paste are not critical to what I'm doing so I won't invest the time to do that, but I just thought I'd mention it.
"
This commit is contained in:
Robert Osfield
2010-09-09 16:49:10 +00:00
parent 78cb15fdf8
commit 687fd9362f
5 changed files with 347 additions and 309 deletions

View File

@@ -25,53 +25,53 @@ namespace osgDB
#define OSG_HEADER_HIGH 0x1AFB4545
// Reader/writer plugin version
#define PLUGIN_VERSION 2
const unsigned int PLUGIN_VERSION = 2;
#define BOOL_SIZE 1
#define CHAR_SIZE 1
#define SHORT_SIZE 2
#define INT_SIZE 4
#define LONG_SIZE 4
#define FLOAT_SIZE 4
#define DOUBLE_SIZE 8
#define GLENUM_SIZE 4
const int BOOL_SIZE = 1;
const int CHAR_SIZE = 1;
const int SHORT_SIZE = 2;
const int INT_SIZE = 4;
const int LONG_SIZE = 4;
const int FLOAT_SIZE = 4;
const int DOUBLE_SIZE = 8;
const int GLENUM_SIZE = 4;
#define ID_BYTE_ARRAY 0
#define ID_UBYTE_ARRAY 1
#define ID_SHORT_ARRAY 2
#define ID_USHORT_ARRAY 3
#define ID_INT_ARRAY 4
#define ID_UINT_ARRAY 5
#define ID_FLOAT_ARRAY 6
#define ID_DOUBLE_ARRAY 7
#define ID_VEC2B_ARRAY 8
#define ID_VEC3B_ARRAY 9
#define ID_VEC4B_ARRAY 10
#define ID_VEC4UB_ARRAY 11
#define ID_VEC2S_ARRAY 12
#define ID_VEC3S_ARRAY 13
#define ID_VEC4S_ARRAY 14
#define ID_VEC2_ARRAY 15
#define ID_VEC3_ARRAY 16
#define ID_VEC4_ARRAY 17
#define ID_VEC2D_ARRAY 18
#define ID_VEC3D_ARRAY 19
#define ID_VEC4D_ARRAY 20
const int ID_BYTE_ARRAY = 0;
const int ID_UBYTE_ARRAY = 1;
const int ID_SHORT_ARRAY = 2;
const int ID_USHORT_ARRAY = 3;
const int ID_INT_ARRAY = 4;
const int ID_UINT_ARRAY = 5;
const int ID_FLOAT_ARRAY = 6;
const int ID_DOUBLE_ARRAY = 7;
const int ID_VEC2B_ARRAY = 8;
const int ID_VEC3B_ARRAY = 9;
const int ID_VEC4B_ARRAY = 10;
const int ID_VEC4UB_ARRAY = 11;
const int ID_VEC2S_ARRAY = 12;
const int ID_VEC3S_ARRAY = 13;
const int ID_VEC4S_ARRAY = 14;
const int ID_VEC2_ARRAY = 15;
const int ID_VEC3_ARRAY = 16;
const int ID_VEC4_ARRAY = 17;
const int ID_VEC2D_ARRAY = 18;
const int ID_VEC3D_ARRAY = 19;
const int ID_VEC4D_ARRAY = 20;
#define ID_DRAWARRAYS 50
#define ID_DRAWARRAY_LENGTH 51
#define ID_DRAWELEMENTS_UBYTE 52
#define ID_DRAWELEMENTS_USHORT 53
#define ID_DRAWELEMENTS_UINT 54
const int ID_DRAWARRAYS = 50;
const int ID_DRAWARRAY_LENGTH = 51;
const int ID_DRAWELEMENTS_UBYTE = 52;
const int ID_DRAWELEMENTS_USHORT = 53;
const int ID_DRAWELEMENTS_UINT = 54;
// Used by BEGIN_BRACKET and END_BRACKET
#define INDENT_VALUE 2
const int INDENT_VALUE = 2;
// Used by the writeImage/readImage parameter
#define IMAGE_INLINE_DATA 0
#define IMAGE_INLINE_FILE 1
#define IMAGE_EXTERNAL 2
#define IMAGE_WRITE_OUT 3
const int IMAGE_INLINE_DATA = 0;
const int IMAGE_INLINE_FILE = 1;
const int IMAGE_EXTERNAL = 2;
const int IMAGE_WRITE_OUT = 3;
struct ObjectGLenum
{

View File

@@ -27,83 +27,84 @@ const std::string DESCENT_STRING("qpl");
class OSGWIDGET_EXPORT Input: public Label
{
public:
public:
Input(const std::string& = "", const std::string& = "", unsigned int = 20);
Input(const std::string& = "", const std::string& = "", unsigned int = 20);
virtual void parented (Window*);
virtual void positioned ();
virtual void parented (Window*);
virtual void positioned ();
virtual bool focus (const WindowManager*);
virtual bool unfocus (const WindowManager*);
virtual bool keyUp (int, int, const WindowManager*);
virtual bool keyDown (int, int, const WindowManager*);
virtual bool mouseDrag (double, double, const WindowManager*);
virtual bool mousePush (double x, double y, const WindowManager*);
virtual bool focus (const WindowManager*);
virtual bool unfocus (const WindowManager*);
virtual bool keyUp (int, int, const WindowManager*);
virtual bool keyDown (int, int, const WindowManager*);
virtual bool mouseDrag (double, double, const WindowManager*);
virtual bool mousePush (double x, double y, const WindowManager*);
virtual bool mouseRelease (double, double, const WindowManager*);
void setCursor (Widget*);
unsigned int calculateBestYOffset (const std::string& = "qgl");
void setCursor (Widget*);
unsigned int calculateBestYOffset (const std::string& = "qgl");
void clear();
void setXOffset(point_type xo) {
_xoff = xo;
}
void setXOffset(point_type xo) {
_xoff = xo;
}
void setYOffset(point_type yo) {
_yoff = yo;
}
void setYOffset(point_type yo) {
_yoff = yo;
}
void setXYOffset(point_type xo, point_type yo) {
_xoff = xo;
_yoff = yo;
}
void setXYOffset(point_type xo, point_type yo) {
_xoff = xo;
_yoff = yo;
}
osg::Drawable* getCursor() {
return _cursor.get();
}
osg::Drawable* getCursor() {
return _cursor.get();
}
const osg::Drawable* getCursor() const {
return _cursor.get();
}
const osg::Drawable* getCursor() const {
return _cursor.get();
}
point_type getXOffset() const {
return _xoff;
}
point_type getXOffset() const {
return _xoff;
}
point_type getYOffset() const {
return _yoff;
}
point_type getYOffset() const {
return _yoff;
}
XYCoord getXYOffset() const {
return XYCoord(_xoff, _yoff);
}
XYCoord getXYOffset() const {
return XYCoord(_xoff, _yoff);
}
protected:
virtual void _calculateSize(const XYCoord&);
protected:
virtual void _calculateSize(const XYCoord&);
void _calculateCursorOffsets();
void _calculateCursorOffsets();
point_type _xoff;
point_type _yoff;
point_type _xoff;
point_type _yoff;
unsigned int _index;
unsigned int _size;
unsigned int _cursorIndex;
unsigned int _maxSize;
unsigned int _textLength;
unsigned int _index;
unsigned int _size;
unsigned int _cursorIndex;
unsigned int _maxSize;
std::vector<point_type> _offsets;
std::vector<unsigned int> _wordsOffsets;
std::vector<point_type> _widths;
osg::ref_ptr<Widget> _cursor;
std::vector<point_type> _offsets;
std::vector<unsigned int> _wordsOffsets;
std::vector<point_type> _widths;
osg::ref_ptr<Widget> _cursor;
bool _insertMode;
bool _insertMode; // Insert was pressed --> true --> typing will overwrite existing text
osg::ref_ptr<Widget> _selection;
unsigned int _selectionStartIndex;
unsigned int _selectionEndIndex;
unsigned int _selectionIndex;
osg::ref_ptr<Widget> _selection;
unsigned int _selectionStartIndex;
unsigned int _selectionEndIndex;
unsigned int _selectionIndex;
point_type _mouseClickX;
point_type _mouseClickX;
};
}

View File

@@ -12,42 +12,42 @@ public:
virtual bool isBinary() const { return true; }
virtual void writeBool( bool b )
{ char c = b?1:0; _out->write( &c, CHAR_SIZE ); }
{ char c = b?1:0; _out->write( &c, osgDB::CHAR_SIZE ); }
virtual void writeChar( char c )
{ _out->write( &c, CHAR_SIZE ); }
{ _out->write( &c, osgDB::CHAR_SIZE ); }
virtual void writeUChar( unsigned char c )
{ _out->write( (char*)&c, CHAR_SIZE ); }
{ _out->write( (char*)&c, osgDB::CHAR_SIZE ); }
virtual void writeShort( short s )
{ _out->write( (char*)&s, SHORT_SIZE ); }
{ _out->write( (char*)&s, osgDB::SHORT_SIZE ); }
virtual void writeUShort( unsigned short s )
{ _out->write( (char*)&s, SHORT_SIZE ); }
{ _out->write( (char*)&s, osgDB::SHORT_SIZE ); }
virtual void writeInt( int i )
{ _out->write( (char*)&i, INT_SIZE ); }
{ _out->write( (char*)&i, osgDB::INT_SIZE ); }
virtual void writeUInt( unsigned int i )
{ _out->write( (char*)&i, INT_SIZE ); }
{ _out->write( (char*)&i, osgDB::INT_SIZE ); }
virtual void writeLong( long l )
{ _out->write( (char*)&l, LONG_SIZE ); }
{ _out->write( (char*)&l, osgDB::LONG_SIZE ); }
virtual void writeULong( unsigned long l )
{ _out->write( (char*)&l, LONG_SIZE ); }
{ _out->write( (char*)&l, osgDB::LONG_SIZE ); }
virtual void writeFloat( float f )
{ _out->write( (char*)&f, FLOAT_SIZE ); }
{ _out->write( (char*)&f, osgDB::FLOAT_SIZE ); }
virtual void writeDouble( double d )
{ _out->write((char*)&d, DOUBLE_SIZE); }
{ _out->write((char*)&d, osgDB::DOUBLE_SIZE); }
virtual void writeString( const std::string& s )
{
int size = s.size();
_out->write( (char*)&size, INT_SIZE );
_out->write( (char*)&size, osgDB::INT_SIZE );
_out->write( s.c_str(), s.size() );
}
@@ -56,10 +56,10 @@ public:
virtual void writeBase( std::ios_base& (*fn)(std::ios_base&) ) {}
virtual void writeGLenum( const osgDB::ObjectGLenum& value )
{ GLenum e = value.get(); _out->write((char*)&e, GLENUM_SIZE); }
{ GLenum e = value.get(); _out->write((char*)&e, osgDB::GLENUM_SIZE); }
virtual void writeProperty( const osgDB::ObjectProperty& prop )
{ if (prop._mapProperty) _out->write((char*)&(prop._value), INT_SIZE); }
{ if (prop._mapProperty) _out->write((char*)&(prop._value), osgDB::INT_SIZE); }
virtual void writeMark( const osgDB::ObjectMark& mark ) {}
@@ -81,65 +81,65 @@ public:
virtual void readBool( bool& b )
{
char c = 0;
_in->read( &c, CHAR_SIZE );
_in->read( &c, osgDB::CHAR_SIZE );
b = (c!=0);
}
virtual void readChar( char& c )
{ _in->read( &c, CHAR_SIZE ); }
{ _in->read( &c, osgDB::CHAR_SIZE ); }
virtual void readSChar( signed char& c )
{ _in->read( (char*)&c, CHAR_SIZE ); }
{ _in->read( (char*)&c, osgDB::CHAR_SIZE ); }
virtual void readUChar( unsigned char& c )
{ _in->read( (char*)&c, CHAR_SIZE ); }
{ _in->read( (char*)&c, osgDB::CHAR_SIZE ); }
virtual void readShort( short& s )
{
_in->read( (char*)&s, SHORT_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&s, SHORT_SIZE );
_in->read( (char*)&s, osgDB::SHORT_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&s, osgDB::SHORT_SIZE );
}
virtual void readUShort( unsigned short& s )
{
_in->read( (char*)&s, SHORT_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&s, SHORT_SIZE );
_in->read( (char*)&s, osgDB::SHORT_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&s, osgDB::SHORT_SIZE );
}
virtual void readInt( int& i )
{
_in->read( (char*)&i, INT_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&i, INT_SIZE );
_in->read( (char*)&i, osgDB::INT_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&i, osgDB::INT_SIZE );
}
virtual void readUInt( unsigned int& i )
{
_in->read( (char*)&i, INT_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&i, INT_SIZE );
_in->read( (char*)&i, osgDB::INT_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&i, osgDB::INT_SIZE );
}
virtual void readLong( long& l )
{
_in->read( (char*)&l, LONG_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&l, LONG_SIZE );
_in->read( (char*)&l, osgDB::LONG_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&l, osgDB::LONG_SIZE );
}
virtual void readULong( unsigned long& l )
{
_in->read( (char*)&l, LONG_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&l, LONG_SIZE );
_in->read( (char*)&l, osgDB::LONG_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&l, osgDB::LONG_SIZE );
}
virtual void readFloat( float& f )
{
_in->read( (char*)&f, FLOAT_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&f, FLOAT_SIZE );
_in->read( (char*)&f, osgDB::FLOAT_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&f, osgDB::FLOAT_SIZE );
}
virtual void readDouble( double& d )
{
_in->read( (char*)&d, DOUBLE_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&d, DOUBLE_SIZE );
_in->read( (char*)&d, osgDB::DOUBLE_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&d, osgDB::DOUBLE_SIZE );
}
virtual void readString( std::string& s )
@@ -159,8 +159,8 @@ public:
virtual void readGLenum( osgDB::ObjectGLenum& value )
{
GLenum e = 0;
_in->read( (char*)&e, GLENUM_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&e, GLENUM_SIZE );
_in->read( (char*)&e, osgDB::GLENUM_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&e, osgDB::GLENUM_SIZE );
value.set( e );
}
@@ -169,8 +169,8 @@ public:
int value = 0;
if ( prop._mapProperty )
{
_in->read( (char*)&value, INT_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&value, INT_SIZE );
_in->read( (char*)&value, osgDB::INT_SIZE );
if ( _byteSwap ) osg::swapBytes( (char*)&value, osgDB::INT_SIZE );
}
prop.set( value );
}

View File

@@ -44,7 +44,6 @@ Input::Input(const std::string& name, const std::string& label, unsigned int siz
_size(0),
_cursorIndex(0),
_maxSize(size),
_textLength(0),
_cursor(new Widget("cursor")),
_insertMode(false),
_selection(new Widget("selection")),
@@ -74,10 +73,9 @@ Input::Input(const std::string& name, const std::string& label, unsigned int siz
EVENT_MASK_MOUSE_DRAG
);
_offsets.resize(size+1, 0.0f);
_widths.resize(size+1, 1.0f);
_offsets.resize(_text->getText().size()+1, 0.0f);
_widths.resize(_text->getText().size()+1, 1.0f);
_text->getText().resize(size, ' ');
_text->update();
_cursor->setDrawCallback( new BlinkCursorCallback(_insertMode) );
@@ -101,10 +99,13 @@ void Input::_calculateSize(const XYCoord& size) {
void Input::_calculateCursorOffsets() {
// Determine the "offset"
_offsets.resize(_text->getText().size()+1, 0.0f);
_widths.resize(_text->getText().size()+1, 1.0f);
if (_text->getText().size()==0)
{
_offsets[0] = 0;
_widths[0] = 0;
_widths[0] = 1.f;
return;
}
@@ -182,7 +183,7 @@ void Input::_calculateCursorOffsets() {
}
_offsets[idx] = lr.x() + pos.x();
_widths[idx]= 1.f;
_widths[idx] = 1.f;
_wordsOffsets.clear();
for ( unsigned int i=0; i<_text->getText().size(); ++i )
@@ -221,43 +222,62 @@ void Input::parented(Window* parent) {
else _selectionIndex = parent->addDrawableAndGetIndex(_selection.get());
}
void Input::positioned() {
point_type ln = static_cast<point_type>(_text->getLineCount());
void Input::positioned()
{
point_type ln = static_cast<point_type>(_text->getLineCount());
ln = ln == 0.0f ? 1.0f : ln;
ln = ln == 0.0f ? 1.0f : ln;
// point_type th = (_text->getCharacterHeight() * ln) + (_text->getLineSpacing() * (ln - 1.0f));
// point_type th = (_text->getCharacterHeight() * ln) + (_text->getLineSpacing() * (ln - 1.0f));
point_type x = getX() + _xoff;
point_type y = getY() + _yoff;
point_type x = getX() + _xoff;
point_type y = getY() + _yoff;
// XYCoord size = getTextSize();
// XYCoord size = getTextSize();
_text->setPosition(osg::Vec3(x, y, _calculateZ(LAYER_MIDDLE)));
_text->setPosition(osg::Vec3(x, y, _calculateZ(LAYER_MIDDLE)));
point_type xoffset = _index > 0 ? _offsets[_index - 1] : 0.0f;
point_type xoffset = _index > 0 ? _offsets[_index - 1] : 0.0f;
_cursor->setSize(_widths[_index], getHeight());
_cursor->setOrigin(getX() + xoffset, getY() );
_cursor->setZ(_calculateZ(LAYER_MIDDLE-1));
if (_insertMode)
{
if (_index < _text->getText().size())
{
_cursor->setSize(_widths[_index], getHeight());
}
else
{
// We're at the end of the string, perhaps the string is empty,
// so get the advance for any character, perhaps a large one, I chose 'A'.
osgText::Glyph* glyph = const_cast<osgText::Font*>(_text->getFont())->getGlyph(osgText::FontResolution(_text->getFontWidth(), _text->getFontHeight()), 'A');
_cursor->setSize(glyph->getHorizontalAdvance(), getHeight());
}
}
else
{
_cursor->setSize(1.f, getHeight());
}
_cursor->setOrigin(getX() + xoffset, getY() );
_cursor->setZ(_calculateZ(LAYER_MIDDLE-1));
unsigned int _selectionMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
unsigned int _selectionMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
unsigned int selectionMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
unsigned int selectionMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
if (_selectionMax-_selectionMin>0)
{
point_type xstart = _selectionMin > 0 ? _offsets[_selectionMin - 1] : 0.0f;
point_type xend = (_selectionMax > 0 ? _offsets[_selectionMax - 1] : 0.0f) + _widths[_selectionMax];
if (selectionMax - selectionMin > 0)
{
point_type xstart = selectionMin > 0 ? _offsets[selectionMin - 1] : 0.0f;
point_type xend = selectionMax > 0 ? _offsets[selectionMax - 1] : 0.0f;
_selection->setSize(xend-xstart, getHeight());
_selection->setOrigin(getX() + xstart, getY());
_selection->setZ(_calculateZ(LAYER_MIDDLE-2));
}
else
{
_selection->setSize(0, getHeight());
}
_selection->setSize(xend-xstart, getHeight());
_selection->setOrigin(getX() + xstart, getY());
_selection->setZ(_calculateZ(LAYER_MIDDLE-2));
}
else
{
_selection->setSize(0, getHeight());
}
}
bool Input::keyUp(int key, int mask, const WindowManager*) {
@@ -269,11 +289,12 @@ bool Input::mouseDrag (double x, double y, const WindowManager*)
_mouseClickX += x;
x = _mouseClickX;
for ( unsigned int i=0; i< _offsets.size()-1; ++i )
for ( unsigned int i = 0; i < _offsets.size(); ++i )
{
point_type offset1 = i > 0 ? _offsets.at(i-1) : 0;
point_type offset2 = _offsets.at(i);
if (x >= offset1 && x <= offset2)
if ((x >= offset1 && x <= offset2) ||
i == _offsets.size() - 1) // If we're at the last one, obviously it will be there.
{
_selectionEndIndex = _index = i;
positioned();
@@ -281,7 +302,7 @@ bool Input::mouseDrag (double x, double y, const WindowManager*)
}
}
return false;
return true;
}
bool Input::mousePush (double x, double y, const WindowManager* wm)
@@ -296,21 +317,28 @@ bool Input::mousePush (double x, double y, const WindowManager* wm)
x -= offset;
_mouseClickX = x;
for ( unsigned int i=0; i< _offsets.size()-1; ++i )
for ( unsigned int i = 0; i < _offsets.size(); ++i )
{
point_type offset1 = i > 0 ? _offsets.at(i-1) : 0;
point_type offset2 = i == 0 ? _offsets.at(1) : _offsets.at(i);
if (x >= offset1 && x <= offset2)
point_type offset2 = _offsets.at(i);
if ((x >= offset1 && x <= offset2) ||
i == _offsets.size() - 1) // If we're at the last one, obviously it will be there.
{
_selectionStartIndex = _selectionEndIndex = _index = i;
positioned();
break;
}
}
return false;
return true;
}
bool Input::keyDown(int key, int mask, const WindowManager*) {
bool Input::mouseRelease(double, double, const WindowManager*)
{
return true;
}
bool Input::keyDown(int key, int mask, const WindowManager*)
{
osgText::String& s = _text->getText();
switch (key)
@@ -319,7 +347,7 @@ bool Input::keyDown(int key, int mask, const WindowManager*) {
if (mask & osgGA::GUIEventAdapter::MODKEY_CTRL)
{
bool found = false;
for (unsigned int i=0; i<_wordsOffsets.size()-1; ++i)
for (unsigned int i = 0; i < _wordsOffsets.size() - 1; ++i)
{
if (_wordsOffsets.at(i) < _index && _index <= _wordsOffsets.at(i+1))
{
@@ -334,7 +362,7 @@ bool Input::keyDown(int key, int mask, const WindowManager*) {
}
}
else
if (_index>0)
if (_index > 0)
{
--_index;
}
@@ -351,7 +379,7 @@ bool Input::keyDown(int key, int mask, const WindowManager*) {
if (mask & osgGA::GUIEventAdapter::MODKEY_CTRL)
{
bool found = false;
for (unsigned int i=0; i<_wordsOffsets.size()-1; ++i)
for (unsigned int i = 0; i < _wordsOffsets.size() - 1; ++i)
{
if (_wordsOffsets.at(i) <= _index && _index < _wordsOffsets.at(i+1))
{
@@ -366,7 +394,7 @@ bool Input::keyDown(int key, int mask, const WindowManager*) {
}
}
else
if (_index<_textLength)
if (_index < s.size())
{
++_index;
}
@@ -392,7 +420,7 @@ bool Input::keyDown(int key, int mask, const WindowManager*) {
}
break;
case osgGA::GUIEventAdapter::KEY_End:
_index = _textLength;
_index = s.size();
if (mask & osgGA::GUIEventAdapter::MODKEY_SHIFT)
{
_selectionEndIndex = _index;
@@ -407,108 +435,66 @@ bool Input::keyDown(int key, int mask, const WindowManager*) {
break;
case osgGA::GUIEventAdapter::KEY_Delete:
{
unsigned int _selectionMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
unsigned int _selectionMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
unsigned int deleteMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
unsigned int deleteMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
if (_selectionMax-_selectionMin>0)
if (deleteMax - deleteMin > 0)
{
unsigned int deleteToIdx = _selectionMax;
for (unsigned int i=0; i < s.size()-_selectionMin; ++i)
{
s[_selectionMin+i] = deleteToIdx+i+1 < s.size() ? s[deleteToIdx+i+1] : ' ';
}
_text->update();
_calculateCursorOffsets();
_textLength -= deleteToIdx-_selectionMin;
_index = _selectionMin;
_selectionStartIndex = _selectionEndIndex = _index;
}
else
if (mask & osgGA::GUIEventAdapter::MODKEY_CTRL)
else if (mask & osgGA::GUIEventAdapter::MODKEY_CTRL)
{
unsigned int deleteToIdx = _textLength;
for (unsigned int i=0; i<_wordsOffsets.size()-1; ++i)
deleteMin = 0;
deleteMax = 0;
for (unsigned int i =0; i < _wordsOffsets.size() - 1; ++i)
{
if (_wordsOffsets.at(i) <= _index && _index < _wordsOffsets.at(i+1))
{
deleteToIdx = _wordsOffsets.at(i+1);
deleteMin = _wordsOffsets.at(i);
deleteMax = _wordsOffsets.at(i+1);
break;
}
}
for (unsigned int i=0; i < s.size()-_index; ++i)
{
s[_index+i] = deleteToIdx+i < s.size() ? s[deleteToIdx+i] : ' ';
}
_text->update();
_calculateCursorOffsets();
_textLength -= deleteToIdx-_index;
}
else
if (_index < s.size()-1)
else if (_index < s.size())
{
for (unsigned int i=_index; i < s.size()-1; ++i)
{
s[i] = s[i+1];
}
_text->update();
_calculateCursorOffsets();
--_textLength;
deleteMin = _index;
deleteMax = _index + 1;
}
if (deleteMin != deleteMax)
s.erase(s.begin() + deleteMin, s.begin() + deleteMax);
_text->update();
_calculateCursorOffsets();
_index = deleteMin;
_selectionStartIndex = _selectionEndIndex = _index;
}
break;
case osgGA::GUIEventAdapter::KEY_BackSpace:
{
unsigned int _selectionMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
unsigned int _selectionMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
unsigned int deleteMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
unsigned int deleteMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
if (_selectionMax-_selectionMin>0)
if (deleteMax - deleteMin > 0)
{
unsigned int deleteToIdx = _selectionMax;
for (unsigned int i=0; i < s.size()-_selectionMin; ++i)
{
s[_selectionMin+i] = deleteToIdx+i+1 < s.size() ? s[deleteToIdx+i+1] : ' ';
}
_text->update();
_calculateCursorOffsets();
_textLength -= deleteToIdx-_selectionMin;
_index = _selectionMin;
_selectionStartIndex = _selectionEndIndex = _index;
}
else
if(_index >= 1) {
else if(_index >= 1)
{
deleteMin = _index - 1;
deleteMax = _index;
}
_index--;
if (_index< s.size()-1)
{
for (unsigned int i=_index; i < s.size()-1; ++i)
{
s[i] = s[i+1];
s[i+1] = ' ';
}
}
else
{
s[s.size()-1] = ' ';
}
if (deleteMin != deleteMax)
s.erase(s.begin() + deleteMin, s.begin() + deleteMax);
_text->update();
_text->update();
_calculateCursorOffsets();
_calculateCursorOffsets();
--_textLength;
}
_index = deleteMin;
_selectionStartIndex = _selectionEndIndex = _index;
}
break;
default:
@@ -516,7 +502,6 @@ bool Input::keyDown(int key, int mask, const WindowManager*) {
if (((key=='v' || key=='V') && (mask & osgGA::GUIEventAdapter::MODKEY_CTRL)) || (key==22))
{
_selectionStartIndex = _selectionEndIndex = _index;
std::string data;
// Data from clipboard
#ifdef WIN32
@@ -531,15 +516,27 @@ bool Input::keyDown(int key, int mask, const WindowManager*) {
#endif
if (!data.empty())
{
data = data.substr(0,_maxSize-_index);
_textLength += data.size();
_selectionEndIndex = _textLength;
unsigned int deleteMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
unsigned int deleteMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
std::string::iterator itr = data.begin();
for ( ; itr != data.end(); ++itr )
if (deleteMax - deleteMin > 0)
{
s[_index++] = *itr;
data = data.substr(0, _maxSize-s.size()-(deleteMax - deleteMin));
s.erase(s.begin() + deleteMin, s.begin() + deleteMax);
s.insert(s.begin() + deleteMin, data.begin(), data.end());
_index = deleteMin + data.size();
}
else
{
data = data.substr(0, _maxSize-s.size());
s.insert(s.begin() + _index, data.begin(), data.end());
_index += data.length();
}
_selectionStartIndex = _selectionEndIndex = _index;
_text->update();
@@ -550,23 +547,19 @@ bool Input::keyDown(int key, int mask, const WindowManager*) {
getParent()->resize();
return false;
}
}
else
if (((key=='c' || key=='C') && (mask & osgGA::GUIEventAdapter::MODKEY_CTRL)) || (key==3))
if (((key=='c' || key=='C' || key=='x' || key=='X') && (mask & osgGA::GUIEventAdapter::MODKEY_CTRL)) || (key==3) || (key==24))
{
unsigned int _selectionMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
unsigned int _selectionMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
unsigned int selectionMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
unsigned int selectionMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
if (_selectionMax-_selectionMin>0)
if (selectionMax - selectionMin > 0)
{
std::string data;
for (unsigned int i=_selectionMin; i<=_selectionMax; ++i)
{
data.push_back(s[i]);
}
data.insert(data.begin(), s.begin() + selectionMin, s.begin() + selectionMax);
// Data to clipboard
#ifdef WIN32
if(::OpenClipboard(NULL))
@@ -580,61 +573,69 @@ bool Input::keyDown(int key, int mask, const WindowManager*) {
::CloseClipboard();
}
#endif
if (key=='x' || key=='X' || key == 24)
{
s.erase(s.begin() + selectionMin, s.begin() + selectionMax);
_index = selectionMin;
_selectionStartIndex = _selectionEndIndex = _index;
_text->update();
_calculateCursorOffsets();
_calculateSize(getTextSize());
getParent()->resize();
}
}
return false;
}
{
unsigned int _selectionMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
unsigned int _selectionMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
if (_selectionMax-_selectionMin>0)
{
// If something is selected, we need to delete it and insert the character there.
unsigned int deleteMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
unsigned int deleteMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
if (deleteMax - deleteMin > 0)
{
unsigned int deleteToIdx = _selectionMax;
for (unsigned int i=0; i < s.size()-_selectionMin; ++i)
{
s[_selectionMin+i] = (deleteToIdx+i+1 < s.size()) ? s[deleteToIdx+i+1] : ' ';
}
s.erase(s.begin() + deleteMin, s.begin() + deleteMax);
_text->update();
_calculateCursorOffsets();
_textLength -= deleteToIdx-_selectionMin;
_index = _selectionMin;
_index = deleteMin;
_selectionStartIndex = _selectionEndIndex = _index;
}
}
if (!_insertMode)
if (_insertMode && _index < s.size())
{
for (unsigned int i=s.size()-1; i>_index; --i)
{
s[i] = s[i-1];
}
s[_index] = key;
}
else
{
if (_index < _maxSize)
s.insert(s.begin() + _index, key);
}
s[_index] = key;
_text->update();
_text->update();
_calculateCursorOffsets();
_calculateCursorOffsets();
_index++;
_index++;
_selectionStartIndex = _selectionEndIndex = _index;
}
if (!_insertMode) ++_textLength;
_calculateSize(getTextSize());
_selectionStartIndex = _selectionEndIndex = _index;
}
getParent()->resize();
// _text->update();
_calculateSize(getTextSize());
getParent()->resize();
return false;
return true;
}
void Input::setCursor(Widget*) {
@@ -662,4 +663,21 @@ unsigned int Input::calculateBestYOffset(const std::string& s)
return descent;
}
void Input::clear()
{
setLabel("");
_text->update();
_calculateCursorOffsets();
_index = 0;
_selectionStartIndex = _selectionEndIndex = _index;
_selectionIndex = _index;
_cursorIndex = _index;
_calculateSize(getTextSize());
getParent()->resize();
}
}

View File

@@ -615,7 +615,26 @@ bool WindowManager::keyDown(int key, int mask) {
}
bool WindowManager::keyUp(int key, int mask) {
return true;
if(_focused.valid()) {
Event ev(this, EVENT_KEY_UP);
ev.makeKey(key, mask);
Widget* focusedWidget = _focused->getFocused();
ev._window = _focused.get();
ev._widget = focusedWidget;
bool handled = false;
if(focusedWidget) handled = focusedWidget->callMethodAndCallbacks(ev);
if(!handled) return _focused->callMethodAndCallbacks(ev);
else return true;
}
return false;
}
// A convenience wrapper for creating a proper orthographic camera using the current