ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/dclient/src/backend/ndk/edit.cpp
Revision: 1.8
Committed: Fri Jan 21 21:54:01 2011 UTC (13 years, 5 months ago) by sf-pippijn
Branch: MAIN
CVS Tags: HEAD
Changes since 1.7: +12 -0 lines
Log Message:
ndk/edit: implement ctrl-u

patch by Jonathan Neuschäfer <j.neuschaefer@gmx.net>

File Contents

# User Rev Content
1 sf-pippijn 1.1 /* edit.cc
2     * This file is part of NDK++ library
3     * Copyright (c) 2003,2004 by Stanislav Ievlev
4     *
5     * This file is covered by the GNU Library General Public License,
6 sf-pippijn 1.6 * which should be included with libndk as the file COPYING.
7 sf-pippijn 1.1 */
8 sf-pippijn 1.6 #include <ndk/application.hh>
9     #include <ndk/edit.hh>
10     #include <ndk/packer.hh>
11     #include <ndk/palette.hh>
12 sf-pippijn 1.1
13 sf-pippijn 1.6 #include <ndk/pen.hh>
14 sf-pippijn 1.1
15     #include <cctype>
16    
17    
18     using ndk::edit;
19    
20 sf-pippijn 1.3 edit::edit (std::string const &str, panel *parent, bool accept)
21 sf-pippijn 1.1 : button (str, parent, accept)
22     , current_ (0)
23     , begin_ (0)
24     , mode_ (normal)
25     {
26     events ()->on_keyboard (slot (&edit::at_keyboard, this));
27     events ()->on_system (slot (&edit::at_system, this));
28     }
29    
30     void
31     edit::resize (int size)
32     {
33     button::resize (size, 1);
34     }
35    
36     void
37 sf-pippijn 1.3 edit::set_text (std::string const &str)
38 sf-pippijn 1.1 {
39     label::set_text (str);
40     current_ = text_.length ();
41     draw ();
42     }
43    
44     void
45     edit::set_mode (echo_mode mode)
46     {
47     mode_ = mode;
48     }
49    
50     void
51     edit::change_color ()
52     {
53 sf-pippijn 1.5 pen (*this).set_color (palette::instance ().find (
54     state_ == engine::enter_focus
55     ? colors::edit_active
56     : colors::edit_inactive
57     )->second);
58 sf-pippijn 1.1 }
59    
60     void
61     edit::draw ()
62     {
63     /* first process flags */
64     std::string out;
65    
66     switch (mode_)
67     {
68     case normal:
69     out.assign (text ());
70     break;
71     case no_echo:
72     out.assign ("");
73     break;
74     case password:
75     out.assign (std::string (text ().size (), '*'));
76     break;
77     default:
78     break;
79     }
80    
81 sf-pippijn 1.7 if (begin_ > out.length ())
82     begin_ = out.length ();
83    
84     label::draw (out, begin_); /* and draw */
85     set_cursor (); /* and finally update cursor position */
86     pen (*this).commit (); /* commit changes to the screen */
87 sf-pippijn 1.1 }
88    
89     ndk::event::result
90 sf-pippijn 1.3 edit::at_system (event const &ev)
91 sf-pippijn 1.1 {
92     event::result res = event::ignored;
93    
94     if (!ev.sender_)
95     {
96     if (engine::enter_focus == ev.type_)
97     {
98 sf-pippijn 1.5 app->cursor_on ();
99 sf-pippijn 1.1 set_cursor (); /* only set cursor position, don't need full redraw */
100     res = event::accepted;
101     }
102     else if (engine::leave_focus == ev.type_)
103     {
104 sf-pippijn 1.5 app->cursor_off ();
105 sf-pippijn 1.1 res = event::accepted;
106     }
107     }
108     return res;
109     }
110    
111     ndk::event::result
112 sf-pippijn 1.3 edit::at_keyboard (keyboard const &ev)
113 sf-pippijn 1.1 {
114     event::result res = event::ignored;
115     unsigned int pos = current_;
116    
117     switch (ev.code ())
118     {
119     case key::right:
120     (scroll_right ()) ? draw () : set_cursor ();
121     res = event::accepted;
122     break;
123     case key::left:
124     (scroll_left ()) ? draw () : set_cursor ();
125     res = event::accepted;
126     break;
127     case key::backspace:
128     --pos; /* try to go to previous position */
129     if (pos < text_.length ())
130     {
131     erase (pos);
132     scroll_left (); /* scroll all view to the left */
133     draw (); /* we always need full redraw */
134     res = event::accepted;
135     }
136     break;
137     case key::dc:
138     if (pos < text_.length ())
139     {
140     erase (pos);
141     draw (); /* we always need full redraw */
142     res = event::accepted;
143     }
144     break;
145 sf-pippijn 1.8 case key::ctrl_u:
146     if (pos)
147     {
148     /* delete all characters up to the current */
149     text_ = text_.substr (pos, text_.length () - pos);
150     current_ = 0;
151     recalibrate (); // TODO: ? draw () : set_cursor (); // or always draw?
152     draw ();
153     pos = 0;
154     }
155     res = event::accepted;
156     break;
157 sf-pippijn 1.1 case key::home:
158     begin_ = 0;
159     current_ = 0;
160     draw ();
161     res = event::accepted;
162     break;
163     case key::end:
164     current_ = text_.length ();
165     (recalibrate ()) ? draw () : set_cursor ();
166     res = event::accepted;
167     break;
168     case '\r':
169     on_commit_ (text_);
170     break;
171     case '\t': /* don't beep on tab */
172     break;
173     default: /* enter key to the string */
174     if (std::isprint (int (ev.code ())))
175     {
176     insert (pos, char (ev.code ()));
177     scroll_right ();
178     draw (); /* we always need full redraw */
179     res = event::accepted;
180     }
181     #if 0
182     else
183     throw ev.code ();
184     #endif
185     break;
186     }
187    
188     return res;
189     }
190    
191     bool
192     edit::scroll_right ()
193     {
194     if (current_ < int (text_.length ()))
195     ++current_; /* increase current */
196     /* recalibrate begin, decide are we need to redraw */
197     return recalibrate ();
198     }
199    
200     bool
201     edit::scroll_left ()
202     {
203     if (current_ > 0)
204     --current_; /* decrease current */
205     /* recalibrate begin, decide are we need to redraw */
206     return recalibrate ();
207     }
208    
209     bool
210     edit::recalibrate ()
211     {
212     bool res = false;
213    
214     if ((begin_ < current_) && ((current_ - begin_) > (width () - 1)))
215     {
216     /* may be cursor is over(after) edit screen? */
217     begin_ = current_ - width () + 1;
218     res = true;
219     }
220     else if (begin_ > current_)
221     {
222     /* may be cursor is over(before) edit screen? */
223     begin_ = current_;
224     res = true;
225     }
226     return res;
227     }
228    
229     void
230     edit::set_cursor ()
231     {
232     /* always move to zero position in no_echo mode */
233 sf-pippijn 1.5 return_unless (pen (*this).move (mode_ != no_echo ? current_ - begin_ : 0, 0));
234     pen (*this).commit ();
235 sf-pippijn 1.1 }
236    
237     void
238     edit::insert (int pos, char sym)
239     {
240     text_.insert (text_.begin () + pos, sym); /* default mode is insert mode */
241     }
242    
243     void
244     edit::erase (int pos)
245     {
246     text_.erase (text_.begin () + pos);
247     }