1 /* slider.cc
2  * This file belongs to Worker, a file manager for UN*X/X11.
3  * Copyright (C) 2005-2019 Ralf Hoffmann.
4  * You can contact me at: ralf@boomerangsworld.de
5  *   or http://www.boomerangsworld.de/worker
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #include "slider.h"
23 #include <stdlib.h>
24 #include "awindow.h"
25 #include "guielement.h"
26 
27 const char *Slider::type = "Slider";
28 
Slider(AGUIX * caguix,int cx,int cy,int cwidth,int cheight,bool cvertical,int cdata)29 Slider::Slider( AGUIX *caguix, int cx, int cy, int cwidth, int cheight, bool cvertical, int cdata ) : GUIElement( caguix )
30 {
31   max_len = 0;
32   offset = 0;
33   maxdisplay = 0;
34   vertical = cvertical;
35 
36   old_offset = -1;
37 
38   this->data = cdata;
39   _x = cx;
40   _y = cy;
41   if ( cwidth > 6 )
42     _w = cwidth;
43   else
44     _w = 6;
45   if ( cheight > 6 )
46     _h = cheight;
47   else
48     _h = 6;
49   bar_dir = 0;
50   bar_pressed = false;
51 
52   displayFocus = false;
53   setCanHandleFocus();
54   setAcceptFocus( true );
55 
56   barMode = BAR_IDLE;
57   grabs = 0;
58   scrollDelta = 0;
59 
60   _init_timer_wait = 0;
61   setAllowTimerEventBreak( true );
62 
63   m_bg = -1;
64 
65   m_show_arrow_buttons = true;
66 }
67 
~Slider()68 Slider::~Slider()
69 {
70 }
71 
resize(int tw,int th)72 void Slider::resize( int tw, int th )
73 {
74   if ( ( tw < 6 ) || ( th < 6 ) ) return;
75   _w = tw;
76   _h = th;
77   if ( isCreated() == true ) {
78     _parent->resizeSubWin( win, tw, th );
79     redraw();
80   }
81 }
82 
getData() const83 int Slider::getData() const
84 {
85   return data;
86 }
87 
setData(int tdata)88 void Slider::setData( int tdata )
89 {
90   this->data = tdata;
91 }
92 
flush()93 void Slider::flush()
94 {
95 }
96 
handleExpose(Window msgwin,int ex,int ey,int ew,int eh)97 void Slider::handleExpose( Window msgwin, int ex, int ey, int ew, int eh )
98 {
99   if ( isCreated() == false ) return;
100   if ( msgwin == win ) {
101     redraw();
102   }
103 }
104 
handleMessage(XEvent * E,Message * msg)105 bool Slider::handleMessage( XEvent *E, Message *msg )
106 {
107   bool returnvalue;
108 
109   if ( isCreated() == false ) return false;
110 
111   returnvalue = false;
112   if ( msg->type == Expose ) {
113     handleExpose( msg->window,
114 		  msg->x,
115 		  msg->y,
116 		  msg->width,
117 		  msg->height );
118   }
119   if ( barMode != BAR_IDLE ) handleBar( msg );
120   else {
121     if ( msg->type == ButtonPress ) {
122       // jetzt muessen wir was machen
123       bool isc = false;
124       if ( msg->window == win ) {
125 	takeFocus();
126 	handleBar( msg );
127 	isc = true;
128       }
129       if ( isc == true ) {
130 	AGMessage *agmsg = AGUIX_allocAGMessage();
131 	agmsg->slider.slider = this;
132 	agmsg->slider.offset = offset;
133 	agmsg->slider.time = msg->time;
134 	agmsg->slider.mouse = true;
135 	agmsg->type = AG_SLIDER_PRESSED;
136         msgAndCB( std::unique_ptr<AGMessage>( agmsg ) );
137       }
138     } else if ( msg->type == KeyPress ) {
139       if ( ( getAcceptFocus() == true ) && ( getHasFocus() == true ) ) {
140 	if ( isVisible() == true ) {
141 	  if ( _parent->isTopParent( msg->window ) == true ) {
142 	    // we have the focus so let's react to some keys
143 	    // lets call an extra handler so it can be overwritten
144 	    returnvalue = handleKeys( msg );
145 	  }
146 	}
147       }
148     }
149   }
150   if ( msg->lockElement == this ) msg->ack = true;
151   return returnvalue;
152 }
153 
redraw()154 void Slider::redraw()
155 {
156   if ( isCreated() == false ) return;
157   int tx, ty, tw, th;
158   int maxlen = getMaxLen();
159   struct point { int x, y; };
160   struct point p[3];
161   XPoint arrow1[3], arrow2[3];
162   int bw, bgbw;
163   AGUIXColor bg_to_use( 0 );
164 
165   bgbw = 1;
166 
167   tw = _w - ( ( displayFocus == true ) ? 2 * bgbw: 0 );
168   th = _h - ( ( displayFocus == true ) ? 2 * bgbw: 0 );
169   ty = ( displayFocus == true ) ? bgbw : 0;
170   tx = ( displayFocus == true ) ? bgbw : 0;
171 
172   bw = 2;
173 
174   if ( m_bg < 0 ) {
175       bg_to_use = _aguix->getFaces().getAGUIXColor( "slider-bg" );
176   } else {
177       bg_to_use = AGUIXColor( m_bg );
178   }
179   _aguix->SetWindowBG( win, bg_to_use );
180   _aguix->ClearWin( win );
181 
182   // draw background
183   if ( displayFocus == true ) {
184     if ( getHasFocus() == true ) {
185       _aguix->setFG( _aguix->getFaceCol_3d_dark() );
186     } else {
187       _aguix->setFG( _aguix->getFaceCol_3d_bright() );
188     }
189     p[0].x = 0;
190     p[0].y = _h - 1;
191     p[1].x = 0;
192     p[1].y = 0;
193     p[2].x = _w - 1;
194     p[2].y = 0;
195     _aguix->DrawLine( win, p[0].x, p[0].y, p[1].x, p[1].y );
196     _aguix->DrawLine( win, p[1].x, p[1].y, p[2].x, p[2].y );
197 
198     if ( getHasFocus() == true ) {
199       _aguix->setFG( _aguix->getFaceCol_3d_bright() );
200     } else {
201       _aguix->setFG( _aguix->getFaceCol_3d_dark() );
202     }
203     p[0].x = 1;
204     p[0].y = _h - 1;
205     p[1].x = _w - 1;
206     p[1].y = _h - 1;
207     p[2].x = _w - 1;
208     p[2].y = 1;
209     _aguix->DrawLine( win, p[0].x, p[0].y, p[1].x, p[1].y );
210     _aguix->DrawLine( win, p[1].x, p[1].y, p[2].x, p[2].y );
211   }
212 
213   if ( vertical == true ) {
214     int dw = ( tw - 1 ) & ~1;
215     dw = ( dw - 2 * bw ) / 2;
216 
217     arrow1[0].x = tx + ( tw - 1 ) / 2 - dw;
218     arrow1[0].y = ty + tw - bw - 1;
219     arrow1[1].x = tx + ( tw - 1 ) / 2;
220     arrow1[1].y = ty + bw;
221     arrow1[2].x = tx + ( tw - 1 )  / 2 + dw;
222     arrow1[2].y = ty + tw - bw - 1;
223 
224     arrow2[0].x = tx + ( tw - 1 ) / 2 - dw;
225     arrow2[0].y = ty + th - tw + bw;
226     arrow2[1].x = tx + ( tw - 1 ) / 2;
227     arrow2[1].y = ty + th - bw - 1;
228     arrow2[2].x = tx + ( tw - 1 )  / 2 + dw;
229     arrow2[2].y = ty + th - tw + bw;
230   } else {
231     int dh = ( th - 1 ) & ~1;
232     dh = ( dh - 2 * bw ) / 2;
233 
234     arrow1[0].x = tx + th - bw - 1;
235     arrow1[0].y = ty + ( th - 1 ) / 2 - dh;
236     arrow1[1].x = tx + bw;
237     arrow1[1].y = ty + ( th - 1 )  / 2;
238     arrow1[2].x = tx + th - bw - 1;
239     arrow1[2].y = ty + ( th - 1 ) / 2 + dh;
240 
241     arrow2[0].x = tx + tw - th + bw;
242     arrow2[0].y = ty + ( th - 1 ) / 2 - dh;
243     arrow2[1].x = tx + tw - bw - 1;
244     arrow2[1].y = ty + ( th - 1 )  / 2;
245     arrow2[2].x = tx + tw - th + bw;
246     arrow2[2].y = ty + ( th - 1 ) / 2 + dh;
247   }
248 
249   if ( m_show_arrow_buttons ) {
250       // left/top arrow box
251       _aguix->drawBorder( win, ( bar_dir == 1 ) ? true : false, tx, ty,  ( vertical == true ) ? tw : th, ( vertical == true ) ? tw : th, 0 );
252 
253       // Left/Up-Arrow
254       _aguix->setFG( _aguix->getFaces().getAGUIXColor( "slider-arrow" ) );
255       _aguix->DrawTriangleFilled( win,
256                                   arrow1[0].x, arrow1[0].y,
257                                   arrow1[1].x, arrow1[1].y,
258                                   arrow1[2].x, arrow1[2].y );
259  }
260 
261   // middle box
262 
263   // dark grey
264   _aguix->setFG( _aguix->getFaces().getAGUIXColor( "slider-bg2" ) );
265   if ( m_show_arrow_buttons ) {
266       _aguix->FillRectangle( win, ( vertical == true ) ? tx : tx + th, ( vertical == true ) ? ty + tw : ty,
267                              ( vertical == true ) ? tw : tw -  2 * th, ( vertical == true ) ? th -  2 * tw : th );
268   } else {
269       _aguix->FillRectangle( win, tx, ty,
270                              tw, th );
271   }
272 
273   _aguix->setFG( _aguix->getFaceCol_3d_dark() );
274   if ( m_show_arrow_buttons ) {
275       p[0].x = ( vertical == true ) ? tx + tw - 1: tx + th;
276       p[0].y = ( vertical == true ) ? ty + tw : ty + th - 1;
277       p[1].x = ( vertical == true ) ? tx + tw - 1: tx + tw - th - 1;
278       p[1].y = ( vertical == true ) ? ty + th - tw - 1: ty + th - 1;
279       _aguix->DrawLine( win, p[0].x, p[0].y, p[1].x, p[1].y );
280   } else {
281       p[0].x = tx + 1;
282       p[0].y = ty + th - 1;
283       p[1].x = tx + tw - 1;
284       p[1].y = ty + th - 1;
285       p[2].x = tx + tw - 1;
286       p[2].y = ty;
287 
288       _aguix->DrawLine( win, p[0].x, p[0].y, p[1].x, p[1].y );
289       _aguix->DrawLine( win, p[1].x, p[1].y, p[2].x, p[2].y );
290   }
291   _aguix->setFG( _aguix->getFaceCol_3d_bright() );
292   if ( m_show_arrow_buttons ) {
293       p[0].x = ( vertical == true ) ? tx : tx + th;
294       p[0].y = ( vertical == true ) ? ty + tw : ty;
295       p[1].x = ( vertical == true ) ? tx : tx + tw - th - 1;
296       p[1].y = ( vertical == true ) ? ty + th - tw - 1 : ty;
297       _aguix->DrawLine( win, p[0].x, p[0].y, p[1].x, p[1].y );
298   } else {
299       p[0].x = tx;
300       p[0].y = ty + th - 1;
301       p[1].x = tx;
302       p[1].y = ty;
303       p[2].x = tx + tw - 2;
304       p[2].y = ty;
305 
306       _aguix->DrawLine( win, p[0].x, p[0].y, p[1].x, p[1].y );
307       _aguix->DrawLine( win, p[1].x, p[1].y, p[2].x, p[2].y );
308   }
309 
310   if ( m_show_arrow_buttons ) {
311       // right/bottom arrow box
312       p[0].x = ( vertical == true ) ? tx : tx + tw - th;
313       p[0].y = ( vertical == true ) ? ty + th - tw : ty;
314       _aguix->drawBorder( win, ( bar_dir == 2 ) ? true : false, p[0].x, p[0].y, ( vertical == true ) ? tw : th, ( vertical == true ) ? tw : th, 0 );
315 
316       // Right-Arrow
317       _aguix->setFG( _aguix->getFaces().getAGUIXColor( "slider-arrow" ) );
318       _aguix->DrawTriangleFilled( win,
319                                   arrow2[0].x, arrow2[0].y,
320                                   arrow2[1].x, arrow2[1].y,
321                                   arrow2[2].x, arrow2[2].y );
322   }
323 
324   // jetzt noch die eigentliche Leiste
325   if ( vertical == true ) {
326     tx++;
327 
328     if ( m_show_arrow_buttons ) {
329         ty += tw;
330         th -= 2 * tw;  // Hoehe wenn alles anzeigbar ist
331     }
332 
333     tw -= 2;
334   } else {
335     ty++;
336 
337     if ( m_show_arrow_buttons ) {
338         tx += th;
339         tw -= 2 * th;  // Breite wenn alles anzeigbar ist
340     }
341 
342     th -= 2;
343   }
344   if ( maxlen > maxdisplay ) {
345     int d = ( ( vertical == true ) ? th : tw ) * maxdisplay;
346     d /= maxlen;
347 
348     if ( d < 10 ) d = 10;
349 
350     int a = maxlen - maxdisplay;
351     double b = ( ( vertical == true ) ? th : tw ) - d;  // das was uebrig bleibt
352     b /= a;            // verteilt sich auch die nichtsichtbaren Zeichen
353     if ( vertical == true ) {
354       ty += (int)( offset * b );
355       th = d;
356     } else {
357       tx += (int)( offset * b );
358       tw = d;
359     }
360   }
361 
362   _aguix->setFG( bg_to_use );
363   _aguix->FillRectangle( win, tx, ty,
364 			 tw, th );
365 
366   _aguix->drawBorder( win, bar_pressed, tx, ty, tw, th, 0 );
367 }
368 
getOffset() const369 int Slider::getOffset() const
370 {
371   return offset;
372 }
373 
setOffset(int nv)374 void Slider::setOffset( int nv )
375 {
376   offset = nv;
377   checkValues();
378   redraw();
379 }
380 
getMaxLen() const381 int Slider::getMaxLen() const
382 {
383   return max_len;
384 }
385 
setMaxLen(int nv)386 void Slider::setMaxLen( int nv )
387 {
388   max_len = nv;
389   checkValues();
390   redraw();
391 }
392 
getMaxDisplay() const393 int Slider::getMaxDisplay() const
394 {
395   return maxdisplay;
396 }
397 
setMaxDisplay(int nv)398 void Slider::setMaxDisplay( int nv )
399 {
400   maxdisplay = nv;
401   checkValues();
402   redraw();
403 }
404 
handleBar(Message * msg)405 void Slider::handleBar( Message *msg )
406 {
407   int mx, my;
408   int dir;
409   int hx, hy, hw, hh;
410   int tx, ty, tw, th;
411   double b = 1.0;
412   int bgbw;
413 
414   if ( isCreated() == false ) return;
415 
416   int maxlen = getMaxLen();
417 
418   mx = msg->mousex;
419   my = msg->mousey;
420 
421   bgbw = 1;
422 
423   hw = _w - ( ( displayFocus == true ) ? 2 * bgbw : 0 );
424   hh = _h - ( ( displayFocus == true ) ? 2 * bgbw : 0 );
425   hx = ( displayFocus == true ) ? bgbw : 0;
426   hy = ( displayFocus == true ) ? bgbw : 0;
427 
428   tw = hw;
429   th = hh;
430   tx = hx;
431   ty = hy;
432 
433   if ( vertical == true ) {
434       tx++;
435       if ( m_show_arrow_buttons ) {
436           ty += tw;
437           th -= 2 * tw;  // Hoehe wenn alles anzeigbar ist
438       }
439       tw -= 2;
440   } else {
441       ty++;
442       if ( m_show_arrow_buttons ) {
443           tx += th;
444           tw -= 2 * th;  // Breite wenn alles anzeigbar ist
445       }
446       th -= 2;
447   }
448 
449   if ( maxlen > maxdisplay ) {
450     int d = ( ( vertical == true ) ? th : tw ) * maxdisplay;
451     d /= maxlen;
452 
453     if ( d < 10 ) d = 10;
454 
455     int a = maxlen - maxdisplay;
456     b = ( ( vertical == true ) ? th : tw ) - d;  // das was uebrig bleibt
457     b /= a;            // verteilt sich auch die nichtsichtbaren Zeichen
458     if ( vertical == true ) {
459       ty += (int)( offset * b );
460       th = d;
461     } else {
462       tx += (int)( offset * b );
463       tw = d;
464     }
465   }
466 
467   if ( msg->type == ButtonPress ) {
468     if ( barMode != BAR_IDLE ) return;
469     if ( msg->window == win ) {
470       dir = 0;
471 
472       if ( m_show_arrow_buttons ) {
473           if ( msg->button == Button1 ) {
474               if ( ( ( vertical == false ) && ( ( mx > hx ) && ( mx <= ( hx + hh ) ) ) ) ||
475                    ( ( vertical == true ) && ( ( my > hy ) && ( my <= ( hy + hw ) ) ) ) ) {
476                   // left
477                   dir = -1;
478                   bar_dir = 1;
479                   barMode = BAR_SCROLL_LEFT;
480               }
481               if ( ( ( vertical == false ) && ( ( mx > ( hx + hw - hh ) ) && ( mx <= ( hx + hw ) ) ) ) ||
482                    ( ( vertical == true ) && ( ( my > ( hy + hh - hw ) ) && ( my <= ( hy + hh ) ) ) ) ) {
483                   // right
484                   dir = 1;
485                   bar_dir = 2;
486                   barMode = BAR_SCROLL_RIGHT;
487               }
488           }
489       }
490 
491       if ( dir != 0 ) {
492 	setOffset( offset + dir );
493 	_aguix->Flush();
494 	_aguix->msgLock( this );
495 	enableTimer();
496       } else if ( msg->button == Button4 ) {
497 	setOffset( offset - a_max( 1, ( maxdisplay - 1 ) / 4 ) );
498 	_aguix->Flush();
499       } else if ( msg->button == Button5 ) {
500 	setOffset( offset + a_max( 1, ( maxdisplay - 1 ) / 4 ) );
501 	_aguix->Flush();
502       } else if ( ( msg->button == Button1 ) &&
503 		  ( ( ( vertical == false ) && ( mx >= tx ) && ( mx <= ( tx + tw ) ) )
504 		    ||
505 		    ( ( vertical == true ) && ( my >= ty ) && ( my <= ( ty + th ) ) )
506 		  )
507 		) {
508 	// the bar-scroller is pressed
509 	if ( maxlen > maxdisplay ) {
510 	  grabs = XGrabPointer( _aguix->getDisplay(),
511 				win,
512 				False,
513 				Button1MotionMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask,
514 				GrabModeAsync,
515 				GrabModeAsync,
516 				None,
517 				None,
518 				CurrentTime );
519 	  _aguix->setCursor( win, ( vertical == true ) ? AGUIX::SCROLLV_CURSOR : AGUIX::SCROLLH_CURSOR );
520 	  scrollDelta = ( vertical == true ) ? my - ty : mx - tx;
521 	  bar_pressed = true;
522 	  redraw();
523 	  _aguix->Flush();
524 	  barMode = BAR_SCROLL;
525 	  _aguix->msgLock( this );
526 	}
527       } else {
528 	if ( msg->button == Button1 ) {
529 	  if ( ( ( vertical == false ) && ( mx < tx ) ) ||
530 	       ( ( vertical == true ) && ( my < ty ) ) ) {
531 	    setOffset( offset - a_max( 1, maxdisplay - 1 ) );
532 	  } else {
533 	    setOffset( offset + a_max( 1, maxdisplay - 1 ) );
534 	  }
535 	  _aguix->Flush();
536 	}
537       }
538     }
539   } else if ( msg->type == MotionNotify ) {
540     if ( ( msg->window == win ) &&
541 	 ( barMode == BAR_SCROLL ) ) {
542       int tmx;
543       double f1;
544 
545       _aguix->queryPointer( win, &mx, &my );
546       tmx = ( vertical == true ) ? my : mx;
547 
548       if ( m_show_arrow_buttons ) {
549           tmx -= ( vertical == true ) ? hy + hw : hx + hh;
550       } else {
551           tmx -= ( vertical == true ) ? hy : hx;
552       }
553 
554       tmx -= scrollDelta;
555       f1 = tmx / b;
556       setOffset( (int)f1 );
557       _aguix->Flush();
558     }
559   } else if ( msg->type == ButtonRelease ) {
560     if ( ( msg->window == win ) &&
561 	 ( msg->button == Button1 ) ) {
562       switch ( barMode ) {
563 	case BAR_SCROLL_LEFT:
564 	case BAR_SCROLL_RIGHT:
565 	  bar_dir = 0;
566 	  redraw();
567 	  _aguix->Flush();
568 	  _aguix->disableTimer();
569 	  _aguix->msgUnlock( this );
570 	  break;
571 	case BAR_SCROLL:
572 	  _aguix->unsetCursor( win );
573 	  if ( grabs == GrabSuccess ) XUngrabPointer( _aguix->getDisplay(), CurrentTime );
574 	  bar_pressed=false;
575 	  redraw();
576 	  _aguix->Flush();
577 	  _aguix->msgUnlock( this );
578 	  break;
579 	default:
580 	  break;
581       }
582       barMode = BAR_IDLE;
583     }
584   } else if ( msg->type == ClientMessage ) {
585     if ( ( msg->specialType == Message::TIMEREVENT ) &&
586 	 ( barMode != BAR_IDLE ) ) {
587       if ( ( msg->time % 2 ) == 0 ) { //HARDCODED
588 	if ( _init_timer_wait < 1 ) {
589 	  switch ( barMode ) {
590 	    case BAR_SCROLL_LEFT:
591 	      setOffset( offset - 1 );
592 	      break;
593 	    case BAR_SCROLL_RIGHT:
594 	      setOffset( offset + 1 );
595 	      break;
596 	    default:
597 	      break;
598 	  }
599 	  _aguix->Flush();
600 	} else {
601 	  _init_timer_wait--;
602 	}
603       }
604     }
605   }
606   msgAndCallback();
607   return;
608 }
609 
getType() const610 const char *Slider::getType() const
611 {
612   return type;
613 }
614 
isType(const char * qtype) const615 bool Slider::isType(const char *qtype) const
616 {
617   if(strcmp(type,qtype)==0) return true;
618   return false;
619 }
620 
isParent(Window child) const621 bool Slider::isParent(Window child) const
622 {
623   if ( isCreated() == true ) {
624     if ( child == win ) return true;
625   }
626   return false;
627 }
628 
handleKeys(Message * msg)629 bool Slider::handleKeys(Message *msg)
630 {
631   bool returnvalue=false;
632 
633   if ( isCreated() == false ) return false;
634   if ( msg != NULL ) {
635     if ( msg->type == KeyPress ) {
636       if ( ( msg->key == XK_Up ) ||
637 	   ( msg->key == XK_Down ) ||
638 	   ( msg->key == XK_Left ) ||
639 	   ( msg->key == XK_Right ) ||
640 	   ( msg->key == XK_Home ) ||
641 	   ( msg->key == XK_End ) ||
642 	   ( msg->key == XK_Prior ) ||
643 	   ( msg->key == XK_Next ) ) {
644 	int noffset = offset;
645 
646 	switch ( msg->key ) {
647 	  case XK_Up:
648 	  case XK_Left:
649 	    noffset--;
650 	    break;
651 	  case XK_Down:
652 	  case XK_Right:
653 	    noffset++;
654 	    break;
655 	  case XK_Home:
656 	    noffset = 0;
657 	    break;
658 	  case XK_End:
659 	    noffset = max_len - 1;
660 	    break;
661 	  case XK_Prior:
662 	    noffset -= a_max( 1, maxdisplay - 1 );
663 	    break;
664 	  case XK_Next:
665 	    noffset += a_max( 1, maxdisplay - 1 );
666 	    break;
667 	  default:
668 	    break;
669 	}
670 	setOffset( noffset );
671 	msgAndCallback();
672       }
673     }
674   }
675   return returnvalue;
676 }
677 
setDisplayFocus(bool nv)678 void Slider::setDisplayFocus( bool nv )
679 {
680   displayFocus = nv;
681   redraw();
682 }
683 
getDisplayFocus() const684 bool Slider::getDisplayFocus() const
685 {
686   return displayFocus;
687 }
688 
checkValues()689 void Slider::checkValues()
690 {
691   if ( max_len < 0 ) max_len = 0;
692   if ( maxdisplay < 0 ) maxdisplay = 0;
693 
694   if ( ( offset + maxdisplay ) >= max_len ) offset = max_len - maxdisplay;
695   if ( offset < 0 ) offset = 0;
696 }
697 
msgAndCallback()698 void Slider::msgAndCallback()
699 {
700   if ( offset != old_offset ) {
701     AGMessage *agmsg = AGUIX_allocAGMessage();
702     agmsg->slider.slider = this;
703     agmsg->slider.offset = offset;
704     agmsg->slider.time = time( NULL );
705     agmsg->slider.mouse = false;
706     agmsg->type = AG_SLIDER_CHANGED;
707     msgAndCB( std::unique_ptr<AGMessage>( agmsg ) );
708 
709     callback( offset );
710 
711     old_offset = offset;
712   }
713 }
714 
enableTimer()715 void Slider::enableTimer()
716 {
717   _aguix->enableTimer();
718   _init_timer_wait = 3;
719 }
720 
getBG() const721 int Slider::getBG() const
722 {
723     return m_bg;
724 }
725 
setBG(int v)726 void Slider::setBG( int v )
727 {
728     m_bg = v;
729 
730     if ( m_bg < 0 )
731         m_bg = -1;
732 
733     redraw();
734 }
735 
setShowArrowButtons(bool nv)736 void Slider::setShowArrowButtons( bool nv )
737 {
738     m_show_arrow_buttons = nv;
739 
740     redraw();
741 }
742 
getShowArrowButtons() const743 bool Slider::getShowArrowButtons() const
744 {
745     return m_show_arrow_buttons;
746 }
747