[gnome-builder] tree: add gb_tree_node_show_popover()



commit 7220a4bcfe518d273559d53fc65728b78a2ee42b
Author: Christian Hergert <christian hergert me>
Date:   Sat Apr 11 01:48:37 2015 -0700

    tree: add gb_tree_node_show_popover()
    
    This helper will ensure that the GbTreeNode is visually onscreen before
    displaying the popover, attached to the node.

 src/tree/gb-tree-node.c |   96 +++++++++++++++++++++++++++++++++++++++++++++++
 src/tree/gb-tree-node.h |    2 +
 2 files changed, 98 insertions(+), 0 deletions(-)
---
diff --git a/src/tree/gb-tree-node.c b/src/tree/gb-tree-node.c
index 1564c83..0dedc13 100644
--- a/src/tree/gb-tree-node.c
+++ b/src/tree/gb-tree-node.c
@@ -33,6 +33,12 @@ struct _GbTreeNodePrivate
   guint          use_markup : 1;
 };
 
+typedef struct
+{
+  GbTreeNode *self;
+  GtkPopover *popover;
+} PopupRequest;
+
 G_DEFINE_TYPE_WITH_PRIVATE (GbTreeNode, gb_tree_node, G_TYPE_INITIALLY_UNOWNED)
 
 enum {
@@ -678,3 +684,93 @@ gb_tree_node_init (GbTreeNode *node)
 {
   node->priv = gb_tree_node_get_instance_private (node);
 }
+
+static gboolean
+gb_tree_node_show_popover_timeout_cb (gpointer data)
+{
+  PopupRequest *popreq = data;
+  GdkRectangle rect;
+  GtkAllocation alloc;
+  GbTree *tree;
+
+  g_assert (popreq);
+  g_assert (GB_IS_TREE_NODE (popreq->self));
+  g_assert (GTK_IS_POPOVER (popreq->popover));
+
+  if (!(tree = gb_tree_node_get_tree (popreq->self)))
+    goto cleanup;
+
+  gb_tree_node_get_area (popreq->self, &rect);
+  gtk_widget_get_allocation (GTK_WIDGET (tree), &alloc);
+
+  if ((rect.x + rect.width) > (alloc.x + alloc.width))
+    rect.width = (alloc.x + alloc.width) - rect.x;
+
+  gtk_popover_set_relative_to (popreq->popover, GTK_WIDGET (tree));
+  gtk_popover_set_pointing_to (popreq->popover, &rect);
+  gtk_widget_show (GTK_WIDGET (popreq->popover));
+
+cleanup:
+  g_object_unref (popreq->self);
+  g_object_unref (popreq->popover);
+  g_free (popreq);
+}
+
+void
+gb_tree_node_show_popover (GbTreeNode *self,
+                           GtkPopover *popover)
+{
+  GdkRectangle cell_area;
+  GdkRectangle visible_rect;
+  GbTree *tree;
+  PopupRequest *popreq;
+
+  g_return_if_fail (GB_IS_TREE_NODE (self));
+  g_return_if_fail (GTK_IS_POPOVER (popover));
+
+  tree = gb_tree_node_get_tree (self);
+  gtk_tree_view_get_visible_rect (GTK_TREE_VIEW (tree), &visible_rect);
+  gb_tree_node_get_area (self, &cell_area);
+  gtk_tree_view_convert_bin_window_to_tree_coords (GTK_TREE_VIEW (tree),
+                                                   cell_area.x,
+                                                   cell_area.y,
+                                                   &cell_area.x,
+                                                   &cell_area.y);
+
+  popreq = g_new0 (PopupRequest, 1);
+  popreq->self = g_object_ref (self);
+  popreq->popover = g_object_ref (popover);
+
+  /*
+   * If the node is not on screen, we need to animate until we get there.
+   */
+  if ((cell_area.y < visible_rect.y) ||
+      ((cell_area.y + cell_area.height) >
+       (visible_rect.y + visible_rect.height)))
+    {
+      GtkTreePath *path;
+
+      path = gb_tree_node_get_path (self);
+      gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (tree), path, NULL, FALSE, 0, 0);
+      gtk_tree_path_free (path);
+
+      /*
+       * FIXME: Time period comes from gtk animation duration.
+       *        Not curently available in pubic API.
+       *        We need to be greater than the max timeout it
+       *        could take to move, since we must have it
+       *        on screen by then.
+       *
+       *        One alternative might be to check the result
+       *        and if we are still not on screen, then just
+       *        pin it to a row-height from the top or bottom.
+       */
+      g_timeout_add (300,
+                     gb_tree_node_show_popover_timeout_cb,
+                     popreq);
+    }
+  else
+    {
+      gb_tree_node_show_popover_timeout_cb (popreq);
+    }
+}
diff --git a/src/tree/gb-tree-node.h b/src/tree/gb-tree-node.h
index b6aae49..c0394d2 100644
--- a/src/tree/gb-tree-node.h
+++ b/src/tree/gb-tree-node.h
@@ -78,6 +78,8 @@ void           gb_tree_node_get_area      (GbTreeNode   *node,
                                            GdkRectangle *area);
 void           gb_tree_node_rebuild       (GbTreeNode   *node);
 gboolean       gb_tree_node_get_expanded  (GbTreeNode   *node);
+void           gb_tree_node_show_popover  (GbTreeNode   *node,
+                                           GtkPopover   *popover);
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]