]> uap-core.de Git - mizunara.git/commitdiff
add MzFilesView selection handler/renderer
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sat, 25 Jan 2025 16:24:57 +0000 (17:24 +0100)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sat, 25 Jan 2025 16:24:57 +0000 (17:24 +0100)
mizunara/gtk-filesview.c
mizunara/gtk-filesview.h

index ab0ee6b6685c4841425b6ec31d710ba5be272ed5..e86e72abaaa87fb2a4f4c5daac0acc56a155b611 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2024 Olaf Wintermann. All rights reserved.
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -94,7 +94,7 @@ MzFilesView* mz_files_view_new(void) {
 
 void mz_files_view_snapshot(GtkWidget *widget, GtkSnapshot *snapshot) {
     MzFilesView *view = (MzFilesView*)widget;
-    printf("MzFilesView snapshot\n");
+    //printf("MzFilesView snapshot\n");
     
     int width = gtk_widget_get_width(widget);
     int height = gtk_widget_get_height(widget);
@@ -109,48 +109,141 @@ void mz_files_view_snapshot(GtkWidget *widget, GtkSnapshot *snapshot) {
     
     int items_per_line = width / item_width;
     
-    if(view->numitems == 0) {
-        return;
+    int highlight_col_start = view->drag_start_col;
+    int highlight_row_start = view->drag_start_row;
+    int highlight_col_end = view->drag_col;
+    int highlight_row_end = view->drag_row;
+    if(highlight_col_start > highlight_col_end) {
+        int tmp = highlight_col_end;
+        highlight_col_end = highlight_col_start;
+        highlight_col_start = tmp;
+    }
+    if(highlight_row_start > highlight_row_end) {
+        int tmp = highlight_row_end;
+        highlight_row_end = highlight_row_start;
+        highlight_row_start = tmp;
     }
     
-    GtkAllocation img_alloc;
-    GtkAllocation label_alloc;
-    img_alloc.width = 100;
-    img_alloc.height = 100;
-    label_alloc.width = 160;
-    label_alloc.height = 60;
+    GdkRGBA highlight_color;
+    gdk_rgba_parse(&highlight_color, "#0a0a0a0a");
     
-    int img_x_offset = (item_width - img_alloc.width) / 2;
-    int img_y_offset = (item_height - img_alloc.height - label_alloc.height) / 2;
-    int label_x_offset = (item_width - label_alloc.width) / 2;
+    GdkRGBA selection_color;
+    gdk_rgba_parse(&selection_color, "#2f0a0a1f");
     
-    int x = 0;
-    int y = 0;
-    for(size_t i=0;i<view->numitems;i++) {
-        img_alloc.x = MZ_GRID_VIEW_PADDING_LEFT + img_x_offset + x * item_width;
-        img_alloc.y = MZ_GRID_VIEW_PADDING_TOP + img_y_offset + y * item_height;
-        gtk_widget_size_allocate(view->items[i].image, &img_alloc, -1);
-        label_alloc.x = MZ_GRID_VIEW_PADDING_LEFT + x * item_width + label_x_offset;
-        label_alloc.y = img_alloc.y + img_alloc.height;
-        gtk_widget_size_allocate(view->items[i].label, &label_alloc, -1);
-        
-        PangoLayout *layout = gtk_label_get_layout(GTK_LABEL(view->items[i].label));
-        pango_layout_set_width(layout, 160 * PANGO_SCALE);
-        pango_layout_set_height(layout, 60 * PANGO_SCALE);
-        pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
-        pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_MIDDLE);
-        pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
+    graphene_rect_t highlight_rect;
+    highlight_rect.size.width =  item_width-5; 
+    highlight_rect.size.height = item_height-5;
+    
+    if(view->numitems > 0) {
+        GtkAllocation img_alloc;
+        GtkAllocation label_alloc;
+        img_alloc.width = 100;
+        img_alloc.height = 100;
+        label_alloc.width = 160;
+        label_alloc.height = 60;
+
+        int img_x_offset = (item_width - img_alloc.width) / 2;
+        int img_y_offset = (item_height - img_alloc.height - label_alloc.height) / 2;
+        int label_x_offset = (item_width - label_alloc.width) / 2;
+
+        int handle_selection = view->drag || view->update_selection;
         
-        x++;
-        if(x >= items_per_line) {
-            x = 0;
-            y++;
+        int x = 0;
+        int y = 0;
+        for(size_t i=0;i<view->numitems;i++) {
+            int base_x = x * item_width + MZ_GRID_VIEW_PADDING_LEFT;
+            int base_y = y * item_height + MZ_GRID_VIEW_PADDING_TOP;
+            if(handle_selection && x >= highlight_col_start && x <= highlight_col_end && y >= highlight_row_start && y <= highlight_row_end) {
+                if(view->drag) {
+                    highlight_rect.origin.x = base_x + 5;
+                    highlight_rect.origin.y = base_y + 5;
+                    gtk_snapshot_append_color(snapshot, &highlight_color, &highlight_rect);
+                } else {
+                    view->items[i].isselected = 1;
+                }
+            } else if (view->update_selection == 1) {
+                view->items[i].isselected = 0;
+            }
+            
+            if(view->items[i].isselected) {
+                highlight_rect.origin.x = base_x + 5;
+                highlight_rect.origin.y = base_y + 5;
+                gtk_snapshot_append_color(snapshot, &selection_color, &highlight_rect);
+            }
+            
+            img_alloc.x = MZ_GRID_VIEW_PADDING_LEFT + img_x_offset + x * item_width;
+            img_alloc.y = MZ_GRID_VIEW_PADDING_TOP + img_y_offset + y * item_height;
+            gtk_widget_size_allocate(view->items[i].image, &img_alloc, -1);
+            label_alloc.x = MZ_GRID_VIEW_PADDING_LEFT + x * item_width + label_x_offset;
+            label_alloc.y = img_alloc.y + img_alloc.height;
+            gtk_widget_size_allocate(view->items[i].label, &label_alloc, -1);
+
+            PangoLayout *layout = gtk_label_get_layout(GTK_LABEL(view->items[i].label));
+            pango_layout_set_width(layout, 160 * PANGO_SCALE);
+            pango_layout_set_height(layout, 60 * PANGO_SCALE);
+            pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
+            pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_MIDDLE);
+            pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
+
+            x++;
+            if(x >= items_per_line) {
+                x = 0;
+                y++;
+            }
         }
     }
-    
+
     // draw children
     GtkWidgetClass *cls = mz_files_view_parent_class;
     cls->snapshot(widget, snapshot);
+    
+    // draw selection rectangle
+    if(view->drag) {
+        GdkRGBA fill_color;
+        GdkRGBA border_color;
+        gdk_rgba_parse(&fill_color, "#3333331f");
+        gdk_rgba_parse(&border_color, "#1111114f");
+        
+        int x = view->drag_start_x;
+        int y = view->drag_start_y;
+        int w = view->drag_width;
+        int h = view->drag_height;
+        if(w < 0) {
+            x += w;
+            w = -w;
+        }
+        if(h < 0) {
+            y += h;
+            h = -h;
+        }
+        
+        GskRoundedRect rect;
+        rect.bounds = GRAPHENE_RECT_INIT(x, y, w, h);
+        for(int i=0;i<4;i++) {
+            rect.corner[i].width = 8;
+            rect.corner[i].height = 8;
+        }
+        
+        GskRenderNode *rect_node = gsk_color_node_new(
+                &fill_color,
+                &rect.bounds);
+        GskRenderNode *node = gsk_rounded_clip_node_new(rect_node, &rect);
+        
+        gtk_snapshot_append_node(snapshot, node);
+        
+        gtk_snapshot_append_border(snapshot, &rect, (float[4]){1,1,1,1}, (GdkRGBA[4]){border_color,border_color,border_color,border_color});
+        
+        
+        
+        /*
+        gtk_snapshot_append_color(
+                snapshot,
+                &fill_color,
+                &GRAPHENE_RECT_INIT(view->drag_start_x, view->drag_start_y, view->drag_width, view->drag_height));
+        */
+    }
+    
+    view->update_selection = 0;
 }
 
 void mz_files_view_measure(GtkWidget *widget,
@@ -213,7 +306,31 @@ static void drag_begin_cb(
         gdouble start_y,
         gpointer user_data)
 {
+    MzFilesView *view = user_data;
+    printf("drag_begin_cb\n");
     
+    // update selection
+    int item_selection_width = 160;
+    int item_selection_height = 160;
+    int selection_offset_x = 5;
+    int selection_offset_y = 5;
+    int item_width = 170;
+    int item_height = 170;
+    
+    int col = start_x / item_width;
+    int row = start_y / item_height;
+    
+    view->drag = TRUE;
+    view->drag_start_x = start_x;
+    view->drag_start_y = start_y;
+    view->drag_width = 0;
+    view->drag_height = 0;
+    view->drag_start_col = col;
+    view->drag_start_row = row;
+    view->drag_col = col;
+    view->drag_row = row;
+    view->update_selection = 0;
+    gtk_widget_queue_draw(GTK_WIDGET(view));
 }
 
 static void drag_end_cb(
@@ -222,7 +339,11 @@ static void drag_end_cb(
         gdouble y,
         gpointer user_data)
 {
+    MzFilesView *view = user_data;
+    view->drag = FALSE;
+    view->update_selection = 1;
     
+    gtk_widget_queue_draw(GTK_WIDGET(view));
 }
 
 static void drag_update_cb(
@@ -231,7 +352,24 @@ static void drag_update_cb(
         gdouble y,
         gpointer user_data)
 {
+    MzFilesView *view = user_data;
+    view->drag_width = x;
+    view->drag_height = y;
     
+    // update selection
+    int item_selection_width = 160;
+    int item_selection_height = 160;
+    int selection_offset_x = 5;
+    int selection_offset_y = 5;
+    int item_width = 170;
+    int item_height = 170;
+    
+    int col = (view->drag_start_x + x) / item_width;
+    int row = (view->drag_start_y + y) / item_height;
+    view->drag_col = col;
+    view->drag_row = row;
+    
+    gtk_widget_queue_draw(GTK_WIDGET(view));
 }
 
 
@@ -269,6 +407,7 @@ void mz_update_files_view(MzFilesView *view, FilesSection *sections, size_t nums
             MzIconGadget gadget;
             gadget.image = gtk_image_new_from_paintable(GDK_PAINTABLE(S_ISDIR(finfo->mode) ? dir_icon : file_icon));
             gadget.label = gtk_label_new(finfo->name);
+            gadget.isselected = 0;
             gtk_label_set_yalign(GTK_LABEL(gadget.label), 0.0);
             //gtk_widget_add_css_class(gadget.label, "ui_test");
             
index 30fbb4dafc06879d40cebf95e7cc3e8a0d432f89..391fb27cd3ad2fc08b279e11addeddee579d79fd 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2024 Olaf Wintermann. All rights reserved.
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -33,6 +33,7 @@
 #include "filebrowser.h"
 
 #include <cx/array_list.h>
+#include <stdbool.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -43,6 +44,7 @@ extern "C" {
 typedef struct MzIconGadget {
     GtkWidget *image;
     GtkWidget *label;
+    int isselected;
 } MzIconGadget;
   
 typedef struct MzViewSection {
@@ -60,6 +62,18 @@ typedef struct MzFilesView {
     int current_width;
     MzViewSection *sections;
     size_t numsections;
+    
+    int drag_start_x;
+    int drag_start_y;
+    int drag_width;
+    int drag_height;
+    int drag_start_col;
+    int drag_start_row;
+    int drag_col;
+    int drag_row;
+    bool drag;
+    
+    int update_selection; // 0: no update, 1: set selection, 2: add selection
 } MzFilesView;
 
 typedef struct MzFilesViewClass {