implement imageviewer useradjustable setting in gtk4 implementation

3 days ago

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 29 Mar 2025 20:03:25 +0100 (3 days ago)
changeset 530
7992a44fe719
parent 529
0a4a6b0d1c82
child 531
9068a5c7caf6

implement imageviewer useradjustable setting in gtk4 implementation

application/main.c file | annotate | diff | comparison | revisions
ui/gtk/image.c file | annotate | diff | comparison | revisions
ui/gtk/image.h file | annotate | diff | comparison | revisions
--- a/application/main.c	Sat Mar 29 18:17:01 2025 +0100
+++ b/application/main.c	Sat Mar 29 20:03:25 2025 +0100
@@ -480,7 +480,7 @@
         }
         ui_tab(obj, "Tab 5") {
             ui_button(obj, .label = "Test Button", .icon = "application-x-generic", .onclick = action_button);
-            ui_imageviewer(obj, .varname = "image", .style_class = "imageviewer", .contextmenu = menubuilder, .scrollarea = TRUE);
+            ui_imageviewer(obj, .varname = "image", .style_class = "imageviewer", .contextmenu = menubuilder, .scrollarea = TRUE, .useradjustable = TRUE);
         }
         
         ui_tab(obj, "Tab 6") {
--- a/ui/gtk/image.c	Sat Mar 29 18:17:01 2025 +0100
+++ b/ui/gtk/image.c	Sat Mar 29 20:03:25 2025 +0100
@@ -69,7 +69,7 @@
     GtkWidget *drawingarea = gtk_drawing_area_new();
     GtkWidget *toplevel;
     GtkWidget *widget = drawingarea;
-    
+      
     gtk_widget_set_size_request(drawingarea, 100, 100);
     
 #if GTK_MAJOR_VERSION < 4
@@ -102,6 +102,7 @@
     imgviewer->adjustsize = args.adjustsize;
     imgviewer->autoscale = args.autoscale;
     imgviewer->useradjustable = args.useradjustable;
+    imgviewer->zoom_scale = 20;
     
     g_object_set_data_full(G_OBJECT(drawingarea), "uiimageviewer", imgviewer, (GDestroyNotify)imageviewer_destroy);
     
@@ -128,12 +129,45 @@
             imageviewer_draw,
             imgviewer,
             NULL);
+    
+    if(args.useradjustable) {
+        gtk_widget_set_focusable(drawingarea, TRUE);
+    }
+    
+    GtkEventController *scrollcontroller = gtk_event_controller_scroll_new(GTK_EVENT_CONTROLLER_SCROLL_VERTICAL);
+    g_signal_connect(scrollcontroller, "scroll", G_CALLBACK(ui_imageviewer_scroll), imgviewer);
+    gtk_widget_add_controller(GTK_WIDGET(drawingarea), GTK_EVENT_CONTROLLER(scrollcontroller));
+    
+    GtkGesture *drag = gtk_gesture_drag_new();
+    g_signal_connect(drag, "drag-begin", G_CALLBACK(ui_imageviewer_drag_begin_cb), imgviewer);
+    g_signal_connect(drag, "drag-end", G_CALLBACK(ui_imageviewer_drag_end_cb), imgviewer);
+    g_signal_connect(drag, "drag-update", G_CALLBACK(ui_imageviewer_drag_update_cb), imgviewer);
+    gtk_widget_add_controller(GTK_WIDGET(drawingarea), GTK_EVENT_CONTROLLER(drag));
+    
 #elif GTK_MAJOR_VERSION == 3
     g_signal_connect(
             drawingarea,
             "draw",
             G_CALLBACK(imageviewer_draw),
             imgviewer);
+    
+    gtk_widget_add_events(eventbox, GDK_SCROLL_MASK);
+    
+    g_signal_connect(
+            eventbox,
+            "scroll-event",
+            G_CALLBACK(ui_imageviewer_scroll_event),
+            imgviewer);
+    g_signal_connect(
+            eventbox,
+            "button-press-event",
+            G_CALLBACK(ui_imageviewer_button_press_event),
+            imgviewer);
+    g_signal_connect(
+            eventbox,
+            "button-release-event",
+            G_CALLBACK(ui_imageviewer_button_release_event),
+            imgviewer);
 
 #endif
     
@@ -141,7 +175,7 @@
         UIMENU menu = ui_contextmenu_create(args.contextmenu, obj, widget);
         ui_widget_set_contextmenu(widget, menu);
     }
-    
+       
     UI_APPLY_LAYOUT1(current, args);
     current->container->add(current->container, toplevel, TRUE);
     
@@ -160,32 +194,31 @@
     
     double dwidth = width;
     double dheight = height;
+    double scale = 1;
     if(imgviewer->autoscale) {
-        double scale = dwidth / dpixwidth;
+        scale = dwidth / dpixwidth;
         if(dpixheight * scale > dheight) {
             scale = dheight / dpixheight;
         }
-        
-        dpixwidth *= scale;
-        dpixheight *= scale;
-        double x = (dwidth - dpixwidth) / 2;
-        double y = (dheight - dpixheight) / 2;
-        cairo_translate(cr, x, y);
-        cairo_scale(cr, scale, scale);
     } else {
-        double x = (dwidth - dpixwidth) / 2;
-        double y = (dheight - dpixheight) / 2;
-        if(x < 0) {
-            x = 0;
-        }
-        if(y < 0) {
-            y = 0;
-        }
-        cairo_translate(cr, (int)x, (int)y);
+        scale = 1 + ((double)imgviewer->zoom / (double)imgviewer->zoom_scale);
     }
+
+    dpixwidth *= scale;
+    dpixheight *= scale;
+    double x = (dwidth - dpixwidth) / 2;
+    double y = (dheight - dpixheight) / 2;
+    
+    x += imgviewer->transx;
+    y += imgviewer->transy;
+    
+    cairo_translate(cr, x, y);
+    cairo_scale(cr, scale, scale);
     
     gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
     cairo_paint(cr);
+    
+    imgviewer->prev_scale = scale;
 }
 
 void* ui_imageviewer_get(UiGeneric *g) {
@@ -240,3 +273,86 @@
        
     return 0;
 }
+
+#if GTK_MAJOR_VERSION >= 4
+
+gboolean ui_imageviewer_scroll(
+        GtkEventControllerScroll *widget,
+        gdouble dx,
+        gdouble dy,
+        gpointer userdata)
+{
+    UiImageViewer *imgviewer = userdata;
+    if(imgviewer->useradjustable) {
+        imgviewer->zoom -= dy;
+        if(imgviewer->zoom < -imgviewer->zoom_scale) {
+            imgviewer->zoom = -imgviewer->zoom_scale;
+        }
+        gtk_widget_queue_draw(imgviewer->widget);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+void ui_imageviewer_drag_begin_cb(
+        GtkGestureDrag* self,
+        gdouble start_x,
+        gdouble start_y,
+        gpointer userdata)
+{
+    UiImageViewer *imgviewer = userdata;
+    imgviewer->begin_transx = imgviewer->transx;
+    imgviewer->begin_transy = imgviewer->transy;
+}
+
+void ui_imageviewer_drag_end_cb(
+        GtkGestureDrag* self,
+        gdouble x,
+        gdouble y,
+        gpointer userdata)
+{
+    
+}
+
+void ui_imageviewer_drag_update_cb(
+        GtkGestureDrag* self,
+        gdouble x,
+        gdouble y,
+        gpointer userdata)
+{
+    UiImageViewer *imgviewer = userdata;
+    if(imgviewer->useradjustable) {
+        imgviewer->transx = imgviewer->begin_transx + x;
+        imgviewer->transy = imgviewer->begin_transy + y;
+        gtk_widget_queue_draw(imgviewer->widget);
+    }
+}
+
+#else
+
+gboolean ui_imageviewer_scroll_event(
+        GtkWidget *widget,
+        GdkEventScroll event,
+        gpointer userdata)
+{
+    printf("scroll event\n");
+    return FALSE;
+}
+
+gboolean ui_imageviewer_button_press_event(
+        GtkWidget *widget,
+        GdkEventButton event,
+        gpointer userdata)
+{
+    printf("button pressed\n");
+}
+
+gboolean ui_imageviewer_button_release_event(
+        GtkWidget *widget,
+        GdkEventButton event,
+        gpointer userdata)
+{
+    printf("button released\n");
+}
+
+#endif
--- a/ui/gtk/image.h	Sat Mar 29 18:17:01 2025 +0100
+++ b/ui/gtk/image.h	Sat Mar 29 20:03:25 2025 +0100
@@ -47,6 +47,14 @@
     UiBool adjustsize;
     UiBool useradjustable;
     GdkPixbuf *pixbuf;
+    
+    int zoom_scale;    
+    int transx;
+    int transy;
+    int begin_transx;
+    int begin_transy;
+    int zoom;
+    double prev_scale;
 } UiImageViewer;
 
 void ui_cairo_draw_image(UiImageViewer *imgviewer, cairo_t *cr, int width, int height);
@@ -55,6 +63,51 @@
 const char* ui_imageviewer_get_type(UiGeneric *g);
 int ui_imageviewer_set(UiGeneric *g, void *value, const char *type);
 
+#if GTK_MAJOR_VERSION >= 4
+
+gboolean ui_imageviewer_scroll(
+        GtkEventControllerScroll *widget,
+        gdouble dx,
+        gdouble dy,
+        gpointer userdata);
+
+void ui_imageviewer_drag_begin_cb(
+        GtkGestureDrag* self,
+        gdouble start_x,
+        gdouble start_y,
+        gpointer userdata);
+
+void ui_imageviewer_drag_end_cb(
+        GtkGestureDrag* self,
+        gdouble x,
+        gdouble y,
+        gpointer userdata);
+
+void ui_imageviewer_drag_update_cb(
+        GtkGestureDrag* self,
+        gdouble x,
+        gdouble y,
+        gpointer userdata);
+
+#else
+
+gboolean ui_imageviewer_scroll_event(
+        GtkWidget *widget,
+        GdkEventScroll event,
+        gpointer userdata);
+
+gboolean ui_imageviewer_button_press_event(
+        GtkWidget *widget,
+        GdkEventButton event,
+        gpointer userdata);
+
+gboolean ui_imageviewer_button_release_event(
+        GtkWidget *widget,
+        GdkEventButton event,
+        gpointer userdata);
+
+#endif
+
 #ifdef __cplusplus
 }
 #endif

mercurial