ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/backend/ndk/text.cpp
Revision: 1.2
Committed: Mon Oct 18 14:11:48 2010 UTC (16 years ago) by sf-pippijn
Branch: MAIN
Changes since 1.1: +5 -4 lines
Log Message:
check and log but do not die when ncurses stuff fails

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