~ubuntu-branches/debian/experimental/openscenegraph/experimental

« back to all changes in this revision

Viewing changes to OpenSceneGraph/src/osgWidget/Input.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alberto Luaces
  • Date: 2011-01-29 11:36:29 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20110129113629-qisrm2kdqlurc7t3
Tags: 2.9.11-1
* Removed bug-555869-ftbfs_with_binutils_gold.dpatch since upstream has
  already taken care of the issue.
* Removed bug-528229.dpatch since the pkgconfig files are now also split
  in upstream.
* Removed explicit dependency on GLU.
* Upstream no longer includes osgIntrospection (Closes: #592420).
* Disabled zip plugin as its implementation stores an embedded copy of
  zlib.
* Enabled Qt support. Thanks James Goppert.
* Enabled SVG and PDF plugins. Thanks James Goppert.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
#include <osg/io_utils>
4
4
#include <osgWidget/WindowManager>
5
5
#include <osgWidget/Input>
 
6
#include <iterator>
 
7
 
 
8
#ifdef WIN32
 
9
#include <windows.h>
 
10
#endif
6
11
 
7
12
namespace osgWidget {
8
13
 
 
14
class BlinkCursorCallback: public osg::Drawable::DrawCallback
 
15
{
 
16
public:
 
17
    BlinkCursorCallback(const bool& insertMode)
 
18
        : _insertMode(insertMode)
 
19
    {
 
20
    }
 
21
 
 
22
    virtual void drawImplementation( osg::RenderInfo & ri,const osg::Drawable* drawable ) const
 
23
    {
 
24
        static bool on = true;
 
25
        static osg::Timer_t startTime = osg::Timer::instance()->tick();
 
26
        osg::Timer_t now = osg::Timer::instance()->tick();
 
27
 
 
28
        if (osg::Timer::instance()->delta_s(startTime,now)>(_insertMode?0.125:0.25))
 
29
        {
 
30
            on = !on;
 
31
            startTime = now;
 
32
        }
 
33
        if (on)
 
34
            drawable->drawImplementation(ri);
 
35
    }
 
36
protected:
 
37
    const bool&    _insertMode;
 
38
};
 
39
 
9
40
Input::Input(const std::string& name, const std::string& label, unsigned int size):
10
 
Label        (name, label),
11
 
_xoff        (0.0f), 
12
 
_yoff        (0.0f),
13
 
_index       (0),
14
 
_size        (0),
15
 
_cursorIndex (0),
16
 
_maxSize     (size),
17
 
_cursor      (new Widget("cursor")) {
18
 
    _text->setAlignment(osgText::Text::LEFT_BOTTOM_BASE_LINE);
19
 
    _text->setKerningType(osgText::KERNING_NONE);
20
 
 
21
 
    // Make the cursor un-copyable.
22
 
    _cursor->setCanClone(false);
23
 
    _cursor->setDataVariance(osg::Object::DYNAMIC);
24
 
    _cursor->setColor(0.0f, 0.0f, 0.0f, 1.0f);
25
 
 
26
 
    setEventMask(
27
 
        // For showing/hiding the "cursor."
28
 
        EVENT_MASK_FOCUS |
29
 
        // For keypresses, obviously.
30
 
        EVENT_MASK_KEY |
31
 
        // For "click" focusing.
32
 
        EVENT_MOUSE_PUSH
33
 
    );
34
 
 
35
 
    _offsets.resize(size, 0.0f);
36
 
 
37
 
    _text->getText().resize(size, ' ');
38
 
    _text->update();
 
41
    Label(name, label),
 
42
    _xoff(0.0f),
 
43
    _yoff(0.0f),
 
44
    _index(0),
 
45
    _size(0),
 
46
    _cursorIndex(0),
 
47
    _maxSize(size),
 
48
    _cursor(new Widget("cursor")),
 
49
    _insertMode(false),
 
50
    _selection(new Widget("selection")),
 
51
    _selectionStartIndex(0),
 
52
    _selectionEndIndex(0),
 
53
    _selectionIndex(0),
 
54
    _mouseClickX(0)
 
55
{
 
56
   _text->setAlignment(osgText::Text::LEFT_BOTTOM_BASE_LINE);
 
57
   _text->setKerningType(osgText::KERNING_NONE);
 
58
 
 
59
   // Make the cursor un-copyable.
 
60
   _cursor->setCanClone(false);
 
61
   _cursor->setDataVariance(osg::Object::DYNAMIC);
 
62
   _cursor->setColor(0.0f, 0.0f, 0.0f, 1.0f);
 
63
 
 
64
   _selection->setCanClone(false);
 
65
   _selection->setDataVariance(osg::Object::DYNAMIC);
 
66
 
 
67
   setEventMask(
 
68
       // For showing/hiding the "cursor."
 
69
       EVENT_MASK_FOCUS |
 
70
       // For keypresses, obviously.
 
71
       EVENT_MASK_KEY |
 
72
       // For "click" focusing.
 
73
       EVENT_MOUSE_PUSH |
 
74
       EVENT_MASK_MOUSE_DRAG
 
75
   );
 
76
 
 
77
   _offsets.resize(_text->getText().size()+1, 0.0f);
 
78
   _widths.resize(_text->getText().size()+1, 1.0f);
 
79
 
 
80
   _text->update();
 
81
 
 
82
   _cursor->setDrawCallback( new BlinkCursorCallback(_insertMode) );
39
83
}
40
84
 
41
85
void Input::_calculateSize(const XYCoord& size) {
42
 
    // An Input cannot currently set it's own size RELIABLY until the osgText implementation
43
 
    // is dratiscally improved. I'm getting wildly crazy results. :(
44
 
    // point_type height = size.y() > _cursor->getHeight() ? size.y() : _cursor->getHeight();
 
86
   // An Input cannot currently set it's own size RELIABLY until the osgText implementation
 
87
   // is dratiscally improved. I'm getting wildly crazy results. :(
 
88
   // point_type height = size.y() > _cursor->getHeight() ? size.y() : _cursor->getHeight();
45
89
 
46
90
#if 0
47
 
    point_type width  = size.x() + _cursor->getWidth();
48
 
    point_type height = _cursor->getHeight();
49
 
 
50
 
    if(width > getWidth()) setWidth(osg::round(width));
51
 
 
52
 
    if(height > getHeight()) setHeight(osg::round(height));
 
91
   point_type width  = size.x() + _cursor->getWidth();
 
92
   point_type height = _cursor->getHeight();
 
93
 
 
94
   if(width > getWidth()) setWidth(osg::round(width));
 
95
 
 
96
   if(height > getHeight()) setHeight(osg::round(height));
53
97
#endif
54
98
}
55
99
 
56
100
void Input::_calculateCursorOffsets() {
57
 
    // Determine the "offset"
58
 
    const osgText::Text::TextureGlyphQuadMap& tgqm = _text->getTextureGlyphQuadMap();
59
 
 
60
 
    const osgText::Text::TextureGlyphQuadMap::const_iterator tgqmi = tgqm.begin();
61
 
    
62
 
    const osgText::Text::GlyphQuads& gq = tgqmi->second;
 
101
   // Determine the "offset"
 
102
 
 
103
   _offsets.resize(_text->getText().size()+1, 0.0f);
 
104
   _widths.resize(_text->getText().size()+1, 1.0f);
 
105
 
 
106
    if (_text->getText().size()==0) 
 
107
    {
 
108
        _offsets[0] = 0;
 
109
        _widths[0] = 1.f;
 
110
        return;
 
111
    }
63
112
 
64
113
    osg::Vec3 pos = _text->getPosition();
65
114
 
66
 
    for(unsigned int i = 0; i < _maxSize; i++) {
67
 
        osg::Vec3 ul = gq.getTransformedCoords(0)[0 + (i * 4)];
68
 
        osg::Vec3 ll = gq.getTransformedCoords(0)[1 + (i * 4)];
69
 
        osg::Vec3 lr = gq.getTransformedCoords(0)[2 + (i * 4)];
70
 
        osg::Vec3 ur = gq.getTransformedCoords(0)[3 + (i * 4)];
71
 
        
72
 
        _offsets[i] = lr.x() - pos.x();
73
 
 
74
 
        // warn() << "vb: " << gq.getGlyphs()[i]->getHorizontalBearing() << std::endl;
75
 
    }
76
 
}
77
 
 
78
 
bool Input::focus(WindowManager*) {
79
 
    _cursor->setColor(0.0f, 0.0f, 0.0f, 1.0f);
80
 
 
81
 
    return true;
82
 
}
83
 
 
84
 
bool Input::unfocus(WindowManager*) {
85
 
    _cursor->setColor(0.0f, 0.0f, 0.0f, 0.0f);
86
 
 
87
 
    return true;
 
115
    osgText::Text::TextureGlyphQuadMap& tgqm = const_cast<osgText::Text::TextureGlyphQuadMap&>(_text->getTextureGlyphQuadMap());
 
116
    osgText::Text::TextureGlyphQuadMap::iterator tgqmi = tgqm.begin();
 
117
 
 
118
    std::vector<osg::Vec2>                coords;
 
119
    std::vector<osgText::Glyph*>    glyphs;
 
120
    for ( ; tgqmi != tgqm.end(); tgqmi++ )
 
121
    {
 
122
        const osgText::Text::GlyphQuads& gq = tgqmi->second;
 
123
 
 
124
        //coords.insert(coords.end(),gq.getTransformedCoords(0).begin(),gq.getTransformedCoords(0).end());
 
125
        coords.insert(coords.end(),gq.getCoords().begin(),gq.getCoords().end());
 
126
        for (unsigned int i=0; i<gq.getGlyphs().size(); ++i)
 
127
        {
 
128
            glyphs.push_back(gq.getGlyphs().at(i));
 
129
        }
 
130
    }
 
131
    
 
132
    std::list<unsigned int> keys;
 
133
    for (unsigned int i=0; i<_text->getText().size(); ++i)
 
134
    {
 
135
        keys.push_back(_text->getText().at(i));
 
136
    }
 
137
    unsigned int idx=0;
 
138
    osg::Vec2 lr;
 
139
    osg::Vec2 ll;
 
140
    while (!keys.empty())
 
141
    {
 
142
        unsigned int key = keys.front();
 
143
        for (unsigned int i=0; i<glyphs.size(); ++i)
 
144
        {
 
145
            static osgText::Glyph* previous_g = 0;
 
146
 
 
147
            osgText::Glyph* g = glyphs.at(i);
 
148
            if (g->getGlyphCode()==key)
 
149
            {
 
150
                lr = coords[2 + (i * 4)];
 
151
                ll = coords[1 + (i * 4)];
 
152
 
 
153
                point_type width = lr.x() - ll.x();
 
154
                _widths[idx] = width == 0 ? g->getHorizontalAdvance() : width;
 
155
 
 
156
                _offsets[idx] = lr.x() + pos.x();
 
157
 
 
158
                if (width == 0)
 
159
                    _offsets[idx] += g->getHorizontalAdvance();
 
160
                ++idx;
 
161
 
 
162
                if (previous_g)
 
163
                {
 
164
                    {
 
165
                        point_type& ref = _offsets[idx];
 
166
                        ref += previous_g->getHorizontalAdvance();
 
167
                    }
 
168
                    {
 
169
                        point_type& ref = _widths[idx];
 
170
                        ref += previous_g->getHorizontalAdvance();
 
171
                    }
 
172
                }
 
173
                previous_g = g;
 
174
 
 
175
                glyphs.erase(glyphs.begin()+i);
 
176
                coords.erase(coords.begin()+i*4);
 
177
                coords.erase(coords.begin()+i*4);
 
178
                coords.erase(coords.begin()+i*4);
 
179
                coords.erase(coords.begin()+i*4);
 
180
                break;
 
181
            }
 
182
        }
 
183
        keys.pop_front();
 
184
    }
 
185
 
 
186
    _offsets[idx] = lr.x() + pos.x();
 
187
    _widths[idx] = 1.f;
 
188
 
 
189
    _wordsOffsets.clear();
 
190
    for ( unsigned int i=0; i<_text->getText().size(); ++i )
 
191
    {
 
192
        while (i<_text->getText().size() && _text->getText().at(i)==' ') ++i;
 
193
        if (i<_text->getText().size())_wordsOffsets.push_back(i);
 
194
        while (i<_text->getText().size() && _text->getText().at(i)!=' ') ++i;
 
195
    }
 
196
 
 
197
    positioned();
 
198
}
 
199
 
 
200
bool Input::focus(const WindowManager*) {
 
201
   _cursor->setColor(0.5f, 0.5f, 0.6f, 1.0f);
 
202
   _selection->setColor(0.8f, 0.8f, 0.9f, 1.0f);
 
203
 
 
204
   return true;
 
205
}
 
206
 
 
207
bool Input::unfocus(const WindowManager*) {
 
208
   _cursor->setColor(0.0f, 0.0f, 0.0f, 0.0f);
 
209
   _selection->setColor(0.0f, 0.0f, 0.0f, 0.0f);
 
210
 
 
211
   return true;
88
212
}
89
213
 
90
214
void Input::parented(Window* parent) {
91
 
    Label::parented(parent);
92
 
 
93
 
    _cursor->setSize(2.0f, _text->getCharacterHeight());
94
 
 
95
 
    if(_cursorIndex) parent->getGeode()->setDrawable(_cursorIndex, _cursor.get());
96
 
 
97
 
    else _cursorIndex = parent->addDrawableAndGetIndex(_cursor.get());
 
215
   Label::parented(parent);
 
216
 
 
217
   _cursor->setSize(_widths[_index], getHeight());
 
218
 
 
219
   if(_cursorIndex) parent->getGeode()->setDrawable(_cursorIndex, _cursor.get());
 
220
   else _cursorIndex = parent->addDrawableAndGetIndex(_cursor.get());
 
221
 
 
222
   if(_selectionIndex) parent->getGeode()->setDrawable(_selectionIndex, _selection.get());
 
223
   else _selectionIndex = parent->addDrawableAndGetIndex(_selection.get());
98
224
}
99
225
 
100
 
void Input::positioned() {
 
226
void Input::positioned()
 
227
{
101
228
    point_type ln = static_cast<point_type>(_text->getLineCount());
102
229
 
103
230
    ln = ln == 0.0f ? 1.0f : ln;
110
237
    // XYCoord size = getTextSize();
111
238
 
112
239
    _text->setPosition(osg::Vec3(x, y, _calculateZ(LAYER_MIDDLE)));
113
 
    
 
240
 
114
241
    point_type xoffset = _index > 0 ? _offsets[_index - 1] : 0.0f;
115
242
 
116
 
    _cursor->setOrigin(x + xoffset + 1.0f, y + 1.0f);
117
 
    _cursor->setZ(_calculateZ(LAYER_MIDDLE));
118
 
}
119
 
 
120
 
bool Input::keyUp(int key, int mask, WindowManager*) {
121
 
    return false;
122
 
}
123
 
 
124
 
bool Input::keyDown(int key, int mask, WindowManager*) {
125
 
    osgText::String& s = _text->getText();
126
 
 
127
 
    if(key == osgGA::GUIEventAdapter::KEY_BackSpace) {
128
 
        if(_index >= 1) {
129
 
            // s.erase(s.begin() + (_index - 1));
130
 
 
131
 
            s[_index - 1] = ' ';
132
 
 
133
 
            _text->update();
134
 
            
135
 
            _calculateCursorOffsets();
136
 
 
137
 
            _index--;
138
 
        }
139
 
    }
140
 
 
141
 
    else {
 
243
    if (_insertMode)
 
244
    {
 
245
        if (_index < _text->getText().size())
 
246
        {
 
247
            _cursor->setSize(_widths[_index], getHeight());
 
248
        }
 
249
        else
 
250
        {
 
251
            // We're at the end of the string, perhaps the string is empty, 
 
252
            // so get the advance for any character, perhaps a large one, I chose 'A'.
 
253
            osgText::Glyph* glyph = const_cast<osgText::Font*>(_text->getFont())->getGlyph(osgText::FontResolution(_text->getFontWidth(), _text->getFontHeight()), 'A');
 
254
            _cursor->setSize(glyph->getHorizontalAdvance(), getHeight());
 
255
        }
 
256
    }
 
257
    else
 
258
    {
 
259
        _cursor->setSize(1.f, getHeight());
 
260
    }
 
261
 
 
262
    _cursor->setOrigin(getX() + xoffset, getY() );
 
263
    _cursor->setZ(_calculateZ(LAYER_MIDDLE-1));
 
264
 
 
265
 
 
266
    unsigned int selectionMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
 
267
    unsigned int selectionMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
 
268
 
 
269
    if (selectionMax - selectionMin > 0)
 
270
    {
 
271
        point_type xstart = selectionMin > 0 ? _offsets[selectionMin - 1] : 0.0f;
 
272
        point_type xend   = selectionMax > 0 ? _offsets[selectionMax - 1] : 0.0f;
 
273
 
 
274
        _selection->setSize(xend-xstart, getHeight());
 
275
        _selection->setOrigin(getX() + xstart, getY());
 
276
        _selection->setZ(_calculateZ(LAYER_MIDDLE-2));
 
277
    }
 
278
    else
 
279
    {
 
280
        _selection->setSize(0, getHeight());
 
281
    }
 
282
}
 
283
 
 
284
bool Input::keyUp(int key, int mask, const WindowManager*) {
 
285
   return false;
 
286
}
 
287
 
 
288
bool Input::mouseDrag (double x, double y, const WindowManager*)
 
289
{
 
290
    _mouseClickX += x;
 
291
    x = _mouseClickX;
 
292
 
 
293
    for ( unsigned int i = 0; i < _offsets.size(); ++i )
 
294
    {
 
295
        point_type offset1 = i > 0 ? _offsets.at(i-1) : 0;
 
296
        point_type offset2 = _offsets.at(i);
 
297
        if ((x >= offset1 && x <= offset2) ||
 
298
            i == _offsets.size() - 1)  // If we're at the last one, obviously it will be there.
 
299
        {
 
300
            _selectionEndIndex = _index = i; 
 
301
            positioned();
 
302
            break;
 
303
        }
 
304
    }
 
305
 
 
306
    return true;
 
307
}
 
308
 
 
309
bool Input::mousePush (double x, double y, const WindowManager* wm)
 
310
{
 
311
    double offset = getOrigin().x();
 
312
    Window* window = getParent();
 
313
    if (window) 
 
314
    { 
 
315
        offset += window->getOrigin().x(); 
 
316
    }
 
317
 
 
318
    x -= offset;
 
319
    _mouseClickX = x;
 
320
 
 
321
    for ( unsigned int i = 0; i < _offsets.size(); ++i )
 
322
    {
 
323
        point_type offset1 = i > 0 ? _offsets.at(i-1) : 0;
 
324
        point_type offset2 = _offsets.at(i);
 
325
        if ((x >= offset1 && x <= offset2) ||
 
326
            i == _offsets.size() - 1)  // If we're at the last one, obviously it will be there.
 
327
        {
 
328
            _selectionStartIndex = _selectionEndIndex = _index = i; 
 
329
            positioned();
 
330
            break;
 
331
        }
 
332
    }
 
333
    return true;
 
334
}
 
335
 
 
336
bool Input::mouseRelease(double, double, const WindowManager*)
 
337
{
 
338
    return true;
 
339
}
 
340
 
 
341
bool Input::keyDown(int key, int mask, const WindowManager*)
 
342
{
 
343
   osgText::String& s = _text->getText();
 
344
 
 
345
   switch (key)
 
346
   {
 
347
    case osgGA::GUIEventAdapter::KEY_Left:
 
348
        if (mask & osgGA::GUIEventAdapter::MODKEY_CTRL)
 
349
        {
 
350
            bool found = false;
 
351
            for (unsigned int i = 0; i < _wordsOffsets.size() - 1; ++i)
 
352
            {
 
353
                if (_wordsOffsets.at(i) < _index && _index <= _wordsOffsets.at(i+1))
 
354
                {
 
355
                    found = true;
 
356
                    _index = _wordsOffsets.at(i);
 
357
                    break;
 
358
                }
 
359
            }
 
360
            if (!found && _wordsOffsets.size())
 
361
            {
 
362
                _index = _wordsOffsets.at(_wordsOffsets.size()-1);
 
363
            }
 
364
        }
 
365
        else
 
366
        if (_index > 0)
 
367
        {
 
368
            --_index;
 
369
        }
 
370
        if (mask & osgGA::GUIEventAdapter::MODKEY_SHIFT)
 
371
        {
 
372
            _selectionEndIndex = _index;
 
373
        }
 
374
        else
 
375
        {
 
376
            _selectionStartIndex = _selectionEndIndex = _index;
 
377
        }
 
378
        break;
 
379
    case osgGA::GUIEventAdapter::KEY_Right:
 
380
        if (mask & osgGA::GUIEventAdapter::MODKEY_CTRL)
 
381
        {
 
382
            bool found = false;
 
383
            for (unsigned int i = 0; i < _wordsOffsets.size() - 1; ++i)
 
384
            {
 
385
                if (_wordsOffsets.at(i) <= _index && _index < _wordsOffsets.at(i+1))
 
386
                {
 
387
                    found = true;
 
388
                    _index = _wordsOffsets.at(i+1);
 
389
                    break;
 
390
                }
 
391
            }
 
392
            if (!found && _wordsOffsets.size())
 
393
            {
 
394
                _index = _wordsOffsets.at(_wordsOffsets.size()-1);
 
395
            }
 
396
        }
 
397
        else
 
398
        if (_index < s.size())
 
399
        {
 
400
            ++_index;
 
401
        }
 
402
 
 
403
        if (mask & osgGA::GUIEventAdapter::MODKEY_SHIFT)
 
404
        {
 
405
            _selectionEndIndex = _index;
 
406
        }
 
407
        else
 
408
        {
 
409
            _selectionStartIndex = _selectionEndIndex = _index;
 
410
        }
 
411
        break;
 
412
    case osgGA::GUIEventAdapter::KEY_Home:
 
413
        _index = 0;
 
414
        if (mask & osgGA::GUIEventAdapter::MODKEY_SHIFT)
 
415
        {
 
416
            _selectionEndIndex = _index;
 
417
        }
 
418
        else
 
419
        {
 
420
            _selectionStartIndex = _selectionEndIndex = _index;
 
421
        }
 
422
        break;
 
423
    case osgGA::GUIEventAdapter::KEY_End:
 
424
        _index = s.size();
 
425
        if (mask & osgGA::GUIEventAdapter::MODKEY_SHIFT)
 
426
        {
 
427
            _selectionEndIndex = _index;
 
428
        }
 
429
        else
 
430
        {
 
431
            _selectionStartIndex = _selectionEndIndex = _index;
 
432
        }
 
433
        break;
 
434
    case osgGA::GUIEventAdapter::KEY_Insert:
 
435
        _insertMode = !_insertMode;
 
436
        break;
 
437
    case osgGA::GUIEventAdapter::KEY_Delete:
 
438
        {
 
439
            unsigned int deleteMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
 
440
            unsigned int deleteMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
 
441
 
 
442
            if (deleteMax - deleteMin > 0)
 
443
            {
 
444
            }
 
445
            else if (mask & osgGA::GUIEventAdapter::MODKEY_CTRL)
 
446
            {
 
447
                deleteMin = 0;
 
448
                deleteMax = 0;
 
449
                for (unsigned int i  =0; i < _wordsOffsets.size() - 1; ++i)
 
450
                {
 
451
                    if (_wordsOffsets.at(i) <= _index && _index < _wordsOffsets.at(i+1))
 
452
                    {
 
453
                        deleteMin = _wordsOffsets.at(i);
 
454
                        deleteMax = _wordsOffsets.at(i+1);
 
455
                        break;
 
456
                    }
 
457
                }
 
458
            }
 
459
            else if (_index < s.size())
 
460
            {
 
461
                deleteMin = _index;
 
462
                deleteMax = _index + 1;
 
463
            }
 
464
 
 
465
            if (deleteMin != deleteMax)
 
466
                s.erase(s.begin() + deleteMin, s.begin() + deleteMax);
 
467
 
 
468
            _text->update();
 
469
 
 
470
            _calculateCursorOffsets();
 
471
 
 
472
            _index = deleteMin;
 
473
            _selectionStartIndex = _selectionEndIndex = _index;
 
474
        }
 
475
        break;
 
476
    case osgGA::GUIEventAdapter::KEY_BackSpace:
 
477
        {
 
478
            unsigned int deleteMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
 
479
            unsigned int deleteMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
 
480
 
 
481
            if (deleteMax - deleteMin > 0)
 
482
            {
 
483
            }
 
484
            else if(_index >= 1)
 
485
            {
 
486
                deleteMin = _index - 1;
 
487
                deleteMax = _index;
 
488
            }
 
489
 
 
490
            if (deleteMin != deleteMax)
 
491
                s.erase(s.begin() + deleteMin, s.begin() + deleteMax);
 
492
 
 
493
            _text->update();
 
494
 
 
495
            _calculateCursorOffsets();
 
496
 
 
497
            _index = deleteMin;
 
498
            _selectionStartIndex = _selectionEndIndex = _index;
 
499
        }
 
500
       break;
 
501
   default:
142
502
        if(key > 255 || _index >= _maxSize) return false;
143
503
 
144
 
        // else if(_index < s.size()) s.insert(s.begin() + _index, key);
145
 
        // else if(_index == s.size()) s.push_back(key);
146
 
 
147
 
        s[_index] = key;
148
 
        
 
504
        if (((key=='v' || key=='V') && (mask & osgGA::GUIEventAdapter::MODKEY_CTRL)) || (key==22))
 
505
        {
 
506
            std::string data;
 
507
// Data from clipboard
 
508
#ifdef WIN32
 
509
            if (::OpenClipboard(NULL))
 
510
            {
 
511
                HANDLE hData = ::GetClipboardData( CF_TEXT );
 
512
                char* buff = (char*)::GlobalLock( hData );
 
513
                if (buff) data = buff;
 
514
                ::GlobalUnlock( hData );
 
515
                ::CloseClipboard();
 
516
            }
 
517
#endif
 
518
            if (!data.empty())
 
519
            {
 
520
                unsigned int deleteMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
 
521
                unsigned int deleteMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
 
522
 
 
523
                if (deleteMax - deleteMin > 0)
 
524
                {
 
525
                    data = data.substr(0, _maxSize-s.size()-(deleteMax - deleteMin));
 
526
 
 
527
                    s.erase(s.begin() + deleteMin, s.begin() + deleteMax);
 
528
                    std::copy(data.begin(), data.end(), std::inserter(s, s.begin() + deleteMin));
 
529
 
 
530
                    _index = deleteMin + data.size();
 
531
                }
 
532
                else
 
533
                {
 
534
                    data = data.substr(0, _maxSize-s.size());
 
535
 
 
536
                    std::copy(data.begin(), data.end(), std::inserter(s, s.begin() + _index));
 
537
                    _index += data.length();
 
538
                }
 
539
 
 
540
                _selectionStartIndex = _selectionEndIndex = _index;
 
541
 
 
542
                _text->update();
 
543
 
 
544
                _calculateCursorOffsets();
 
545
 
 
546
                _calculateSize(getTextSize());
 
547
 
 
548
                getParent()->resize();
 
549
 
 
550
                return false;
 
551
            }
 
552
        }
 
553
        else
 
554
        if (((key=='c' || key=='C' || key=='x' || key=='X') && (mask & osgGA::GUIEventAdapter::MODKEY_CTRL)) || (key==3) || (key==24))
 
555
        {
 
556
            unsigned int selectionMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
 
557
            unsigned int selectionMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
 
558
 
 
559
            if (selectionMax - selectionMin > 0)
 
560
            {
 
561
                std::string data;
 
562
                std::copy(s.begin() + selectionMin, s.begin() + selectionMax, std::inserter(data, data.begin()));
 
563
 
 
564
// Data to clipboard
 
565
#ifdef WIN32
 
566
                if(::OpenClipboard(NULL))
 
567
                {
 
568
                    ::EmptyClipboard();
 
569
                    HGLOBAL clipbuffer = ::GlobalAlloc(GMEM_DDESHARE, data.length()+1);
 
570
                    char* buffer = (char*)::GlobalLock(clipbuffer);
 
571
                    strcpy(buffer, data.c_str());
 
572
                    ::GlobalUnlock(clipbuffer);
 
573
                    ::SetClipboardData(CF_TEXT,clipbuffer);
 
574
                    ::CloseClipboard();
 
575
                }
 
576
#endif
 
577
 
 
578
                if (key=='x' || key=='X' || key == 24)
 
579
                {
 
580
                    s.erase(s.begin() + selectionMin, s.begin() + selectionMax);
 
581
 
 
582
                    _index = selectionMin;
 
583
 
 
584
                    _selectionStartIndex = _selectionEndIndex = _index;
 
585
 
 
586
                    _text->update();
 
587
 
 
588
                    _calculateCursorOffsets();
 
589
 
 
590
                    _calculateSize(getTextSize());
 
591
 
 
592
                    getParent()->resize();
 
593
                }
 
594
            }
 
595
            return false;
 
596
        }
 
597
 
 
598
        {
 
599
            // If something is selected, we need to delete it and insert the character there.
 
600
            unsigned int deleteMin = osg::minimum(_selectionStartIndex,_selectionEndIndex);
 
601
            unsigned int deleteMax = osg::maximum(_selectionStartIndex,_selectionEndIndex);
 
602
 
 
603
            if (deleteMax - deleteMin > 0)
 
604
            {
 
605
                s.erase(s.begin() + deleteMin, s.begin() + deleteMax);
 
606
 
 
607
                _text->update();
 
608
 
 
609
                _calculateCursorOffsets();
 
610
 
 
611
                _index = deleteMin;
 
612
                _selectionStartIndex = _selectionEndIndex = _index;
 
613
            }
 
614
        }
 
615
 
 
616
        if (_insertMode && _index < s.size())
 
617
        {
 
618
            s[_index] = key;
 
619
        }
 
620
        else
 
621
        {
 
622
            if (_index < _maxSize)
 
623
                s.insert(s.begin() + _index, key);
 
624
        }
 
625
 
149
626
        _text->update();
150
 
        
 
627
 
151
628
        _calculateCursorOffsets();
152
629
 
153
630
        _index++;
 
631
 
 
632
        _selectionStartIndex = _selectionEndIndex = _index;
154
633
    }
155
634
 
156
 
    // _text->update();
157
 
 
158
635
    _calculateSize(getTextSize());
159
636
 
160
637
    getParent()->resize();
161
638
 
162
 
    return false;
 
639
    return true;
163
640
}
164
641
 
165
642
void Input::setCursor(Widget*) {
167
644
 
168
645
unsigned int Input::calculateBestYOffset(const std::string& s)
169
646
{
170
 
 
171
 
    const osgText::FontResolution fr(static_cast<unsigned int>(_text->getCharacterHeight()),
172
 
                                     static_cast<unsigned int>(_text->getCharacterHeight()));
173
 
 
174
 
    osgText::String utf(s);
175
 
 
176
 
    unsigned int descent = 0;
177
 
 
178
 
    for(osgText::String::iterator i = utf.begin(); i != utf.end(); i++) {
179
 
        osgText::Font*        font  = const_cast<osgText::Font*>(_text->getFont());
180
 
        osgText::Font::Glyph* glyph = font->getGlyph(fr, *i);
181
 
        unsigned int          d     = abs((int)glyph->getHorizontalBearing().y());
182
 
 
183
 
        if(d > descent) descent = d;
184
 
    }
185
 
 
186
 
    return descent;
187
 
}
188
 
 
189
 
}
190
 
 
 
647
    if (!_text->getFont()) return 0;
 
648
 
 
649
   const osgText::FontResolution fr(static_cast<unsigned int>(_text->getCharacterHeight()),
 
650
                                    static_cast<unsigned int>(_text->getCharacterHeight()));
 
651
 
 
652
   osgText::String utf(s);
 
653
 
 
654
   unsigned int descent = 0;
 
655
 
 
656
   for(osgText::String::iterator i = utf.begin(); i != utf.end(); i++) {
 
657
       osgText::Font*        font  = const_cast<osgText::Font*>(_text->getFont());
 
658
       osgText::Glyph* glyph = font->getGlyph(fr, *i);
 
659
       unsigned int          d     = abs((int)glyph->getHorizontalBearing().y());
 
660
 
 
661
       if(d > descent) descent = d;
 
662
   }
 
663
 
 
664
   return descent;
 
665
}
 
666
 
 
667
void Input::clear()
 
668
{
 
669
    setLabel("");
 
670
    _text->update();
 
671
    _calculateCursorOffsets();
 
672
 
 
673
    _index = 0;
 
674
    _selectionStartIndex = _selectionEndIndex = _index;
 
675
    _selectionIndex = _index;
 
676
    _cursorIndex = _index;
 
677
 
 
678
    _calculateSize(getTextSize());
 
679
 
 
680
    getParent()->resize();
 
681
}
 
682
 
 
683
 
 
684
}