/* * Proview $Id: glow_curvewidget_gtk.cpp,v 1.6 2008-02-27 15:07:41 claes Exp $ * Copyright (C) 2005 SSAB Oxel�sund AB. * * 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 the program, if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. **/ #include <stdlib.h> #include "glow_std.h" #include <gtk/gtk.h> #include <gtk/gtkprivate.h> #include "glow_curvewidget_gtk.h" #include "glow.h" #include "glow_ctx.h" #include "glow_curvectx.h" #include "glow_draw.h" #include "glow_draw_gtk.h" typedef struct _CurveWidgetGtk CurveWidgetGtk; typedef struct _CurveWidgetGtkClass CurveWidgetGtkClass; typedef struct { GtkWidget *curve; GtkWidget *form; GtkWidget *scroll_h; GtkWidget *scroll_v; int scroll_h_managed; int scroll_v_managed; } curvewidget_sScroll; struct _CurveWidgetGtk { GtkDrawingArea parent; /* Private */ void *curve_ctx; void *draw_ctx; int (*init_proc)(GlowCtx *ctx, void *clien_data); int is_navigator; int is_realized; int realize_navigator; void *client_data; GtkWidget *main_curve_widget; GtkWidget *navigator_widget; GtkWidget *scroll_h; GtkWidget *scroll_v; GtkWidget *form; int scroll_h_ignore; int scroll_v_ignore; gdouble scroll_h_value; gdouble scroll_v_value; int scroll_h_pagesize; int scroll_v_pagesize; int scroll_h_upper; int scroll_v_upper; gint scroll_timerid; glow_sScroll scroll_data; int scroll_configure; }; struct _CurveWidgetGtkClass { GtkDrawingAreaClass parent_class; }; G_DEFINE_TYPE( CurveWidgetGtk, curvewidgetgtk, GTK_TYPE_DRAWING_AREA); static gboolean scroll_callback_cb( void *d); static void scroll_callback( glow_sScroll *data) { curvewidget_sScroll *scroll_data = (curvewidget_sScroll *) data->scroll_data; if ( ((CurveWidgetGtk *)scroll_data->curve)->scroll_timerid) g_source_remove( ((CurveWidgetGtk *)scroll_data->curve)->scroll_timerid); ((CurveWidgetGtk *)scroll_data->curve)->scroll_timerid = g_timeout_add( 200, scroll_callback_cb, scroll_data->curve); ((CurveWidgetGtk *)scroll_data->curve)->scroll_data = *data; } static gboolean scroll_callback_cb( void *d) { glow_sScroll *data = &((CurveWidgetGtk *)d)->scroll_data; curvewidget_sScroll *scroll_data = (curvewidget_sScroll *) data->scroll_data; if ( data->total_width <= data->window_width) { if ( data->offset_x == 0) data->total_width = data->window_width; if ( scroll_data->scroll_h_managed) { // Remove horizontal scrollbar } } else { if ( !scroll_data->scroll_h_managed) { // Insert horizontal scrollbar } } if ( data->total_height <= data->window_height) { if ( data->offset_y == 0) data->total_height = data->window_height; if ( scroll_data->scroll_v_managed) { // Remove vertical scrollbar } } else { if ( !scroll_data->scroll_v_managed) { // Insert vertical scrollbar } } if ( data->offset_x < 0) { data->total_width += -data->offset_x; data->offset_x = 0; } if ( data->offset_y < 0) { data->total_height += -data->offset_y; data->offset_y = 0; } if ( data->total_height < data->window_height + data->offset_y) data->total_height = data->window_height + data->offset_y; if ( data->total_width < data->window_width + data->offset_x) data->total_width = data->window_width + data->offset_x; if ( data->window_width < 1) data->window_width = 1; if ( data->window_height < 1) data->window_height = 1; if ( scroll_data->scroll_v_managed) { ((CurveWidgetGtk *)scroll_data->curve)->scroll_v_ignore = 1; if ( data->window_height != ((CurveWidgetGtk *)scroll_data->curve)->scroll_v_pagesize || data->total_height != ((CurveWidgetGtk *)scroll_data->curve)->scroll_v_upper || ((CurveWidgetGtk *)scroll_data->curve)->scroll_configure) { g_object_set( ((GtkScrollbar *)scroll_data->scroll_v)->range.adjustment, "upper", (gdouble)data->total_height, "page-size", (gdouble)data->window_height, "value", (gdouble)data->offset_y, NULL); gtk_adjustment_changed( ((GtkScrollbar *)scroll_data->scroll_v)->range.adjustment); } else { g_object_set( ((GtkScrollbar *)scroll_data->scroll_v)->range.adjustment, "value", (gdouble)data->offset_y, NULL); gtk_adjustment_value_changed( ((GtkScrollbar *)scroll_data->scroll_v)->range.adjustment); } ((CurveWidgetGtk *)scroll_data->curve)->scroll_v_value = (gdouble)data->offset_y; ((CurveWidgetGtk *)scroll_data->curve)->scroll_h_pagesize = data->window_width; ((CurveWidgetGtk *)scroll_data->curve)->scroll_h_upper = data->total_width; } ((CurveWidgetGtk *)scroll_data->curve)->scroll_configure = 0; return FALSE; #if 0 if ( scroll_data->scroll_h_managed) { ((CurveWidgetGtk *)scroll_data->curve)->scroll_h_ignore = 1; g_object_set( ((GtkScrollbar *)scroll_data->scroll_h)->range.adjustment, "upper", (gdouble)data->total_width, "page-size", (gdouble)data->window_width, "value", (gdouble)data->offset_x, NULL); gtk_adjustment_changed( ((GtkScrollbar *)scroll_data->scroll_h)->range.adjustment); } if ( scroll_data->scroll_v_managed) { ((CurveWidgetGtk *)scroll_data->curve)->scroll_v_ignore = 1; g_object_set( ((GtkScrollbar *)scroll_data->scroll_v)->range.adjustment, "upper", (gdouble)data->total_height, "page-size", (gdouble)data->window_height, "value", (gdouble)data->offset_y, NULL); gtk_adjustment_changed( ((GtkScrollbar *)scroll_data->scroll_v)->range.adjustment); } #endif } static void scroll_h_action( GtkWidget *w, gpointer data) { CurveWidgetGtk *curvew = (CurveWidgetGtk *)data; if ( curvew->scroll_h_ignore) { curvew->scroll_h_ignore = 0; return; } printf( "Horizontal scroll callback\n"); CurveCtx *ctx = (CurveCtx *) curvew->curve_ctx; gdouble value; g_object_get( w, "value", &value, NULL); glow_scroll_horizontal( ctx, int(value), 0); } static void scroll_v_action( GtkWidget *w, gpointer data) { CurveWidgetGtk *curvew = (CurveWidgetGtk *)data; if ( curvew->scroll_v_ignore) { curvew->scroll_v_ignore = 0; return; } printf( "Vertical scroll callback\n"); CurveCtx *ctx = (CurveCtx *) curvew->curve_ctx; gdouble value; g_object_get( w, "value", &value, NULL); glow_scroll_vertical( ctx, int(value), 0); } static int curve_init_proc( GtkWidget *w, GlowCtx *fctx, void *client_data) { curvewidget_sScroll *scroll_data; CurveCtx *ctx; ctx = (CurveCtx *) ((CurveWidgetGtk *) w)->curve_ctx; if ( ((CurveWidgetGtk *) w)->scroll_h) { scroll_data = (curvewidget_sScroll *) malloc( sizeof( curvewidget_sScroll)); scroll_data->curve = w; scroll_data->scroll_h = ((CurveWidgetGtk *) w)->scroll_h; scroll_data->scroll_v = ((CurveWidgetGtk *) w)->scroll_v; scroll_data->form = ((CurveWidgetGtk *) w)->form; scroll_data->scroll_h_managed = 1; scroll_data->scroll_v_managed = 1; ctx->register_scroll_callback( (void *) scroll_data, scroll_callback); } return (((CurveWidgetGtk *) w)->init_proc)( ctx, client_data); } static gboolean curvewidgetgtk_expose( GtkWidget *glow, GdkEventExpose *event) { if ( !((CurveWidgetGtk *)glow)->curve_ctx) // Navigator not yet created return TRUE; ((GlowDrawGtk *)((CurveCtx *)((CurveWidgetGtk *)glow)->curve_ctx)->gdraw)->event_handler( *(GdkEvent *)event); return TRUE; } static void curvewidgetgtk_grab_focus( GtkWidget *glow) { if ( !glow->window) return; GTK_WIDGET_CLASS( curvewidgetgtk_parent_class)->grab_focus( glow); gdk_window_focus( glow->window, GDK_CURRENT_TIME); } static gboolean curvewidgetgtk_event( GtkWidget *glow, GdkEvent *event) { if ( !((CurveWidgetGtk *)glow)->curve_ctx) // Navigator not yet created return TRUE; if ( event->type == GDK_MOTION_NOTIFY) { gdk_display_flush( ((GlowDrawGtk *)((CurveCtx *)((CurveWidgetGtk *)glow)->curve_ctx)->gdraw)->display); GdkEvent *next = gdk_event_peek(); if ( next && next->type == GDK_MOTION_NOTIFY) { gdk_event_free( next); return TRUE; } else if ( next) gdk_event_free( next); } else if ( event->type == GDK_CONFIGURE) { ((CurveWidgetGtk *)glow)->scroll_configure = 1; } ((GlowDrawGtk *)((CurveCtx *)((CurveWidgetGtk *)glow)->curve_ctx)->gdraw)->event_handler( *event); return TRUE; } static void curvewidgetgtk_realize( GtkWidget *widget) { GdkWindowAttr attr; gint attr_mask; CurveWidgetGtk *curve; g_return_if_fail (widget != NULL); g_return_if_fail (IS_CURVEWIDGETGTK( widget)); curve = CURVEWIDGETGTK( widget); GTK_WIDGET_SET_FLAGS( widget, GTK_REALIZED); attr.x = widget->allocation.x; attr.y = widget->allocation.y; attr.width = widget->allocation.width; attr.height = widget->allocation.height; attr.wclass = GDK_INPUT_OUTPUT; attr.window_type = GDK_WINDOW_CHILD; attr.event_mask = gtk_widget_get_events( widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK; attr.visual = gtk_widget_get_visual( widget); attr.colormap = gtk_widget_get_colormap( widget); attr_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; widget->window = gdk_window_new( widget->parent->window, &attr, attr_mask); widget->style = gtk_style_attach( widget->style, widget->window); gdk_window_set_user_data( widget->window, widget); gtk_style_set_background( widget->style, widget->window, GTK_STATE_ACTIVE); GTK_WIDGET_SET_FLAGS( widget, GTK_CAN_FOCUS); if ( curve->is_navigator) { if ( !curve->curve_ctx) { CurveWidgetGtk *main_curve = (CurveWidgetGtk *) curve->main_curve_widget; if ( !main_curve->is_realized) { main_curve->realize_navigator = 1; main_curve->navigator_widget = widget; } else { curve->curve_ctx = main_curve->curve_ctx; curve->draw_ctx = main_curve->draw_ctx; ((GlowDrawGtk *)curve->draw_ctx)->init_nav( widget); } } } else { if ( !curve->curve_ctx) { curve->draw_ctx = new GlowDrawGtk( widget, &curve->curve_ctx, curve_init_proc, curve->client_data, glow_eCtxType_Curve); } if ( curve->realize_navigator) { CurveWidgetGtk *nav_curve = (CurveWidgetGtk *) curve->navigator_widget; nav_curve->curve_ctx = curve->curve_ctx; nav_curve->draw_ctx = curve->draw_ctx; ((GlowDrawGtk *)nav_curve->draw_ctx)->init_nav( (GtkWidget *)nav_curve); } } curve->is_realized = 1; } static void curvewidgetgtk_class_init( CurveWidgetGtkClass *klass) { GtkWidgetClass *widget_class; widget_class = GTK_WIDGET_CLASS( klass); widget_class->realize = curvewidgetgtk_realize; widget_class->expose_event = curvewidgetgtk_expose; widget_class->event = curvewidgetgtk_event; widget_class->grab_focus = curvewidgetgtk_grab_focus; } static void curvewidgetgtk_init( CurveWidgetGtk *glow) { } GtkWidget *curvewidgetgtk_new( int (*init_proc)(GlowCtx *ctx, void *client_data), void *client_data) { CurveWidgetGtk *w; w = (CurveWidgetGtk *) g_object_new( CURVEWIDGETGTK_TYPE, NULL); w->init_proc = init_proc; w->curve_ctx = 0; w->is_navigator = 0; w->client_data = client_data; w->scroll_h = 0; w->scroll_v = 0; return (GtkWidget *) w; } GtkWidget *scrolledcurvewidgetgtk_new( int (*init_proc)(GlowCtx *ctx, void *client_data), void *client_data, GtkWidget **curvewidget) { CurveWidgetGtk *w; GtkWidget *form = gtk_scrolled_window_new( NULL, NULL); w = (CurveWidgetGtk *) g_object_new( CURVEWIDGETGTK_TYPE, NULL); w->init_proc = init_proc; w->curve_ctx = 0; w->is_navigator = 0; w->client_data = client_data; w->scroll_h = GTK_SCROLLED_WINDOW(form)->hscrollbar; w->scroll_v = GTK_SCROLLED_WINDOW(form)->vscrollbar; w->scroll_h_ignore = 0; w->scroll_v_ignore = 0; w->scroll_h_value = 0; w->scroll_v_value = 0; w->scroll_configure = 0; w->form = form; *curvewidget = GTK_WIDGET( w); g_signal_connect( ((GtkScrollbar *)w->scroll_h)->range.adjustment, "value-changed", G_CALLBACK(scroll_h_action), w); g_signal_connect( ((GtkScrollbar *)w->scroll_v)->range.adjustment, "value-changed", G_CALLBACK(scroll_v_action), w); GtkWidget *viewport = gtk_viewport_new( NULL, NULL); gtk_container_add( GTK_CONTAINER(viewport), GTK_WIDGET(w)); gtk_container_add( GTK_CONTAINER(form), GTK_WIDGET(viewport)); return (GtkWidget *) form; } GtkWidget *curvenavwidgetgtk_new( GtkWidget *main_curve) { CurveWidgetGtk *w; w = (CurveWidgetGtk *) g_object_new( CURVEWIDGETGTK_TYPE, NULL); w->init_proc = 0; w->curve_ctx = 0; w->is_navigator = 1; w->main_curve_widget = main_curve; w->client_data = 0; w->scroll_h = 0; w->scroll_v = 0; w->scroll_h_ignore = 0; w->scroll_v_ignore = 0; w->scroll_h_value = 0; w->scroll_v_value = 0; w->scroll_configure = 0; return (GtkWidget *) w; } #if 0 GType curvewidgetgtk_get_type(void) { static GType curvewidgetgtk_type = 0; if ( !curvewidgetgtk_type) { static const GTypeInfo curvewidgetgtk_info = { sizeof(CurveWidgetGtkClass), NULL, NULL, (GClassInitFunc)curvewidgetgtk_class_init, NULL, NULL, sizeof(CurveWidgetGtk), 1, NULL, NULL}; curvewidgetgtk_type = g_type_register_static( G_TYPE_OBJECT, "CurveWidgetGtk", &curvewidgetgtk_info, (GTypeFlags)0); } return curvewidgetgtk_type; } #endif