diff options
-rw-r--r-- | ui.c | 13 | ||||
-rw-r--r-- | window.c | 72 | ||||
-rw-r--r-- | window.h | 7 |
3 files changed, 63 insertions, 29 deletions
@@ -26,7 +26,14 @@ static const gchar *uiData = "</ui>"; - +static void handleAction(GtkAction *action, gpointer user_data) { + const gchar* name = gtk_action_get_name(action); + + if(!strcmp(name, "zoomIn")) + zoomInCentered(1.2); + else if(!strcmp(name, "zoomOut")) + zoomOutCentered(1.2); +} static GtkActionGroup *createActions() { GtkActionGroup *actionGroup = gtk_action_group_new("actions"); @@ -51,11 +58,11 @@ static GtkActionGroup *createActions() { gtk_action_group_add_action(actionGroup, action); action = gtk_action_new("zoomIn", "Zoom _in", NULL, GTK_STOCK_ZOOM_IN); - g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(zoomIn), NULL); + g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(handleAction), NULL); gtk_action_group_add_action_with_accel(actionGroup, action, NULL); action = gtk_action_new("zoomOut", "Zoom _out", NULL, GTK_STOCK_ZOOM_OUT); - g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(zoomOut), NULL); + g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(handleAction), NULL); gtk_action_group_add_action_with_accel(actionGroup, action, NULL); action = gtk_action_new("quit", "_Quit", NULL, GTK_STOCK_QUIT); @@ -8,10 +8,22 @@ static GtkWidget *drawingArea = NULL; static GtkAdjustment *hAdjustment = NULL, *vAdjustment = NULL; -static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) { +static gboolean deleteEvent(GtkWidget *widget, GdkEvent *event, gpointer data) { return FALSE; } +static gboolean scrollEvent(GtkWidget *widget, GdkEventScroll *event, gpointer user_data) { + const gdouble x = event->x/widget->allocation.width, y = event->y/widget->allocation.height; + + switch(event->direction) { + case GDK_SCROLL_UP: + zoomIn(1.1, x, y); + break; + case GDK_SCROLL_DOWN: + zoomOut(1.1, x, y); + } +} + static void destroy(GtkWidget *widget, gpointer data) { gtk_main_quit(); } @@ -27,36 +39,44 @@ static void refreshScrolling() { else setYTranslate(gtk_adjustment_get_value(vAdjustment)); - gdk_window_invalidate_rect(drawingArea->window, NULL, FALSE); + gtk_widget_queue_draw(drawingArea); } -static void updateScrollbars() { +static void updateScrollbars(double x, double y) { const gdouble imageWidth = getImageWidth(), imageHeight = getImageHeight(); const gdouble width = drawingArea->allocation.width, height = drawingArea->allocation.height; gdouble upper, pageSize, value; + gdk_window_freeze_updates(drawingArea->window); + g_object_get(G_OBJECT(hAdjustment), "upper", &upper, "page_size", &pageSize, NULL); g_object_set(G_OBJECT(hAdjustment), "upper", imageWidth, "page_size", width, NULL); gtk_adjustment_changed(hAdjustment); - if(pageSize > upper && width < imageWidth) + if((pageSize > upper && width < imageWidth) || upper == 0) value = (imageWidth-width)/2; else - value = MAX(MIN(gtk_adjustment_get_value(hAdjustment) - (width-pageSize)/2 + (imageWidth-upper)/2, imageWidth-width), 0); - gtk_adjustment_set_value(hAdjustment, value); + value = (gtk_adjustment_get_value(hAdjustment)+pageSize*x)/upper*imageWidth-width*x; + gtk_adjustment_set_value(hAdjustment, MAX(MIN(value, imageWidth-width), 0)); g_object_get(G_OBJECT(vAdjustment), "upper", &upper, "page_size", &pageSize, NULL); g_object_set(G_OBJECT(vAdjustment), "upper", imageHeight, "page_size", height, NULL); - if(pageSize > upper && height < imageHeight) + if((pageSize > upper && height < imageHeight) || upper == 0) value = (imageHeight-height)/2; else - value = MAX(MIN(gtk_adjustment_get_value(vAdjustment) - (height-pageSize)/2 + (imageHeight-upper)/2, imageHeight-height), 0); - gtk_adjustment_set_value(vAdjustment, value); + value = (gtk_adjustment_get_value(vAdjustment)+pageSize*y)/upper*imageHeight-height*y; + gtk_adjustment_set_value(vAdjustment, MAX(MIN(value, imageHeight-height), 0)); + + gdk_window_thaw_updates(drawingArea->window); refreshScrolling(); } +static void updateScrollbarsCentered() { + updateScrollbars(0.5, 0.5); +} + GtkWidget* createMainWindow() { GtkWidget *window, *vbox, *menubar, *toolbar, *table, *vScroll, *hScroll; GdkColor color = {0, 0, 0, 0}; @@ -64,7 +84,7 @@ GtkWidget* createMainWindow() { window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(window), 640, 480); - g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_event), NULL); + g_signal_connect(G_OBJECT(window), "delete-event", G_CALLBACK(deleteEvent), NULL); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL); vbox = gtk_vbox_new(FALSE, 0); @@ -72,11 +92,9 @@ GtkWidget* createMainWindow() { menubar = getMenu(); gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0); - gtk_widget_show(menubar); toolbar = getToolbar(); gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0); - gtk_widget_show(toolbar); gtk_window_add_accel_group(GTK_WINDOW(window), getAccels()); @@ -85,35 +103,41 @@ GtkWidget* createMainWindow() { drawingArea = gtk_drawing_area_new(); gtk_widget_modify_bg(drawingArea, GTK_WIDGET_STATE(drawingArea), &color); - g_signal_connect(G_OBJECT(drawingArea), "configure-event", G_CALLBACK(updateScrollbars), NULL); + g_signal_connect(G_OBJECT(drawingArea), "configure-event", G_CALLBACK(updateScrollbarsCentered), NULL); g_signal_connect(G_OBJECT(drawingArea), "expose-event", G_CALLBACK(drawTopView), NULL); + g_signal_connect(G_OBJECT(drawingArea), "scroll-event", G_CALLBACK(scrollEvent), NULL); + gtk_widget_add_events(drawingArea, GDK_SCROLL_MASK); gtk_table_attach(GTK_TABLE(table), drawingArea, 0, 1, 0, 1, GTK_FILL|GTK_EXPAND|GTK_SHRINK, GTK_FILL|GTK_EXPAND|GTK_SHRINK, 0, 0); - gtk_widget_show(drawingArea); hAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 10, 100, 100)); hScroll = gtk_hscrollbar_new(hAdjustment); g_signal_connect(G_OBJECT(hScroll), "value-changed", G_CALLBACK(refreshScrolling), NULL); gtk_table_attach(GTK_TABLE(table), hScroll, 0, 1, 1, 2, GTK_FILL|GTK_EXPAND|GTK_SHRINK, 0, 0, 0); - gtk_widget_show(hScroll); vAdjustment = GTK_ADJUSTMENT(gtk_adjustment_new(0, 0, 0, 10, 100, 100)); vScroll = gtk_vscrollbar_new(vAdjustment); g_signal_connect(G_OBJECT(vScroll), "value-changed", G_CALLBACK(refreshScrolling), NULL); gtk_table_attach(GTK_TABLE(table), vScroll, 1, 2, 0, 1, 0, GTK_FILL|GTK_EXPAND|GTK_SHRINK, 0, 0); - gtk_widget_show(vScroll); - gtk_widget_show(table); - gtk_widget_show(vbox); + gtk_widget_show_all(vbox); return window; } -void zoomIn() { - setScale(getScale()*1.5); - updateScrollbars(); +void zoomIn(double factor, double x, double y) { + setScale(getScale()*factor); + updateScrollbars(x, y); +} + +void zoomOut(double factor, double x, double y) { + setScale(getScale()/factor); + updateScrollbars(x, y); +} + +void zoomInCentered(double factor) { + zoomIn(factor, 0.5, 0.5); } -void zoomOut() { - setScale(getScale()/1.5); - updateScrollbars(); +void zoomOutCentered(double factor) { + zoomOut(factor, 0.5, 0.5); } @@ -5,7 +5,10 @@ GtkWidget* createMainWindow(); -void zoomIn(); -void zoomOut(); + +void zoomIn(double factor, double x, double y); +void zoomOut(double factor, double x, double y); +void zoomInCentered(double factor); +void zoomOutCentered(double factor); #endif /*WINDOW_H_*/ |