libyui-ncurses  2.44.1
/usr/src/RPM/BUILD/libyui-ncurses-2.44.1/src/NCPadWidget.cc
00001 /*
00002   Copyright (C) 2000-2012 Novell, Inc
00003   This library is free software; you can redistribute it and/or modify
00004   it under the terms of the GNU Lesser General Public License as
00005   published by the Free Software Foundation; either version 2.1 of the
00006   License, or (at your option) version 3.0 of the License. This library
00007   is distributed in the hope that it will be useful, but WITHOUT ANY
00008   WARRANTY; without even the implied warranty of MERCHANTABILITY or
00009   FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
00010   License for more details. You should have received a copy of the GNU
00011   Lesser General Public License along with this library; if not, write
00012   to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
00013   Floor, Boston, MA 02110-1301 USA
00014 */
00015 
00016 
00017 /*-/
00018 
00019    File:       NCPadWidget.cc
00020 
00021    Author:     Michael Andres <ma@suse.de>
00022 
00023 /-*/
00024 
00025 #define  YUILogComponent "ncurses"
00026 #include <yui/YUILog.h>
00027 #include "NCPadWidget.h"
00028 
00029 
00030 class NCScrollbar
00031 {
00032 public:
00033 
00034     enum orientation { HORZ, VERT };
00035 
00036 private:
00037 
00038     chtype ch_forward;
00039     chtype ch_backward;
00040     chtype ch_barbeg;
00041     chtype ch_barend;
00042     chtype ch_barone;
00043 
00044     const NCWidget & parw;
00045     NCursesWindow *  win;
00046     orientation      type;
00047     unsigned         len;
00048 
00049     unsigned total;
00050     unsigned visible;
00051     unsigned at;
00052 
00053 private:
00054 
00055     void adjust()
00056     {
00057         if ( visible > total )
00058         {
00059             yuiDebug() << "adjust visible " << visible << " > total " << total << std::endl;
00060             visible = total;
00061         }
00062 
00063         if ( at + visible > total )
00064         {
00065             yuiDebug() << "adjust at " << at << " + visible " << visible << " > total " << total << std::endl;
00066             at = total - visible;
00067         }
00068     }
00069 
00070     void draw_line( unsigned p, unsigned l, chtype ch = 0 )
00071     {
00072         if ( !l )
00073             return;
00074 
00075         if ( type == HORZ )
00076             win->hline( 0, p, l, ch );
00077         else
00078             win->vline( p, 0, l, ch );
00079     }
00080 
00081     void draw_bar( unsigned p, unsigned l )
00082     {
00083         if ( !l )
00084             return;
00085 
00086         if ( l == 1 )
00087         {
00088             if ( type == HORZ )
00089                 win->addch( 0, p, ch_barone );
00090             else
00091                 win->addch( p, 0, ch_barone );
00092 
00093             return;
00094         }
00095 
00096         unsigned e = p + l - 1; // barend
00097 
00098         l -= 2; // inner bar
00099 
00100         if ( type == HORZ )
00101         {
00102             win->addch( 0, p, ch_barbeg );
00103             win->addch( 0, e, ch_barend );
00104 
00105             if ( l )
00106                 win->hline( 0, p + 1, l );
00107         }
00108         else
00109         {
00110             win->addch( p, 0, ch_barbeg );
00111             win->addch( e, 0, ch_barend );
00112 
00113             if ( l )
00114                 win->vline( p + 1, 0, l );
00115         }
00116     }
00117 
00118     void draw()
00119     {
00120         if ( !win )
00121             return;
00122 
00123         bool topvis = ( at == 0 );
00124 
00125         bool botvis = ( at + visible == total );
00126 
00127         const NCstyle::StWidget & style( parw.frameStyle() );
00128 
00129         win->bkgdset( style.plain );
00130 
00131         draw_line( 0, len );
00132 
00133         if ( topvis && botvis )
00134         {
00135             // no scroll at all
00136             return;
00137         }
00138 
00139         switch ( len )
00140         {
00141             case 1:
00142                 win->bkgdset( style.scrl );
00143 
00144                 if ( topvis == botvis )
00145                 {
00146                     // both == false; otherwise handled above
00147                     win->addch( 0, 0, ch_barone );
00148                 }
00149                 else
00150                 {
00151                     win->addch( 0, 0, ( topvis ? ch_forward : ch_backward ) );
00152                 }
00153 
00154                 break;
00155 
00156             case 2:
00157                 win->bkgdset( style.scrl );
00158 
00159                 if ( !topvis )
00160                     win->addch( 0, 0, ch_backward );
00161 
00162                 if ( !botvis )
00163                     win->addch( win->maxy(), win->maxx(), ch_forward );
00164 
00165                 break;
00166 
00167             default:
00168 
00169             case 3:
00170                 {
00171                     unsigned blen;
00172                     unsigned bat;
00173 
00174                     if ( visible + 1 == total )
00175                     {
00176                         // just one invisible line
00177                         blen = len - 1;
00178                         bat  = at ? 1 : 0;
00179                     }
00180                     else
00181                     {
00182                         blen = ( visible * ( len - 2 ) / total ) + 1;
00183 
00184                         if ( topvis == botvis )
00185                         {
00186                             // both == false; otherwise handled above
00187                             bat = ( at * ( len - 2 ) / total ) + 1;
00188                         }
00189                         else
00190                         {
00191                             bat = ( topvis ? 0 : len - blen );
00192                         }
00193                     }
00194 
00195                     win->bkgdset( style.plain );
00196 
00197                     draw_line( 0, len );
00198                     win->bkgdset( style.scrl );
00199                     draw_bar( bat, blen );
00200                 }
00201 
00202                 break;
00203         }
00204     }
00205 
00206 public:
00207 
00208     NCScrollbar( const NCWidget & parwid, NCursesWindow & par, wpos p, unsigned l, orientation orient )
00209             : ch_forward( orient == HORZ ? ACS_RARROW : ACS_DARROW )
00210             , ch_backward( orient == HORZ ? ACS_LARROW : ACS_UARROW )
00211             , ch_barbeg( orient == HORZ ? ACS_LTEE : ACS_TTEE )
00212             , ch_barend( orient == HORZ ? ACS_RTEE : ACS_BTEE )
00213             , ch_barone( orient == HORZ ? ACS_VLINE : ACS_HLINE )
00214             , parw( parwid )
00215             , win( 0 )
00216             , type( orient )
00217             , len( l ? l : 1 )
00218             , total( 0 )
00219             , visible( 0 )
00220             , at( 0 )
00221     {
00222         try
00223         {
00224             win = new NCursesWindow( par,
00225                                      ( type == HORZ ? 1 : len ), // height
00226                                      ( type == VERT ? 1 : len ), // width
00227                                      p.L, p.C,
00228                                      'r' );
00229         }
00230         catch ( NCursesException & err )
00231         {
00232             yuiDebug() << "NCScrollbar: " << err.message
00233             << ": at " << p << " len " << len << " in " << par << std::endl;
00234             return;
00235         }
00236     }
00237 
00238     virtual ~NCScrollbar()
00239     {
00240         delete win;
00241     }
00242 
00243 public:
00244 
00245     void set( unsigned tot, unsigned vis, unsigned start )
00246     {
00247         total   = tot;
00248         visible = vis;
00249         at      = start;
00250         adjust();
00251         draw();
00252     }
00253 
00254 };
00255 
00256 
00257 
00258 
00259 NCPadWidget::NCPadWidget( NCWidget * myparent )
00260         : NCWidget( myparent )
00261         , padwin( 0 )
00262         , hsb( 0 )
00263         , vsb( 0 )
00264         , multidraw( false )
00265         , pad( 0 )
00266         , hasHeadline( false )
00267         , activeLabelOnly( false )
00268 {
00269     yuiDebug() << std::endl;
00270     hotlabel = &label;
00271     defsze = wsze( 3, 10 ) + 2;
00272 }
00273 
00274 
00275 NCPadWidget::NCPadWidget( YWidget * myparent )
00276         : NCWidget( myparent )
00277         , padwin( 0 )
00278         , hsb( 0 )
00279         , vsb( 0 )
00280         , multidraw( false )
00281         , pad( 0 )
00282         , hasHeadline( false )
00283         , activeLabelOnly( false )
00284 {
00285     yuiDebug() << std::endl;
00286     hotlabel = &label;
00287     defsze = wsze( 3, 10 ) + 2;
00288 }
00289 
00290 
00291 NCPadWidget::~NCPadWidget()
00292 {
00293     delete pad;
00294 
00295     if ( padwin != win )
00296         delete padwin;
00297 
00298     yuiDebug() << std::endl;
00299 }
00300 
00301 
00302 void NCPadWidget::wCreate( const wrect & newrect )
00303 {
00304     NCWidget::wCreate( newrect );
00305 
00306     if ( win )
00307     {
00308         wrect padrect( newrect.inside() );
00309 
00310         if ( hasHeadline )
00311         {
00312             if ( padrect.Sze.H > 1 )
00313             {
00314                 padrect.Pos.L += 1;
00315                 padrect.Sze.H -= 1;
00316             }
00317             else
00318                 hasHeadline = false;
00319         }
00320 
00321         padwin = new NCursesWindow( *win,
00322 
00323                                     padrect.Sze.H, padrect.Sze.W,
00324                                     padrect.Pos.L, padrect.Pos.C,
00325                                     'r' );
00326         hsb = new NCScrollbar( *this, *win, wpos( win->maxy(), 1 ), win->width() - 2, NCScrollbar::HORZ );
00327         vsb = new NCScrollbar( *this, *win, wpos( 1, win->maxx() ), win->height() - 2, NCScrollbar::VERT );
00328     }
00329     else
00330     {
00331         padwin = 0;
00332         hsb = 0;
00333         vsb = 0;
00334     }
00335 }
00336 
00337 
00338 void NCPadWidget::wDelete()
00339 {
00340     if ( pad )
00341     {
00342         pad->Destwin( 0 );
00343     }
00344 
00345     if ( padwin )
00346     {
00347         if ( padwin != win )
00348         {
00349             delete padwin;
00350         }
00351 
00352         padwin = 0;
00353     }
00354 
00355     delete hsb;
00356 
00357     hsb = 0;
00358     delete vsb;
00359     vsb = 0;
00360     NCWidget::wDelete();
00361 }
00362 
00363 
00364 void NCPadWidget::InitPad()
00365 {
00366     if ( pad )
00367         return;
00368 
00369     pad = CreatePad();
00370     pad->SendSchrollCB( this );
00371     AdjustPad( wsze( pad->height(), pad->width() ) );
00372     DrawPad();
00373 }
00374 
00375 
00376 void NCPadWidget::AdjustPadSize( wsze & minsze )
00377 {
00378     minPadSze = minsze;
00379     minsze    = wsze::max( minsze, defPadSze() );
00380 }
00381 
00382 
00383 void NCPadWidget::AdjustPad( wsze nsze )
00384 {
00385     if ( !pad )
00386         return;
00387 
00388     pad->resize( nsze );
00389 }
00390 
00391 
00392 void NCPadWidget::DelPad()
00393 {
00394     delete pad;
00395     pad = 0;
00396 }
00397 
00398 
00399 void NCPadWidget::setLabel( const NClabel & nlabel )
00400 {
00401     label = nlabel;
00402     label.stripHotkey();
00403     Redraw();
00404 }
00405 
00406 
00407 void NCPadWidget::wRedraw()
00408 {
00409     if ( !win )
00410         return;
00411 
00412     yuiDebug() << "wRedraw called for: " << win << std::endl;
00413 
00414     const NCstyle::StWidget & style( frameStyle() );
00415 
00416     win->bkgdset( style.plain );
00417 
00418     win->box();
00419 
00420     if ( !activeLabelOnly || GetState() == NC::WSactive )
00421         label.drawAt( *win, style, wpos( 0, 1 ),
00422                       wsze( 1, win->width() - 2 ), NC::TOPLEFT, false );
00423 
00424     InitPad();
00425 
00426     if ( !pad->Destwin() )
00427     {
00428         AdjustPad( minPadSze );
00429         pad->Destwin( padwin );
00430     }
00431     else
00432     {
00433         pad->setDirty();
00434         pad->setpos();
00435         pad->SendHead();
00436     }
00437 }
00438 
00439 
00440 void NCPadWidget::wRecoded()
00441 {
00442     if ( pad )
00443         pad->wRecoded();
00444 
00445     wRedraw();
00446 }
00447 
00448 
00449 void NCPadWidget::HScroll( unsigned total, unsigned visible, unsigned start )
00450 {
00451     hsb->set( total, visible, start );
00452 }
00453 
00454 
00455 void NCPadWidget::VScroll( unsigned total, unsigned visible, unsigned start )
00456 {
00457     vsb->set( total, visible, start );
00458 }
00459 
00460 
00461 void NCPadWidget::ScrollHead( NCursesWindow & w, unsigned ccol )
00462 {
00463     if ( hasHeadline && win )
00464     {
00465         w.copywin( *win, 0, ccol, 1, 1, 1, win->width() - 2, false );
00466     }
00467 }
00468 
00469 
00470 NCPad * NCPadWidget::CreatePad()
00471 {
00472     wsze    psze( defPadSze() );
00473     NCPad * npad = new NCPad( psze.H, psze.W, *this );
00474     npad->bkgd( wStyle().list.item.plain );
00475 
00476     return npad;
00477 }
00478 
00479 
00480 void NCPadWidget::DrawPad()
00481 {
00482     if ( pad && !inMultidraw() )
00483     {
00484         pad->update();
00485         Redraw();
00486     }
00487 }
00488 
00489 
00490 bool NCPadWidget::handleInput( wint_t key )
00491 {
00492     return pad->handleInput( key );
00493 }
 All Classes Functions Variables