libyui-ncurses  2.44.1
 All Classes Functions Variables
NCBusyIndicator.cc
1 /*
2  Copyright (C) 2000-2012 Novell, Inc
3  This library is free software; you can redistribute it and/or modify
4  it under the terms of the GNU Lesser General Public License as
5  published by the Free Software Foundation; either version 2.1 of the
6  License, or (at your option) version 3.0 of the License. This library
7  is distributed in the hope that it will be useful, but WITHOUT ANY
8  WARRANTY; without even the implied warranty of MERCHANTABILITY or
9  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10  License for more details. You should have received a copy of the GNU
11  Lesser General Public License along with this library; if not, write
12  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
13  Floor, Boston, MA 02110-1301 USA
14 */
15 
16 
17 /*-/
18 
19  File: NCBusyIndicator.cc
20 
21  Author: Thomas Goettlicher <tgoettlicher@suse.de>
22  Maintainer: Thomas Goettlicher <tgoettlicher@suse.de>
23 
24 /-*/
25 
26 #define YUILogComponent "ncurses"
27 #include <yui/YUILog.h>
28 #include "NCurses.h"
29 #include "NCBusyIndicator.h"
30 #include <signal.h>
31 #include <unistd.h>
32 #include <sys/time.h>
33 
34 #define REPAINT_INTERVAL 100 // in ms
35 #define STEP_SIZE .05
36 
37 /*
38  Some words about the timer stuff:
39  With each SIG_ALRM signal _timer_progress gets incremented by _timer_divisor.
40  When a tick is received [=setAlive(true) is called] _timer_progress is std::set to 0.
41  If _timer_progress is larger than 1 the widget goes to stalled state.
42 
43  How the timer works:
44  NCBusyIndicatorHandlerWrapper is registered as signal handler for SIG_ALRM
45  signal and calls NCBusyIndicatorObject->handler(). This wrapper is needed
46  because a member function cannot be registered as signal handler.
47 
48  LIMITATIONS:
49  i) Only one BusyIndicator widget works at the same time, because the
50  wrapper function only calls the handler() member function of the last
51  created instance of BusyIndicator.
52 
53  ii) The UserInput widget cannot be used, because UserInput is a blocking
54  function. When UserInput waits for UserInput no SIG_ALRM signal is sent
55  and therefore the BusyIndicator widget doesn't show progress.
56  Please use the TimeoutUserInput widget in a loop instead.
57 */
58 
59 struct itimerval interval;
60 NCBusyIndicator* NCBusyIndicatorObject;
61 #if 0
62 void NCBusyIndicatorHandlerWrapper( int sig_num );
63 #endif
64 
65 
66 
67 NCBusyIndicator::NCBusyIndicator( YWidget * parent,
68  const std::string & nlabel,
69  int timeout )
70  : YBusyIndicator( parent, nlabel, timeout )
71  , NCWidget( parent )
72  , _label( nlabel )
73  , _timeout( timeout )
74  , _lwin( 0 )
75  , _twin( 0 )
76  , _position( .5 )
77  , _rightwards( true )
78  , _alive( true )
79 {
80  yuiDebug() << std::endl;
81 
82  if ( timeout <= 0 )
83  timeout = 1;
84 
85  setLabel( nlabel );
86  hotlabel = &_label;
87  wstate = NC::WSdumb;
88  NCBusyIndicatorObject = this;
89  _timer_divisor = ( double ) REPAINT_INTERVAL / ( double ) timeout;
90  _timer_progress = 0;
91 
92 #if 0
93  signal( SIGALRM, NCBusyIndicatorHandlerWrapper );
94  interval.it_value.tv_sec = 0;
95  interval.it_value.tv_usec = REPAINT_INTERVAL * 1000;
96  setitimer( ITIMER_REAL, &interval, NULL );
97 #endif
98 }
99 
100 
101 NCBusyIndicator::~NCBusyIndicator()
102 {
103  NCBusyIndicatorObject = NULL;
104  delete _lwin;
105  delete _twin;
106  yuiDebug() << std::endl;
107 }
108 
109 
110 int NCBusyIndicator::preferredWidth()
111 {
112  return wGetDefsze().W;
113 }
114 
115 
116 int NCBusyIndicator::preferredHeight()
117 {
118  return wGetDefsze().H;
119 }
120 
121 
122 void NCBusyIndicator::setEnabled( bool do_bv )
123 {
124  NCWidget::setEnabled( do_bv );
125  YBusyIndicator::setEnabled( do_bv );
126 }
127 
128 
129 void NCBusyIndicator::setSize( int newwidth, int newheight )
130 {
131  wRelocate( wpos( 0 ), wsze( newheight, newwidth ) );
132 }
133 
134 
135 void NCBusyIndicator::setDefsze()
136 {
137  defsze = wsze( _label.height() + 1,
138  _label.width() < 5 ? 5 : _label.width() );
139 }
140 
141 
142 void NCBusyIndicator::wCreate( const wrect & newrect )
143 {
144  NCWidget::wCreate( newrect );
145 
146  if ( !win )
147  return;
148 
149  wrect lrect( 0, wsze::min( newrect.Sze,
150  wsze( _label.height(), newrect.Sze.W ) ) );
151 
152  wrect trect( 0, wsze( 1, newrect.Sze.W ) );
153 
154  if ( lrect.Sze.H == newrect.Sze.H )
155  lrect.Sze.H -= 1;
156 
157  trect.Pos.L = lrect.Sze.H > 0 ? lrect.Sze.H : 0;
158 
159  _lwin = new NCursesWindow( *win,
160  lrect.Sze.H, lrect.Sze.W,
161  lrect.Pos.L, lrect.Pos.C,
162  'r' );
163 
164  _twin = new NCursesWindow( *win,
165  trect.Sze.H, trect.Sze.W,
166  trect.Pos.L, trect.Pos.C,
167  'r' );
168 }
169 
170 
171 void NCBusyIndicator::wDelete()
172 {
173  delete _lwin;
174  delete _twin;
175  _lwin = 0;
176  _twin = 0;
177  NCWidget::wDelete();
178 }
179 
180 
181 void NCBusyIndicator::setLabel( const std::string & nlabel )
182 {
183  _label = NCstring( nlabel );
184  setDefsze();
185  YBusyIndicator::setLabel( nlabel );
186  Redraw();
187 }
188 
189 
190 /**
191  * handler, called by NCBusyIndicatorHandlerWrapper
192  **/
193 void NCBusyIndicator::handler( int sig_num )
194 {
195  _timer_progress += _timer_divisor;
196 
197  if ( _timer_progress >= 1 )
198  {
199  _timer_progress = 0;
200  _alive = false;
201  }
202 
203  update();
204 
205 #if 0
206  interval.it_value.tv_sec = 0;
207  interval.it_value.tv_usec = REPAINT_INTERVAL * 1000;
208  setitimer( ITIMER_REAL, &interval, NULL );
209 #endif
210 
211 }
212 
213 
214 /**
215  * static wrapper for member function handler
216  **/
217 #if 0
218 void NCBusyIndicatorHandlerWrapper( int sig_num )
219 {
220  signal( SIGALRM, SIG_IGN );
221  NCBusyIndicatorObject->handler( sig_num );
222  signal( SIGALRM, NCBusyIndicatorHandlerWrapper );
223 }
224 
225 #endif
226 
227 
228 /**
229  * Calculate position of moving bar
230  **/
231 void NCBusyIndicator::update()
232 {
233  if ( !_alive )
234  return;
235 
236  if ( _position > 1.0 || _position < 0 )
237  _rightwards = !_rightwards;
238 
239  if ( _rightwards )
240  _position += STEP_SIZE;
241  else
242  _position -= STEP_SIZE;
243 
244  Redraw();
245  refresh();
246 }
247 
248 
249 /**
250  * std::set alive or stalled
251  **/
252 void NCBusyIndicator::setAlive( bool newAlive )
253 {
254  _alive = newAlive;
255 
256  if ( newAlive )
257  _timer_progress = 0;
258 }
259 
260 
261 void NCBusyIndicator::setTimeout( int newTimeout )
262 {
263  if ( newTimeout < 1 )
264  newTimeout = 1;
265 
266  _timeout = newTimeout;
267  YBusyIndicator::setTimeout( newTimeout );
268  _timer_divisor = (double) REPAINT_INTERVAL / (double) _timeout;
269 }
270 
271 
272 /**
273  * draw busy indicator widget
274  **/
276 {
277  if ( !win )
278  return;
279 
280  // label
281  chtype bg = wStyle().dumb.text;
282  _lwin->bkgdset( bg );
283  _lwin->clear();
284  _label.drawAt( *_lwin, bg, bg );
285  tUpdate();
286 }
287 
288 
289 /**
290  * Draw busy bar
291  **/
292 void NCBusyIndicator::tUpdate()
293 {
294  if ( !win )
295  return;
296 
297  int cp = ( int )(( _twin->maxx() ) * _position );
298 
299  const NCstyle::StProgbar & style( wStyle().progbar );
300 
301  _twin->bkgdset( style.nonbar.chattr );
302  _twin->clear();
303 
304  if ( cp <= _twin->maxx() )
305  {
306  _twin->bkgdset( NCattribute::getNonChar( style.bar.chattr ) );
307  _twin->move( 0, cp );
308  _twin->addch( NCattribute::getChar( style.bar.chattr ) );
309  }
310 }
C++ class for windows.
Definition: ncursesw.h:904
void bkgdset(chtype ch)
Definition: ncursesw.h:1448
int maxx() const
Definition: ncursesw.h:1090
virtual void setAlive(bool newAlive)
Definition: position.h:109
int addch(const char ch)
Definition: ncursesw.h:1228
virtual void setEnabled(bool do_bv)
void handler(int sig_num)
virtual void wRedraw()
int move(int y, int x)
Definition: ncursesw.h:1155
virtual void setEnabled(bool do_bv)=0
Definition: NCWidget.cc:391
Definition: position.h:154