]> uap-core.de Git - note.git/commitdiff
limit embedded widget size to current textview size
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 21 Apr 2025 14:58:50 +0000 (16:58 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 21 Apr 2025 14:58:50 +0000 (16:58 +0200)
application/gtk-image.c
application/gtk-image.h
application/gtk-text.c
application/gtk-text.h

index fec2cd26ad16a3930f33b2ddb1633c44c4bdf52b..983bea2ec9d0d0938d12baf06f886fd793991c72 100644 (file)
 
 #if GTK_MAJOR_VERSION >= 4
 
-GtkWidget* embedded_image_create(GdkPixbuf *pix) {
-    GtkWidget *grid = gtk_grid_new();
-    gtk_widget_add_css_class(grid, "ui_test"); // TODO: replace with new class
-    
-    GdkTexture *texture = gdk_texture_new_for_pixbuf(pix);
-    GtkWidget *picture = gtk_picture_new_for_paintable(GDK_PAINTABLE(texture));
+static void embedded_image_adjust_size(EmbeddedWidget *em, int max_width) {
+    GtkWidget *picture = em->wdata1;
+    GdkTexture *texture = em->wdata2;
     
     double width = gdk_texture_get_width(texture);
     double height = gdk_texture_get_height(texture);
     
-    if(width > EDITOR_IMAGE_MAX_WIDTH) {
-        height = height * (EDITOR_IMAGE_MAX_WIDTH / width);
-        width = EDITOR_IMAGE_MAX_WIDTH;
+    printf("max width: %d\n", max_width);
+    if(width > max_width) {
+        height = height * (max_width / width);
+        width = max_width;
     }
     
     gtk_widget_set_size_request(picture, width, height);
+}
+
+GtkWidget* embedded_image_create(EmbeddedWidget *em, GdkPixbuf *pix) {
+    GtkWidget *grid = gtk_grid_new();
+    gtk_widget_add_css_class(grid, "ui_test"); // TODO: replace with new class
+    
+    GdkTexture *texture = gdk_texture_new_for_pixbuf(pix);
+    GtkWidget *picture = gtk_picture_new_for_paintable(GDK_PAINTABLE(texture));
     
     gtk_grid_attach(GTK_GRID(grid), picture, 0, 0, 1, 1);
     
+    em->wdata1 = picture;
+    em->wdata2 = texture;
+    em->adjust_size = embedded_image_adjust_size;
     
     return grid;
 }
 
 #else
 
-GtkWidget* embedded_image_create(GdkPixbuf *pix) {
+static void embedded_image_adjust_size(EmbeddedWidget *em, int max_width) {
+    GtkWidget *image = em->wdata1;
+    GdkPixmap *pix = em->wdata2;
+    
+    double width = gdk_pixbuf_get_width(pix);
+    double height = gdk_pixbuf_get_height(pix);
+    
+    if(width > max_width) {
+        height = height * (max_width / width);
+        width = max_width;
+    }
+    
+    gtk_widget_set_size_request(picture, width, height);
+}
+
+GtkWidget* embedded_image_create(EmbeddedWidget *em, GdkPixbuf *pix) {
     GtkWidget *image = gtk_image_new_from_pixbuf(pix);
     
     int width = gdk_pixbuf_get_width(pix);
     int height = gdk_pixbuf_get_height(pix);
     gtk_widget_set_size_request(image, width, height);
     
+    em->wdata1 = image;
+    em->wdata2 = pix;
+    em->adjust_size = embedded_image_adjust_size;
+    
     return image;
 }
 
index a710d75fd13ec6fc7bea7e30ab3dec99947d0969..6fe6b79ca15b9b113b58e12f2f574fa810d0eb5e 100644 (file)
@@ -33,9 +33,9 @@
 #include "note.h"
 #include "attachment.h"
 
-#define EDITOR_IMAGE_MAX_WIDTH 600
+#include "gtk-text.h"
 
-GtkWidget* embedded_image_create(GdkPixbuf *pix);
+GtkWidget* embedded_image_create(EmbeddedWidget *em, GdkPixbuf *pix);
 
 #endif /* GTK_IMAGE_H */
 
index 35dd2e1d071dd0dfbe8174356730913da377a1a5..41b7fb126176de8ba68deeaf7f535073fde5485d 100644 (file)
@@ -84,8 +84,6 @@ static gboolean editor_drop_cb(
         double y,
         NoteEditor *editor);
 
-static void editor_update_width(NoteEditor *editor);
-
 #else
 
 static gboolean editor_textview_event_after(GtkWidget *textview, GdkEvent *ev, NoteEditor *editor);
@@ -104,6 +102,9 @@ static void editor_update_width(NoteEditor *editor);
 
 #endif
 
+// different implementations for gtk versions
+static void editor_update_width(NoteEditor *editor);
+
 static void editor_realize(GtkWidget *unused, NoteEditor *editor) {
     editor_update_width(editor);
 }
@@ -177,7 +178,6 @@ void editor_init_textview(UiObject *obj, UIWIDGET textview) {
 
 static void editor_resize(NoteEditor *editor) {
     editor_update_width(editor);
-    printf("editor resize: %d\n", editor->width);
 }
 
 
@@ -250,6 +250,8 @@ static void editor_set_buffer_cb(
 #endif
         }
     }
+    
+    editor_update_width(editor);
 }
 
 static void em_remove_anchor(BufferEmbeddedObjects *em, GtkTextChildAnchor *anchor) {
@@ -326,25 +328,32 @@ static void editor_insert_image(NoteEditor *editor, Attachment *attachment, GtkT
     }
     
     GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(buffer, iter);
-    GtkWidget *image = embedded_image_create(pixbuf);
+    
+    // remember widget and store a reference in the textbuffer
+    // TODO: we need a cleanup strategy
+    EmbeddedWidget *em = malloc(sizeof(EmbeddedWidget));
+    memset(em, 0, sizeof(EmbeddedWidget));
+    
+    GtkWidget *image = embedded_image_create(em, pixbuf);
     gtk_text_view_add_child_at_anchor(textview, image, anchor);
 #if GTK_MAJOR_VERSION < 4
     gtk_widget_show_all(image);
 #endif
     
-    // remember widget and store a reference in the textbuffer
-    // TODO: we need a cleanup strategy
-    EmbeddedWidget *em = malloc(sizeof(EmbeddedWidget));
     em->widget = image;
     em->anchor = anchor;
     em->data1 = attachment;
-    em->data2 = NULL;
     em->serialize = md_serialize_image;
     g_object_ref(image);
     g_object_ref(anchor);
     
     g_object_set_data(G_OBJECT(anchor), "em", em);
     
+    int em_width = editor->width - EM_WIDGET_HPADDING;
+    if(em->adjust_size && em_width > 0) {
+        em->adjust_size(em, em_width);
+    }
+    
     BufferEmbeddedObjects *embedded_objects = g_object_get_data(G_OBJECT(buffer), "embedded");
     cxListAdd(embedded_objects->objects, em);
 }
@@ -435,10 +444,25 @@ static void editor_gtk4_resize(
     }   
 }
 
+static void editor_gtk4_draw_func(
+        GtkDrawingArea *drawing_area,
+        cairo_t *cr,
+        int width,
+        int height,
+        gpointer userdata)
+{
+    MainWindow *wdata = userdata;
+    NoteEditor *editor = g_object_get_data(G_OBJECT(ui_textarea_gettextwidget(wdata->textview)), "editor");
+    if(editor && editor->width == 0) {
+        editor_resize(editor);
+    }
+}
+
 GtkWidget* editor_gtk4_workaround(UiObject *obj, UiWidgetArgs args, void *userdata) {
     GtkWidget *drawingarea = gtk_drawing_area_new();
     //gtk_widget_add_css_class(drawingarea, "ui_test");
     gtk_widget_set_size_request(drawingarea, 10, 1);
+    gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(drawingarea), editor_gtk4_draw_func, userdata, NULL);
     g_signal_connect(drawingarea, "resize", G_CALLBACK(editor_gtk4_resize), userdata);
     return drawingarea;
 }
@@ -507,6 +531,7 @@ static gboolean editor_drop_cb(
 
 static void editor_update_width(NoteEditor *editor) {
     editor->width = gtk_widget_get_width(gtk_widget_get_parent(editor->textview));
+    editor_update_embedded_widgets(editor);
 }
 
 #else
@@ -591,6 +616,22 @@ void editor_try_follow_link(NoteEditor *editor, GtkTextIter *pos) {
     }
 }
 
+void editor_update_embedded_widgets(NoteEditor *editor) {
+    GtkTextView *textview = GTK_TEXT_VIEW(editor->textview);
+    GtkTextBuffer *buffer = gtk_text_view_get_buffer(textview);
+
+    BufferEmbeddedObjects *embedded_objects = g_object_get_data(G_OBJECT(buffer), "embedded");
+    int em_width = editor->width - EM_WIDGET_HPADDING;
+    if(embedded_objects && em_width > 0) {
+        CxIterator i = cxListIterator(embedded_objects->objects);
+        cx_foreach(EmbeddedWidget *, em, i) {
+            if(em->adjust_size) {
+                em->adjust_size(em, em_width);
+            }
+        }
+    }
+}
+
 static void buffer_embedded_objects_free(BufferEmbeddedObjects *em) {
     cxListFree(em->objects);
     free(em);
index c6eeaead4f1c4ab5edfece0afc4a160c99c42fce..1bed17ab5861a60901a35beac581f30a1239449c 100644 (file)
@@ -36,6 +36,8 @@
 extern "C" {
 #endif
     
+#define EM_WIDGET_HPADDING 60
+    
 typedef struct NoteEditor {
     UiObject *obj;
     GtkWidget *textview;
@@ -60,8 +62,13 @@ typedef struct EmbeddedWidget EmbeddedWidget;
 struct EmbeddedWidget {
     GtkWidget *widget;
     GtkTextChildAnchor *anchor;
+    int width;
+    int height;
+    void (*adjust_size)(EmbeddedWidget *em, int max_width);
     void *data1;
     void *data2;
+    void *wdata1; // wdata1/wdata2 filled by widget constructor
+    void *wdata2; // and used by adjust_size
     void (*serialize)(EmbeddedWidget *e, CxBuffer *out);
 };
 
@@ -69,6 +76,8 @@ typedef void (*set_style_cb)(MDActiveStyles *style, GtkTextTag *tag);
 
 void editor_try_follow_link(NoteEditor *editor, GtkTextIter *pos);
 
+void editor_update_embedded_widgets(NoteEditor *editor);
+
 void init_textbuf(GtkTextBuffer *buf);
 void init_tagtable(GtkTextTagTable *table);