Logo Search packages:      
Sourcecode: qasmixer version File versions  Download package

ds_slider.cpp

//
// C++ Implementation:
//
// Description:
//
//
// Author: Sebastian Holtermann <sebholt@xwmw.org>, (C) 2010-2011
//
// Copyright: See COPYING file that comes with this distribution
//
//

#include "ds_slider.hpp"

#include <QEvent>
#include <QMouseEvent>
#include <QPainter>

#include <cassert>
#include <climits>
#include <cmath>

#include "color_methods.hpp"

#include <iostream>


namespace Wdg
{


DS_Slider::DS_Slider (
      QWidget * parent_n,
      Shared_Pixmaps_Set_Hub * hub_n ) :
QWidget ( parent_n ),
_current_index ( 0 ),
_maximum_index ( 0 ),
_wheel_degrees ( 720 ),
_step_single ( 0 ),
_step_page ( 0 ),
_pxm_bg ( 0 ),
_pxm_handle ( 0 ),
_pxm_marker ( 0 ),
_handle_pos ( 0 ),
_handle_pos_index ( 0 ),
_handle_pos_hint ( 0 ),
_handle_pos_max ( 0 ),
_map_hp_idx ( 0 ),
_map_idx_hp ( 0 ),
_slider_down ( false ),
_update_pixmaps ( true ),
_cursor_select_allowed ( false ),
_cursor_over_handle ( false ),
_cursor_value_hinting ( false ),
_anim_run_snap ( false ),
_handle_min_height ( 15 ),
_handle_max_height ( 99 ),
_hub ( hub_n )
{
      setSizePolicy ( QSizePolicy::Expanding, QSizePolicy::Expanding );
      setFocusPolicy ( Qt::StrongFocus );
      setMouseTracking ( true );

      // Animation timer
      {
            const unsigned int fps ( 60 );
            _anim_timer.setInterval ( 1000 / fps );
            connect ( &_anim_timer, SIGNAL ( timeout() ),
                  this, SLOT ( anim_tick() ) );
      }

      update_index_mappers();
      update_painter_utils();
}


DS_Slider::~DS_Slider ( )
{
      set_hub ( 0 );
      clear_index_mappers();
}


QSize
DS_Slider::sizeHint ( ) const
{
      const int def_len ( fontMetrics().height() );
      return QSize ( def_len, def_len*10 );
}


QSize
DS_Slider::minimumSizeHint ( ) const
{
      const int def_len ( fontMetrics().height() );
      return QSize ( def_len, def_len*4 );
}


void
DS_Slider::set_wheel_degrees (
      unsigned int degrees_n )
{
      _wheel_degrees = ( degrees_n > 0 ) ? degrees_n : 1;
}


void
DS_Slider::set_hub (
      Shared_Pixmaps_Set_Hub * hub_n )
{
      if ( _hub != 0 ) {
            _hub->return_pixmaps ( _pxm_bg );
            _hub->return_pixmaps ( _pxm_handle );
            _hub->return_pixmaps ( _pxm_marker );
      }

      _hub = hub_n;

      if ( _hub != 0 ) {

      }

      _update_pixmaps = true;
      update();
}


void
DS_Slider::set_pixmaps_meta_bg (
      const DS_Slider_Pixmaps_Meta_Bg & cfg_n )
{
      _pxm_meta_bg = cfg_n;

      _update_pixmaps = true;
      update();
}


void
DS_Slider::set_pixmaps_meta_handle (
      const DS_Slider_Pixmaps_Meta_Handle & cfg_n )
{
      _pxm_meta_handle = cfg_n;

      _update_pixmaps = true;
      update();
}


void
DS_Slider::set_pixmaps_meta_marker (
      const DS_Slider_Pixmaps_Meta_Marker & cfg_n )
{
      _pxm_meta_marker = cfg_n;

      _update_pixmaps = true;
      update();
}


void
DS_Slider::set_current_index (
      unsigned long idx_n )
{
      if ( idx_n > maximum_index() ) {
            idx_n = maximum_index();
      }
      if ( current_index() != idx_n ) {
            _current_index = idx_n;
            this->current_index_changed();
            emit sig_current_index_changed ( idx_n );
      }
}


void
DS_Slider::adjust_current_index (
      long idx_delta_n )
{
      unsigned long idx ( current_index() );
      if ( idx_delta_n >= 0 ) {
            unsigned long dplus ( idx_delta_n );
            if ( dplus >= maximum_index() ) {
                  idx = maximum_index();
            } else {
                  if ( ( maximum_index() - dplus ) <= idx ) {
                        idx = maximum_index();
                  } else {
                        idx += dplus;
                  }
            }
      } else {
            unsigned long dplus ( -idx_delta_n );
            if ( dplus > idx ) {
                  idx = 0;
            } else {
                  idx -= dplus;
            }
      }
      set_current_index ( idx );
}


void
DS_Slider::set_maximum_index (
      unsigned long idx_n )
{
      if ( maximum_index() != idx_n ) {
            _maximum_index = idx_n;
            this->maximum_index_changed();
            emit sig_maximum_index_changed ( idx_n );
      }
}


void
DS_Slider::set_slider_down (
      bool down_n )
{
      _slider_down = down_n;
}


void
DS_Slider::current_index_changed ( )
{
      _handle_pos_index = map_index_to_handle_pos ( current_index() );
      if ( !slider_down() ) {
            anim_snap_start();
      }
      update();
}


void
DS_Slider::maximum_index_changed ( )
{
      update_index_mappers();

      if ( current_index() > maximum_index() ) {
            set_current_index ( maximum_index() );
      }

      unsigned long delta ( maximum_index() );
      unsigned long div;
      unsigned long val;
      unsigned long mod;

      // Single step
      div = 100;
      val = delta / div;
      mod = delta % div;
      if ( mod > ( div / 2 ) ) {
            ++val;
      }
      if ( val == 0 ) {
            ++val;
      }
      _step_single = val;

      // Page step
      div = 12;
      val = delta / div;
      mod = delta % div;
      if ( mod > ( div / 2 ) ) {
            ++val;
      }
      if ( val == 0 ) {
            ++val;
      }
      _step_page = val;

      // Update pixmap config
      _pxm_meta_bg.ticks_max_idx = delta;
      _update_pixmaps = true;
      update();
}


unsigned long
DS_Slider::map_handle_pos_to_index (
      int handle_pos_n )
{
      unsigned long res ( 0 );

      if ( handle_pos_n <= 0 ) {
            res = maximum_index();
      } else {
            unsigned int hpos ( handle_pos_n );
            if ( hpos <= _handle_pos_max ) {
                  hpos = _handle_pos_max - hpos;
                  res = _map_hp_idx->map ( hpos );
            }
      }

      return res;
}


unsigned int
DS_Slider::map_index_to_handle_pos (
      unsigned long idx_n )
{
      unsigned int res ( _handle_pos_max );

      if ( idx_n <= maximum_index() ) {
            res = _map_idx_hp->map ( idx_n );
            if ( res > _handle_pos_max ) {
                  res = 0;
            } else {
                  res = _handle_pos_max - res;
            }
      }

      return res;
}


unsigned int
DS_Slider::map_tick_pos_to_handle_pos (
      int tick_pos_n )
{
      unsigned int res ( 0 );
      const int delta ( _handle_rect.height() / 2 );
      if ( tick_pos_n > delta ) {
            res = ( tick_pos_n - delta );
            if ( res > _handle_pos_max ) {
                  res = _handle_pos_max;
            }
      }
      return res;
}


unsigned int
DS_Slider::map_handle_pos_to_tick_pos (
      int handle_pos_n )
{
      unsigned int res ( 0 );
      if ( handle_pos_n > 0 ) {
            res = handle_pos_n;
            if ( res > _handle_pos_max ) {
                  res = _handle_pos_max;
            }
      }
      res += ( _handle_rect.height() / 2 );
      return res;
}


unsigned int
DS_Slider::map_index_to_tick_pos (
      unsigned long idx_n )
{
      unsigned int res = map_index_to_handle_pos ( idx_n );
      res = map_handle_pos_to_tick_pos ( res );
      return res;
}


unsigned long
DS_Slider::map_tick_pos_to_index (
      int tick_pos_n )
{
      unsigned long res = map_tick_pos_to_handle_pos ( tick_pos_n );
      res = map_handle_pos_to_index ( res );
      return res;
}


void
DS_Slider::clear_index_mappers ( )
{
      if ( _map_idx_hp != 0 ) {
            delete _map_idx_hp;
            _map_idx_hp = 0;
      }
      if ( _map_hp_idx != 0 ) {
            delete _map_hp_idx;
            _map_hp_idx = 0;
      }
}


void
DS_Slider::update_index_mappers ( )
{
      clear_index_mappers();

      if ( maximum_index() > _handle_pos_max ) {
            _map_idx_hp = new UInt_Mapper_Down ( maximum_index(), _handle_pos_max );
            _map_hp_idx = new UInt_Mapper_Up ( _handle_pos_max, maximum_index() );
      } else {
            _map_idx_hp = new UInt_Mapper_Up ( maximum_index(), _handle_pos_max );
            _map_hp_idx = new UInt_Mapper_Down ( _handle_pos_max, maximum_index() );
      }
}


bool
DS_Slider::update_cursor_mode ( )
{
      //std::cout << "DS_Slider::update_cursor_mode " << "\n";

      bool res ( false ); // Indicates a cursor mode change

      const QPoint cur_pos ( mapFromGlobal ( QCursor::pos() ) );

      { // Check if the cursor is over the handle
            const bool over_handle ( _handle_rect.contains ( cur_pos ) );
            if ( over_handle != _cursor_over_handle ) {
                  _cursor_over_handle = over_handle;
                  res = true;
            }
      }

      { // Update cursor value hinting
            const bool show_hint (
                  _cursor_select_allowed &&
                  rect().contains ( cur_pos ) &&
                  !_cursor_over_handle &&
                  !slider_down() );

            if ( show_hint ) {
                  unsigned long hpos;
                  hpos = map_tick_pos_to_index ( cur_pos.y() );
                  hpos = map_index_to_handle_pos ( hpos );

                  if ( _handle_pos_hint != hpos ) {
                        _handle_pos_hint = hpos;
                        res = true;
                  }
            }

            if ( _cursor_value_hinting != show_hint ) {
                  _cursor_value_hinting = show_hint;
                  res = true;
            }
      }

      { // Update cursor shape
            Qt::CursorShape cshape ( Qt::ArrowCursor );
            if ( slider_down() ) {
                  cshape = Qt::ClosedHandCursor;
            } else if ( _cursor_over_handle ) {
                  cshape = Qt::OpenHandCursor;
            } else if ( _cursor_value_hinting ) {
                  cshape = Qt::CrossCursor;
00450             }

            QCursor curs ( cursor() );
            if ( curs.shape() != cshape ) {
                  curs.setShape ( cshape );
                  setCursor ( curs );
                  res = true;
            }
      }

      return res;
}


bool
DS_Slider::set_handle_pos (
      unsigned int pos_n )
{
      //std::cout << "DS_Slider::set_handle_pos " << pos_n << "\n";

      if ( pos_n > _handle_pos_max ) {
            pos_n = _handle_pos_max;
      }

      if ( _handle_pos != pos_n ) {
            _handle_pos = pos_n;
            _handle_rect.moveTop ( _handle_pos );
            return true;
      }

      return false;
}


void
DS_Slider::update_value_from_handle_pos ( )
{
      unsigned long idx = map_handle_pos_to_index ( _handle_pos );
      set_current_index ( idx );
}


void
DS_Slider::finish_handle_manipulation ( )
{
      set_slider_down ( false );

      _handle_pos_index = map_index_to_handle_pos ( current_index() );
      anim_snap_start();

      update_cursor_mode();
}


void
DS_Slider::changeEvent (
      QEvent * event_n )
{
      QWidget::changeEvent ( event_n );

      switch ( event_n->type() ) {
            case QEvent::ActivationChange:
            case QEvent::EnabledChange:
            case QEvent::StyleChange:
            case QEvent::PaletteChange:
            case QEvent::LayoutDirectionChange:

                  update_painter_utils();
                  _update_pixmaps = true;
                  update();
                  break;

            default:
                  break;
      }
}


// Focus events
void
DS_Slider::focusInEvent (
      QFocusEvent * event_n )
{
      //std::cout << "DS_Slider::focusInEvent " << "\n";

      QWidget::focusInEvent ( event_n );

      switch ( event_n->reason() ) {
            case Qt::MouseFocusReason:
            case Qt::ActiveWindowFocusReason:
                  _cursor_select_allowed = false;
                  break;

            default:
                  _cursor_select_allowed = true;
                  break;
      }

      update_cursor_mode();
      update();
}


void
DS_Slider::focusOutEvent (
      QFocusEvent * event_n )
{
      //std::cout << "DS_Slider::focusOutEvent " << "\n";

      QWidget::focusOutEvent ( event_n );

      _cursor_select_allowed = false;
      _cursor_value_hinting = false;
      finish_handle_manipulation();
      update();
}


void
DS_Slider::enterEvent (
      QEvent * event_n )
{
      //std::cout << "DS_Slider::enterEvent" << "\n";

      QWidget::enterEvent ( event_n );

      update_cursor_mode();
      update();
}


void
DS_Slider::leaveEvent (
      QEvent * event_n )
{
      //std::cout << "DS_Slider::leaveEvent" << "\n";

      QWidget::leaveEvent ( event_n );

      update_cursor_mode();
      update();
}


// Mouse events
void
DS_Slider::mousePressEvent (
      QMouseEvent * event_n )
{
      //std::cout << "DS_Slider::mousePressEvent" << "\n";

      QWidget::mousePressEvent ( event_n );

      if ( event_n->button() == Qt::LeftButton ) {

            if ( _cursor_over_handle ) {
                  // Start slider drag
                  set_slider_down ( true );
            } else {
                  // Select a value on the slider range
                  if ( _cursor_select_allowed ) {
                        set_slider_down ( true );
                        const unsigned int hpos (
                              map_tick_pos_to_handle_pos ( event_n->pos().y() ) );
                        if ( set_handle_pos ( hpos ) ) {
                              update_value_from_handle_pos();
                        }
                  }
            }

            if ( slider_down() ) {
                  anim_stop();
            }

            // After a click selection should be allowed
            if ( hasFocus() ) {
                  _cursor_select_allowed = true;
            }
            update_cursor_mode();
            update();
      }

}


void
DS_Slider::mouseReleaseEvent (
      QMouseEvent * event_n )
{
      //std::cout << "DS_Slider::mouseReleaseEvent" << "\n";

      QWidget::mouseReleaseEvent ( event_n );

      if ( event_n->button() == Qt::LeftButton ) {
            if ( slider_down() ) {
                  finish_handle_manipulation();
                  update();
            }
      }
}


void
DS_Slider::mouseMoveEvent (
      QMouseEvent * event_n )
{
      //std::cout << "DS_Slider::mouseMoveEvent" << "\n";

      QWidget::mouseMoveEvent ( event_n );

      bool do_update ( false );

      if ( slider_down() ) {
            int delta ( 0 );

            {
                  int p_now ( event_n->pos().y() );
                  int p_prev ( _mouse_last.y() );

                  if ( p_now != p_prev ) {
                        int p_min;
                        int p_max;
                        if ( p_now > p_prev ) {
                              // For moving downwards the cursor positions must be in this range
                              p_min = _tick_min;
                              p_max = height() - 1;
                        } else {
                              // For moving upwards the cursor positions must be in this range
                              p_min = 0;
                              p_max = _tick_max;
                        }
                        p_now = qBound ( p_min, p_now, p_max );
                        p_prev = qBound ( p_min, p_prev, p_max );

                        delta = ( p_now - p_prev );
                  }
            }

            //std::cout << "DS_Slider::mouseMoveEvent: Delta " << delta << "\n";
            unsigned int hpos ( _handle_pos );
            if ( delta < 0 ) {
                  delta = -delta;
                  if ( (unsigned int)delta < hpos ) {
                        hpos -= delta;
                  } else {
                        hpos = 0;
                  }
            } else {
                  hpos += delta;
            }
            if ( set_handle_pos ( hpos ) ) {
                  update_value_from_handle_pos();
                  do_update = true;
            }
      }

      _mouse_last = event_n->pos();

      // Test if the cursor is over the handle
      if ( update_cursor_mode() ) {
            do_update = true;
      }

      if ( do_update ) {
            update();
      }
}


void
DS_Slider::wheelEvent (
      QWheelEvent * event_n )
{

      QWidget::wheelEvent ( event_n );

      if ( rect().contains ( event_n->pos() ) ) {
            event_n->accept();
            setFocus();

            long delta;
            {
                  double amount ( maximum_index() / double ( _wheel_degrees ) );
                  amount *= ( event_n->delta() / 8.0 );
                  if ( amount > 0 ) {
                        delta = std::ceil ( amount );
                  } else {
                        delta = std::floor ( amount );
                  }
            }
            if ( delta == 0 ) {
                  if ( event_n->delta() > 0 ) {
                        delta = 1;
                  } else {
                        delta = -1;
                  }
            }

            adjust_current_index ( delta );

      } else {
            event_n->ignore();
      }
}


void
DS_Slider::keyPressEvent (
      QKeyEvent * event_n )
{

      QWidget::keyPressEvent ( event_n );

      long idx_adjust ( 0 );
      switch ( event_n->key() ) {
            case Qt::Key_Left:
                  idx_adjust = -_step_single;
                  break;
            case Qt::Key_Up:
                  idx_adjust = _step_single;
                  break;
            case Qt::Key_Right:
                  idx_adjust = _step_single;
                  break;
            case Qt::Key_Down:
                  idx_adjust = -_step_single;
                  break;
            case Qt::Key_PageUp:
                  idx_adjust = _step_page;
                  break;
            case Qt::Key_PageDown:
                  idx_adjust = -_step_page;
                  break;
            default:
                  break;
      }
      if ( idx_adjust != 0 ) {
            adjust_current_index ( idx_adjust );
      }
}


void
DS_Slider::keyReleaseEvent (
      QKeyEvent * event_n )
{
      QWidget::keyReleaseEvent ( event_n );
}


// Window events
void
DS_Slider::resizeEvent (
      QResizeEvent * event_n )
{
      QWidget::resizeEvent ( event_n );

      anim_stop();

      if ( ( width() <= 0 ) || ( height() <= 0 ) ) {
            return;
      }

      // Handle rect
      unsigned int handle_height;
      handle_height = height() / 10;
      if ( handle_height > _handle_max_height ) {
            handle_height = _handle_max_height;
      }
      if ( handle_height < _handle_min_height ) {
            handle_height = _handle_min_height;
      }
      handle_height += ( handle_height + 1 ) % 2; // Make odd

      _handle_rect.setRect (
            0, _handle_pos,
            width(), handle_height );

      // Handle range
      _handle_pos_max = 0;
      if ( (unsigned int)height() > handle_height ) {
            _handle_pos_max = ( height() - handle_height );
      }
      update_index_mappers();

      _tick_min = handle_height / 2;
      _tick_max = _tick_min + ( _handle_pos_max + 1 );

      // Update pixmap config
      _pxm_meta_bg.ticks_range_max_idx = _handle_pos_max;
      _pxm_meta_bg.ticks_range_start = handle_height / 2;


      // Marker size
      {
            int mww ( _handle_rect.height() / 5 );
            int mhh ( _handle_rect.width() / 7 );
            mww = qMin ( mww, mhh );

            if ( mww < 6 ) {
                  mww = 6;
            }
            if ( ( ( _handle_rect.width() - mww ) % 2 ) != 0 ) {
                  --mww;
            }

            mhh = mww;
            if ( ( mhh % 2 ) == 0 ) {
                  --mhh; // height should be odd
            }
            _marker_size.setWidth ( mww );
            _marker_size.setHeight ( mhh );
      }


      // Update value marker painting position offset
      {
            int off_x ( _handle_rect.width() );
            int off_y ( _handle_rect.height() / 2 );
            off_x -= _marker_size.width();
            off_y -= _marker_size.height() / 2;
            off_x /= 2;
            _marker_offset[0] = off_x;
            _marker_offset[1] = off_y;
      }


      // Update handle position
      _handle_pos_index = map_index_to_handle_pos ( current_index() );
      set_handle_pos ( _handle_pos_index );
      update_cursor_mode();


      // Request new pixmaps
      _update_pixmaps = true;
}


void
DS_Slider::paintEvent (
      QPaintEvent * event_n )
{
      QWidget::paintEvent ( event_n );

      if ( _update_pixmaps ) {
            _update_pixmaps = false;
            update_pixmaps();
      }

      if (
            ( _pxm_bg == 0 ) ||
            ( _pxm_handle == 0 ) ||
            ( _pxm_marker == 0 ) )
      {
            return;
      }

      // Keep a local state buffer
      const bool loc_under_mouse ( underMouse() );
      const bool loc_is_enabled ( isEnabled() );
      const bool loc_has_focus ( hasFocus() );
      const bool loc_slider_down ( slider_down() );

      QPainter painter ( this );

      // Draw slider background
      {
            int idx ( 0 );
            if ( loc_has_focus ) {
                  idx = 1;
            } else {
                  if ( loc_under_mouse && loc_is_enabled ) {
                        idx = 2;
                  }
            }
            unsigned int mid_pos ( _handle_pos_index + _handle_rect.height() / 2 );
            {
                  QRect re_img ( 0, 0, width(), mid_pos );
                  const QPixmap & pxm ( _pxm_bg->pixmap ( idx ) );
                  painter.drawPixmap ( re_img, pxm, re_img );
            }
            {
                  QRect re_img ( 0, mid_pos, width(), height() - mid_pos );
                  const QPixmap & pxm ( _pxm_bg->pixmap ( idx + 3 ) );
                  painter.drawPixmap ( re_img, pxm, re_img );
            }
      }

      // Draw value marker
      if ( loc_slider_down || _anim_run_snap ) {

            // Draw snapping line
            unsigned int pos_diff;
            if ( _handle_pos > _handle_pos_index ) {
                  pos_diff = _handle_pos - _handle_pos_index;
            } else {
                  pos_diff = _handle_pos_index - _handle_pos;
            }
            if ( pos_diff > 5 ) {
                  const qreal x_mid ( width() / 2.0 );
                  qreal dx1 ( _marker_size.width() / 5.0 );
                  dx1 = qMax ( dx1, 1.5 );
                  qreal yy1 ( map_handle_pos_to_tick_pos ( _handle_pos       ) );
                  qreal yy2 ( map_handle_pos_to_tick_pos ( _handle_pos_index ) );
                  yy1 += 0.5;
                  yy2 += 0.5;
                  const qreal yym ( ( yy1 + yy2 ) / 2.0 );

                  const int num_pts ( 6 );
                  QPointF pts[num_pts] = {
                        QPointF ( x_mid + dx1, yy1 ),
                        QPointF ( x_mid      , yym ),
                        QPointF ( x_mid + dx1, yy2 ),
                        QPointF ( x_mid - dx1, yy2 ),
                        QPointF ( x_mid      , yym ),
                        QPointF ( x_mid - dx1, yy1 )
                  };
                  painter.setRenderHint ( QPainter::Antialiasing );
                  painter.setPen ( _snap_pen );
                  painter.setBrush ( _snap_brush );
                  painter.drawPolygon ( pts, num_pts );
            }

            // Draw value marker
            {
                  QPointF pp (
                        _marker_offset[0],
                        _marker_offset[1] + _handle_pos_index );
                  painter.drawPixmap (
                        pp, _pxm_marker->pixmap ( 0 ) );
            }
      }

      {
            // Draw value hint marker
            if ( _cursor_value_hinting ) {
                  QPointF pp (
                        _marker_offset[0],
                        _marker_offset[1] + _handle_pos_hint );
                  painter.drawPixmap (
                        pp, _pxm_marker->pixmap ( 1 ) );
            }
      }


      // Draw handle
      {
            int idx;
            if ( loc_slider_down ) {
00999                   idx = 4;
            } else {
                  idx = loc_has_focus ? 1 : 0;
                  if ( loc_under_mouse && loc_is_enabled ) {
                        idx += 2;
                  }
            }
            painter.drawPixmap (
                  _handle_rect.topLeft(),
                  _pxm_handle->pixmap ( idx ) );
      }
}


void
DS_Slider::update_pixmaps ( )
{
      _pxm_meta_bg.size = size();
      _pxm_meta_handle.size = _handle_rect.size();
      _pxm_meta_marker.size = _marker_size;

      _pxm_meta_bg.palette = palette();
      _pxm_meta_handle.palette = palette();
      _pxm_meta_marker.palette = palette();

      if ( _hub != 0 ) {
            _hub->update_pixmaps ( _pxm_bg, _pxm_meta_bg );
            _hub->update_pixmaps ( _pxm_handle, _pxm_meta_handle );
            _hub->update_pixmaps ( _pxm_marker, _pxm_meta_marker );
      }
}


void
DS_Slider::update_painter_utils ( )
{
      QColor col;
      {
            QColor col_bg ( palette().color ( QPalette::Window ) );
            QColor col_fg ( palette().color ( QPalette::WindowText ) );
            col = ::Wdg::Painter::col_mix ( col_bg, col_fg, 1, 2 );
      }
      col.setAlpha ( 70 );

      _snap_pen.setStyle ( Qt::NoPen );
      _snap_pen.setColor ( col );

      _snap_brush.setStyle ( Qt::SolidPattern );
      _snap_brush.setColor ( col );
}


void
DS_Slider::anim_stop ( )
{
      _anim_run_snap = false;
      _anim_timer.stop();
}


void
DS_Slider::anim_tick ( )
{
      bool do_update ( false );

      if ( _anim_run_snap ) {
            // Passed seconds since the animation start
            unsigned int msec ( abs ( _anim_snap_time.elapsed() ) );
            if ( msec >= _anim_snap_msec_max ) {
                  msec = _anim_snap_msec_max;
                  _anim_run_snap = false;
            }
            if ( anim_snap_tick ( msec ) ) {
                  do_update = true;
            }
            if ( _handle_pos == _handle_pos_index ) {
                  _anim_run_snap = false;
                  do_update = true;
            }
      }

      if ( !_anim_run_snap ) {
            anim_stop();
      }
      if ( do_update ) {
            update_cursor_mode();
            update();
      }
}


void
DS_Slider::anim_snap_start ( )
{
      if ( ( _handle_pos != _handle_pos_index ) ) {

            // Current speed
            double v_x0 ( 0.0 );

            if ( _anim_run_snap ) {
                  // A snapping annimation is already running.
                  unsigned int msec ( abs ( _anim_snap_time.elapsed() ) );
                  if ( msec < _anim_snap_msec_max ) {
                        // Acquire the current speed
                        v_x0 = double ( msec ) / 1000.0;
                        v_x0 = _cubic_curve.eval_speed ( v_x0 );
                  } else {
                        msec = _anim_snap_msec_max;
                  }
                  // Do a anim tick
                  anim_snap_tick ( msec );
            } else {
                  _anim_run_snap = true;
            }

            _anim_snap_time.start();
            if ( !_anim_timer.isActive() ) {
                  _anim_timer.start();
            }

            if ( _handle_pos_max > 0 ) {
                  unsigned int pos_diff;
                  if ( _handle_pos > _handle_pos_index ) {
                        pos_diff = _handle_pos - _handle_pos_index;
                  } else {
                        pos_diff = _handle_pos_index - _handle_pos;
                  }

                  _anim_snap_msec_max = ( 800 * pos_diff ) / _handle_pos_max;
            } else {
                  _anim_snap_msec_max = 500;
            }
            _anim_snap_msec_max = qBound ( 100, (int)_anim_snap_msec_max, 600 );

            _cubic_curve.set_params (
                  _handle_pos, v_x0,
                  _handle_pos_index,
                  _anim_snap_msec_max / 1000.0 );
      }
}


bool
DS_Slider::anim_snap_tick (
      unsigned int msec_n )
{
      unsigned int hpos ( _handle_pos_index );
      if ( msec_n <= _anim_snap_msec_max ) {
            // Calculate the position from the easing curve
            double dpos ( double ( msec_n ) / 1000.0 );
            dpos = _cubic_curve.eval ( dpos );
            dpos = std::floor ( dpos + 0.5 ); // Round
            if ( dpos > 0.0 ) {
                  hpos = static_cast < unsigned int > ( dpos );
            } else {
                  hpos = 0;
            }
      }

      return set_handle_pos ( hpos );
}


} // End of namespace

Generated by  Doxygen 1.6.0   Back to index