[gnome-builder/wip/gtk4-port: 471/495] tree: port IdeTree to GTK 4
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/gtk4-port: 471/495] tree: port IdeTree to GTK 4
- Date: Thu, 24 Mar 2022 23:51:40 +0000 (UTC)
commit 5e9e47ab60b1730e45216041572c4c3ec5cf08cd
Author: Christian Hergert <chergert redhat com>
Date: Fri Sep 24 12:58:13 2021 -0700
tree: port IdeTree to GTK 4
This still needs some additional work after an initial port.
* Use Icons for Status cell renderer so we get texture caching
* Make DnD work, which will need drop-target work
src/libide/tree/ide-cell-renderer-status.c | 44 +++----
src/libide/tree/ide-tree-addin.c | 18 +--
src/libide/tree/ide-tree-addin.h | 40 +++---
src/libide/tree/ide-tree-model.c | 47 ++++---
src/libide/tree/ide-tree-node.c | 1 -
src/libide/tree/ide-tree.c | 191 ++++++++++++++++-------------
src/libide/tree/ide-tree.h | 52 ++++----
7 files changed, 204 insertions(+), 189 deletions(-)
---
diff --git a/src/libide/tree/ide-cell-renderer-status.c b/src/libide/tree/ide-cell-renderer-status.c
index 29bc39e45..ea082a5ad 100644
--- a/src/libide/tree/ide-cell-renderer-status.c
+++ b/src/libide/tree/ide-cell-renderer-status.c
@@ -80,50 +80,50 @@ ide_cell_renderer_status_get_preferred_width (GtkCellRenderer *cell,
}
static void
-ide_cell_renderer_status_render (GtkCellRenderer *cell,
- cairo_t *cr,
- GtkWidget *widget,
- const GdkRectangle *bg_area,
- const GdkRectangle *cell_area,
- GtkCellRendererState state)
+ide_cell_renderer_status_snapshot (GtkCellRenderer *cell,
+ GtkSnapshot *snapshot,
+ GtkWidget *widget,
+ const GdkRectangle *bg_area,
+ const GdkRectangle *cell_area,
+ GtkCellRendererState state)
{
IdeCellRendererStatus *self = (IdeCellRendererStatus *)cell;
GtkStyleContext *style_context;
+ cairo_t *cr;
GdkRGBA color;
g_assert (IDE_IS_CELL_RENDERER_STATUS (self));
- g_assert (cr != NULL);
g_assert (GTK_IS_WIDGET (widget));
g_assert (bg_area != NULL);
g_assert (cell_area != NULL);
+ /* FIXME-GTK4: This should be ported to use symbolic icons instead */
+
if (self->flags == 0)
return;
style_context = gtk_widget_get_style_context (widget);
- gtk_style_context_save (style_context);
-
- if (state & GTK_CELL_RENDERER_SELECTED)
- gtk_style_context_set_state (style_context,
- gtk_style_context_get_state (style_context) & GTK_STATE_FLAG_SELECTED);
- gtk_style_context_get_color (style_context,
- gtk_style_context_get_state (style_context),
- &color);
- gdk_cairo_set_source_rgba (cr, &color);
+ gtk_style_context_get_color (style_context, &color);
+
+ cr = gtk_snapshot_append_cairo (snapshot,
+ &GRAPHENE_RECT_INIT (cell_area->x,
+ cell_area->y,
+ cell_area->width,
+ cell_area->height));
cairo_arc (cr,
- cell_area->x + cell_area->width - RPAD - (CELL_WIDTH/2),
- cell_area->y + (cell_area->height / 2),
+ cell_area->width - RPAD - (CELL_WIDTH/2),
+ (cell_area->height / 2),
3,
0,
M_PI * 2);
+ gdk_cairo_set_source_rgba (cr, &color);
if (self->flags & IDE_TREE_NODE_FLAGS_ADDED)
cairo_fill_preserve (cr);
-
cairo_stroke (cr);
- gtk_style_context_restore (style_context);
+ cairo_destroy (cr);
}
static void
@@ -175,7 +175,7 @@ ide_cell_renderer_status_class_init (IdeCellRendererStatusClass *klass)
renderer_class->get_preferred_height = ide_cell_renderer_status_get_preferred_height;
renderer_class->get_preferred_width = ide_cell_renderer_status_get_preferred_width;
- renderer_class->render = ide_cell_renderer_status_render;
+ renderer_class->snapshot = ide_cell_renderer_status_snapshot;
properties [PROP_FLAGS] =
g_param_spec_uint ("flags",
@@ -183,7 +183,7 @@ ide_cell_renderer_status_class_init (IdeCellRendererStatusClass *klass)
"The flags for the state",
0, G_MAXUINT, 0,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
+
g_object_class_install_properties (object_class, N_PROPS, properties);
}
diff --git a/src/libide/tree/ide-tree-addin.c b/src/libide/tree/ide-tree-addin.c
index 973ce7ffa..c8a86731d 100644
--- a/src/libide/tree/ide-tree-addin.c
+++ b/src/libide/tree/ide-tree-addin.c
@@ -67,7 +67,7 @@ static void
ide_tree_addin_real_node_dropped_async (IdeTreeAddin *self,
IdeTreeNode *drag_node,
IdeTreeNode *drop_node,
- GtkSelectionData *selection,
+ const GValue *value,
GdkDragAction actions,
GCancellable *cancellable,
GAsyncReadyCallback callback,
@@ -298,17 +298,17 @@ ide_tree_addin_node_draggable (IdeTreeAddin *self,
}
gboolean
-ide_tree_addin_node_droppable (IdeTreeAddin *self,
- IdeTreeNode *drag_node,
- IdeTreeNode *drop_node,
- GtkSelectionData *selection)
+ide_tree_addin_node_droppable (IdeTreeAddin *self,
+ IdeTreeNode *drag_node,
+ IdeTreeNode *drop_node,
+ const GValue *value)
{
g_return_val_if_fail (IDE_IS_TREE_ADDIN (self), FALSE);
g_return_val_if_fail (!drag_node || IDE_IS_TREE_NODE (drag_node), FALSE);
g_return_val_if_fail (!drop_node || IDE_IS_TREE_NODE (drop_node), FALSE);
if (IDE_TREE_ADDIN_GET_IFACE (self)->node_droppable)
- return IDE_TREE_ADDIN_GET_IFACE (self)->node_droppable (self, drag_node, drop_node, selection);
+ return IDE_TREE_ADDIN_GET_IFACE (self)->node_droppable (self, drag_node, drop_node, value);
return FALSE;
}
@@ -317,7 +317,7 @@ void
ide_tree_addin_node_dropped_async (IdeTreeAddin *self,
IdeTreeNode *drag_node,
IdeTreeNode *drop_node,
- GtkSelectionData *selection,
+ const GValue *value,
GdkDragAction actions,
GCancellable *cancellable,
GAsyncReadyCallback callback,
@@ -327,13 +327,13 @@ ide_tree_addin_node_dropped_async (IdeTreeAddin *self,
g_return_if_fail (IDE_IS_TREE_ADDIN (self));
g_return_if_fail (!drag_node || IDE_IS_TREE_NODE (drag_node));
g_return_if_fail (!drop_node || IDE_IS_TREE_NODE (drop_node));
- g_return_if_fail (selection != NULL);
+ g_return_if_fail (value != NULL);
g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
IDE_TREE_ADDIN_GET_IFACE (self)->node_dropped_async (self,
drag_node,
drop_node,
- selection,
+ value,
actions,
cancellable,
callback,
diff --git a/src/libide/tree/ide-tree-addin.h b/src/libide/tree/ide-tree-addin.h
index 92275620d..6dce9936a 100644
--- a/src/libide/tree/ide-tree-addin.h
+++ b/src/libide/tree/ide-tree-addin.h
@@ -28,9 +28,9 @@
G_BEGIN_DECLS
-#define IDE_TYPE_TREE_ADDIN (ide_tree_addin_get_type ())
+#define IDE_TYPE_TREE_ADDIN (ide_tree_addin_get_type())
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
G_DECLARE_INTERFACE (IdeTreeAddin, ide_tree_addin, IDE, TREE_ADDIN, GObject)
struct _IdeTreeAddinInterface
@@ -72,11 +72,11 @@ struct _IdeTreeAddinInterface
gboolean (*node_droppable) (IdeTreeAddin *self,
IdeTreeNode *drag_node,
IdeTreeNode *drop_node,
- GtkSelectionData *selection);
+ const GValue *value);
void (*node_dropped_async) (IdeTreeAddin *self,
IdeTreeNode *drag_node,
IdeTreeNode *drop_node,
- GtkSelectionData *selection,
+ const GValue *value,
GdkDragAction actions,
GCancellable *cancellable,
GAsyncReadyCallback callback,
@@ -86,62 +86,62 @@ struct _IdeTreeAddinInterface
GError **error);
};
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
void ide_tree_addin_load (IdeTreeAddin *self,
IdeTree *tree,
IdeTreeModel *model);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
void ide_tree_addin_unload (IdeTreeAddin *self,
IdeTree *tree,
IdeTreeModel *model);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
void ide_tree_addin_build_node (IdeTreeAddin *self,
IdeTreeNode *node);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
void ide_tree_addin_build_children_async (IdeTreeAddin *self,
IdeTreeNode *node,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
gboolean ide_tree_addin_build_children_finish (IdeTreeAddin *self,
GAsyncResult *result,
GError **error);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
gboolean ide_tree_addin_node_activated (IdeTreeAddin *self,
IdeTree *tree,
IdeTreeNode *node);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
void ide_tree_addin_selection_changed (IdeTreeAddin *self,
IdeTreeNode *selection);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
void ide_tree_addin_node_expanded (IdeTreeAddin *self,
IdeTreeNode *node);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
void ide_tree_addin_node_collapsed (IdeTreeAddin *self,
IdeTreeNode *node);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
gboolean ide_tree_addin_node_draggable (IdeTreeAddin *self,
IdeTreeNode *node);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
gboolean ide_tree_addin_node_droppable (IdeTreeAddin *self,
IdeTreeNode *drag_node,
IdeTreeNode *drop_node,
- GtkSelectionData *selection);
-IDE_AVAILABLE_IN_3_32
+ const GValue *value);
+IDE_AVAILABLE_IN_ALL
void ide_tree_addin_node_dropped_async (IdeTreeAddin *self,
IdeTreeNode *drag_node,
IdeTreeNode *drop_node,
- GtkSelectionData *selection,
+ const GValue *value,
GdkDragAction actions,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
gboolean ide_tree_addin_node_dropped_finish (IdeTreeAddin *self,
GAsyncResult *result,
GError **error);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
void ide_tree_addin_cell_data_func (IdeTreeAddin *self,
IdeTreeNode *node,
GtkCellRenderer *cell);
diff --git a/src/libide/tree/ide-tree-model.c b/src/libide/tree/ide-tree-model.c
index a9318e871..aa6c7e467 100644
--- a/src/libide/tree/ide-tree-model.c
+++ b/src/libide/tree/ide-tree-model.c
@@ -46,7 +46,7 @@ typedef struct
{
IdeTreeNode *drag_node;
IdeTreeNode *drop_node;
- GtkSelectionData *selection;
+ GValue value;
GdkDragAction actions;
gint n_active;
} DragDataReceived;
@@ -80,7 +80,7 @@ drag_data_received_free (DragDataReceived *data)
g_clear_object (&data->drag_node);
g_clear_object (&data->drop_node);
- g_clear_pointer (&data->selection, gtk_selection_data_free);
+ g_value_unset (&data->value);
g_slice_free (DragDataReceived, data);
}
@@ -1378,19 +1378,17 @@ ide_tree_model_row_draggable (GtkTreeDragSource *source,
return state.draggable;
}
-static gboolean
+static GdkContentProvider *
ide_tree_model_drag_data_get (GtkTreeDragSource *source,
- GtkTreePath *path,
- GtkSelectionData *selection)
+ GtkTreePath *path)
{
IdeTreeModel *self = (IdeTreeModel *)source;
g_assert (IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_TREE_MODEL (self));
g_assert (path != NULL);
- g_assert (selection != NULL);
- return gtk_tree_set_row_drag_data (selection, GTK_TREE_MODEL (self), path);
+ return gtk_tree_create_row_drag_content (GTK_TREE_MODEL (self), path);
}
static gboolean
@@ -1471,7 +1469,7 @@ ide_tree_model_drag_data_received_cb (IdeExtensionSetAdapter *set,
ide_tree_addin_node_dropped_async (addin,
state->drag_node,
state->drop_node,
- state->selection,
+ &state->value,
state->actions,
NULL,
ide_tree_model_drag_data_received_addin_cb,
@@ -1479,9 +1477,9 @@ ide_tree_model_drag_data_received_cb (IdeExtensionSetAdapter *set,
}
static gboolean
-ide_tree_model_drag_data_received (GtkTreeDragDest *dest,
- GtkTreePath *path,
- GtkSelectionData *selection)
+ide_tree_model_drag_data_received (GtkTreeDragDest *dest,
+ GtkTreePath *path,
+ const GValue *value)
{
IdeTreeModel *self = (IdeTreeModel *)dest;
g_autoptr(GtkTreePath) source_path = NULL;
@@ -1495,9 +1493,9 @@ ide_tree_model_drag_data_received (GtkTreeDragDest *dest,
g_assert (IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_TREE_MODEL (self));
g_assert (path != NULL);
- g_assert (selection != NULL);
+ g_assert (value != NULL);
- if (gtk_tree_get_row_drag_data (selection, &source_model, &source_path))
+ if (gtk_tree_get_row_drag_data (value, &source_model, &source_path))
{
if (IDE_IS_TREE_MODEL (source_model))
{
@@ -1511,10 +1509,9 @@ ide_tree_model_drag_data_received (GtkTreeDragDest *dest,
state = g_slice_new0 (DragDataReceived);
g_set_object (&state->drag_node, drag_node);
g_set_object (&state->drop_node, drop_node);
- state->selection = gtk_selection_data_copy (selection);
+ g_value_copy (value, &state->value);
state->actions = _ide_tree_get_drop_actions (self->tree);
-
task = ide_task_new (self, NULL, NULL, NULL);
ide_task_set_source_tag (task, ide_tree_model_drag_data_received);
ide_task_set_task_data (task, state, drag_data_received_free);
@@ -1538,7 +1535,7 @@ ide_tree_model_row_drop_possible_cb (IdeExtensionSetAdapter *set,
struct {
IdeTreeNode *drag_node;
IdeTreeNode *drop_node;
- GtkSelectionData *selection;
+ const GValue *value;
gboolean drop_possible;
} *state = user_data;
@@ -1547,18 +1544,18 @@ ide_tree_model_row_drop_possible_cb (IdeExtensionSetAdapter *set,
g_assert (plugin_info != NULL);
g_assert (IDE_IS_TREE_ADDIN (exten));
g_assert (state != NULL);
- g_assert (state->selection != NULL);
+ g_assert (state->value != NULL);
state->drop_possible |= ide_tree_addin_node_droppable (IDE_TREE_ADDIN (exten),
state->drag_node,
state->drop_node,
- state->selection);
+ state->value);
}
static gboolean
-ide_tree_model_row_drop_possible (GtkTreeDragDest *dest,
- GtkTreePath *path,
- GtkSelectionData *selection)
+ide_tree_model_row_drop_possible (GtkTreeDragDest *dest,
+ GtkTreePath *path,
+ const GValue *value)
{
IdeTreeModel *self = (IdeTreeModel *)dest;
g_autoptr(GtkTreePath) source_path = NULL;
@@ -1569,16 +1566,16 @@ ide_tree_model_row_drop_possible (GtkTreeDragDest *dest,
struct {
IdeTreeNode *drag_node;
IdeTreeNode *drop_node;
- GtkSelectionData *selection;
+ const GValue *value;
gboolean drop_possible;
} state;
g_assert (IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_TREE_MODEL (self));
g_assert (path != NULL);
- g_assert (selection != NULL);
+ g_assert (value != NULL);
- if (gtk_tree_get_row_drag_data (selection, &source_model, &source_path))
+ if (gtk_tree_get_row_drag_data (value, &source_model, &source_path))
{
if (IDE_IS_TREE_MODEL (source_model))
{
@@ -1603,7 +1600,7 @@ ide_tree_model_row_drop_possible (GtkTreeDragDest *dest,
state.drag_node = drag_node;
state.drop_node = drop_node;
- state.selection = selection;
+ state.value = value;
state.drop_possible = FALSE;
ide_extension_set_adapter_foreach (self->addins,
diff --git a/src/libide/tree/ide-tree-node.c b/src/libide/tree/ide-tree-node.c
index 200b9ff70..680f48a03 100644
--- a/src/libide/tree/ide-tree-node.c
+++ b/src/libide/tree/ide-tree-node.c
@@ -1723,7 +1723,6 @@ ide_tree_node_show_popover_timeout_cb (gpointer data)
break;
}
- gtk_popover_set_relative_to (popreq->popover, GTK_WIDGET (popreq->tree));
gtk_popover_set_pointing_to (popreq->popover, &rect);
gtk_popover_popup (popreq->popover);
diff --git a/src/libide/tree/ide-tree.c b/src/libide/tree/ide-tree.c
index 2c6dce4ec..837e252fc 100644
--- a/src/libide/tree/ide-tree.c
+++ b/src/libide/tree/ide-tree.c
@@ -32,6 +32,13 @@
#include "ide-tree-node.h"
#include "ide-tree-private.h"
+/* FIXME-GTK4:
+ *
+ * We still need DnD work here but that has changed so much
+ * that it would help to have a plugin using this to ensure
+ * we're porting it correctly.
+ */
+
typedef struct
{
/* This #GCancellable will be automatically cancelled when the widget is
@@ -392,9 +399,8 @@ ide_tree_row_collapsed (GtkTreeView *tree_view,
static void
ide_tree_popup (IdeTree *self,
IdeTreeNode *node,
- GdkEventButton *event,
- gint target_x,
- gint target_y)
+ double target_x,
+ double target_y)
{
IdeTreePrivate *priv = ide_tree_get_instance_private (self);
const GdkRectangle area = { target_x, target_y, 0, 0 };
@@ -408,89 +414,57 @@ ide_tree_popup (IdeTree *self,
ide_tree_show_popover_at_node (self, node, priv->popover);
}
-static gboolean
-ide_tree_button_press_event (GtkWidget *widget,
- GdkEventButton *event)
+static void
+ide_tree_click_pressed_cb (IdeTree *self,
+ int n_presses,
+ double x,
+ double y,
+ GtkGestureClick *gesture)
{
- IdeTree *self = (IdeTree *)widget;
+ g_autoptr(GtkTreePath) path = NULL;
IdeTreeModel *model;
+ int cell_y;
g_assert (IDE_IS_TREE (self));
- g_assert (event != NULL);
-
- if ((model = ide_tree_get_model (self)) &&
- (event->type == GDK_BUTTON_PRESS) &&
- (event->button == GDK_BUTTON_SECONDARY))
- {
- g_autoptr(GtkTreePath) path = NULL;
- gint cell_y;
+ g_assert (GTK_IS_GESTURE_CLICK (gesture));
- if (!gtk_widget_has_focus (GTK_WIDGET (self)))
- gtk_widget_grab_focus (GTK_WIDGET (self));
+ if (!(model = ide_tree_get_model (self)))
+ return;
- gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (self),
- event->x,
- event->y,
- &path,
- NULL,
- NULL,
- &cell_y);
- if (path == NULL)
- {
- ide_tree_unselect (self);
- }
- else
- {
- GtkAllocation alloc;
- GtkTreeIter iter;
+ if (!gtk_widget_has_focus (GTK_WIDGET (self)))
+ gtk_widget_grab_focus (GTK_WIDGET (self));
- gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
-
- if (gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path))
- {
- IdeTreeNode *node;
+ gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (self),
+ x,
+ y,
+ &path,
+ NULL,
+ NULL,
+ &cell_y);
- node = ide_tree_model_get_node (IDE_TREE_MODEL (model), &iter);
- ide_tree_select (self, node);
- ide_tree_popup (self, node, event, alloc.x + alloc.width, event->y - cell_y);
- }
- }
-
- return GDK_EVENT_STOP;
+ if (path == NULL)
+ {
+ ide_tree_unselect (self);
}
+ else
+ {
+ GtkAllocation alloc;
+ GtkTreeIter iter;
- return GTK_WIDGET_CLASS (ide_tree_parent_class)->button_press_event (widget, event);
-}
-
-static gboolean
-ide_tree_drag_motion (GtkWidget *widget,
- GdkDragContext *context,
- gint x,
- gint y,
- guint time_)
-{
- IdeTree *self = (IdeTree *)widget;
- IdeTreePrivate *priv = ide_tree_get_instance_private (self);
- gboolean ret;
-
- g_assert (IDE_IS_MAIN_THREAD ());
- g_assert (IDE_IS_TREE (self));
- g_assert (context != NULL);
-
- ret = GTK_WIDGET_CLASS (ide_tree_parent_class)->drag_motion (widget, context, x, y, time_);
+ gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
- /*
- * Cache the current drop position so we can use it
- * later to determine how to drop on a given node.
- */
- g_clear_pointer (&priv->drop_path, gtk_tree_path_free);
- gtk_tree_view_get_drag_dest_row (GTK_TREE_VIEW (self), &priv->drop_path, &priv->drop_pos);
+ if (gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, path))
+ {
+ IdeTreeNode *node;
- /* Save the drag action for builders dispatch */
- priv->drop_action = gdk_drag_context_get_selected_action (context);
+ node = ide_tree_model_get_node (IDE_TREE_MODEL (model), &iter);
+ ide_tree_select (self, node);
+ ide_tree_popup (self, node, alloc.x + alloc.width, y - cell_y);
+ }
+ }
- return ret;
+ gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
}
static gboolean
@@ -530,6 +504,21 @@ ide_tree_query_tooltip (GtkWidget *widget,
return FALSE;
}
+static void
+ide_tree_size_allocate (GtkWidget *widget,
+ int width,
+ int height,
+ int baseline)
+{
+ IdeTree *self = (IdeTree *)widget;
+ IdeTreePrivate *priv = ide_tree_get_instance_private (self);
+
+ g_assert (IDE_IS_TREE (self));
+
+ if (priv->popover != NULL)
+ gtk_popover_present (priv->popover);
+}
+
static gboolean
ide_tree_popup_menu_cb (IdeTree *tree,
gpointer user_data)
@@ -550,9 +539,9 @@ ide_tree_popup_menu_cb (IdeTree *tree,
}
static void
-ide_tree_destroy (GtkWidget *widget)
+ide_tree_dispose (GObject *object)
{
- IdeTree *self = (IdeTree *)widget;
+ IdeTree *self = (IdeTree *)object;
IdeTreePrivate *priv = ide_tree_get_instance_private (self);
IdeTreeModel *model;
@@ -561,8 +550,7 @@ ide_tree_destroy (GtkWidget *widget)
if ((model = ide_tree_get_model (self)))
_ide_tree_model_release_addins (model);
- if (priv->popover != NULL)
- gtk_widget_destroy (GTK_WIDGET (priv->popover));
+ g_clear_pointer ((GtkWidget **)&priv->popover, gtk_widget_unparent);
gtk_tree_view_set_model (GTK_TREE_VIEW (self), NULL);
@@ -575,19 +563,20 @@ ide_tree_destroy (GtkWidget *widget)
g_clear_pointer (&priv->header_attributes, pango_attr_list_unref);
g_clear_pointer (&priv->drop_path, gtk_tree_path_free);
- GTK_WIDGET_CLASS (ide_tree_parent_class)->destroy (widget);
+ G_OBJECT_CLASS (ide_tree_parent_class)->dispose (object);
}
static void
ide_tree_class_init (IdeTreeClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkTreeViewClass *tree_view_class = GTK_TREE_VIEW_CLASS (klass);
- widget_class->destroy = ide_tree_destroy;
- widget_class->button_press_event = ide_tree_button_press_event;
- widget_class->drag_motion = ide_tree_drag_motion;
+ object_class->dispose = ide_tree_dispose;
+
widget_class->query_tooltip = ide_tree_query_tooltip;
+ widget_class->size_allocate = ide_tree_size_allocate;
tree_view_class->row_activated = ide_tree_row_activated;
tree_view_class->row_expanded = ide_tree_row_expanded;
@@ -598,9 +587,20 @@ static void
ide_tree_init (IdeTree *self)
{
IdeTreePrivate *priv = ide_tree_get_instance_private (self);
+ GtkGesture *gesture;
GtkCellRenderer *cell;
GtkTreeViewColumn *column;
+ /* Show popover on right-click */
+ gesture = gtk_gesture_click_new ();
+ gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), 2);
+ g_signal_connect_object (gesture,
+ "pressed",
+ G_CALLBACK (ide_tree_click_pressed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
+
priv->cancellable = g_cancellable_new ();
gtk_widget_set_has_tooltip (GTK_WIDGET (self), TRUE);
@@ -654,6 +654,22 @@ ide_tree_new (void)
return g_object_new (IDE_TYPE_TREE, NULL);
}
+static void
+ide_tree_popover_closed_cb (IdeTree *self,
+ GtkPopover *popover)
+{
+ IdeTreePrivate *priv = ide_tree_get_instance_private (self);
+
+ g_assert (IDE_IS_TREE (self));
+ g_assert (GTK_IS_POPOVER (popover));
+
+ if (priv->popover == popover)
+ {
+ gtk_widget_unparent (GTK_WIDGET (popover));
+ priv->popover = NULL;
+ }
+}
+
void
ide_tree_set_context_menu (IdeTree *self,
GMenu *menu)
@@ -668,16 +684,17 @@ ide_tree_set_context_menu (IdeTree *self,
GtkTextDirection dir;
if (priv->popover != NULL)
- gtk_widget_destroy (GTK_WIDGET (priv->popover));
+ gtk_widget_unparent (GTK_WIDGET (priv->popover));
- priv->popover = GTK_POPOVER (gtk_popover_new_from_model (GTK_WIDGET (self),
- G_MENU_MODEL (priv->context_menu)));
+ priv->popover = GTK_POPOVER (gtk_popover_menu_new_from_model (G_MENU_MODEL (priv->context_menu)));
dir = gtk_widget_get_direction (GTK_WIDGET (self));
gtk_popover_set_position (priv->popover, dir == GTK_TEXT_DIR_LTR ? GTK_POS_RIGHT : GTK_POS_LEFT);
- g_signal_connect (priv->popover,
- "destroy",
- G_CALLBACK (gtk_widget_destroyed),
- &priv->popover);
+ g_signal_connect_object (priv->popover,
+ "closed",
+ G_CALLBACK (ide_tree_popover_closed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ gtk_widget_set_parent (GTK_WIDGET (priv->popover), GTK_WIDGET (self));
}
}
diff --git a/src/libide/tree/ide-tree.h b/src/libide/tree/ide-tree.h
index 0b4c16b6e..17e3fc33c 100644
--- a/src/libide/tree/ide-tree.h
+++ b/src/libide/tree/ide-tree.h
@@ -29,7 +29,7 @@ G_BEGIN_DECLS
#define IDE_TYPE_TREE (ide_tree_get_type())
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
G_DECLARE_DERIVABLE_TYPE (IdeTree, ide_tree, IDE, TREE, GtkTreeView)
struct _IdeTreeClass
@@ -37,31 +37,33 @@ struct _IdeTreeClass
GtkTreeViewClass parent_type;
/*< private >*/
- gpointer _reserved[16];
+ gpointer _reserved[8];
};
-IDE_AVAILABLE_IN_3_32
-GtkWidget *ide_tree_new (void);
-IDE_AVAILABLE_IN_3_32
-void ide_tree_set_context_menu (IdeTree *self,
- GMenu *menu);
-IDE_AVAILABLE_IN_3_32
-void ide_tree_show_popover_at_node (IdeTree *self,
- IdeTreeNode *node,
- GtkPopover *popover);
-IDE_AVAILABLE_IN_3_32
-IdeTreeNode *ide_tree_get_selected_node (IdeTree *self);
-IDE_AVAILABLE_IN_3_32
-void ide_tree_select_node (IdeTree *self,
- IdeTreeNode *node);
-IDE_AVAILABLE_IN_3_32
-void ide_tree_expand_node (IdeTree *self,
- IdeTreeNode *node);
-IDE_AVAILABLE_IN_3_32
-void ide_tree_collapse_node (IdeTree *self,
- IdeTreeNode *node);
-IDE_AVAILABLE_IN_3_32
-gboolean ide_tree_node_expanded (IdeTree *self,
- IdeTreeNode *node);
+IDE_AVAILABLE_IN_ALL
+GtkWidget *ide_tree_new (void);
+IDE_AVAILABLE_IN_ALL
+void ide_tree_set_context_menu (IdeTree *self,
+ GMenu *menu);
+IDE_AVAILABLE_IN_ALL
+void ide_tree_show_popover_at_node (IdeTree *self,
+ IdeTreeNode *node,
+ GtkPopover *popover);
+IDE_AVAILABLE_IN_ALL
+IdeTreeNode *ide_tree_get_selected_node (IdeTree *self);
+IDE_AVAILABLE_IN_ALL
+void ide_tree_select_node (IdeTree *self,
+ IdeTreeNode *node);
+IDE_AVAILABLE_IN_ALL
+void ide_tree_expand_node (IdeTree *self,
+ IdeTreeNode *node);
+IDE_AVAILABLE_IN_ALL
+void ide_tree_collapse_node (IdeTree *self,
+ IdeTreeNode *node);
+IDE_AVAILABLE_IN_ALL
+gboolean ide_tree_node_expanded (IdeTree *self,
+ IdeTreeNode *node);
+IDE_AVAILABLE_IN_ALL
+GtkDropTarget *ide_tree_get_drop_target (IdeTree *self);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]