libyui-ncurses
2.44.1
|
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 }