ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/backend/ndk/text.cpp
Revision: 1.1
Committed: Sun Oct 17 08:15:09 2010 UTC (16 years ago) by sf-pippijn
Branch: MAIN
Log Message:
initial import

File Contents

# User Rev Content
1 sf-pippijn 1.1 /* text.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 <ncurses/pen.hh>
9    
10     #include <ndk++/palette.hh>
11     #include <ndk++/packer.hh>
12     #include <ndk++/text.hh>
13    
14     using ndk::text;
15     using ndk::text_view;
16    
17     text::text (const std::string &str, ndk::panel *parent, wrap_type wrapping)
18     : ndk::panel (parent)
19     , x_ (0)
20     , y_ (0)
21     , wrapping_ (wrapping)
22     {
23     ncurses::pen pen (pad_);
24    
25     if (!str.empty ())
26     {
27     int h = string_height (str);
28     if (*(str.end () - 1) != '\n')
29     ++h; /* extra hack only for the first time */
30     int const w = string_width (str);
31     resize (w, h);
32     pen.write (str); /* add next text to the pad */
33     }
34     pen.fill (palette::instance ()[colors::label]);
35    
36     events ()->on_keyboard (slot (&text::at_keyboard, this));
37     }
38    
39     void
40     text::add_text (const std::string &str)
41     {
42     bool at_bottom = y_ + height () >= pad_.height ();
43    
44     /* calculate new height */
45     pad_.resize ( wrapping_ == wrap
46     ? width ()
47     : std::max (pad_.width (), string_width (str) + 1)
48     , std::max (height (), ncurses::pen (pad_).y () + string_height (str))
49     );
50     ncurses::pen (pad_).write (str); /* add next text to the pad */
51    
52     if (at_bottom)
53     while (down ())
54     ;
55     }
56    
57     void
58     text::draw () /**< draw frame on the panel */
59     {
60     pad_.draw (*this, x_, y_); /* draw pad content in the viewport */
61     }
62    
63     bool
64     text::right ()
65     {
66     if (x_ + width () < pad_.width () - 1)
67     {
68     ++x_;
69     draw ();
70     return true;
71     }
72     return false;
73     }
74    
75     bool
76     text::left ()
77     {
78     if (x_ > 0)
79     {
80     --x_;
81     draw ();
82     return true;
83     }
84     return false;
85     }
86    
87     bool
88     text::down ()
89     {
90     if (y_ + height () < pad_.height ())
91     {
92     ++y_;
93     draw ();
94     return true;
95     }
96     return false;
97     }
98    
99     bool
100     text::up ()
101     {
102     if (y_ > 0)
103     {
104     --y_;
105     draw ();
106     return true;
107     }
108     return false;
109     }
110    
111     ndk::event::result
112     text::at_keyboard (const keyboard &ev)
113     {
114     event::result res = event::ignored;
115    
116     switch (ev.code ())
117     {
118     case key::right:
119     right ();
120     res = event::accepted;
121     break;
122     case key::left:
123     left ();
124     res = event::accepted;
125     break;
126     case key::up:
127     up ();
128     res = event::accepted;
129     break;
130     case key::down:
131     down ();
132     res = event::accepted;
133     break;
134     default:
135     break;
136     }
137     if (event::accepted == res)
138     {
139     ncurses::pen (*this).commit ();
140     emit (changed);
141     }
142    
143     return res;
144     }
145    
146     int
147     text::string_height (const std::string &str) /**< @return number of strings */
148     {
149     int count = 0;
150    
151     if (wrapping_ == wrap)
152     /* in wrap mode we need additional recalculations of the string height */
153     count = str.length () / width () + (str.length () % width () != 0 ? 1 : 0);
154     else
155     /* not wrap mode: only calculate number of '\n' */
156     count = std::count (str.begin (), str.end (), '\n');
157    
158     /* we also need an additional space below if line have '\n' at the end */
159     if (*(str.end () - 1) == '\n')
160     ++count; /* grow width if nesessary */
161     return count;
162     }
163    
164     int
165     text::string_width (const std::string &str) /**< @return maximum string length */
166     {
167     std::string::const_iterator beg = str.begin ();
168     const std::string::const_iterator end = str.end ();
169     ptrdiff_t max_len = 0;
170     bool need_fix = true;
171    
172     do
173     {
174     std::string::const_iterator curr (std::find (beg, str.end (), '\n'));
175     max_len = std::max (max_len,
176     std::distance (beg, curr) + ((need_fix) ? ncurses::pen (pad_).x () : 0));
177     beg = (curr == end) ? curr : (curr + 1);
178     need_fix = false;
179     }
180     while (beg != end);
181    
182     return max_len;
183     }
184    
185     void
186     text::resize (int w, int h)
187     {
188     panel::resize (w, h);
189     /* grow size of the text if we need it */
190     pad_.resize (std::max (pad_.width (), w + 1), std::max (pad_.height (), h));
191     }
192    
193     void
194     text::clear ()
195     {
196     ncurses::pen (pad_).clear ();
197     x_ = 0;
198     y_ = 0;
199     /* truncate buffer to viewport size */
200     pad_.resize (this->width (), this->height ());
201     draw ();
202     }
203    
204     void
205     text::set_text (const std::string &str)
206     {
207     clear ();
208     add_text (str);
209     draw ();
210     }
211    
212     int
213     text::length () const
214     {
215     return pad_.height ();
216     }
217    
218     int
219     text::last_line () const
220     {
221     return y_ + height ();
222     }
223    
224     text_view::text_view (const std::string &title, ndk::panel *parent)
225     : frame (title, parent)
226     , text_ ("", this, text::no_wrap)
227     , title_ (title)
228     {
229     events ()->on_system (slot (&text_view::at_system, this));
230     in_focus (text_);
231     }
232    
233     void
234     text_view::add_text (const std::string &str)
235     {
236     text_.add_text (str);
237     }
238    
239     void
240     text_view::set_text (const std::string &str)
241     {
242     text_.set_text (str);
243     }
244    
245     void
246     text_view::draw ()
247     {
248     /* pack widgets */
249     packer<pack::horizontal, pack::no_resizer> pack (this, align::center);
250     pack.add (&text_);
251     pack.pack ();
252    
253     frame::draw ();
254    
255     ncurses::pen pen (*this);
256    
257     if (!title_.empty ())
258     {
259     std::string out (title_);
260    
261     /* if we have enough width made title more beautiful */
262     const int len = title_.length ();
263     const int wid = width ();
264     if (len < wid)
265     {
266     if (len + 6 < wid)
267     out = " " + out + " ";
268     pen.move (align::pos (out.size (), wid, align::center), 0);
269     }
270     else
271     {
272     out = out.substr (0, wid);
273     pen.move (0, 0);
274     }
275     pen.write (out);
276     }
277     }
278    
279     int
280     text_view::padding () const
281     {
282     /* save frame during packing */
283     return 1;
284     }
285    
286     void
287     text_view::resize (int w, int h)
288     {
289     panel::resize (w, h);
290     if ((w > 2) && (h > 2))
291     {
292     w -= 2;
293     h -= 2;
294     text_.resize (w, h);
295     }
296     }
297    
298     ndk::event::result
299     text_view::at_system (const event &ev)
300     {
301     event::result res = event::ignored;
302    
303     if (text_.events () == ev.sender_ && text::changed == ev.type_)
304     res = event::accepted;
305     return res;
306     }