libyui-ncurses  2.44.1
/usr/src/RPM/BUILD/libyui-ncurses-2.44.1/src/NCBusyIndicator.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:       NCBusyIndicator.cc
00020 
00021    Author:     Thomas Goettlicher <tgoettlicher@suse.de>
00022    Maintainer: Thomas Goettlicher <tgoettlicher@suse.de>
00023 
00024 /-*/
00025 
00026 #define  YUILogComponent "ncurses"
00027 #include <yui/YUILog.h>
00028 #include "NCurses.h"
00029 #include "NCBusyIndicator.h"
00030 #include <signal.h>
00031 #include <unistd.h>
00032 #include <sys/time.h>
00033 
00034 #define REPAINT_INTERVAL        100     // in ms
00035 #define STEP_SIZE               .05
00036 
00037 /*
00038  Some words about the timer stuff:
00039  With each SIG_ALRM signal _timer_progress gets incremented by _timer_divisor.
00040  When a tick is received [=setAlive(true) is called] _timer_progress is std::set to 0.
00041  If _timer_progress is larger than 1 the widget goes to stalled state.
00042 
00043  How the timer works:
00044  NCBusyIndicatorHandlerWrapper is registered as signal handler for SIG_ALRM
00045  signal and calls NCBusyIndicatorObject->handler(). This wrapper is needed
00046  because a member function cannot be registered as signal handler.
00047 
00048  LIMITATIONS:
00049  i)  Only one BusyIndicator widget works at the same time, because the
00050      wrapper function only calls the handler() member function of the last
00051      created instance of BusyIndicator.
00052 
00053  ii) The UserInput widget cannot be used, because UserInput is a blocking
00054      function. When UserInput waits for UserInput no SIG_ALRM signal is sent
00055      and therefore the BusyIndicator widget doesn't show progress.
00056      Please use the TimeoutUserInput widget in a loop instead.
00057 */
00058 
00059 struct itimerval interval;
00060 NCBusyIndicator* NCBusyIndicatorObject;
00061 #if 0
00062 void NCBusyIndicatorHandlerWrapper( int sig_num );
00063 #endif
00064 
00065 
00066 
00067 NCBusyIndicator::NCBusyIndicator( YWidget * parent,
00068                                   const std::string & nlabel,
00069                                   int timeout )
00070     : YBusyIndicator( parent, nlabel, timeout )
00071     , NCWidget( parent )
00072     , _label( nlabel )
00073     , _timeout( timeout )
00074     , _lwin( 0 )
00075     , _twin( 0 )
00076     , _position( .5 )
00077     , _rightwards( true )
00078     , _alive( true )
00079 {
00080     yuiDebug() << std::endl;
00081 
00082     if ( timeout <= 0 )
00083         timeout = 1;
00084 
00085     setLabel( nlabel );
00086     hotlabel = &_label;
00087     wstate = NC::WSdumb;
00088     NCBusyIndicatorObject = this;
00089     _timer_divisor = ( double ) REPAINT_INTERVAL / ( double ) timeout;
00090     _timer_progress = 0;
00091 
00092 #if 0
00093     signal( SIGALRM, NCBusyIndicatorHandlerWrapper );
00094     interval.it_value.tv_sec = 0;
00095     interval.it_value.tv_usec = REPAINT_INTERVAL * 1000;
00096     setitimer( ITIMER_REAL, &interval, NULL );
00097 #endif
00098 }
00099 
00100 
00101 NCBusyIndicator::~NCBusyIndicator()
00102 {
00103     NCBusyIndicatorObject = NULL;
00104     delete _lwin;
00105     delete _twin;
00106     yuiDebug() << std::endl;
00107 }
00108 
00109 
00110 int NCBusyIndicator::preferredWidth()
00111 {
00112     return wGetDefsze().W;
00113 }
00114 
00115 
00116 int NCBusyIndicator::preferredHeight()
00117 {
00118     return wGetDefsze().H;
00119 }
00120 
00121 
00122 void NCBusyIndicator::setEnabled( bool do_bv )
00123 {
00124     NCWidget::setEnabled( do_bv );
00125     YBusyIndicator::setEnabled( do_bv );
00126 }
00127 
00128 
00129 void NCBusyIndicator::setSize( int newwidth, int newheight )
00130 {
00131     wRelocate( wpos( 0 ), wsze( newheight, newwidth ) );
00132 }
00133 
00134 
00135 void NCBusyIndicator::setDefsze()
00136 {
00137     defsze = wsze( _label.height() + 1,
00138                    _label.width() < 5 ? 5 : _label.width() );
00139 }
00140 
00141 
00142 void NCBusyIndicator::wCreate( const wrect & newrect )
00143 {
00144     NCWidget::wCreate( newrect );
00145 
00146     if ( !win )
00147         return;
00148 
00149     wrect lrect( 0, wsze::min( newrect.Sze,
00150                                wsze( _label.height(), newrect.Sze.W ) ) );
00151 
00152     wrect trect( 0, wsze( 1, newrect.Sze.W ) );
00153 
00154     if ( lrect.Sze.H == newrect.Sze.H )
00155         lrect.Sze.H -= 1;
00156 
00157     trect.Pos.L = lrect.Sze.H > 0 ? lrect.Sze.H : 0;
00158 
00159     _lwin = new NCursesWindow( *win,
00160                                lrect.Sze.H, lrect.Sze.W,
00161                                lrect.Pos.L, lrect.Pos.C,
00162                                'r' );
00163 
00164     _twin = new NCursesWindow( *win,
00165                                trect.Sze.H, trect.Sze.W,
00166                                trect.Pos.L, trect.Pos.C,
00167                                'r' );
00168 }
00169 
00170 
00171 void NCBusyIndicator::wDelete()
00172 {
00173     delete _lwin;
00174     delete _twin;
00175     _lwin = 0;
00176     _twin = 0;
00177     NCWidget::wDelete();
00178 }
00179 
00180 
00181 void NCBusyIndicator::setLabel( const std::string & nlabel )
00182 {
00183     _label = NCstring( nlabel );
00184     setDefsze();
00185     YBusyIndicator::setLabel( nlabel );
00186     Redraw();
00187 }
00188 
00189 
00190 /**
00191  * handler, called by NCBusyIndicatorHandlerWrapper
00192  **/
00193 void NCBusyIndicator::handler( int sig_num )
00194 {
00195     _timer_progress += _timer_divisor;
00196 
00197     if ( _timer_progress >= 1 )
00198     {
00199         _timer_progress = 0;
00200         _alive = false;
00201     }
00202 
00203     update();
00204 
00205 #if 0
00206     interval.it_value.tv_sec = 0;
00207     interval.it_value.tv_usec = REPAINT_INTERVAL * 1000;
00208     setitimer( ITIMER_REAL, &interval, NULL );
00209 #endif
00210 
00211 }
00212 
00213 
00214 /**
00215  * static wrapper for member function handler
00216  **/
00217 #if 0
00218 void NCBusyIndicatorHandlerWrapper( int sig_num )
00219 {
00220     signal( SIGALRM, SIG_IGN );
00221     NCBusyIndicatorObject->handler( sig_num );
00222     signal( SIGALRM, NCBusyIndicatorHandlerWrapper );
00223 }
00224 
00225 #endif
00226 
00227 
00228 /**
00229  * Calculate position of moving bar
00230  **/
00231 void NCBusyIndicator::update()
00232 {
00233     if ( !_alive )
00234         return;
00235 
00236     if ( _position > 1.0 || _position < 0 )
00237         _rightwards = !_rightwards;
00238 
00239     if ( _rightwards )
00240         _position += STEP_SIZE;
00241     else
00242         _position -= STEP_SIZE;
00243 
00244     Redraw();
00245     refresh();
00246 }
00247 
00248 
00249 /**
00250  * std::set alive or stalled
00251  **/
00252 void NCBusyIndicator::setAlive( bool newAlive )
00253 {
00254     _alive = newAlive;
00255 
00256     if ( newAlive )
00257         _timer_progress = 0;
00258 }
00259 
00260 
00261 void NCBusyIndicator::setTimeout( int newTimeout )
00262 {
00263     if ( newTimeout < 1 )
00264         newTimeout = 1;
00265 
00266     _timeout = newTimeout;
00267     YBusyIndicator::setTimeout( newTimeout );
00268     _timer_divisor = (double) REPAINT_INTERVAL / (double) _timeout;
00269 }
00270 
00271 
00272 /**
00273  * draw busy indicator widget
00274  **/
00275 void NCBusyIndicator::wRedraw()
00276 {
00277     if ( !win )
00278         return;
00279 
00280     // label
00281     chtype bg = wStyle().dumb.text;
00282     _lwin->bkgdset( bg );
00283     _lwin->clear();
00284     _label.drawAt( *_lwin, bg, bg );
00285     tUpdate();
00286 }
00287 
00288 
00289 /**
00290  * Draw busy bar
00291  **/
00292 void NCBusyIndicator::tUpdate()
00293 {
00294     if ( !win )
00295         return;
00296 
00297     int cp = ( int )(( _twin->maxx() ) * _position );
00298 
00299     const NCstyle::StProgbar & style( wStyle().progbar );
00300 
00301     _twin->bkgdset( style.nonbar.chattr );
00302     _twin->clear();
00303 
00304     if ( cp <= _twin->maxx() )
00305     {
00306         _twin->bkgdset( NCattribute::getNonChar( style.bar.chattr ) );
00307         _twin->move( 0, cp );
00308         _twin->addch( NCattribute::getChar( style.bar.chattr ) );
00309     }
00310 }
 All Classes Functions Variables