ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/cf.schmorp.de/dclient/src/backend/ndk/text.cpp
Revision: 1.3
Committed: Mon Oct 18 15:34:23 2010 UTC (16 years ago) by sf-pippijn
Branch: MAIN
Changes since 1.2: +18 -26 lines
Log Message:
first attempt to support maximising windows

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 sf-pippijn 1.3 text::text (std::string const &str, ndk::panel *parent, wrap_type wrapping)
19 sf-pippijn 1.1 : 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 sf-pippijn 1.3 text::add_text (std::string const &str)
42 sf-pippijn 1.1 {
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 sf-pippijn 1.3 text::at_keyboard (keyboard const &ev)
114 sf-pippijn 1.1 {
115     switch (ev.code ())
116     {
117     case key::right:
118     right ();
119     break;
120     case key::left:
121     left ();
122     break;
123     case key::up:
124     up ();
125     break;
126     case key::down:
127     down ();
128     break;
129     default:
130 sf-pippijn 1.3 return event::ignored;
131 sf-pippijn 1.1 }
132    
133 sf-pippijn 1.3 ncurses::pen (*this).commit ();
134     emit (changed);
135    
136     return event::accepted;
137 sf-pippijn 1.1 }
138    
139     int
140 sf-pippijn 1.3 text::string_height (std::string const &str) /**< @return number of strings */
141 sf-pippijn 1.1 {
142     int count = 0;
143    
144     if (wrapping_ == wrap)
145     /* in wrap mode we need additional recalculations of the string height */
146     count = str.length () / width () + (str.length () % width () != 0 ? 1 : 0);
147     else
148     /* not wrap mode: only calculate number of '\n' */
149     count = std::count (str.begin (), str.end (), '\n');
150    
151     /* we also need an additional space below if line have '\n' at the end */
152     if (*(str.end () - 1) == '\n')
153     ++count; /* grow width if nesessary */
154     return count;
155     }
156    
157     int
158 sf-pippijn 1.3 text::string_width (std::string const &str) /**< @return maximum string length */
159 sf-pippijn 1.1 {
160     std::string::const_iterator beg = str.begin ();
161 sf-pippijn 1.3 std::string::const_iterator end = str.end ();
162 sf-pippijn 1.1 ptrdiff_t max_len = 0;
163     bool need_fix = true;
164    
165     do
166     {
167     std::string::const_iterator curr (std::find (beg, str.end (), '\n'));
168     max_len = std::max (max_len,
169     std::distance (beg, curr) + ((need_fix) ? ncurses::pen (pad_).x () : 0));
170     beg = (curr == end) ? curr : (curr + 1);
171     need_fix = false;
172     }
173     while (beg != end);
174    
175     return max_len;
176     }
177    
178     void
179     text::resize (int w, int h)
180     {
181     panel::resize (w, h);
182     /* grow size of the text if we need it */
183     pad_.resize (std::max (pad_.width (), w + 1), std::max (pad_.height (), h));
184     }
185    
186     void
187     text::clear ()
188     {
189     ncurses::pen (pad_).clear ();
190     x_ = 0;
191     y_ = 0;
192     /* truncate buffer to viewport size */
193     pad_.resize (this->width (), this->height ());
194     draw ();
195     }
196    
197     void
198 sf-pippijn 1.3 text::set_text (std::string const &str)
199 sf-pippijn 1.1 {
200     clear ();
201     add_text (str);
202     draw ();
203     }
204    
205     int
206     text::length () const
207     {
208     return pad_.height ();
209     }
210    
211     int
212     text::last_line () const
213     {
214     return y_ + height ();
215     }
216    
217 sf-pippijn 1.3 text_view::text_view (std::string const &title, ndk::panel *parent)
218 sf-pippijn 1.1 : frame (title, parent)
219     , text_ ("", this, text::no_wrap)
220     , title_ (title)
221     {
222     events ()->on_system (slot (&text_view::at_system, this));
223     in_focus (text_);
224     }
225    
226     void
227 sf-pippijn 1.3 text_view::add_text (std::string const &str)
228 sf-pippijn 1.1 {
229     text_.add_text (str);
230     }
231    
232     void
233 sf-pippijn 1.3 text_view::set_text (std::string const &str)
234 sf-pippijn 1.1 {
235     text_.set_text (str);
236     }
237    
238     void
239     text_view::draw ()
240     {
241     /* pack widgets */
242     packer<pack::horizontal, pack::no_resizer> pack (this, align::center);
243     pack.add (&text_);
244     pack.pack ();
245    
246     frame::draw ();
247    
248     ncurses::pen pen (*this);
249    
250     if (!title_.empty ())
251     {
252     std::string out (title_);
253    
254     /* if we have enough width made title more beautiful */
255 sf-pippijn 1.3 int const len = title_.length ();
256     int const wid = width ();
257 sf-pippijn 1.1 if (len < wid)
258     {
259     if (len + 6 < wid)
260     out = " " + out + " ";
261 sf-pippijn 1.2 return_unless (pen.move (align::pos (out.size (), wid, align::center), 0));
262 sf-pippijn 1.1 }
263     else
264     {
265     out = out.substr (0, wid);
266 sf-pippijn 1.2 return_unless (pen.move (0, 0));
267 sf-pippijn 1.1 }
268     pen.write (out);
269     }
270     }
271    
272     int
273     text_view::padding () const
274     {
275     /* save frame during packing */
276     return 1;
277     }
278    
279     void
280     text_view::resize (int w, int h)
281     {
282     panel::resize (w, h);
283     if ((w > 2) && (h > 2))
284     {
285     w -= 2;
286     h -= 2;
287     text_.resize (w, h);
288     }
289     }
290    
291     ndk::event::result
292 sf-pippijn 1.3 text_view::at_system (event const &ev)
293 sf-pippijn 1.1 {
294     event::result res = event::ignored;
295    
296     if (text_.events () == ev.sender_ && text::changed == ev.type_)
297     res = event::accepted;
298     return res;
299     }