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

# Content
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 * which should be included with libndk as the file COPYING.
7 */
8 #include <ndk/application.hh>
9 #include <ndk/edit.hh>
10 #include <ndk/packer.hh>
11 #include <ndk/palette.hh>
12
13 #include <ndk/pen.hh>
14
15 #include <cctype>
16
17
18 using ndk::edit;
19
20 edit::edit (std::string const &str, panel *parent, bool accept)
21 : 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 edit::set_text (std::string const &str)
38 {
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 pen (*this).set_color (palette::instance ().find (
54 state_ == engine::enter_focus
55 ? colors::edit_active
56 : colors::edit_inactive
57 )->second);
58 }
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 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 }
88
89 ndk::event::result
90 edit::at_system (event const &ev)
91 {
92 event::result res = event::ignored;
93
94 if (!ev.sender_)
95 {
96 if (engine::enter_focus == ev.type_)
97 {
98 app->cursor_on ();
99 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 app->cursor_off ();
105 res = event::accepted;
106 }
107 }
108 return res;
109 }
110
111 ndk::event::result
112 edit::at_keyboard (keyboard const &ev)
113 {
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 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 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 return_unless (pen (*this).move (mode_ != no_echo ? current_ - begin_ : 0, 0));
234 pen (*this).commit ();
235 }
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 }