From d990084845d1c6defbc1efab290b1a8b5b52e800 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sun, 22 Aug 2010 16:02:17 +0000 Subject: [PATCH] Allow the sprite viewer window to pan. --- src/gtk/editor.cpp | 84 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 9 deletions(-) diff --git a/src/gtk/editor.cpp b/src/gtk/editor.cpp index fd28a94e..01d6aff9 100644 --- a/src/gtk/editor.cpp +++ b/src/gtk/editor.cpp @@ -20,6 +20,8 @@ static volatile int quit = 0; static int ticking = 0; +static int panning = 0; +static double xpan = 0.0f, ypan = 0.0f; static float const FPS = 30.0f; static MapViewer *mv; @@ -56,8 +58,63 @@ static gboolean tick(void *widget) return TRUE; } +static gboolean mouse_button(GtkWidget *widget, GdkEventButton *event, + gpointer user_data) +{ + if (event->type == GDK_BUTTON_PRESS && event->button == 2) + { + panning = 1; + xpan = event->x; + ypan = event->y; + GdkCursor *cursor = gdk_cursor_new(GDK_HAND1); + gdk_window_set_cursor(widget->window, cursor); + gdk_cursor_unref(cursor); + return FALSE; + } + else if (event->type == GDK_BUTTON_RELEASE && event->button == 2) + { + panning = 0; + gdk_window_set_cursor(widget->window, NULL); + return FALSE; + } + + return TRUE; +} + +static gboolean mouse_motion(GtkWidget *widget, GdkEventMotion *event, + gpointer user_data) +{ + if (panning) + { + if (event->x != xpan) + { + double val = gtk_adjustment_get_value(hadj); + val += xpan - event->x; + xpan = event->x; + if (val + widget->allocation.width > mv->GetWidth()) + val = mv->GetWidth() - widget->allocation.width; + gtk_adjustment_set_value(hadj, val); + gtk_adjustment_value_changed(hadj); + } + + if (event->y != ypan) + { + double val = gtk_adjustment_get_value(vadj); + val += ypan - event->y; + ypan = event->y; + if (val + widget->allocation.height > mv->GetHeight()) + val = mv->GetHeight() - widget->allocation.height; + gtk_adjustment_set_value(vadj, val); + gtk_adjustment_value_changed(vadj); + } + } + + return TRUE; +} + static gint init(GtkWidget *widget) { + /* Manage adjustments */ struct { GtkAdjustment *adj; @@ -77,21 +134,22 @@ static gint init(GtkWidget *widget) gtk_adjustment_set_page_increment(s[i].adj, s[i].sw_size); gtk_adjustment_set_page_size(s[i].adj, s[i].sw_size); - float hval = gtk_adjustment_get_value(s[i].adj); - if (hval + s[i].sw_size > s[i].map_size) + float val = gtk_adjustment_get_value(s[i].adj); + if (val + s[i].sw_size > s[i].map_size) { gtk_adjustment_set_value(s[i].adj, s[i].map_size - s[i].sw_size); gtk_adjustment_value_changed(s[i].adj); } } + /* Set up display */ if (gtk_gl_area_make_current(GTK_GL_AREA(widget))) Video::Setup(widget->allocation.width, widget->allocation.height); return TRUE; } -static gint reshape_gl(GtkWidget *widget, GdkEventConfigure *event) +static gint reshape(GtkWidget *widget, GdkEventConfigure *event) { (void)event; @@ -163,9 +221,15 @@ int main(int argc, char **argv) glarea = gtk_gl_area_new(attrlist); gtk_widget_set_usize(glarea, 400, 300); - gtk_widget_set_events(glarea, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK); + gtk_widget_set_events(glarea, GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK + | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); gtk_container_add(GTK_CONTAINER(viewport), glarea); + /* We tick from the idle function instead of a timeout to avoid + * stealing time from the GTK loop when the callback time exceeds + * the timeout value. */ + gtk_idle_add(tick, glarea); + /* Connect signals and show window */ gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(main_quit), NULL); @@ -173,19 +237,21 @@ int main(int argc, char **argv) gtk_signal_connect(GTK_OBJECT(glarea), "expose_event", GTK_SIGNAL_FUNC(draw), NULL); gtk_signal_connect(GTK_OBJECT(glarea), "configure_event", - GTK_SIGNAL_FUNC(reshape_gl), NULL); + GTK_SIGNAL_FUNC(reshape), NULL); gtk_signal_connect(GTK_OBJECT(glarea), "realize", GTK_SIGNAL_FUNC(init), NULL); + gtk_signal_connect(GTK_OBJECT(glarea), "button_press_event", + GTK_SIGNAL_FUNC(mouse_button), NULL); + gtk_signal_connect(GTK_OBJECT(glarea), "button_release_event", + GTK_SIGNAL_FUNC(mouse_button), NULL); + gtk_signal_connect(GTK_OBJECT(glarea), "motion_notify_event", + GTK_SIGNAL_FUNC(mouse_motion), NULL); // FIXME: detect when the map viewer is killed mv = new MapViewer("maps/testmap.tmx"); new DebugFps(); - /* We tick from the idle function instead of a timeout to avoid - * stealing time from the GTK loop when the callback time exceeds - * the timeout value. */ gtk_widget_show_all(window); - gtk_idle_add(tick, glarea); gtk_main(); return EXIT_SUCCESS;