From: Olaf Wintermann Date: Sat, 25 Jan 2025 16:24:57 +0000 (+0100) Subject: add MzFilesView selection handler/renderer X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=22d5e360314c0136e7048d0d563b73d9c9f54aaf;p=mizunara.git add MzFilesView selection handler/renderer --- diff --git a/mizunara/gtk-filesview.c b/mizunara/gtk-filesview.c index ab0ee6b..e86e72a 100644 --- a/mizunara/gtk-filesview.c +++ b/mizunara/gtk-filesview.c @@ -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;inumitems;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;inumitems;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"); diff --git a/mizunara/gtk-filesview.h b/mizunara/gtk-filesview.h index 30fbb4d..391fb27 100644 --- a/mizunara/gtk-filesview.h +++ b/mizunara/gtk-filesview.h @@ -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 +#include #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 {