/*
* 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:
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);
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,
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(
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(
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));
}
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");