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

generic_motion_feedback.cc

/*
    Copyright (C) 1998-99 Paul Barton-Davis
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    $Id: generic_motion_feedback.cc,v 1.3 2004/02/22 23:04:01 taybin Exp $
*/

#include <cmath>
#include <unistd.h>

#include <gdk/gdkkeysyms.h>
#include <gtk--.h>
#include <gtkmmext/pix.h>
#include <gtkmmext/shaped_window.h>
#include <gtkmmext/generic_motion_feedback.h>


GenericMotionFeedback::GenericMotionFeedback (Gtk::Widget &widg,
                                    const char *widget_name, 
                                    Gtk::Adjustment *adj,
                                    gfloat yscale_factor) :
      _yscale (yscale_factor),
      widget (widg)

{
      set_homogeneous (false);

      if (adj == NULL) {
          i_own_my_adjustment = true;
          set_adjustment (new Gtk::Adjustment (0, 0, 10000, 1, 10, 0));
      } else {
          i_own_my_adjustment = false;
          set_adjustment (adj);
      }

      set_spacing (3);
      pack_start (widget, false, true);

      current_step = adjustment->gtkobj()->value;

      widget.add_events (GDK_BUTTON_PRESS_MASK|
                     GDK_BUTTON_RELEASE_MASK|
                     GDK_POINTER_MOTION_MASK|
                     GDK_ENTER_NOTIFY_MASK|
                     GDK_LEAVE_NOTIFY_MASK|
                     GDK_KEY_PRESS_MASK|
                     GDK_KEY_RELEASE_MASK);

      widget.set_flags (GTK_CAN_FOCUS);

      /* Proxy all important events on the pixwin to ourselves */

      widget.button_press_event.connect(SigC::slot(this,&GenericMotionFeedback::widget_button_press_event));
      widget.button_release_event.connect(SigC::slot(this,&GenericMotionFeedback::widget_button_release_event));
      widget.motion_notify_event.connect(SigC::slot(this,&GenericMotionFeedback::widget_motion_notify_event));
      widget.enter_notify_event.connect(SigC::slot(this,&GenericMotionFeedback::widget_enter_notify_event));
      widget.leave_notify_event.connect(SigC::slot(this,&GenericMotionFeedback::widget_leave_notify_event));
      widget.key_press_event.connect(SigC::slot(this,&GenericMotionFeedback::widget_key_press_event));
}

GenericMotionFeedback::~GenericMotionFeedback()

{
      if (i_own_my_adjustment) {
            delete adjustment;
      }
}

void
GenericMotionFeedback::set_adjustment (Gtk::Adjustment *adj)

{
      adjustment = adj;

      _lower = adj->gtkobj()->lower;
      _upper = adj->gtkobj()->upper;
      _range = _upper - _lower;
      step_inc = adj->gtkobj()->step_increment;
      page_inc = adj->gtkobj()->page_increment;
}

gint 
GenericMotionFeedback::widget_button_press_event (GdkEventButton *ev) 
{ 
      switch (ev->button) {
      case 2:
            return FALSE;  /* XXX why ? */

      case 1:
            grab_is_fine = false;
            break;
      case 3:
            grab_is_fine = true;
            break;
      }

      gtk_grab_add(GTK_WIDGET(widget.gtkobj()));
      grabbed_y = ev->y_root;
      grabbed_x = ev->x_root;

      /* XXX should we return TRUE ? */

      return FALSE;
}

gint 
GenericMotionFeedback::widget_button_release_event (GdkEventButton *ev) 
{ 
      switch (ev->button) {
      case 1:
            if (widget.has_grab()) {
                  if (!grab_is_fine) {
                        gtk_grab_remove
                              (GTK_WIDGET(widget.gtkobj()));
                  }
            }
            break;
            
      case 3:
            if (widget.has_grab()) {
                  if (grab_is_fine) {
                        gtk_grab_remove
                              (GTK_WIDGET(widget.gtkobj()));
                  }
            }
            break;
      }

      return Gtk::VBox::button_release_event_impl(ev); 
}

gint 
GenericMotionFeedback::widget_motion_notify_event (GdkEventMotion *ev) 
{ 
      gfloat multiplier;
      gfloat x_delta;
      gfloat y_delta;

      if(!widget.has_grab()) return Gtk::VBox::motion_notify_event_impl(ev); 

      multiplier = (ev->state & GDK_SHIFT_MASK ? 100 : 1) *
          (ev->state & GDK_CONTROL_MASK ? 10 : 1) * 
          (ev->state & GDK_MOD1_MASK ? 2 : 1);

      y_delta = grabbed_y - ev->y_root;
      grabbed_y = ev->y_root;

      x_delta = ev->x_root - grabbed_x;

      if (y_delta == 0) return TRUE;

      y_delta *= 1 + (x_delta/100);
      y_delta *= multiplier;
      y_delta /= _yscale;

      adjustment->set_value (adjustment->get_value() + 
                         ((grab_is_fine ? step_inc : page_inc) * y_delta));

      return TRUE;
}

gint 
GenericMotionFeedback::widget_enter_notify_event (GdkEventCrossing *ev) 

{
      widget.grab_focus();
      return FALSE;
}

gint 
GenericMotionFeedback::widget_leave_notify_event (GdkEventCrossing *ev) 

{
      widget.unset_flags (GTK_HAS_FOCUS);
      return FALSE;
}

gint 
GenericMotionFeedback::widget_key_press_event (GdkEventKey *ev) 

{
        gint retval = FALSE;
      gfloat curval;
      gfloat multiplier;

      multiplier = (ev->state & GDK_SHIFT_MASK ? 100 : 1) *
          (ev->state & GDK_CONTROL_MASK ? 10 : 1) * 
          (ev->state & GDK_MOD1_MASK ? 2 : 1);

      switch (ev->keyval) {
      case GDK_Page_Up:
              retval = TRUE;
            curval = adjustment->get_value();
            adjustment->set_value (curval + (multiplier * page_inc));
            break;

      case GDK_Page_Down:
              retval = TRUE;
            curval = adjustment->get_value();
            adjustment->set_value (curval - (multiplier * page_inc));
            break;

      case GDK_Up:
              retval = TRUE;
            curval = adjustment->get_value();
            adjustment->set_value (curval + (multiplier * step_inc));
            break;

      case GDK_Down:
              retval = TRUE;
            curval = adjustment->get_value();
            adjustment->set_value (curval - (multiplier * step_inc));
            break;

      case GDK_Home:
              retval = TRUE;
            adjustment->set_value (_lower);
            break;

      case GDK_End:
              retval = TRUE;
            adjustment->set_value (_upper);
            break;
      }
      
      if (retval) {
            gtk_signal_emit_stop_by_name (GTK_OBJECT(widget.gtkobj()),
                                    "key_press_event");
      }

      return retval;
}


Generated by  Doxygen 1.6.0   Back to index