libyui-ncurses  2.44.1
/usr/src/RPM/BUILD/libyui-ncurses-2.44.1/src/NCWidget.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:       NCWidget.cc
00020 
00021    Author:     Michael Andres <ma@suse.de>
00022 
00023 /-*/
00024 
00025 #include <climits>
00026 
00027 #define  YUILogComponent "ncurses"
00028 #include <yui/YUILog.h>
00029 #include "tnode.h"
00030 #include "NCWidget.h"
00031 #include <yui/YWidget.h>
00032 
00033 
00034 NCWidget::NCWidget( YWidget * parent )
00035     : tnode<NCWidget*>( this )
00036     , magic( YWIDGET_MAGIC )
00037     , grabedBy( 0 )
00038     , win( 0 )
00039     , defsze( 11, 45 )
00040     , framedim( 0, 0 )
00041     , inparent( -1, -1 )
00042     , noUpdates( false )
00043     , skipNoDimWin( true )
00044     , wstate( NC::WSnormal )
00045     , hotlabel( 0 )
00046 {
00047     NCWidget * myparent = dynamic_cast<NCWidget *>( parent );
00048 
00049     if ( myparent )
00050     {
00051         ReparentTo( *myparent );
00052 
00053         yuiDebug() <<  "CCC " << this << " parent " << myparent << std::endl;
00054     }
00055 }
00056 
00057 
00058 NCWidget::NCWidget( NCWidget * myparent )
00059     : tnode<NCWidget*>( this )
00060     , magic( YWIDGET_MAGIC )
00061     , grabedBy( 0 )
00062     , win( 0 )
00063     , defsze( 11, 45 )
00064     , framedim( 0, 0 )
00065     , inparent( -1, -1 )
00066     , noUpdates( false )
00067     , skipNoDimWin( true )
00068     , wstate( NC::WSnormal )
00069     , hotlabel( 0 )
00070 {
00071     if ( myparent )
00072     {
00073         ReparentTo( *myparent );
00074     }
00075 
00076     yuiDebug() <<  "CCC " << this << " parent " << myparent << std::endl;
00077 }
00078 
00079 
00080 
00081 NCWidget::~NCWidget()
00082 {
00083     yuiDebug() << "DD+ " << this << std::endl;
00084     wDelete();
00085 
00086     while ( Fchild() )
00087         Fchild()->Disconnect();
00088 
00089     Disconnect();
00090 
00091     invalidate();
00092 
00093     yuiDebug() << "DD- " << this << std::endl;
00094 }
00095 
00096 
00097 
00098 
00099 void NCWidget::PreDisconnect()
00100 {
00101     grabRelease( 0 );
00102 }
00103 
00104 
00105 
00106 void NCWidget::PostDisconnect()
00107 {}
00108 
00109 
00110 
00111 void NCWidget::PreReparent()
00112 {}
00113 
00114 
00115 
00116 void NCWidget::PostReparent()
00117 {}
00118 
00119 
00120 
00121 bool NCWidget::grabFocus()
00122 {
00123     return Top().Value()->wantFocus( *this );
00124 }
00125 
00126 
00127 
00128 // Actualy perform sreen update.
00129 void NCWidget::wUpdate( bool forced_br )
00130 {
00131     if ( !win )
00132         return;
00133 
00134     if ( noUpdates && !forced_br )
00135         return;
00136 
00137     NCurses::Update();
00138 }
00139 
00140 
00141 
00142 // Redirect Update request to topmost widget
00143 void NCWidget::Update()
00144 {
00145     if ( noUpdates )
00146         return;
00147 
00148     if ( Parent() )
00149     {
00150         Parent()->Value()->Update();
00151     }
00152     else
00153     {
00154         wUpdate();
00155     }
00156 }
00157 
00158 
00159 
00160 NCursesWindow * NCWidget::ParentWin()
00161 {
00162     if ( !Parent() )
00163     {
00164         return 0;
00165     }
00166 
00167     return Parent()->Value()->win;
00168 }
00169 
00170 
00171 
00172 void NCWidget::wMoveChildTo( NCWidget & child, const wpos & newpos )
00173 {
00174     yuiDebug() << "mc+ " << DLOC << child << " -> " << newpos << " in " << this << std::endl;
00175 
00176     try
00177     {
00178         child.wMoveTo( newpos );
00179         Redraw( true );
00180     }
00181     catch ( NCursesError & err )
00182     {
00183         yuiError() << DLOC << child << " -> " << newpos << " in " << this << std::endl;
00184         yuiError() << err << std::endl;
00185         ::endwin();
00186         abort();
00187     }
00188 
00189     yuiDebug() << "mc- " << DLOC << child << std::endl;
00190 }
00191 
00192 
00193 
00194 void NCWidget::wRelocate( const wrect & newrect )
00195 {
00196     yuiDebug() << "rl+ " << this << " -> " << newrect << std::endl;
00197 
00198     try
00199     {
00200         if ( win )
00201         {
00202             wDelete();
00203         }
00204 
00205         wCreate( newrect );
00206         SetState( wstate, true );
00207     }
00208     catch ( NCursesError & err )
00209     {
00210         yuiError() << *this << std::endl;
00211         yuiError() << err << std::endl;
00212         ::endwin();
00213         abort();
00214     }
00215 
00216     yuiDebug() << "rl- " << this << std::endl;
00217 }
00218 
00219 
00220 
00221 void NCWidget::wMoveTo( const wpos & newpos )
00222 {
00223     if ( !win )
00224     {
00225         yuiDebug() << "No win to move: " << this << " -> " << newpos << std::endl;
00226         return;
00227     }
00228 
00229     if ( !Parent() )
00230         throw NCError( "wMoveTo: got no parent" );
00231 
00232     if ( skipNoDimWin && inparent.Sze.H == 0 )
00233     {
00234         yuiDebug() << "Skip widget with zero height: " << this << ' ' << inparent << " par " << Parent()->Value() << std::endl;
00235         return;
00236     }
00237 
00238     if ( skipNoDimWin && inparent.Sze.W == 0 )
00239     {
00240         yuiDebug() << "Skip widget with zero width: " << this << ' ' << inparent << " par " << Parent()->Value() << std::endl;
00241         return;
00242     }
00243 
00244     if ( inparent.Pos != newpos )
00245     {
00246         yuiDebug() << "mv+ " << this << " -> " << newpos << " par " << Parent()->Value() << std::endl;
00247         NCWidget & p( *Parent()->Value() );
00248         p.win->mvsubwin( win,
00249                          newpos.L + Parent()->Value()->framedim.Pos.L,
00250                          newpos.C + Parent()->Value()->framedim.Pos.C );
00251         inparent.Pos = newpos;
00252         yuiDebug() << "mv- " << this << std::endl;
00253     }
00254 }
00255 
00256 
00257 
00258 void NCWidget::wCreate( const wrect & newrect )
00259 {
00260     if ( win )
00261         throw NCError( "wCreate: already have win" );
00262 
00263     if ( !Parent() )
00264         throw NCError( "wCreate: got no parent" );
00265 
00266     inparent = newrect;
00267 
00268     if ( skipNoDimWin && inparent.Sze == wsze( 0, 0 ) )
00269     {
00270         yuiDebug() << "Skip nodim widget: " << this << ' ' << inparent << " par " << Parent()->Value() << std::endl;
00271         return;
00272     }
00273 
00274     if ( skipNoDimWin && inparent.Sze.H == 0 )
00275     {
00276         yuiDebug() << "Skip widget with zero height: " << this << ' ' << inparent << " par " << Parent()->Value() << std::endl;
00277         return;
00278     }
00279 
00280     if ( skipNoDimWin && inparent.Sze.W == 0 )
00281     {
00282         yuiDebug() << "Skip widget with zero width: " << this << ' ' << inparent << " par " << Parent()->Value() << std::endl;
00283         return;
00284     }
00285 
00286     NCursesWindow * parw = ParentWin();
00287 
00288     if ( Parent() && !parw )
00289     {
00290         yuiError() << "Can't create widget in nodim parent: " << this << ' ' << inparent << " par " << Parent()->Value() << std::endl;
00291         inparent.Sze = wsze( 0, 0 );
00292         return;
00293     }
00294 
00295     yuiDebug() << "cw+ " << this << ' ' << inparent << " par " << Parent()->Value() << std::endl;
00296 
00297     if ( parw )
00298     {
00299         try
00300         {
00301             win = new NCursesWindow( *parw,
00302                                      inparent.Sze.H, inparent.Sze.W,
00303                                      inparent.Pos.L + Parent()->Value()->framedim.Pos.L,
00304                                      inparent.Pos.C + Parent()->Value()->framedim.Pos.C,
00305                                      'r' );
00306         }
00307         catch ( ... )
00308         {
00309             try
00310             {
00311                 win = new NCursesWindow( *parw,
00312                                          inparent.Sze.H, inparent.Sze.W,
00313                                          inparent.Pos.L,
00314                                          inparent.Pos.C,
00315                                          'r' );
00316             }
00317             catch ( ... )
00318             {
00319                 inparent.Sze = wsze( 1, 1 );
00320                 inparent.Pos = wpos( 0, 0 );
00321                 win = new NCursesWindow( *parw, 1, 1, 0, 0, 'r' );
00322             }
00323         }
00324     }
00325     else
00326     {
00327         win = new NCursesWindow( inparent.Sze.H, inparent.Sze.W,
00328                                  inparent.Pos.L, inparent.Pos.C );
00329     }
00330 
00331     yuiDebug() << "cw- " << this << ' ' << inparent << std::endl;
00332 }
00333 
00334 
00335 
00336 void NCWidget::wDelete()
00337 {
00338     if ( win )
00339     {
00340         yuiDebug() << "wd+ " << this << std::endl;
00341 
00342         for ( tnode<NCWidget *> * ch = Fchild(); ch; ch = ch->Nsibling() )
00343         {
00344             ch->Value()->wDelete();
00345         }
00346 
00347         win->clear();
00348 
00349         delete win;
00350         win = 0;
00351         inparent = wrect( -1, -1 );
00352         yuiDebug() << "wd- " << this << std::endl;
00353     }
00354 }
00355 
00356 
00357 
00358 wpos NCWidget::ScreenPos() const
00359 {
00360     if ( !win )
00361         return -1;
00362 
00363     if ( Parent() )
00364     {
00365         return Parent()->Value()->ScreenPos() + inparent.Pos;
00366     }
00367 
00368     return wsze( win->begy(), win->begx() );
00369 }
00370 
00371 
00372 
00373 void NCWidget::SetState( const NC::WState newstate, const bool force )
00374 {
00375     if ( newstate != wstate || force )
00376     {
00377         yuiDebug() << DLOC << wstate << " -> " << newstate << std::endl;
00378         wstate = newstate;
00379 
00380         if ( win )
00381         {
00382             win->bkgd( wStyle().getWidget( wstate ).plain );
00383         }
00384 
00385         Redraw();
00386     }
00387 }
00388 
00389 
00390 
00391 void NCWidget::setEnabled( bool do_bv )
00392 {
00393     yuiDebug() << DLOC << this << ' ' << do_bv << ' ' << wstate << std::endl;
00394 
00395     tnode<NCWidget*> *c = this;
00396 
00397     // If widget has children ([HV]Boxes, alignments,...), disable all of
00398     // them recursively (#256707).
00399 
00400     if ( c->HasChildren() )
00401     {
00402         yuiMilestone() <<  this << "setEnabled children recursively" << std::endl;
00403 
00404         for ( c = this->Next();
00405               c && c->IsDescendantOf( this );
00406               c = c->Next() )
00407         {
00408             if ( c->Value()->GetState() != NC::WSdumb )
00409                 c->Value()->setEnabled( do_bv );
00410         }
00411     }
00412 
00413     else
00414     {
00415         if ( wstate == NC::WSdumb )
00416             return;
00417 
00418         if ( do_bv && wstate == NC::WSdisabeled )
00419         {
00420             SetState( NC::WSnormal );
00421         }
00422         else if ( !do_bv && wstate != NC::WSdisabeled )
00423         {
00424             if ( wstate == NC::WSactive )
00425                 grabRelease( 0 );
00426 
00427             SetState( NC::WSdisabeled );
00428         }
00429     }
00430 }
00431 
00432 
00433 
00434 void NCWidget::Redraw( const bool sub )
00435 {
00436     if ( !win )
00437     {
00438         return;
00439     }
00440 
00441     bool savNoUpdates = noUpdates;
00442 
00443     noUpdates = true;
00444 
00445     if ( sub )
00446     {
00447         win->clear();
00448         wRedraw();
00449 
00450         for ( tnode<NCWidget *> * ch = Fchild(); ch; ch = ch->Nsibling() )
00451         {
00452             ch->Value()->Redraw( sub );
00453         }
00454     }
00455     else
00456     {
00457         wRedraw();
00458     }
00459 
00460     noUpdates = savNoUpdates;
00461 
00462     Update();
00463 }
00464 
00465 
00466 
00467 void NCWidget::wRedraw()
00468 {
00469 }
00470 
00471 
00472 
00473 void NCWidget::Recoded()
00474 {
00475     if ( !win )
00476     {
00477         return;
00478     }
00479 
00480     bool savNoUpdates = noUpdates;
00481 
00482     noUpdates = true;
00483     wRecoded();
00484 
00485     for ( tnode<NCWidget *> * ch = Fchild(); ch; ch = ch->Nsibling() )
00486     {
00487         ch->Value()->Recoded();
00488     }
00489 
00490     noUpdates = savNoUpdates;
00491 
00492     Update();
00493 }
00494 
00495 
00496 
00497 void NCWidget::wRecoded()
00498 {
00499     wRedraw();
00500 }
00501 
00502 
00503 
00504 bool NCWidget::HasHotkey( int key )
00505 {
00506     if ( key < 0 || UCHAR_MAX < key )
00507         return false;
00508 
00509     if ( !( hotlabel && hotlabel->hasHotkey() ) )
00510         return false;
00511 
00512     return( tolower( key ) == tolower( hotlabel->hotkey() ) );
00513 }
00514 
00515 
00516 
00517 bool NCWidget::HasFunctionHotkey( int key ) const
00518 {
00519     const YWidget * w = dynamic_cast<const YWidget *>( this );
00520 
00521     if ( w )
00522     {
00523         if ( key < 0 || ( ! w->hasFunctionKey() ) )
00524             return false;
00525 
00526         return( key == KEY_F( w->functionKey() ) );
00527     }
00528     else
00529     {
00530         yuiError() << "No YWidget" << std::endl;
00531         return false;
00532     }
00533 }
00534 
00535 
00536 
00537 NCursesEvent NCWidget::wHandleHotkey( wint_t /*key*/ )
00538 {
00539     return wHandleInput( KEY_HOTKEY );
00540 }
00541 
00542 
00543 
00544 NCursesEvent NCWidget::wHandleInput( wint_t /*key*/ )
00545 {
00546     return NCursesEvent::none;
00547 }
00548 
00549 
00550 std::ostream & operator<<( std::ostream & STREAM, const NCWidget * OBJ )
00551 {
00552     if ( OBJ && OBJ->isValid() )
00553         return STREAM << *OBJ;
00554 
00555     return STREAM << "(NoNCWidget)";
00556 }
00557 
00558 
00559 std::ostream & operator<<( std::ostream & STREAM, const NCWidget & OBJ )
00560 {
00561     if ( OBJ.isValid() )
00562         return STREAM << OBJ.location() << ( void* )&OBJ
00563                << '(' << OBJ.win
00564                << ' ' << OBJ.inparent
00565                << ' ' << OBJ.wstate
00566                << ')';
00567 
00568     return STREAM << "( invalid NCWidget)";
00569 }
00570 
00571 
00572 
00573 void NCWidget::DumpOn( std::ostream & str, std::string prfx ) const
00574 {
00575     str
00576     //<< prfx << "|" << std::endl
00577     << prfx << "+-" << this << std::endl;
00578     prfx += ( Nsibling() ? "| " : "  " );
00579 
00580     for ( const tnode<NCWidget *> * ch = Fchild(); ch; ch = ch->Nsibling() )
00581     {
00582         ch->Value()->DumpOn( str, prfx );
00583     }
00584 }
00585 
 All Classes Functions Variables