]> git.tdb.fi Git - libs/gltk.git/commitdiff
Support multiline text editing
authorMikko Rasa <tdb@tdb.fi>
Sat, 24 Apr 2010 20:47:55 +0000 (20:47 +0000)
committerMikko Rasa <tdb@tdb.fi>
Sat, 24 Apr 2010 20:47:55 +0000 (20:47 +0000)
source/entry.cpp
source/entry.h
source/text.cpp
source/text.h

index 28b454d90d10c62ab589ae5e8daca9246bd044f8..7d5ecb66986d4ef9580745ca3c5594c942cd0182 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgltk
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -22,6 +22,7 @@ namespace GLtk {
 Entry::Entry(const Resources &r, const string &t):
        Widget(r),
        text(),
+       multiline(false),
        edit_pos(0)
 {
        update_style();
@@ -34,6 +35,11 @@ void Entry::set_text(const string &t)
        edit_pos=text.size();
 }
 
+void Entry::set_multiline(bool m)
+{
+       multiline = m;
+}
+
 void Entry::key_press(unsigned key, unsigned, wchar_t ch)
 {
        if(key==Input::KEY_LEFT)
@@ -46,13 +52,33 @@ void Entry::key_press(unsigned key, unsigned, wchar_t ch)
                if(edit_pos<text.size())
                        ++edit_pos;
        }
+       else if(key==Input::KEY_DOWN && multiline)
+       {
+               unsigned row, col;
+               text.offset_to_coords(edit_pos, row, col);
+               edit_pos=text.coords_to_offset(row+1, col);
+       }
+       else if(key==Input::KEY_UP && multiline)
+       {
+               unsigned row, col;
+               text.offset_to_coords(edit_pos, row, col);
+               if(row>0)
+                       edit_pos=text.coords_to_offset(row-1, col);
+               else
+                       edit_pos=0;
+       }
        else if(key==Input::KEY_BACKSPACE)
        {
                if(edit_pos>0)
                        text.erase(--edit_pos, 1);
        }
        else if(key==Input::KEY_ENTER)
-               signal_enter.emit();
+       {
+               if(multiline)
+                       text.insert(edit_pos++, "\n");
+               else
+                       signal_enter.emit();
+       }
        else if(ch>=' ')
        {
                text.insert(edit_pos, Codecs::encode<Codecs::Utf8>(Codecs::ustring(1, ch)));
@@ -69,17 +95,15 @@ void Entry::render_special(const Part &part) const
                if(!part.get_graphic(state))
                        return;
 
-               const GL::Font *const font=style->get_font();
-               const float font_size=font->get_default_size();
+               unsigned row, col;
+               text.offset_to_coords(edit_pos, row, col);
 
-               Geometry rgeom=part.get_geometry();
-               rgeom.x=static_cast<unsigned>(font->get_string_width(text.get().substr(0, edit_pos))*font_size);
-               rgeom.w=static_cast<unsigned>(font->get_string_width(text.get())*font_size);
+               Geometry rgeom=text.coords_to_geometry(row, col);
                part.get_alignment().apply(rgeom, geom, part.get_margin());
 
                GL::push_matrix();
                GL::translate(rgeom.x, rgeom.y, 0);
-               part.get_graphic(state)->render(part.get_geometry().w, rgeom.h);
+               part.get_graphic(state)->render(part.get_geometry().w, part.get_geometry().h);
                GL::pop_matrix();
        }
 }
index 7355067d2db2f634d3db1cd5fd9eb8c8e6e1dc1a..0ff5466a613e11bcd545002b4409727b253ef9ef 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspgltk
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2010  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -33,6 +33,7 @@ public:
 
 private:
        Text text;
+       bool multiline;
        unsigned edit_pos;
 
 public:
@@ -42,6 +43,8 @@ public:
 
        void set_text(const std::string &);
        const std::string &get_text() const { return text.get(); }
+       void set_multiline(bool);
+       bool is_multiline() const { return multiline; }
 
        virtual void key_press(unsigned, unsigned, wchar_t);
 private:
index 31db228071943fc55f0f3942b16a32a50dcb3c90..d18d7b5ba6c03fc233026afd178220d30b2babe0 100644 (file)
@@ -1,3 +1,10 @@
+/* $Id$
+
+This file is part of libmspgltk
+Copyright © 2009-2010  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
 #include <msp/gl/immediate.h>
 #include <msp/gl/matrix.h>
 #include "style.h"
@@ -86,6 +93,63 @@ void Text::insert(unsigned pos, const string &s)
        }
 }
 
+unsigned Text::get_line_length(unsigned i) const
+{
+       if(i>=lines.size())
+               throw InvalidParameterValue("Invalid line number");
+       return lines[i].length;
+}
+
+void Text::offset_to_coords(unsigned offs, unsigned &row, unsigned &col) const
+{
+       if(lines.empty())
+       {
+               row=0;
+               col=0;
+               return;
+       }
+
+       for(unsigned i=0; i<lines.size(); ++i)
+               if(offs>=lines[i].start && offs<=lines[i].start+lines[i].length)
+               {
+                       row=i;
+                       col=offs-lines[i].start;
+                       return;
+               }
+}
+
+unsigned Text::coords_to_offset(unsigned row, unsigned col) const
+{
+       if(row>=lines.size())
+               return text.size();
+
+       return lines[row].start+min(col, lines[row].length);
+}
+
+Geometry Text::coords_to_geometry(unsigned row, unsigned col) const
+{
+       if(row>=lines.size())
+               row=lines.size()-1;
+       const Line &line=lines[row];
+       if(col>line.length)
+               col=line.length;
+
+       const GL::Font *font=style->get_font();
+       float font_size=font->get_default_size();
+       unsigned line_height=static_cast<unsigned>((font->get_ascent()-font->get_descent())*font_size);
+       unsigned line_spacing=static_cast<unsigned>(font_size*6/5);
+       unsigned height=line_height+(lines.size()-1)*line_spacing;
+       int y_offset=static_cast<int>(-font->get_descent()*font_size);
+
+       Geometry geom;
+       geom.w=line.width;
+       geom.h=height;
+       geom.x=static_cast<unsigned>(font->get_string_width(text.substr(line.start, col))*font_size);
+       geom.y=(lines.size()-1-row)*line_spacing+y_offset;
+
+       return geom;
+}
+
 void Text::render(const Part &part, const Geometry &geom) const
 {
        if(lines.empty())
@@ -94,7 +158,7 @@ void Text::render(const Part &part, const Geometry &geom) const
        const GL::Font *font=style->get_font();
        float font_size=font->get_default_size();
        unsigned line_height=static_cast<unsigned>((font->get_ascent()-font->get_descent())*font_size);
-       unsigned line_spacing=font_size*6/5;
+       unsigned line_spacing=static_cast<unsigned>(font_size*6/5);
        unsigned height=line_height+(lines.size()-1)*line_spacing;
        int y_offset=static_cast<int>(-font->get_descent()*font_size);
 
index d964aa19bbf4575ce7d10c9ceea743d38a15017c..0e1afaebd198b3230736d38bf1c198b7cc4dc25c 100644 (file)
@@ -1,3 +1,10 @@
+/* $Id$
+
+This file is part of libmspgltk
+Copyright © 2009-2010  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
 #ifndef MSP_GLTK_TEXT_H_
 #define MSP_GLTK_TEXT_H_
 
@@ -42,6 +49,11 @@ public:
        void insert(unsigned, const std::string &);
        const std::string &get() const { return text; }
        unsigned size() const { return text.size(); }
+       unsigned get_n_lines() const { return lines.size(); }
+       unsigned get_line_length(unsigned) const;
+       void offset_to_coords(unsigned, unsigned &, unsigned &) const;
+       unsigned coords_to_offset(unsigned, unsigned) const;
+       Geometry coords_to_geometry(unsigned, unsigned) const;
 
        void render(const Part &, const Geometry &) const;