Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

gtkenhancedscale.c

Go to the documentation of this file.
00001 /* GtkEnhancedScale - A gtk(h)scale with multiple sliders
00002 * Copyright (C) 2001 - Ronald Bultje
00003 * Copyright (C) 2001-2007 Dan Dennedy <dan@dennedy.org>
00004 * 
00005 * This program is free software; you can redistribute it and/or
00006 * modify it under the terms of the GNU General Public License
00007 * as published by the Free Software Foundation; either version 2
00008 * of the License, or (at your option) any later version.
00009 * 
00010 * This program is distributed in the hope that it will be useful,
00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013 * GNU General Public License for more details.
00014 * 
00015 * You should have received a copy of the GNU General Public License
00016 * along with this program; if not, write to the Free Software
00017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 
00018 * USA.
00019 */
00020 
00021 /* Some code used was taken from GtkScale and GtkRange, all part
00022  * of the Gimp Toolkit (Gtk+), http://www.gtk.org/
00023  */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #include <config.h>
00027 #endif
00028 
00029 #include <gtk/gtkmain.h>
00030 #include <gtk/gtksignal.h>
00031 #include <gdk/gdkkeysyms.h>
00032 #include <gtk/gtkadjustment.h>
00033 #include "gtkenhancedscale.h"
00034 #include <string.h>
00035 #include <stdio.h>
00036 #include <malloc.h>
00037 #include <math.h>
00038 
00039 #undef FANCY
00040 #define ENHANCED_SCALE_CLASS(w)  GTK_ENHANCED_SCALE_CLASS ( G_OBJECT_GET_CLASS( G_OBJECT( w )  ) ) 
00041 // #define DEBUG
00042 
00043 static void gtk_enhanced_scale_class_init ( GtkEnhancedScaleClass *klass );
00044 static void gtk_enhanced_scale_init ( GtkEnhancedScale *enhanced_scale );
00045 static void gtk_enhanced_scale_destroy ( GtkObject *object );
00046 static void gtk_enhanced_scale_realize ( GtkWidget *widget );
00047 static void gtk_enhanced_scale_unrealize ( GtkWidget *widget );
00048 static void gtk_enhanced_scale_size_request ( GtkWidget *widget, GtkRequisition *requisition );
00049 static void gtk_enhanced_scale_size_allocate ( GtkWidget *widget, GtkAllocation *allocation );
00050 static gint gtk_enhanced_scale_expose ( GtkWidget *widget, GdkEventExpose *event );
00051 static void gtk_enhanced_scale_pos_trough ( GtkEnhancedScale *enhanced_scale, gint *x, gint *y, gint *w, gint *h );
00052 static void gtk_enhanced_scale_draw ( GtkWidget *widget, GdkRectangle *area );
00053 static void gtk_enhanced_scale_draw_slider ( GtkEnhancedScale *enhanced_scale, gint i );
00054 static void gtk_enhanced_scale_draw_trough ( GtkEnhancedScale *enhanced_scale );
00055 static void gtk_enhanced_scale_slider_update ( GtkEnhancedScale *enhanced_scale, gint i );
00056 static void gtk_enhanced_scale_trough_hdims ( GtkEnhancedScale *enhanced_scale, gint *left, gint *right, gint i );
00057 static void gtk_enhanced_scale_get_slider_position( GtkEnhancedScale *enhanced_scale, gint *x, gint *y, gint i );
00058 static gint gtk_enhanced_scale_get_trough_border( GtkWidget *widget );
00059 static gint gtk_enhanced_scale_get_slider_width( GtkWidget *widget );
00060 static gint gtk_enhanced_scale_button_press( GtkWidget *widget, GdkEventButton *event );
00061 static gint gtk_enhanced_scale_button_release( GtkWidget *widget, GdkEventButton *event );
00062 static gint gtk_enhanced_scale_motion_notify( GtkWidget *widget, GdkEventMotion *event );
00063 static void gtk_enhanced_scale_motion_x( GtkEnhancedScale *enhanced_scale, gint x, gint i );
00064 static gint gtk_enhanced_scale_key_press( GtkWidget *widget, GdkEventKey *event );
00065 static gint gtk_enhanced_scale_enter_notify( GtkWidget *widget, GdkEventCrossing *event );
00066 static gint gtk_enhanced_scale_leave_notify( GtkWidget *widget, GdkEventCrossing *event );
00067 static gint gtk_enhanced_scale_focus_in( GtkWidget *widget, GdkEventFocus *event );
00068 static gint gtk_enhanced_scale_focus_out( GtkWidget *widget, GdkEventFocus *event );
00069 static void gtk_enhanced_scale_style_set( GtkWidget *widget, GtkStyle *style );
00070 static void gtk_enhanced_scale_adjustment_value_changed( GtkAdjustment *adjustment, gpointer data );
00071 
00072 static GtkWidgetClass *parent_class = NULL;
00073 
00074 /* ================================================================= */
00075 
00076 GType gtk_enhanced_scale_get_type ()
00077 {
00078     static GType enhanced_scale_type = 0;
00079 
00080     if ( !enhanced_scale_type )
00081     {
00082         GtkTypeInfo enhanced_scale_info =
00083             {
00084                 "GtkEnhancedScale",
00085                 sizeof ( GtkEnhancedScale ),
00086                 sizeof ( GtkEnhancedScaleClass ),
00087                 ( GtkClassInitFunc ) gtk_enhanced_scale_class_init,
00088                 ( GtkObjectInitFunc ) gtk_enhanced_scale_init,
00089                 NULL,
00090                 NULL,
00091             };
00092         enhanced_scale_type = gtk_type_unique ( gtk_widget_get_type (),
00093                                                 &enhanced_scale_info );
00094     }
00095     return enhanced_scale_type;
00096 }
00097 
00098 static void gtk_enhanced_scale_class_init ( GtkEnhancedScaleClass *class )
00099 {
00100     GtkObjectClass *object_class;
00101     GtkWidgetClass *widget_class;
00102 
00103     object_class = ( GtkObjectClass* ) class;
00104     widget_class = ( GtkWidgetClass* ) class;
00105     parent_class = gtk_type_class ( gtk_widget_get_type () );
00106 
00107     object_class->destroy = gtk_enhanced_scale_destroy;
00108 
00109     widget_class->realize = gtk_enhanced_scale_realize;
00110     widget_class->unrealize = gtk_enhanced_scale_unrealize;
00111     widget_class->expose_event = gtk_enhanced_scale_expose;
00112     widget_class->size_request = gtk_enhanced_scale_size_request;
00113     widget_class->size_allocate = gtk_enhanced_scale_size_allocate;
00114 
00115     /* Events and their corresponding reaction-functions */
00116     widget_class->button_press_event = gtk_enhanced_scale_button_press;
00117     widget_class->button_release_event = gtk_enhanced_scale_button_release;
00118     widget_class->motion_notify_event = gtk_enhanced_scale_motion_notify;
00119     widget_class->key_press_event = gtk_enhanced_scale_key_press;
00120     widget_class->enter_notify_event = gtk_enhanced_scale_enter_notify;
00121     widget_class->leave_notify_event = gtk_enhanced_scale_leave_notify;
00122     widget_class->focus_in_event = gtk_enhanced_scale_focus_in;
00123     widget_class->focus_out_event = gtk_enhanced_scale_focus_out;
00124     widget_class->style_set = gtk_enhanced_scale_style_set;
00125 
00126     class->slider_width = 32;
00127     class->trough_width = 10;
00128     class->trough = 1;
00129     class->slider = 2;
00130     class->arrow_width = 20;
00131     class->arrow_height = 10;
00132 }
00133 
00134 static void gtk_enhanced_scale_init ( GtkEnhancedScale *enhanced_scale )
00135 {
00136     enhanced_scale->in_child = 0;
00137     enhanced_scale->click_child = 0;
00138     enhanced_scale->active_slider = 0; /* default */
00139     enhanced_scale->clicked_slider = -1; /* none */
00140     enhanced_scale->x_click_point = 0;
00141     enhanced_scale->breaks = NULL;
00142 
00143     GTK_WIDGET_SET_FLAGS ( GTK_WIDGET( enhanced_scale ), GTK_CAN_FOCUS );
00144 }
00145 
00146 GtkWidget* gtk_enhanced_scale_new ( GtkObject *adjustment[],
00147                                     gint num_adjustments )
00148 {
00149     GtkEnhancedScale * enhanced_scale;
00150     int i;
00151 
00152     for ( i = 0;i < num_adjustments;i++ )
00153     {
00154         if ( adjustment[ i ] == NULL )
00155             return NULL;
00156     }
00157 
00158     enhanced_scale = gtk_type_new ( gtk_enhanced_scale_get_type () );
00159     enhanced_scale->adjustment = adjustment;
00160     enhanced_scale->num_adjustments = num_adjustments;
00161 
00162     enhanced_scale->handler_id = malloc( num_adjustments * sizeof(*enhanced_scale->handler_id) );
00163 
00164     for ( i = 0;i < num_adjustments;i++ )
00165     {
00166         enhanced_scale->handler_id[ i ] = g_signal_connect ( adjustment[ i ], "value_changed",
00167                                           G_CALLBACK( gtk_enhanced_scale_adjustment_value_changed ),
00168                                           ( gpointer ) enhanced_scale );
00169     }
00170 
00171     return GTK_WIDGET ( enhanced_scale );
00172 }
00173 
00174 static void gtk_enhanced_scale_destroy ( GtkObject *object )
00175 {
00176     GtkEnhancedScale * enhanced_scale;
00177     gint i;
00178 
00179     g_return_if_fail ( object != NULL );
00180     g_return_if_fail ( GTK_IS_ENHANCED_SCALE ( object ) );
00181 
00182     enhanced_scale = GTK_ENHANCED_SCALE ( object );
00183 #ifdef DEBUG
00184 
00185     printf( "Received destroy signal, let's disappear!\n" );
00186 #endif
00187 
00188     for ( i = 0;i < enhanced_scale->num_adjustments;i++ )
00189         gtk_signal_disconnect( enhanced_scale->adjustment[ i ], enhanced_scale->handler_id[ i ] );
00190 
00191     if ( enhanced_scale->breaks != NULL )
00192         g_array_free( enhanced_scale->breaks, TRUE );
00193 
00194     if ( GTK_OBJECT_CLASS ( parent_class ) ->destroy )
00195         ( * GTK_OBJECT_CLASS ( parent_class ) ->destroy ) ( object );
00196 #ifdef DEBUG
00197 
00198     printf( "Finished destroy signal\n" );
00199 #endif
00200 }
00201 
00202 static void gtk_enhanced_scale_realize ( GtkWidget *widget )
00203 {
00204     GdkWindowAttr attributes;
00205     GtkEnhancedScale *enhanced_scale;
00206     gint attributes_mask;
00207     gint x = 0, y = 0, w = 0, h = 0;
00208     gint slider_width;
00209     gint i;
00210 
00211     g_return_if_fail ( widget != NULL );
00212     g_return_if_fail ( GTK_IS_ENHANCED_SCALE ( widget ) );
00213 
00214     slider_width = gtk_enhanced_scale_get_slider_width( widget );
00215 
00216     GTK_WIDGET_SET_FLAGS ( widget, GTK_REALIZED );
00217     enhanced_scale = GTK_ENHANCED_SCALE ( widget );
00218 
00219     attributes.x = widget->allocation.x;
00220     attributes.y = widget->allocation.y;
00221     attributes.width = widget->allocation.width;
00222     attributes.height = widget->allocation.height;
00223     attributes.wclass = GDK_INPUT_OUTPUT;
00224     attributes.window_type = GDK_WINDOW_CHILD;
00225     attributes.event_mask = gtk_widget_get_events ( widget ) |
00226                             GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK |
00227                             GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
00228                             GDK_POINTER_MOTION_HINT_MASK;
00229     attributes.visual = gtk_widget_get_visual ( widget );
00230     attributes.colormap = gtk_widget_get_colormap ( widget );
00231     attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
00232     widget->window = gdk_window_new ( widget->parent->window, &attributes, attributes_mask );
00233 
00234     gtk_enhanced_scale_pos_trough ( enhanced_scale, &x, &y, &w, &h );
00235     attributes.x = x;
00236     attributes.y = y;
00237     attributes.width = w;
00238     attributes.height = h;
00239     attributes.wclass = GDK_INPUT_OUTPUT;
00240     attributes.window_type = GDK_WINDOW_CHILD;
00241     attributes.event_mask = gtk_widget_get_events ( widget ) |
00242                             ( GDK_EXPOSURE_MASK |
00243                               GDK_BUTTON_PRESS_MASK |
00244                               GDK_BUTTON_RELEASE_MASK |
00245                               GDK_ENTER_NOTIFY_MASK |
00246                               GDK_LEAVE_NOTIFY_MASK );
00247     attributes.visual = gtk_widget_get_visual ( widget );
00248     attributes.colormap = gtk_widget_get_colormap ( widget );
00249     attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
00250 #ifdef DEBUG
00251 
00252     printf( "Scale trough properties - x: %d, y: %d, w: %d, h: %d\n", x, y, w, h );
00253 #endif
00254 
00255     enhanced_scale->trough = gdk_window_new ( widget->window, &attributes, attributes_mask );
00256 
00257     enhanced_scale->slider = malloc( enhanced_scale->num_adjustments * sizeof(*enhanced_scale->handler_id) );
00258     attributes.width = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width;
00259     attributes.height = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height;
00260     attributes.event_mask |= ( GDK_BUTTON_MOTION_MASK |
00261                                GDK_POINTER_MOTION_HINT_MASK );
00262     enhanced_scale->slider[ 0 ] = gdk_window_new ( enhanced_scale->trough,
00263                                   &attributes, attributes_mask );
00264     attributes.y += ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height + ENHANCED_SCALE_CLASS ( enhanced_scale ) ->trough_width - 1;
00265     attributes.width = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2;
00266     for ( i = 1;i < enhanced_scale->num_adjustments;i++ )
00267         enhanced_scale->slider[ i ] = gdk_window_new ( enhanced_scale->trough,
00268                                       &attributes, attributes_mask );
00269 
00270     widget->style = gtk_style_attach ( widget->style, widget->window );
00271 
00272 
00273     for ( i = 0;i < enhanced_scale->num_adjustments;i++ )
00274         gdk_window_set_user_data ( enhanced_scale->slider[ i ], widget );
00275     gdk_window_set_user_data ( enhanced_scale->trough, widget );
00276     gdk_window_set_user_data ( widget->window, widget );
00277 
00278     for ( i = 0;i < enhanced_scale->num_adjustments;i++ )
00279         gtk_style_set_background ( widget->style, enhanced_scale->slider[ i ], GTK_STATE_NORMAL );
00280     gtk_style_set_background ( widget->style, enhanced_scale->trough, GTK_STATE_NORMAL );
00281     gtk_style_set_background ( widget->style, widget->window, GTK_STATE_NORMAL );
00282 
00283     for ( i = 0;i < enhanced_scale->num_adjustments;i++ )
00284     {
00285         gtk_enhanced_scale_slider_update ( GTK_ENHANCED_SCALE ( widget ), i );
00286         gdk_window_show ( enhanced_scale->slider[ i ] );
00287     }
00288     gdk_window_show ( enhanced_scale->trough );
00289 }
00290 
00291 static void gtk_enhanced_scale_unrealize ( GtkWidget *widget )
00292 {
00293     GtkEnhancedScale * enhanced_scale;
00294     int i;
00295 
00296     g_return_if_fail ( widget != NULL );
00297     g_return_if_fail ( GTK_IS_ENHANCED_SCALE ( widget ) );
00298 
00299     enhanced_scale = GTK_ENHANCED_SCALE ( widget );
00300 
00301     for ( i = 0;i < enhanced_scale->num_adjustments;i++ )
00302     {
00303         if ( enhanced_scale->slider[ i ] )
00304         {
00305             gdk_window_set_user_data ( enhanced_scale->slider[ i ], NULL );
00306             gdk_window_destroy ( enhanced_scale->slider[ i ] );
00307             enhanced_scale->slider[ i ] = NULL;
00308         }
00309     }
00310     if ( enhanced_scale->trough )
00311     {
00312         gdk_window_set_user_data ( enhanced_scale->trough, NULL );
00313         gdk_window_destroy ( enhanced_scale->trough );
00314         enhanced_scale->trough = NULL;
00315     }
00316 
00317     gdk_window_set_user_data ( widget->window, NULL );
00318 #ifdef DEBUG
00319 
00320     printf( "Received unrealize signal, let's disappear!\n" );
00321 #endif
00322 
00323     if ( GTK_WIDGET_CLASS ( parent_class ) ->unrealize )
00324         ( * GTK_WIDGET_CLASS ( parent_class ) ->unrealize ) ( widget );
00325 }
00326 
00327 static void gtk_enhanced_scale_size_request ( GtkWidget *widget,
00328         GtkRequisition *requisition )
00329 {
00330     GtkEnhancedScale * enhanced_scale;
00331     gint trough_border, slider_width;
00332 
00333     enhanced_scale = GTK_ENHANCED_SCALE ( widget );
00334 
00335 #ifdef DEBUG
00336 
00337     printf( "Received size_request signal\n" );
00338 #endif
00339 
00340     trough_border = gtk_enhanced_scale_get_trough_border( GTK_WIDGET( enhanced_scale ) );
00341     slider_width = gtk_enhanced_scale_get_slider_width( GTK_WIDGET( enhanced_scale ) );
00342 
00343     requisition->width = ( ENHANCED_SCALE_CLASS( enhanced_scale ) ->arrow_width + trough_border ) * 4;
00344     requisition->height = ( slider_width + trough_border * 2 );
00345 
00346 }
00347 
00348 static void gtk_enhanced_scale_size_allocate ( GtkWidget *widget,
00349         GtkAllocation *allocation )
00350 {
00351     GtkEnhancedScale * enhanced_scale;
00352 
00353     g_return_if_fail ( widget != NULL );
00354     g_return_if_fail ( GTK_IS_ENHANCED_SCALE ( widget ) );
00355     g_return_if_fail ( allocation != NULL );
00356 
00357     widget->allocation = *allocation;
00358     enhanced_scale = GTK_ENHANCED_SCALE ( widget );
00359 
00360 #ifdef DEBUG
00361 
00362     printf( "Received size allocate signal: %d\n", allocation->width );
00363 #endif
00364 
00365     if ( GTK_WIDGET_REALIZED ( widget ) )
00366     {
00367         gint i, x, y, width, height;
00368 
00369         gdk_window_move_resize ( widget->window,
00370                                  allocation->x, allocation->y,
00371                                  allocation->width, allocation->height );
00372 
00373         x = allocation->x;
00374         y = allocation->y;
00375         width = allocation->width;
00376         height = allocation->height;
00377         gtk_enhanced_scale_pos_trough( enhanced_scale, &x, &y, &width, &height );
00378         gdk_window_move_resize ( enhanced_scale->trough, x, y, width, height );
00379 
00380         for ( i = 0; i < enhanced_scale->num_adjustments; i++ )
00381             gtk_enhanced_scale_slider_update( enhanced_scale, i );
00382 
00383     }
00384 
00385 }
00386 
00387 static gint gtk_enhanced_scale_expose ( GtkWidget *widget, GdkEventExpose *event )
00388 {
00389     GtkEnhancedScale * enhanced_scale;
00390     GdkRectangle area;
00391 
00392     g_return_val_if_fail ( widget != NULL, FALSE );
00393     g_return_val_if_fail ( GTK_IS_ENHANCED_SCALE ( widget ), FALSE );
00394     g_return_val_if_fail ( event != NULL, FALSE );
00395     g_return_val_if_fail ( widget->window != NULL, FALSE );
00396 
00397     if ( event->count > 0 )
00398         return FALSE;
00399 
00400     enhanced_scale = GTK_ENHANCED_SCALE ( widget );
00401 
00402     gdk_window_clear_area ( widget->window, 0, 0,
00403                             widget->allocation.width, widget->allocation.height );
00404 
00405     /* This would be the place to draw it */
00406     area.x = 0;
00407     area.y = 0;
00408     area.width = widget->allocation.width;
00409     area.height = widget->allocation.height;
00410     gtk_enhanced_scale_draw ( widget, &area );
00411 
00412     return FALSE;
00413 }
00414 
00415 /* =========================================================================
00416  * Paint functions
00417  * Some were directly taken from GtkScale, GtkHScale and GtkRange
00418  */
00419 
00420 static void gtk_enhanced_scale_draw ( GtkWidget *widget, GdkRectangle *area )
00421 {
00422     GtkEnhancedScale * enhanced_scale;
00423     GdkRectangle tmp_area;
00424     gint x = 0, y = 0, w = 0, h = 0;
00425 
00426     g_return_if_fail ( widget != NULL );
00427     g_return_if_fail ( GTK_IS_ENHANCED_SCALE ( widget ) );
00428 #ifdef DEBUG
00429 
00430     printf( "Trying to draw enhanced_scale\n" );
00431 #endif
00432 
00433     if ( GTK_WIDGET_VISIBLE ( widget ) && GTK_WIDGET_MAPPED ( widget ) )
00434     {
00435         gint i;
00436 #ifdef DEBUG
00437 
00438         printf( "Drawing enhanced_scale\n" );
00439 #endif
00440 
00441         enhanced_scale = GTK_ENHANCED_SCALE ( widget );
00442 
00443         gtk_enhanced_scale_pos_trough ( GTK_ENHANCED_SCALE ( widget ), &x, &y, &w, &h );
00444 
00445         tmp_area.x = x;
00446         tmp_area.y = y;
00447         tmp_area.width = w;
00448         tmp_area.height = h;
00449 
00450 #ifdef DEBUG
00451 
00452         printf( "Drawing enhanced_scale with size = %d\n", w );
00453 #endif
00454         //if (gdk_rectangle_intersect (area, &tmp_area, area))
00455         {
00456             for ( i = 0;i < enhanced_scale->num_adjustments;i++ )
00457             {
00458                 gtk_enhanced_scale_slider_update ( enhanced_scale, i );
00459                 gtk_enhanced_scale_draw_slider ( enhanced_scale, i );
00460             }
00461             gtk_enhanced_scale_draw_trough ( enhanced_scale );
00462         }
00463     }
00464 }
00465 
00466 static void gtk_enhanced_scale_draw_trough ( GtkEnhancedScale *enhanced_scale )
00467 {
00468     g_return_if_fail ( enhanced_scale != NULL );
00469     g_return_if_fail ( GTK_IS_ENHANCED_SCALE( enhanced_scale ) );
00470 
00471     if ( enhanced_scale->trough )
00472     {
00473         gint x, x2, y, b;
00474         gint left, right;
00475 
00476 #ifdef DEBUG
00477 
00478         printf( "Drawing trough: %d\n", GTK_WIDGET( enhanced_scale ) ->allocation.width - 2 );
00479 #endif
00480 
00481         if ( enhanced_scale->num_adjustments > 1 )
00482         {
00483             /* trough */
00484             b = gtk_enhanced_scale_get_trough_border( GTK_WIDGET( enhanced_scale ) );
00485             gtk_enhanced_scale_trough_hdims ( enhanced_scale, &left, &right, 0 );
00486 
00487 #ifdef FANCY
00488             gtk_paint_box (GTK_WIDGET (enhanced_scale)->style,
00489                                  enhanced_scale->trough, GTK_STATE_NORMAL,
00490                                  GTK_SHADOW_IN, NULL, GTK_WIDGET(enhanced_scale),
00491                                  "trough", ENHANCED_SCALE_CLASS (enhanced_scale)->arrow_width/2,
00492                                  ENHANCED_SCALE_CLASS (enhanced_scale)->arrow_height + b, right-left + 4,
00493                                  ENHANCED_SCALE_CLASS (enhanced_scale)->trough_width);
00494 #endif
00495                             
00496             gdk_draw_rectangle( enhanced_scale->trough, GTK_WIDGET ( enhanced_scale ) ->style->mid_gc[ GTK_STATE_NORMAL ],
00497                                 TRUE, ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2 + 1,
00498                                 ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height + b + 1,
00499                                 right - left + 1,
00500                                 ENHANCED_SCALE_CLASS ( enhanced_scale ) ->trough_width - 2
00501                               );
00502 
00503             /* selected area */
00504             gtk_enhanced_scale_get_slider_position( enhanced_scale, &x, &y, 1 );
00505             gtk_enhanced_scale_get_slider_position( enhanced_scale, &x2, &y, 2 );
00506             if ( x2 - x - ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2 > 0 )
00507             {
00508                 gdk_draw_rectangle( enhanced_scale->trough,
00509                                     GTK_WIDGET ( enhanced_scale ) ->style->mid_gc[ GTK_STATE_SELECTED ],
00510                                     TRUE,
00511                                     x + ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2,
00512                                     ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height + b + 1,
00513                                     x2 - x - ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2,
00514                                     ENHANCED_SCALE_CLASS ( enhanced_scale ) ->trough_width - 2
00515                                   );
00516             }
00517         }
00518         else
00519         {
00520             /* trough */
00521             b = gtk_enhanced_scale_get_trough_border( GTK_WIDGET( enhanced_scale ) );
00522             gtk_enhanced_scale_trough_hdims ( enhanced_scale, &left, &right, 0 );
00523 
00524 #ifdef FANCY
00525             gtk_paint_box (GTK_WIDGET (enhanced_scale)->style,
00526                                  enhanced_scale->trough, GTK_STATE_NORMAL,
00527                                  GTK_SHADOW_IN, NULL, GTK_WIDGET(enhanced_scale),
00528                                  "trough", ENHANCED_SCALE_CLASS (enhanced_scale)->arrow_width/2,
00529                                  ENHANCED_SCALE_CLASS (enhanced_scale)->arrow_height + b, right-left + 4,
00530                                  ENHANCED_SCALE_CLASS (enhanced_scale)->trough_width);
00531 #endif
00532                                  
00533             gdk_draw_rectangle( enhanced_scale->trough, GTK_WIDGET ( enhanced_scale ) ->style->mid_gc[ GTK_STATE_NORMAL ],
00534                                 TRUE, ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2 + 1,
00535                                 ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height + b + 1,
00536                                 right - left + 1,
00537                                 ENHANCED_SCALE_CLASS ( enhanced_scale ) ->trough_width - 2
00538                               );
00539         }
00540 
00541         /* scene breaks */
00542         if ( enhanced_scale->breaks != NULL )
00543             if ( enhanced_scale->breaks->len > 1 )
00544                 for ( x2 = 0; x2 < ( enhanced_scale->breaks->len - 1 ); x2++ )
00545                 {
00546                     gint left, right;
00547 
00548                     gtk_enhanced_scale_trough_hdims ( enhanced_scale, &left, &right, 0 );
00549                     x = left + ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2;
00550                     x += ( ( right - left ) * ( g_array_index( enhanced_scale->breaks, gint, x2 ) -
00551                                                 GTK_ADJUSTMENT( enhanced_scale->adjustment[ 0 ] ) ->lower ) /
00552                            ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ 0 ] ) ->upper -
00553                              GTK_ADJUSTMENT( enhanced_scale->adjustment[ 0 ] ) ->lower -
00554                              GTK_ADJUSTMENT( enhanced_scale->adjustment[ 0 ] ) ->page_size ) );
00555                     gdk_draw_line ( enhanced_scale->trough, GTK_WIDGET ( enhanced_scale ) ->style->light_gc[ GTK_STATE_NORMAL ],
00556                                     x,
00557                                     ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height + b,
00558                                     x,
00559                                     ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height + b + ENHANCED_SCALE_CLASS ( enhanced_scale ) ->trough_width - 1
00560                                   );
00561 
00562                 }
00563 #ifdef FANCY
00564         /* frame position */
00565         gtk_enhanced_scale_get_slider_position( enhanced_scale, &x, &y, 0 );
00566         gtk_paint_box (GTK_WIDGET (enhanced_scale)->style,
00567                          enhanced_scale->trough, GTK_STATE_NORMAL,
00568                          GTK_SHADOW_OUT, NULL, GTK_WIDGET(enhanced_scale),
00569                          NULL,
00570                          x + ENHANCED_SCALE_CLASS (enhanced_scale)->arrow_width/2 - 1,
00571                          ENHANCED_SCALE_CLASS (enhanced_scale)->arrow_height + b - 1,
00572                          3,
00573                          ENHANCED_SCALE_CLASS (enhanced_scale)->trough_width);
00574 #endif
00575     }
00576 }
00577 
00578 static void gtk_enhanced_scale_draw_slider ( GtkEnhancedScale *enhanced_scale, gint i )
00579 {
00580     GtkStateType state_type;
00581     GdkPoint points[ 3 ];
00582 
00583     g_return_if_fail ( enhanced_scale != NULL );
00584     g_return_if_fail ( GTK_IS_ENHANCED_SCALE ( enhanced_scale ) );
00585     g_return_if_fail ( i >= 0 );
00586     g_return_if_fail ( i < enhanced_scale->num_adjustments );
00587 
00588     if ( enhanced_scale->slider[ i ] )
00589     {
00590 #ifdef DEBUG
00591         printf( "Drawing slider %d\n", i );
00592 #endif
00593 
00594         if ( ( enhanced_scale->in_child == ENHANCED_SCALE_CLASS ( enhanced_scale ) ->slider ) ||
00595                 ( enhanced_scale->click_child == ENHANCED_SCALE_CLASS ( enhanced_scale ) ->slider ) )
00596             state_type = GTK_STATE_SELECTED;
00597         else
00598             state_type = GTK_STATE_SELECTED;
00599 
00600         switch ( i )
00601         {
00602         case 0:
00603             gdk_draw_line ( enhanced_scale->slider[ i ], GTK_WIDGET ( enhanced_scale ) ->style->dark_gc[ GTK_STATE_NORMAL ],
00604                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width,
00605                             0,
00606                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2 + 1,
00607                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height - 1
00608                           );
00609             gdk_draw_line ( enhanced_scale->slider[ i ], GTK_WIDGET ( enhanced_scale ) ->style->dark_gc[ GTK_STATE_NORMAL ],
00610                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width + 1,
00611                             1,
00612                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2 + 2,
00613                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height
00614                           );
00615             points[ 0 ].x = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width;
00616             points[ 0 ].y = 0;
00617             points[ 1 ].x = 0;
00618             points[ 1 ].y = 0;
00619             points[ 2 ].x = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2;
00620             points[ 2 ].y = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height;
00621             break;
00622         case 1:
00623             gdk_draw_line ( enhanced_scale->slider[ i ], GTK_WIDGET ( enhanced_scale ) ->style->dark_gc[ GTK_STATE_NORMAL ],
00624                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2 - 1,
00625                             2,
00626                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2 - 1,
00627                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height - 1
00628                           );
00629             gdk_draw_line ( enhanced_scale->slider[ i ], GTK_WIDGET ( enhanced_scale ) ->style->dark_gc[ GTK_STATE_NORMAL ],
00630                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2 - 1,
00631                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height - 1,
00632                             2,
00633                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height - 1
00634                           );
00635             points[ 0 ].x = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2 - 1;
00636             points[ 0 ].y = 0;
00637             points[ 1 ].x = 0;
00638             points[ 1 ].y = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height - 1;
00639             points[ 2 ].x = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2 - 1;
00640             points[ 2 ].y = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height - 1;
00641             break;
00642         case 2:
00643             gdk_draw_line ( enhanced_scale->slider[ i ], GTK_WIDGET ( enhanced_scale ) ->style->dark_gc[ GTK_STATE_NORMAL ],
00644                             2,
00645                             2,
00646                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2 - 1,
00647                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height - 1
00648                           );
00649             gdk_draw_line ( enhanced_scale->slider[ i ], GTK_WIDGET ( enhanced_scale ) ->style->dark_gc[ GTK_STATE_NORMAL ],
00650                             1,
00651                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height - 1,
00652                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2,
00653                             ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height - 1
00654                           );
00655             points[ 0 ].x = 0;
00656             points[ 0 ].y = 0;
00657             points[ 1 ].x = 0;
00658             points[ 1 ].y = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height - 1;
00659             points[ 2 ].x = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_width / 2 - 1;
00660             points[ 2 ].y = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->arrow_height - 1;
00661             break;
00662         default:
00663             return ;
00664         }
00665         gdk_draw_polygon( enhanced_scale->slider[ i ],
00666                           GTK_WIDGET( enhanced_scale ) ->style->bg_gc[ state_type ], TRUE, points, 3 );
00667     }
00668 }
00669 
00670 /* =========================================================================
00671  * Functions to make life easier
00672  * positioning functions etc, mostly directly taken from GtkScale, GtkHScale
00673  * and GtkRange
00674  */
00675 
00676 static void gtk_enhanced_scale_pos_trough ( GtkEnhancedScale *enhanced_scale,
00677         gint *x, gint *y, gint *w, gint *h )
00678 {
00679     GtkWidget * widget;
00680     gint trough_border, slider_width;
00681 
00682     g_return_if_fail ( enhanced_scale != NULL );
00683     g_return_if_fail ( GTK_IS_ENHANCED_SCALE ( enhanced_scale ) );
00684     g_return_if_fail ( ( x != NULL ) && ( y != NULL ) && ( w != NULL ) && ( h != NULL ) );
00685 
00686     widget = GTK_WIDGET ( enhanced_scale );
00687     trough_border = gtk_enhanced_scale_get_trough_border( GTK_WIDGET( enhanced_scale ) );
00688     slider_width = gtk_enhanced_scale_get_slider_width( GTK_WIDGET( enhanced_scale ) );
00689 
00690     *w = widget->allocation.width - 2;
00691     *h = ( slider_width + trough_border * 2 );
00692     *x = 1;
00693     *y = ( widget->allocation.height - *h ) / 2;
00694 }
00695 
00696 static void gtk_enhanced_scale_slider_update ( GtkEnhancedScale *enhanced_scale, gint i )
00697 {
00698     /* i is the number of the adjustment */
00699     gint left;
00700     gint right;
00701     gint x;
00702     gint trough_border;
00703 
00704     g_return_if_fail ( enhanced_scale != NULL );
00705     g_return_if_fail ( GTK_IS_ENHANCED_SCALE ( enhanced_scale ) );
00706     g_return_if_fail ( i >= 0 );
00707     g_return_if_fail ( i < enhanced_scale->num_adjustments );
00708 
00709     trough_border = gtk_enhanced_scale_get_trough_border( GTK_WIDGET( enhanced_scale ) );
00710 
00711     if ( GTK_WIDGET_REALIZED ( enhanced_scale ) )
00712     {
00713         gtk_enhanced_scale_trough_hdims ( enhanced_scale, &left, &right, i );
00714         x = left;
00715 #ifdef DEBUG
00716 
00717         printf( "Updating slider %d\n", i );
00718 #endif
00719 
00720         if ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->value <
00721                 GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->lower )
00722         {
00723             GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->value =
00724                 GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->lower;
00725             g_signal_emit_by_name ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ), "value_changed" );
00726         }
00727         else if ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->value >
00728                   GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->upper )
00729         {
00730             GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->value =
00731                 GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->upper;
00732             g_signal_emit_by_name( GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ), "value_changed" );
00733         }
00734         if ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->lower !=
00735                 ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->upper -
00736                   GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->page_size ) )
00737         {
00738             x += ( ( right - left ) * ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->value -
00739                                         GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->lower ) /
00740                    ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->upper -
00741                      GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->lower -
00742                      GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->page_size ) );
00743         }
00744         /*
00745         if (GTK_ADJUSTMENT(enhanced_scale->adjustment[i])->lower !=
00746             (GTK_ADJUSTMENT(enhanced_scale->adjustment[i])->upper))
00747         {
00748             x += ((right - left) * (GTK_ADJUSTMENT(enhanced_scale->adjustment[i])->value -
00749                 GTK_ADJUSTMENT(enhanced_scale->adjustment[i])->lower) /
00750                 (GTK_ADJUSTMENT(enhanced_scale->adjustment[i])->upper -
00751                 GTK_ADJUSTMENT(enhanced_scale->adjustment[i])->lower));
00752         }
00753         */
00754         if ( x < left )
00755             x = left;
00756         else if ( x > right )
00757             x = right;
00758 
00759         gdk_window_move ( enhanced_scale->slider[ i ], x,
00760                           trough_border + ( i > 0 ? ENHANCED_SCALE_CLASS( enhanced_scale ) ->arrow_height + ENHANCED_SCALE_CLASS( enhanced_scale ) ->trough_width - 1 : 0 ) );
00761     }
00762 }
00763 
00764 static void gtk_enhanced_scale_trough_hdims ( GtkEnhancedScale *enhanced_scale, gint *left, gint *right, gint i )
00765 {
00766     gint trough_width;
00767     gint slider_length;
00768     gint tleft;
00769     gint tright;
00770     gint trough_border;
00771 
00772     g_return_if_fail ( enhanced_scale != NULL );
00773 
00774     gdk_window_get_size ( enhanced_scale->trough, &trough_width, NULL );
00775     gdk_window_get_size ( enhanced_scale->slider[ 0 ], &slider_length, NULL );
00776 
00777     trough_border = gtk_enhanced_scale_get_trough_border( GTK_WIDGET( enhanced_scale ) );
00778 
00779     tleft = trough_border;
00780     tright = trough_width - slider_length + trough_border;
00781     if ( i == 2 )
00782     {
00783         tleft += slider_length / 2;
00784         tright += slider_length / 2;
00785     }
00786 
00787     if ( left )
00788         * left = tleft;
00789     if ( right )
00790         * right = tright;
00791 }
00792 
00793 static void gtk_enhanced_scale_get_slider_position( GtkEnhancedScale *enhanced_scale, gint *x, gint *y, gint i )
00794 {
00795     g_return_if_fail ( enhanced_scale != NULL );
00796     g_return_if_fail ( GTK_IS_ENHANCED_SCALE ( enhanced_scale ) );
00797     g_return_if_fail ( i >= 0 );
00798     g_return_if_fail ( i < enhanced_scale->num_adjustments );
00799 
00800     gdk_window_get_position( enhanced_scale->slider[ i ], x, y );
00801 }
00802 
00803 static gint gtk_enhanced_scale_get_trough_border( GtkWidget *widget )
00804 {
00805     /*return gtk_style_get_prop_experimental (widget->style,
00806         "GtkEnhancedScale::trough_border",
00807         widget->style->klass->xthickness);*/ 
00808     return widget->style->ythickness;
00809 }
00810 
00811 static gint gtk_enhanced_scale_get_slider_width( GtkWidget *widget )
00812 {
00813     /*return gtk_style_get_prop_experimental (widget->style,
00814         "GtkEnhancedScale::slider_width",
00815         ENHANCED_SCALE_CLASS (widget)->slider_width);*/ 
00816     return ENHANCED_SCALE_CLASS ( widget ) ->slider_width;
00817 }
00818 
00819 /* =========================================================================
00820  * Signal handlers/Callbacks for motion, buttons, keys, focus etc.
00821  * Partly helped by code from GtkScale/GtkRange
00822  */
00823 
00824 static gint gtk_enhanced_scale_button_press( GtkWidget *widget, GdkEventButton *event )
00825 {
00826     GtkEnhancedScale * enhanced_scale;
00827     int i;
00828 
00829     g_return_val_if_fail ( widget != NULL, FALSE );
00830     g_return_val_if_fail ( GTK_IS_ENHANCED_SCALE ( widget ), FALSE );
00831     g_return_val_if_fail ( event != NULL, FALSE );
00832 
00833     if ( !GTK_WIDGET_HAS_FOCUS ( widget ) )
00834         gtk_widget_grab_focus ( widget );
00835 #ifdef DEBUG
00836 
00837     printf( "Received press event, button %d\n", event->button );
00838 #endif
00839 
00840     enhanced_scale = GTK_ENHANCED_SCALE ( widget );
00841     enhanced_scale->x_click_point = event->x;
00842 
00843     if ( event->window == enhanced_scale->trough )
00844     {
00845         gint x, y;
00846         
00847 #if 0   /* old behaviour to nudge around the sliders by clicking around them. */
00848         gint n, left, right;
00849         //gtk_enhanced_scale_get_slider_position( enhanced_scale, &x, &y, enhanced_scale->active_slider );
00850         gtk_enhanced_scale_trough_hdims ( enhanced_scale, &left, &right,
00851                                           enhanced_scale->active_slider );
00852         n = ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ enhanced_scale->active_slider ] ) ->page_increment )
00853             * ( right - left )
00854             / ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ enhanced_scale->active_slider ] ) ->upper -
00855                 GTK_ADJUSTMENT( enhanced_scale->adjustment[ enhanced_scale->active_slider ] ) ->lower );
00856 
00857         if ( event->x > x + gtk_enhanced_scale_get_slider_width( widget ) )   /* Click at right of slider */
00858         {
00859             gtk_enhanced_scale_motion_x( enhanced_scale, n, enhanced_scale->active_slider );
00860         }
00861         else if ( event->x < x )   /* click at left of active slider */
00862         {
00863             gtk_enhanced_scale_motion_x( enhanced_scale, -n, enhanced_scale->active_slider );
00864         }
00865 #endif
00866 #ifdef DEBUG
00867 
00868         printf( "Source: trough. Active slider: %d (pos: %d,%d). Click position: %d,%d.\n",
00869                 enhanced_scale->active_slider, x, y, ( int ) ( event->x ), ( int ) ( event->y ) );
00870 #endif
00871         /* New behaviour: a click anywhere not on arrow moves slider 0 to the click spot. */
00872         gtk_enhanced_scale_get_slider_position(enhanced_scale, &x, &y, 0 );
00873         gtk_enhanced_scale_motion_x( enhanced_scale, event->x - x - 
00874             ENHANCED_SCALE_CLASS( enhanced_scale )->arrow_width/2 + 1, 0 );
00875     }
00876     else
00877         for ( i = 0;i < enhanced_scale->num_adjustments;i++ )
00878         {
00879             gint x, y;
00880             gtk_enhanced_scale_get_slider_position( enhanced_scale, &x, &y, i );
00881             if ( event->window == enhanced_scale->slider[ i ] )
00882             {
00883 #ifdef DEBUG
00884 
00885                 printf( "Source: slider %d (pos: %d,%d)\n", i, x, y );
00886 #endif
00887                 enhanced_scale->active_slider = i;
00888                 enhanced_scale->clicked_slider = i;
00889                 break;
00890             }
00891         }
00892     return TRUE;
00893 }
00894 
00895 static gint gtk_enhanced_scale_button_release( GtkWidget *widget, GdkEventButton *event )
00896 {
00897     GtkEnhancedScale * enhanced_scale;
00898 
00899     g_return_val_if_fail ( widget != NULL, FALSE );
00900     g_return_val_if_fail ( GTK_IS_ENHANCED_SCALE ( widget ), FALSE );
00901     g_return_val_if_fail ( event != NULL, FALSE );
00902 
00903     enhanced_scale = GTK_ENHANCED_SCALE ( widget );
00904 
00905 #ifdef DEBUG
00906     printf( "Button released" );
00907     if ( enhanced_scale->clicked_slider != -1 )
00908         printf( " - slider %d unselected", enhanced_scale->clicked_slider );
00909     printf( "\n" );
00910 #endif
00911 
00912     enhanced_scale->x_click_point = 0;
00913     enhanced_scale->clicked_slider = -1;
00914     gtk_widget_queue_draw ( widget );
00915 
00916     return TRUE;
00917 }
00918 
00919 static gint gtk_enhanced_scale_motion_notify( GtkWidget *widget, GdkEventMotion *event )
00920 {
00921     GtkEnhancedScale * enhanced_scale;
00922     int x, y;
00923     GdkModifierType mods;
00924 
00925     g_return_val_if_fail ( widget != NULL, FALSE );
00926     g_return_val_if_fail ( GTK_IS_ENHANCED_SCALE ( widget ), FALSE );
00927     g_return_val_if_fail ( event != NULL, FALSE );
00928 
00929     enhanced_scale = GTK_ENHANCED_SCALE ( widget );
00930 
00931     if ( enhanced_scale->clicked_slider != -1 )
00932     {
00933         gdk_window_get_pointer ( enhanced_scale->slider[ enhanced_scale->clicked_slider ], &x, &y, &mods );
00934 #ifdef DEBUG
00935 
00936         printf( "Motion notify\n" );
00937 #endif
00938 
00939         if ( mods & GDK_BUTTON1_MASK )
00940             gtk_enhanced_scale_motion_x( enhanced_scale, x - enhanced_scale->x_click_point,
00941                                          enhanced_scale->clicked_slider );
00942     }
00943 
00944     return TRUE;
00945 }
00946 
00947 static void gtk_enhanced_scale_motion_x( GtkEnhancedScale *enhanced_scale, gint delta_x, gint i )
00948 {
00949     gdouble old_value;
00950     gint left, right;
00951     gint slider_x, slider_y;
00952     gint new_pos;
00953 
00954     g_return_if_fail ( enhanced_scale != NULL );
00955     g_return_if_fail ( GTK_IS_ENHANCED_SCALE ( enhanced_scale ) );
00956     g_return_if_fail ( i >= 0 );
00957     g_return_if_fail ( i < enhanced_scale->num_adjustments );
00958 
00959     gdk_window_get_position ( enhanced_scale->slider[ i ], &slider_x, &slider_y );
00960     gtk_enhanced_scale_trough_hdims ( enhanced_scale, &left, &right, i );
00961 #ifdef DEBUG
00962 
00963     printf( "motion_x called: delta_x = %d, slider_x = %d, l/r=%d/%d\n", delta_x, slider_x, left, right );
00964 #endif
00965 
00966     if ( left == right )
00967         return ;
00968 
00969     new_pos = slider_x + delta_x;
00970 
00971     if ( new_pos < left )
00972         new_pos = left;
00973     else if ( new_pos > right )
00974         new_pos = right;
00975 
00976     old_value = GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->value;
00977     GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->value = ( gint )
00978             ( ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->upper -
00979                 GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->lower -
00980                 GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->page_size ) *
00981               ( new_pos - left ) / ( right - left ) +
00982               GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->lower );
00983     if ( ( int ) old_value != ( int ) GTK_ADJUSTMENT( enhanced_scale->adjustment[ i ] ) ->value )
00984     {
00985         g_signal_emit_by_name ( enhanced_scale->adjustment[ i ], "value_changed" );
00986     }
00987 }
00988 
00989 static gint gtk_enhanced_scale_key_press( GtkWidget *widget, GdkEventKey *event )
00990 {
00991     GtkEnhancedScale * enhanced_scale;
00992 #ifdef DEBUG
00993 
00994     char *key;
00995 #endif
00996 
00997     g_return_val_if_fail ( widget != NULL, FALSE );
00998     g_return_val_if_fail ( GTK_IS_ENHANCED_SCALE ( widget ), FALSE );
00999     g_return_val_if_fail ( event != NULL, FALSE );
01000 #ifdef DEBUG
01001 
01002     key = "unkown";
01003 #endif
01004 
01005     enhanced_scale = GTK_ENHANCED_SCALE ( widget );
01006 
01007     if ( enhanced_scale->active_slider >= 0 && enhanced_scale->active_slider < enhanced_scale->num_adjustments )
01008     {
01009         gint n1, n2, left, right;
01010 
01011         gtk_enhanced_scale_trough_hdims ( enhanced_scale, &left, &right,
01012                                           enhanced_scale->active_slider );
01013         n1 = ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ enhanced_scale->active_slider ] ) ->
01014                page_increment ) * ( right - left ) /
01015              ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ enhanced_scale->active_slider ] ) ->upper -
01016                GTK_ADJUSTMENT( enhanced_scale->adjustment[ enhanced_scale->active_slider ] ) ->lower );
01017         n2 = ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ enhanced_scale->active_slider ] ) ->
01018                step_increment ) * ( right - left ) /
01019              ( GTK_ADJUSTMENT( enhanced_scale->adjustment[ enhanced_scale->active_slider ] ) ->upper -
01020                GTK_ADJUSTMENT( enhanced_scale->adjustment[ enhanced_scale->active_slider ] ) ->lower );
01021 
01022         switch ( event->keyval )
01023         {
01024         case GDK_Left:
01025             if ( event->state & GDK_CONTROL_MASK )
01026                 gtk_enhanced_scale_motion_x( enhanced_scale,
01027                                              -n1, enhanced_scale->active_slider );
01028             else
01029                 gtk_enhanced_scale_motion_x( enhanced_scale,
01030                                              -n2, enhanced_scale->active_slider );
01031 #ifdef DEBUG
01032 
01033             key = "left_arrow";
01034 #endif
01035 
01036             break;
01037         case GDK_Right:
01038             if ( event->state & GDK_CONTROL_MASK )
01039                 gtk_enhanced_scale_motion_x( enhanced_scale,
01040                                              n1, enhanced_scale->active_slider );
01041             else
01042                 gtk_enhanced_scale_motion_x( enhanced_scale,
01043                                              n2, enhanced_scale->active_slider );
01044 #ifdef DEBUG
01045 
01046             key = "right_arrow";
01047 #endif
01048 
01049             break;
01050         case GDK_Home:
01051             /* Clumsy, but the check in gtk_enhanced_scale_motion_x() will take care */
01052             gtk_enhanced_scale_motion_x( enhanced_scale,
01053                                          0 - GTK_ADJUSTMENT( enhanced_scale->adjustment[ enhanced_scale->active_slider ] ) ->upper,
01054                                          enhanced_scale->active_slider );
01055 #ifdef DEBUG
01056 
01057             key = "home";
01058 #endif
01059 
01060             break;
01061         case GDK_End:
01062             /* Clumsy, but the check in gtk_enhanced_scale_motion_x() will take care */
01063             gtk_enhanced_scale_motion_x( enhanced_scale,
01064                                          GTK_ADJUSTMENT( enhanced_scale->adjustment[ enhanced_scale->active_slider ] ) ->upper,
01065                                          enhanced_scale->active_slider );
01066 #ifdef DEBUG
01067 
01068             key = "end";
01069 #endif
01070 
01071             break;
01072         }
01073     }
01074 #ifdef DEBUG
01075     printf( "Key pressed: %s\n", key );
01076 #endif
01077 
01078     return TRUE;
01079 }
01080 
01081 static gint gtk_enhanced_scale_enter_notify( GtkWidget *widget, GdkEventCrossing *event )
01082 {
01083     GtkEnhancedScale * enhanced_scale;
01084     gint i;
01085 
01086     g_return_val_if_fail ( widget != NULL, FALSE );
01087     g_return_val_if_fail ( GTK_IS_ENHANCED_SCALE ( widget ), FALSE );
01088     g_return_val_if_fail ( event != NULL, FALSE );
01089 
01090     enhanced_scale = GTK_ENHANCED_SCALE ( widget );
01091 
01092     if ( event->window == enhanced_scale->trough )
01093     {
01094         enhanced_scale->in_child = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->trough;
01095     }
01096     else
01097     {
01098         for ( i = 0;i < enhanced_scale->num_adjustments;i++ )
01099         {
01100             if ( event->window == enhanced_scale->slider[ i ] )
01101             {
01102                 enhanced_scale->in_child = ENHANCED_SCALE_CLASS ( enhanced_scale ) ->slider;
01103                 break;
01104             }
01105         }
01106     }
01107 
01108     return TRUE;
01109 }
01110 
01111 static gint gtk_enhanced_scale_leave_notify( GtkWidget *widget, GdkEventCrossing *event )
01112 {
01113     GtkEnhancedScale * enhanced_scale;
01114 
01115     g_return_val_if_fail ( widget != NULL, FALSE );
01116     g_return_val_if_fail ( GTK_IS_ENHANCED_SCALE ( widget ), FALSE );
01117     g_return_val_if_fail ( event != NULL, FALSE );
01118 
01119     enhanced_scale = GTK_ENHANCED_SCALE ( widget );
01120     enhanced_scale->in_child = 0;
01121     
01122     return TRUE;
01123 }
01124 
01125 static gint gtk_enhanced_scale_focus_in( GtkWidget *widget, GdkEventFocus *event )
01126 {
01127     g_return_val_if_fail ( widget != NULL, FALSE );
01128     g_return_val_if_fail ( GTK_IS_ENHANCED_SCALE ( widget ), FALSE );
01129     g_return_val_if_fail ( event != NULL, FALSE );
01130 
01131     GTK_WIDGET_SET_FLAGS ( widget, GTK_HAS_FOCUS );
01132     //gtk_widget_queue_draw ( widget );
01133 #ifdef DEBUG
01134 
01135     printf( "focus_in\n" );
01136 #endif
01137     return FALSE;
01138 }
01139 
01140 static gint gtk_enhanced_scale_focus_out( GtkWidget *widget, GdkEventFocus *event )
01141 {
01142     g_return_val_if_fail ( widget != NULL, FALSE );
01143     g_return_val_if_fail ( GTK_IS_ENHANCED_SCALE ( widget ), FALSE );
01144     g_return_val_if_fail ( event != NULL, FALSE );
01145 
01146     GTK_WIDGET_UNSET_FLAGS ( widget, GTK_HAS_FOCUS );
01147     //gtk_widget_queue_draw ( widget );
01148 #ifdef DEBUG
01149 
01150     printf( "focus_out\n" );
01151 #endif
01152     return FALSE;
01153 }
01154 
01155 static void gtk_enhanced_scale_style_set( GtkWidget *widget, GtkStyle *style )
01156 {
01157     GtkEnhancedScale * enhanced_scale;
01158     int i;
01159 
01160     g_return_if_fail ( widget != NULL );
01161     g_return_if_fail ( GTK_IS_ENHANCED_SCALE ( widget ) );
01162 
01163     enhanced_scale = GTK_ENHANCED_SCALE ( widget );
01164 
01165     if ( GTK_WIDGET_REALIZED ( widget ) )
01166     {
01167         if ( enhanced_scale->trough )
01168             gtk_style_set_background ( widget->style, enhanced_scale->trough, GTK_STATE_NORMAL );
01169 
01170         for ( i = 0;i < enhanced_scale->num_adjustments;i++ )
01171             if ( enhanced_scale->slider[ i ] )
01172                 gtk_style_set_background ( widget->style, enhanced_scale->slider[ i ],
01173                                            GTK_STATE_NORMAL );
01174     }
01175 }
01176 
01177 static void gtk_enhanced_scale_adjustment_value_changed( GtkAdjustment *adjustment, gpointer data )
01178 {
01179     GtkEnhancedScale * enhanced_scale;
01180     gint i;
01181 
01182     g_return_if_fail ( adjustment != NULL );
01183     g_return_if_fail ( data != NULL );
01184 
01185 #ifdef DEBUG
01186     printf( "gtk_enhanced_scale_adjustment_value_changed: %p\n", adjustment );
01187 #endif
01188     enhanced_scale = GTK_ENHANCED_SCALE( data );
01189     gtk_enhanced_scale_draw ( GTK_WIDGET( enhanced_scale ), NULL );
01190     return;
01191 
01192     for ( i = 0;i < enhanced_scale->num_adjustments;i++ )
01193     {
01194         if ( adjustment == GTK_ADJUSTMENT( enhanced_scale->adjustment[i] ) )
01195         {
01196             gtk_enhanced_scale_slider_update( enhanced_scale, i );
01197             break;
01198         }
01199     }
01200 }
01201 
01202 void gtk_enhanced_scale_set_breaks( GtkWidget *widget, GArray *breaks )
01203 {
01204     GtkEnhancedScale * enhanced_scale;
01205     GdkRectangle area;
01206 
01207     g_return_if_fail( widget != NULL );
01208     g_return_if_fail( breaks != NULL );
01209 
01210     if ( GTK_WIDGET_REALIZED ( widget ) )
01211     {
01212         enhanced_scale = GTK_ENHANCED_SCALE( widget );
01213         enhanced_scale->breaks = breaks;
01214 
01215         gdk_window_clear_area ( widget->window, 0, 0,
01216                             widget->allocation.width, widget->allocation.height );
01217 
01218         /* This would be the place to draw it */
01219         area.x = 0;
01220         area.y = 0;
01221         area.width = widget->allocation.width;
01222         area.height = widget->allocation.height;
01223         gtk_enhanced_scale_draw ( widget, &area );
01224     }
01225 }

Generated on Sun Mar 11 22:11:45 2007 for Kino by  doxygen 1.4.2