]> uap-core.de Git - mizunara.git/commitdiff
add key event handler to the filesview widget
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 21 Jul 2025 19:23:26 +0000 (21:23 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 21 Jul 2025 19:23:26 +0000 (21:23 +0200)
mizunara/gtk-filesview.c

index 01a81befe62a87b89a3803dd47bfe57d03f5507c..7326f2e6064bfb024aa6cd2eee320f0d67d88359 100644 (file)
@@ -78,6 +78,15 @@ static void button_pressed(
         gdouble y,
         gpointer user_data);
 
+static gboolean key_pressed(
+    GtkEventControllerKey* self,
+    guint keyval,
+    guint keycode,
+    GdkModifierType state,
+    MzFilesView *view);
+
+
+
 static void mz_files_view_class_init(MzFilesViewClass *klass) {
     printf("mz_files_view_class_init\n");
     klass->parent_class.snapshot = mz_files_view_snapshot;
@@ -103,7 +112,9 @@ static void mz_files_view_init(MzFilesView *self) {
     // default item size
     self->item_width = 180;
     self->item_height = 170;
-      
+    
+    gtk_widget_set_focusable(GTK_WIDGET(self), TRUE);
+    
     // event handler
     GtkDragSource *dnd_source = gtk_drag_source_new();
     g_signal_connect(dnd_source, "prepare", G_CALLBACK(dnd_prepare), self);
@@ -123,6 +134,10 @@ static void mz_files_view_init(MzFilesView *self) {
     GtkGesture *click = gtk_gesture_click_new ();
     g_signal_connect(click, "pressed", G_CALLBACK(button_pressed), self);
     gtk_widget_add_controller(GTK_WIDGET(self), GTK_EVENT_CONTROLLER(click));
+    
+    GtkEventController *keyctrl = gtk_event_controller_key_new();
+    g_signal_connect(keyctrl, "key-pressed", G_CALLBACK(key_pressed), self);
+    gtk_widget_add_controller(GTK_WIDGET(self), keyctrl);
 }
 
 void mz_files_view_dispose(GObject *object) {
@@ -495,6 +510,7 @@ static void drag_begin_cb(
 {
     MzFilesView *view = user_data;
     printf("drag_begin_cb: %f\n", start_x);
+    gtk_widget_grab_focus((GtkWidget*)view);
     
     // update selection
     int item_width = view->item_width;
@@ -654,6 +670,80 @@ static void button_pressed(
     }
 }
 
+static gboolean key_pressed(
+    GtkEventControllerKey* self,
+    guint keyval,
+    guint keycode,
+    GdkModifierType state,
+    MzFilesView *view)
+{
+    int x = 0;
+    int y = 0;
+    switch (keyval) {
+        case GDK_KEY_Left:
+            x--;
+            break;
+        case GDK_KEY_Right:
+            x++;
+            break;
+        case GDK_KEY_Up:
+            y--;
+            break;
+        case GDK_KEY_Down:
+            y++;
+            break;
+        default:
+            return FALSE;
+    }
+    
+    if(view->numitems == 0) {
+        return TRUE;
+    }
+    
+    if(view->selection_count == 0) {
+        view->items[0].isselected = TRUE;
+    } else {
+        // find first selection and unselect everything else
+        size_t selx = -1;
+        size_t sely = -1;
+        size_t selcount = view->selection_count;
+        for(size_t i=0;i<view->numitems;i++) {
+            if(view->items[i].isselected) {
+                if(selx == -1) {
+                    selx = i % view->current_items_per_line;
+                    sely = i / view->current_items_per_line;
+                }
+                view->items[i].isselected = FALSE;
+                if(--selcount == 0) {
+                    break;
+                }
+            }
+        }
+        
+        selx += x;
+        sely += y;
+        if(selx >= view->current_items_per_line) {
+            selx = 0;
+            sely++;
+        }
+        if(selx < 0) {
+            selx = view->current_items_per_line-1;
+            sely--;
+        }
+        
+        if(sely < 0) {
+            return TRUE;
+        }
+        
+        size_t selected_index = sely * view->current_items_per_line + selx;
+        if(selected_index < view->numitems) {
+            view->items[selected_index].isselected = TRUE;
+        }
+    }
+    
+    gtk_widget_queue_draw(GTK_WIDGET(view));
+    return TRUE;
+}
 
 /* -------------------------- public -------------------------- */