libyui-ncurses  2.55.0
NCPadWidget.cc
1 /*
2  Copyright (C) 2000-2012 Novell, Inc
3  This library is free software; you can redistribute it and/or modify
4  it under the terms of the GNU Lesser General Public License as
5  published by the Free Software Foundation; either version 2.1 of the
6  License, or (at your option) version 3.0 of the License. This library
7  is distributed in the hope that it will be useful, but WITHOUT ANY
8  WARRANTY; without even the implied warranty of MERCHANTABILITY or
9  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10  License for more details. You should have received a copy of the GNU
11  Lesser General Public License along with this library; if not, write
12  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
13  Floor, Boston, MA 02110-1301 USA
14 */
15 
16 
17 /*-/
18 
19  File: NCPadWidget.cc
20 
21  Author: Michael Andres <ma@suse.de>
22 
23 /-*/
24 
25 #define YUILogComponent "ncurses"
26 #include <yui/YUILog.h>
27 #include "NCPadWidget.h"
28 
29 
31 {
32 public:
33 
34  enum orientation { HORZ, VERT };
35 
36 private:
37 
38  chtype ch_forward;
39  chtype ch_backward;
40  chtype ch_barbeg;
41  chtype ch_barend;
42  chtype ch_barone;
43 
44  const NCWidget & parw;
45  NCursesWindow * win;
46  orientation type;
47  unsigned len;
48 
49  unsigned total;
50  unsigned visible;
51  unsigned at;
52 
53 private:
54 
55  void adjust()
56  {
57  if ( visible > total )
58  {
59  yuiDebug() << "adjust visible " << visible << " > total " << total << std::endl;
60  visible = total;
61  }
62 
63  if ( at + visible > total )
64  {
65  yuiDebug() << "adjust at " << at << " + visible " << visible << " > total " << total << std::endl;
66  at = total - visible;
67  }
68  }
69 
70  void draw_line( unsigned p, unsigned l, chtype ch = 0 )
71  {
72  if ( !l )
73  return;
74 
75  if ( type == HORZ )
76  win->hline( 0, p, l, ch );
77  else
78  win->vline( p, 0, l, ch );
79  }
80 
81  void draw_bar( unsigned p, unsigned l )
82  {
83  if ( !l )
84  return;
85 
86  if ( l == 1 )
87  {
88  if ( type == HORZ )
89  win->addch( 0, p, ch_barone );
90  else
91  win->addch( p, 0, ch_barone );
92 
93  return;
94  }
95 
96  unsigned e = p + l - 1; // barend
97 
98  l -= 2; // inner bar
99 
100  if ( type == HORZ )
101  {
102  win->addch( 0, p, ch_barbeg );
103  win->addch( 0, e, ch_barend );
104 
105  if ( l )
106  win->hline( 0, p + 1, l );
107  }
108  else
109  {
110  win->addch( p, 0, ch_barbeg );
111  win->addch( e, 0, ch_barend );
112 
113  if ( l )
114  win->vline( p + 1, 0, l );
115  }
116  }
117 
118  void draw()
119  {
120  if ( !win )
121  return;
122 
123  bool topvis = ( at == 0 );
124 
125  bool botvis = ( at + visible == total );
126 
127  const NCstyle::StWidget & style( parw.frameStyle() );
128 
129  win->bkgdset( style.plain );
130 
131  draw_line( 0, len );
132 
133  if ( topvis && botvis )
134  {
135  // no scroll at all
136  return;
137  }
138 
139  switch ( len )
140  {
141  case 1:
142  win->bkgdset( style.scrl );
143 
144  if ( topvis == botvis )
145  {
146  // both == false; otherwise handled above
147  win->addch( 0, 0, ch_barone );
148  }
149  else
150  {
151  win->addch( 0, 0, ( topvis ? ch_forward : ch_backward ) );
152  }
153 
154  break;
155 
156  case 2:
157  win->bkgdset( style.scrl );
158 
159  if ( !topvis )
160  win->addch( 0, 0, ch_backward );
161 
162  if ( !botvis )
163  win->addch( win->maxy(), win->maxx(), ch_forward );
164 
165  break;
166 
167  default:
168 
169  case 3:
170  {
171  unsigned blen;
172  unsigned bat;
173 
174  if ( visible + 1 == total )
175  {
176  // just one invisible line
177  blen = len - 1;
178  bat = at ? 1 : 0;
179  }
180  else
181  {
182  blen = ( visible * ( len - 2 ) / total ) + 1;
183 
184  if ( topvis == botvis )
185  {
186  // both == false; otherwise handled above
187  bat = ( at * ( len - 2 ) / total ) + 1;
188  }
189  else
190  {
191  bat = ( topvis ? 0 : len - blen );
192  }
193  }
194 
195  win->bkgdset( style.plain );
196 
197  draw_line( 0, len );
198  win->bkgdset( style.scrl );
199  draw_bar( bat, blen );
200  }
201 
202  break;
203  }
204  }
205 
206 public:
207 
208  NCScrollbar( const NCWidget & parwid, NCursesWindow & par, wpos p, unsigned l, orientation orient )
209  : ch_forward( orient == HORZ ? ACS_RARROW : ACS_DARROW )
210  , ch_backward( orient == HORZ ? ACS_LARROW : ACS_UARROW )
211  , ch_barbeg( orient == HORZ ? ACS_LTEE : ACS_TTEE )
212  , ch_barend( orient == HORZ ? ACS_RTEE : ACS_BTEE )
213  , ch_barone( orient == HORZ ? ACS_VLINE : ACS_HLINE )
214  , parw( parwid )
215  , win( 0 )
216  , type( orient )
217  , len( l ? l : 1 )
218  , total( 0 )
219  , visible( 0 )
220  , at( 0 )
221  {
222  try
223  {
224  win = new NCursesWindow( par,
225  ( type == HORZ ? 1 : len ), // height
226  ( type == VERT ? 1 : len ), // width
227  p.L, p.C,
228  'r' );
229  }
230  catch ( NCursesException & err )
231  {
232  yuiDebug() << "NCScrollbar: " << err.message
233  << ": at " << p << " len " << len << " in " << par << std::endl;
234  return;
235  }
236  }
237 
238  virtual ~NCScrollbar()
239  {
240  delete win;
241  }
242 
243 public:
244 
245  void set( unsigned tot, unsigned vis, unsigned start )
246  {
247  total = tot;
248  visible = vis;
249  at = start;
250  adjust();
251  draw();
252  }
253 
254 };
255 
256 
257 
258 
259 NCPadWidget::NCPadWidget( NCWidget * myparent )
260  : NCWidget( myparent )
261  , padwin( 0 )
262  , hsb( 0 )
263  , vsb( 0 )
264  , multidraw( false )
265  , pad( 0 )
266  , hasHeadline( false )
267  , activeLabelOnly( false )
268 {
269  yuiDebug() << std::endl;
270  hotlabel = &label;
271  defsze = wsze( 3, 10 ) + 2;
272 }
273 
274 
275 NCPadWidget::NCPadWidget( YWidget * myparent )
276  : NCWidget( myparent )
277  , padwin( 0 )
278  , hsb( 0 )
279  , vsb( 0 )
280  , multidraw( false )
281  , pad( 0 )
282  , hasHeadline( false )
283  , activeLabelOnly( false )
284 {
285  yuiDebug() << std::endl;
286  hotlabel = &label;
287  defsze = wsze( 3, 10 ) + 2;
288 }
289 
290 
291 NCPadWidget::~NCPadWidget()
292 {
293  delete pad;
294 
295  if ( padwin != win )
296  delete padwin;
297 
298  yuiDebug() << std::endl;
299 }
300 
301 
302 void NCPadWidget::wCreate( const wrect & newrect )
303 {
304  const int bsize = 2; // space allocated for the pad border
305 
306  NCWidget::wCreate( newrect );
307 
308  if ( win )
309  {
310  wrect padrect( newrect.inside() );
311 
312  if ( hasHeadline )
313  {
314  if ( padrect.Sze.H > 1 )
315  {
316  padrect.Pos.L += 1;
317  padrect.Sze.H -= 1;
318  }
319  else
320  hasHeadline = false;
321  }
322 
323  padwin = new NCursesWindow( *win,
324 
325  padrect.Sze.H, padrect.Sze.W,
326  padrect.Pos.L, padrect.Pos.C,
327  'r' );
328 
329  // Scrollbar has to be at least one character large otherwise ncurses window
330  // for the scrollbar will fail to create and we end with an exception which
331  // crashes whole UI consequently.
332  //
333  // scrollbar size is lowered by -2 bcs there is an overhead for frames etc.
334  if(win->width() - bsize)
335  {
336  hsb = new NCScrollbar( *this, *win, wpos( win->maxy(), 1 ), win->width() - bsize, NCScrollbar::HORZ );
337  }
338  else
339  {
340  // no space no scrollbar, scrolling still works using arrows
341  hsb = nullptr;
342  }
343 
344  if(win->height() - bsize)
345  {
346  // we have enough space for vertical scrollbar
347  vsb = new NCScrollbar( *this, *win, wpos( 1, win->maxx() ), win->height() - bsize, NCScrollbar::VERT );
348  }
349  else
350  {
351  // no space no scrollbar, scrolling still works using arrows
352  vsb = nullptr;
353  }
354  }
355  else
356  {
357  padwin = 0;
358  hsb = 0;
359  vsb = 0;
360  }
361 }
362 
363 
364 void NCPadWidget::wDelete()
365 {
366  if ( pad )
367  {
368  pad->Destwin( 0 );
369  }
370 
371  if ( padwin )
372  {
373  if ( padwin != win )
374  {
375  delete padwin;
376  }
377 
378  padwin = 0;
379  }
380 
381  delete hsb;
382 
383  hsb = 0;
384  delete vsb;
385  vsb = 0;
386  NCWidget::wDelete();
387 }
388 
389 
390 void NCPadWidget::InitPad()
391 {
392  if ( pad )
393  return;
394 
395  pad = CreatePad();
396  pad->SendSchrollCB( this );
397  AdjustPad( wsze( pad->height(), pad->width() ) );
398  DrawPad();
399 }
400 
401 
402 void NCPadWidget::AdjustPadSize( wsze & minsze )
403 {
404  minPadSze = minsze;
405  minsze = wsze::max( minsze, defPadSze() );
406 }
407 
408 
409 void NCPadWidget::AdjustPad( wsze nsze )
410 {
411  if ( !pad )
412  return;
413 
414  pad->resize( nsze );
415 }
416 
417 
418 void NCPadWidget::DelPad()
419 {
420  delete pad;
421  pad = 0;
422 }
423 
424 
425 void NCPadWidget::setLabel( const NClabel & nlabel )
426 {
427  label = nlabel;
428  label.stripHotkey();
429  Redraw();
430 }
431 
432 
433 void NCPadWidget::wRedraw()
434 {
435  if ( !win )
436  return;
437 
438  yuiDebug() << "wRedraw called for: " << win << std::endl;
439 
440  const NCstyle::StWidget & style( frameStyle() );
441 
442  win->bkgdset( style.plain );
443 
444  win->box();
445 
446  if ( !activeLabelOnly || GetState() == NC::WSactive )
447  label.drawAt( *win, style, wpos( 0, 1 ),
448  wsze( 1, win->width() - 2 ), NC::TOPLEFT, false );
449 
450  InitPad();
451 
452  if ( !pad->Destwin() )
453  {
454  AdjustPad( minPadSze );
455  pad->Destwin( padwin );
456  }
457  else
458  {
459  pad->setDirty();
460  pad->setpos();
461  pad->SendHead();
462  }
463 }
464 
465 
466 void NCPadWidget::wRecoded()
467 {
468  if ( pad )
469  pad->wRecoded();
470 
471  wRedraw();
472 }
473 
474 
475 void NCPadWidget::HScroll( unsigned total, unsigned visible, unsigned start )
476 {
477  // horizontal scroll bar might got disabled bcs of lack of space. See
478  // NCPadWidget::wCreate
479  if(hsb)
480  {
481  hsb->set( total, visible, start );
482  }
483 }
484 
485 
486 void NCPadWidget::VScroll( unsigned total, unsigned visible, unsigned start )
487 {
488  // vertical scroll bar might got disabled bcs of lack of space. See
489  // NCPadWidget::wCreate
490  if(vsb)
491  {
492  vsb->set( total, visible, start );
493  }
494 }
495 
496 
497 void NCPadWidget::ScrollHead( NCursesWindow & w, unsigned ccol )
498 {
499  if ( hasHeadline && win )
500  {
501  w.copywin( *win, 0, ccol, 1, 1, 1, win->width() - 2, false );
502  }
503 }
504 
505 
506 NCPad * NCPadWidget::CreatePad()
507 {
508  wsze psze( defPadSze() );
509  NCPad * npad = new NCPad( psze.H, psze.W, *this );
510  npad->bkgd( wStyle().list.item.plain );
511 
512  return npad;
513 }
514 
515 
516 void NCPadWidget::DrawPad()
517 {
518  if ( pad && !inMultidraw() )
519  {
520  pad->update();
521  Redraw();
522  }
523 }
524 
525 
526 bool NCPadWidget::handleInput( wint_t key )
527 {
528  return pad->handleInput( key );
529 }
NCursesWindow::addch
int addch(const char ch)
Put attributed character to the window.
Definition: ncursesw.h:1227
wsze
Definition: position.h:155
NCursesWindow::hline
int hline(int len, chtype ch=0)
Draw a horizontal line of len characters with the given character.
Definition: ncursesw.h:1484
NCursesWindow
C++ class for windows.
Definition: ncursesw.h:904
NClabel
Definition: NCtext.h:82
NCursesWindow::copywin
int copywin(NCursesWindow &win, int sminrow, int smincol, int dminrow, int dmincol, int dmaxrow, int dmaxcol, bool overlay=TRUE)
Overlay or overwrite the rectangle in win given by dminrow,dmincol, dmaxrow,dmaxcol with the rectangl...
Definition: ncursesw.h:1731
NCursesWindow::box
int box()
Draw a box around the window with the given vertical and horizontal drawing characters.
Definition: ncursesw.h:1461
NCWidget
Definition: NCWidget.h:46
NCursesWindow::maxy
int maxy() const
Largest y coord in window.
Definition: ncursesw.h:1094
NCstyle::StWidget
Definition: NCstyle.h:358
NCursesWindow::width
int width() const
Number of columns in this window.
Definition: ncursesw.h:1074
NCPad
Definition: NCPad.h:94
wpos
Definition: position.h:110
NCursesWindow::vline
int vline(int len, chtype ch=0)
Draw a vertical line of len characters with the given character.
Definition: ncursesw.h:1498
NCursesWindow::bkgd
int bkgd(const chtype ch)
Set the background property and apply it to the window.
Definition: ncursesw.h:1442
NCursesWindow::height
int height() const
Number of lines in this window.
Definition: ncursesw.h:1069
NCScrollbar
Definition: NCPadWidget.cc:31
wrect
Definition: position.h:198
NCursesWindow::bkgdset
void bkgdset(chtype ch)
Set the background property.
Definition: ncursesw.h:1447
NCursesWindow::maxx
int maxx() const
Largest x coord in window.
Definition: ncursesw.h:1089