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: 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 }