[gnome-builder/wip/gtk4-port] libide/gui: add get_frame_at_position vfunc



commit b2347fd7fb9a28bca6f8ca99fcf1613116a7a319
Author: Christian Hergert <chergert redhat com>
Date:   Thu Apr 7 14:33:56 2022 -0700

    libide/gui: add get_frame_at_position vfunc
    
    This can be useful for areas where we will need to reposition things or
    even just open a document on the same or nearby frame.

 src/libide/editor/ide-editor-workspace.c |  18 +++++
 src/libide/gui/ide-primary-workspace.c   |  18 +++++
 src/libide/gui/ide-workspace-private.h   |  40 ++++++-----
 src/libide/gui/ide-workspace.c           | 111 +++++++++++++++++++++----------
 src/libide/gui/ide-workspace.h           |  57 ++++++++--------
 5 files changed, 165 insertions(+), 79 deletions(-)
---
diff --git a/src/libide/editor/ide-editor-workspace.c b/src/libide/editor/ide-editor-workspace.c
index 59d790c38..1f43e8100 100644
--- a/src/libide/editor/ide-editor-workspace.c
+++ b/src/libide/editor/ide-editor-workspace.c
@@ -149,6 +149,23 @@ ide_editor_workspace_get_most_recent_frame (IdeWorkspace *workspace)
   return IDE_FRAME (panel_grid_get_most_recent_frame (PANEL_GRID (self->grid)));
 }
 
+static PanelFrame *
+ide_editor_workspace_get_frame_at_position (IdeWorkspace     *workspace,
+                                            IdePanelPosition *position)
+{
+  IdeEditorWorkspace *self = (IdeEditorWorkspace *)workspace;
+
+  g_assert (IDE_IS_EDITOR_WORKSPACE (self));
+  g_assert (position != NULL);
+
+  return _ide_workspace_find_frame (workspace,
+                                    position,
+                                    self->edge_start,
+                                    self->edge_end,
+                                    self->edge_bottom,
+                                    self->grid);
+}
+
 static void
 ide_editor_workspace_dispose (GObject *object)
 {
@@ -177,6 +194,7 @@ ide_editor_workspace_class_init (IdeEditorWorkspaceClass *klass)
   workspace_class->add_page = ide_editor_workspace_add_page;
   workspace_class->add_pane = ide_editor_workspace_add_pane;
   workspace_class->get_most_recent_frame = ide_editor_workspace_get_most_recent_frame;
+  workspace_class->get_frame_at_position = ide_editor_workspace_get_frame_at_position;
 
   ide_workspace_class_set_kind (workspace_class, "editor");
 
diff --git a/src/libide/gui/ide-primary-workspace.c b/src/libide/gui/ide-primary-workspace.c
index 6c13b9ad0..6017e0274 100644
--- a/src/libide/gui/ide-primary-workspace.c
+++ b/src/libide/gui/ide-primary-workspace.c
@@ -132,6 +132,23 @@ ide_primary_workspace_get_most_recent_frame (IdeWorkspace *workspace)
   return IDE_FRAME (panel_grid_get_most_recent_frame (PANEL_GRID (self->grid)));
 }
 
+static PanelFrame *
+ide_primary_workspace_get_frame_at_position (IdeWorkspace     *workspace,
+                                             IdePanelPosition *position)
+{
+  IdePrimaryWorkspace *self = (IdePrimaryWorkspace *)workspace;
+
+  g_assert (IDE_IS_PRIMARY_WORKSPACE (self));
+  g_assert (position != NULL);
+
+  return _ide_workspace_find_frame (workspace,
+                                    position,
+                                    self->edge_start,
+                                    self->edge_end,
+                                    self->edge_bottom,
+                                    self->grid);
+}
+
 static void
 ide_primary_workspace_dispose (GObject *object)
 {
@@ -160,6 +177,7 @@ ide_primary_workspace_class_init (IdePrimaryWorkspaceClass *klass)
   workspace_class->add_page = ide_primary_workspace_add_page;
   workspace_class->add_pane = ide_primary_workspace_add_pane;
   workspace_class->get_most_recent_frame = ide_primary_workspace_get_most_recent_frame;
+  workspace_class->get_frame_at_position = ide_primary_workspace_get_frame_at_position;
 
   ide_workspace_class_set_kind (workspace_class, "primary");
 
diff --git a/src/libide/gui/ide-workspace-private.h b/src/libide/gui/ide-workspace-private.h
index 9ea8ac973..7dc2d90c2 100644
--- a/src/libide/gui/ide-workspace-private.h
+++ b/src/libide/gui/ide-workspace-private.h
@@ -26,22 +26,28 @@
 
 G_BEGIN_DECLS
 
-void   _ide_workspace_init_actions           (IdeWorkspace        *self);
-GList *_ide_workspace_get_mru_link           (IdeWorkspace        *self);
-void   _ide_workspace_add_page_mru           (IdeWorkspace        *self,
-                                              GList               *mru_link);
-void   _ide_workspace_remove_page_mru        (IdeWorkspace        *self,
-                                              GList               *mru_link);
-void   _ide_workspace_move_front_page_mru    (IdeWorkspace        *workspace,
-                                              GList               *mru_link);
-void   _ide_workspace_set_context            (IdeWorkspace        *workspace,
-                                              IdeContext          *context);
-void   _ide_workspace_add_widget             (IdeWorkspace        *workspace,
-                                              PanelWidget         *widget,
-                                              IdePanelPosition    *position,
-                                              PanelPaned          *dock_start,
-                                              PanelPaned          *dock_end,
-                                              PanelPaned          *dock_bottom,
-                                              IdeGrid             *grid);
+void        _ide_workspace_init_actions        (IdeWorkspace        *self);
+GList      *_ide_workspace_get_mru_link        (IdeWorkspace        *self);
+void        _ide_workspace_add_page_mru        (IdeWorkspace        *self,
+                                                GList               *mru_link);
+void        _ide_workspace_remove_page_mru     (IdeWorkspace        *self,
+                                                GList               *mru_link);
+void        _ide_workspace_move_front_page_mru (IdeWorkspace        *workspace,
+                                                GList               *mru_link);
+void        _ide_workspace_set_context         (IdeWorkspace        *workspace,
+                                                IdeContext          *context);
+void        _ide_workspace_add_widget          (IdeWorkspace        *workspace,
+                                                PanelWidget         *widget,
+                                                IdePanelPosition    *position,
+                                                PanelPaned          *dock_start,
+                                                PanelPaned          *dock_end,
+                                                PanelPaned          *dock_bottom,
+                                                IdeGrid             *grid);
+PanelFrame *_ide_workspace_find_frame          (IdeWorkspace        *workspace,
+                                                IdePanelPosition    *position,
+                                                PanelPaned          *dock_start,
+                                                PanelPaned          *dock_end,
+                                                PanelPaned          *dock_bottom,
+                                                IdeGrid             *grid);
 
 G_END_DECLS
diff --git a/src/libide/gui/ide-workspace.c b/src/libide/gui/ide-workspace.c
index 37ef69f05..6dce17394 100644
--- a/src/libide/gui/ide-workspace.c
+++ b/src/libide/gui/ide-workspace.c
@@ -828,7 +828,7 @@ ide_workspace_addin_find_by_module_name (IdeWorkspace *workspace,
  * Adds @page to @workspace.
  *
  * In future versions, @position may be updated to reflect the
- * postion in which @page was added.
+ * position in which @page was added.
  */
 void
 ide_workspace_add_page (IdeWorkspace     *self,
@@ -855,7 +855,7 @@ ide_workspace_add_page (IdeWorkspace     *self,
  * Adds @pane to @workspace.
  *
  * In future versions, @position may be updated to reflect the
- * postion in which @pane was added.
+ * position in which @pane was added.
  */
 void
 ide_workspace_add_pane (IdeWorkspace     *self,
@@ -1069,6 +1069,12 @@ find_most_recent_frame (IdeWorkspace *workspace,
     }
 }
 
+static gboolean
+dummy_cb (gpointer data)
+{
+  return G_SOURCE_REMOVE;
+}
+
 void
 _ide_workspace_add_widget (IdeWorkspace     *self,
                            PanelWidget      *widget,
@@ -1078,14 +1084,9 @@ _ide_workspace_add_widget (IdeWorkspace     *self,
                            PanelPaned       *dock_bottom,
                            IdeGrid          *grid)
 {
-  PanelDockPosition edge;
-  PanelPaned *paned = NULL;
-  GtkWidget *parent;
+  PanelFrame *frame;
   gboolean depth_set;
   guint depth;
-  guint column = 0;
-  guint row = 0;
-  guint nth = 0;
 
   IDE_ENTRY;
 
@@ -1097,32 +1098,53 @@ _ide_workspace_add_widget (IdeWorkspace     *self,
   g_return_if_fail (!dock_bottom || PANEL_IS_PANED (dock_bottom));
   g_return_if_fail (IDE_IS_GRID (grid));
 
-  if (!ide_panel_position_get_edge (position, &edge))
+  if (!(frame = _ide_workspace_find_frame (self, position, dock_start, dock_end, dock_bottom, grid)))
     {
-      if (IDE_IS_PAGE (widget))
-        edge = PANEL_DOCK_POSITION_CENTER;
-      else
-        edge = PANEL_DOCK_POSITION_START;
+      /* Extreme failure case, try to be nice and wait until
+       * end of the main loop to destroy
+       */
+      g_idle_add_full (G_PRIORITY_LOW,
+                       dummy_cb,
+                       g_object_ref_sink (widget),
+                       g_object_unref);
+      IDE_EXIT;
     }
 
-  /* Force pages to be always be loaded in the center */
-  if (IDE_IS_PAGE (widget) && edge != PANEL_DOCK_POSITION_CENTER)
-    {
-      g_warning ("Attempt to add a page to a position other than center. Ignoring.");
-      edge = PANEL_DOCK_POSITION_CENTER;
-    }
+  depth_set = ide_panel_position_get_depth (position, &depth);
+  add_to_frame_with_depth (frame, widget, depth, depth_set);
 
-  /* Don't allow non-pages to be added to the center */
-  if (!IDE_IS_PAGE (widget) && edge == PANEL_DOCK_POSITION_CENTER)
-    {
-      g_warning ("Attempt to add a non-page to the center. Ignoring.");
-      edge = PANEL_DOCK_POSITION_START;
-    }
+  IDE_EXIT;
+}
+
+PanelFrame *
+_ide_workspace_find_frame (IdeWorkspace     *self,
+                           IdePanelPosition *position,
+                           PanelPaned       *dock_start,
+                           PanelPaned       *dock_end,
+                           PanelPaned       *dock_bottom,
+                           IdeGrid          *grid)
+{
+  PanelDockPosition edge;
+  PanelPaned *paned = NULL;
+  PanelFrame *ret;
+  GtkWidget *parent;
+  guint column = 0;
+  guint row = 0;
+  guint nth = 0;
+
+  IDE_ENTRY;
+
+  g_return_val_if_fail (IDE_IS_WORKSPACE (self), NULL);
+  g_return_val_if_fail (position != NULL, NULL);
+  g_return_val_if_fail (!dock_start || PANEL_IS_PANED (dock_start), NULL);
+  g_return_val_if_fail (!dock_end || PANEL_IS_PANED (dock_end), NULL);
+  g_return_val_if_fail (!dock_bottom || PANEL_IS_PANED (dock_bottom), NULL);
+
+  if (!ide_panel_position_get_edge (position, &edge))
+    edge = PANEL_DOCK_POSITION_CENTER;
 
   if (edge == PANEL_DOCK_POSITION_CENTER)
     {
-      PanelFrame *frame;
-
       /* If we are adding a page, and no row or column is set, then the next
        * best thing to do is to try to find an open frame. If we can't do that
        * then we'll try to find the most recent frame.
@@ -1134,11 +1156,9 @@ _ide_workspace_add_widget (IdeWorkspace     *self,
             find_most_recent_frame (self, grid, &column, &row);
         }
 
-      depth_set = ide_panel_position_get_depth (position, &depth);
-      frame = panel_grid_column_get_row (panel_grid_get_column (PANEL_GRID (grid), column), row);
-      add_to_frame_with_depth (frame, widget, depth, depth_set);
+      ret = panel_grid_column_get_row (panel_grid_get_column (PANEL_GRID (grid), column), row);
 
-      IDE_EXIT;
+      IDE_RETURN (ret);
     }
 
   switch (edge)
@@ -1160,11 +1180,11 @@ _ide_workspace_add_widget (IdeWorkspace     *self,
 
     case PANEL_DOCK_POSITION_TOP:
       g_warning ("Top panel is not supported");
-      return;
+      return NULL;
 
     case PANEL_DOCK_POSITION_CENTER:
     default:
-      return;
+      return NULL;
     }
 
   while (!(parent = panel_paned_get_nth_child (paned, nth)))
@@ -1180,8 +1200,27 @@ _ide_workspace_add_widget (IdeWorkspace     *self,
       panel_paned_append (paned, parent);
     }
 
-  depth_set = ide_panel_position_get_depth (position, &depth);
-  add_to_frame_with_depth (PANEL_FRAME (parent), widget, depth, depth_set);
+  IDE_RETURN (PANEL_FRAME (parent));
+}
 
-  IDE_EXIT;
+/**
+ * ide_workspace_get_frame_at_position:
+ * @self: an #IdeWorkspace
+ * @position: an #IdePanelPosition
+ *
+ * Attempts to locate the #PanelFrame at a given position.
+ *
+ * Returns: (transfer none) (nullable): a #PaneFrame or %NULL
+ */
+PanelFrame *
+ide_workspace_get_frame_at_position (IdeWorkspace     *self,
+                                     IdePanelPosition *position)
+{
+  g_return_val_if_fail (IDE_IS_WORKSPACE (self), NULL);
+  g_return_val_if_fail (position != NULL, NULL);
+
+  if (IDE_WORKSPACE_GET_CLASS (self)->get_frame_at_position)
+    return IDE_WORKSPACE_GET_CLASS (self)->get_frame_at_position (self, position);
+
+  return NULL;
 }
diff --git a/src/libide/gui/ide-workspace.h b/src/libide/gui/ide-workspace.h
index 54b919f61..b87d77220 100644
--- a/src/libide/gui/ide-workspace.h
+++ b/src/libide/gui/ide-workspace.h
@@ -54,32 +54,34 @@ struct _IdeWorkspaceClass
   guint has_statusbar : 1;
   guint _unused_flags : 31;
 
-  void      (*context_set)           (IdeWorkspace         *self,
-                                      IdeContext           *context);
-  void      (*foreach_page)          (IdeWorkspace         *self,
-                                      IdePageCallback       callback,
-                                      gpointer              user_data);
-  IdePage  *(*get_most_recent_page)  (IdeWorkspace         *self);
-  IdeFrame *(*get_most_recent_frame) (IdeWorkspace         *self);
-  void      (*agree_to_close_async)  (IdeWorkspace         *self,
-                                      GCancellable         *cancellable,
-                                      GAsyncReadyCallback   callback,
-                                      gpointer              user_data);
-  gboolean  (*agree_to_close_finish) (IdeWorkspace         *self,
-                                      GAsyncResult         *result,
-                                      GError              **error);
-  void      (*add_pane)              (IdeWorkspace         *self,
-                                      IdePane              *pane,
-                                      IdePanelPosition     *position);
-  void      (*add_page)              (IdeWorkspace         *self,
-                                      IdePage              *page,
-                                      IdePanelPosition     *position);
-  void      (*restore_size)          (IdeWorkspace         *self,
-                                      int                   width,
-                                      int                   height);
-  gboolean  (*save_size)             (IdeWorkspace         *self,
-                                      int                  *width,
-                                      int                  *height);
+  void        (*context_set)           (IdeWorkspace         *self,
+                                        IdeContext           *context);
+  void        (*foreach_page)          (IdeWorkspace         *self,
+                                        IdePageCallback       callback,
+                                        gpointer              user_data);
+  IdePage    *(*get_most_recent_page)  (IdeWorkspace         *self);
+  IdeFrame   *(*get_most_recent_frame) (IdeWorkspace         *self);
+  void        (*agree_to_close_async)  (IdeWorkspace         *self,
+                                        GCancellable         *cancellable,
+                                        GAsyncReadyCallback   callback,
+                                        gpointer              user_data);
+  gboolean    (*agree_to_close_finish) (IdeWorkspace         *self,
+                                        GAsyncResult         *result,
+                                        GError              **error);
+  void        (*add_pane)              (IdeWorkspace         *self,
+                                        IdePane              *pane,
+                                        IdePanelPosition     *position);
+  void        (*add_page)              (IdeWorkspace         *self,
+                                        IdePage              *page,
+                                        IdePanelPosition     *position);
+  PanelFrame *(*get_frame_at_position) (IdeWorkspace         *self,
+                                        IdePanelPosition     *position);
+  void        (*restore_size)          (IdeWorkspace         *self,
+                                        int                   width,
+                                        int                   height);
+  gboolean    (*save_size)             (IdeWorkspace         *self,
+                                        int                  *width,
+                                        int                  *height);
 };
 
 IDE_AVAILABLE_IN_ALL
@@ -100,6 +102,9 @@ IdePage        *ide_workspace_get_most_recent_page     (IdeWorkspace      *self)
 IDE_AVAILABLE_IN_ALL
 IdeFrame       *ide_workspace_get_most_recent_frame    (IdeWorkspace      *self);
 IDE_AVAILABLE_IN_ALL
+PanelFrame     *ide_workspace_get_frame_at_position    (IdeWorkspace      *self,
+                                                        IdePanelPosition  *position);
+IDE_AVAILABLE_IN_ALL
 void            ide_workspace_add_pane                 (IdeWorkspace      *self,
                                                         IdePane           *pane,
                                                         IdePanelPosition  *position);


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