[gnome-builder] views: add document selection popover



commit f8cc584bf67d2b9e75e2f6ede8637d8602931ea3
Author: Christian Hergert <christian hergert me>
Date:   Tue Mar 24 14:36:59 2015 -0700

    views: add document selection popover
    
    I'm not sure about this long term, but this is a stop gap until we figure
    out the design further. In particular, it is difficult to select documents
    that are not yet in git.
    
    Some alternate approaches are to simply add the files to git immediately.
    This was going to be the case once we have templates for things like
    GObjects, widgets, resources, icons, etc. However, that doesn't help the
    situation for temporary buffers.
    
    Clearly we could choose a better icon.
    
    This needs design review, and some careful planning as we go forward. I
    have a couple other ideas on placement, but this is the minimal patch
    that solves the problem at hand.
    
    
    Signed-off-by: Christian Hergert <christian hergert me>

 data/ui/gb-view-stack.ui          |   42 ++++++++++++
 src/views/gb-view-stack-private.h |    2 +
 src/views/gb-view-stack.c         |  129 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 170 insertions(+), 3 deletions(-)
---
diff --git a/data/ui/gb-view-stack.ui b/data/ui/gb-view-stack.ui
index 860dc47..9aaff68 100644
--- a/data/ui/gb-view-stack.ui
+++ b/data/ui/gb-view-stack.ui
@@ -62,6 +62,26 @@
                     </child>
                   </object>
                 </child>
+                <child>
+                  <object class="GtkMenuButton" id="views_button">
+                    <property name="visible">true</property>
+                    <property name="popover">views_popover</property>
+                    <style>
+                      <class name="dim-label"/>
+                      <class name="image-button"/>
+                      <class name="flat"/>
+                    </style>
+                    <child>
+                      <object class="GtkImage">
+                        <property name="visible">true</property>
+                        <property name="icon-name">system-file-manager-symbolic</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="pack-type">start</property>
+                  </packing>
+                </child>
                 <child type="center">
                   <object class="GtkMenuButton" id="document_button">
                     <property name="hexpand">true</property>
@@ -326,6 +346,28 @@
       </object>
     </child>
   </object>
+  <object class="GtkPopover" id="views_popover">
+    <child>
+      <object class="GtkBox">
+        <property name="orientation">vertical</property>
+        <property name="visible">true</property>
+        <child>
+          <object class="GbScrolledWindow">
+            <property name="max-content-height">400</property>
+            <property name="min-content-height">30</property>
+            <property name="min-content-width">100</property>
+            <property name="max-content-width">300</property>
+            <property name="visible">true</property>
+            <child>
+              <object class="GtkListBox" id="views_listbox">
+                <property name="visible">true</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </object>
   <object class="GtkSizeGroup">
     <property name="mode">horizontal</property>
     <widgets>
diff --git a/src/views/gb-view-stack-private.h b/src/views/gb-view-stack-private.h
index b1d2456..4d34a7e 100644
--- a/src/views/gb-view-stack-private.h
+++ b/src/views/gb-view-stack-private.h
@@ -47,6 +47,8 @@ struct _GbViewStack
   GtkPopover         *popover;
   GtkStack           *stack;
   GtkLabel           *title_label;
+  GtkListBox         *views_button;
+  GtkListBox         *views_listbox;
 
   guint               destroyed : 1;
   guint               focused : 1;
diff --git a/src/views/gb-view-stack.c b/src/views/gb-view-stack.c
index 47d6cd7..d8aade5 100644
--- a/src/views/gb-view-stack.c
+++ b/src/views/gb-view-stack.c
@@ -46,6 +46,90 @@ static GParamSpec *gParamSpecs [LAST_PROP];
 static guint       gSignals [LAST_SIGNAL];
 
 static void
+gb_view_stack_add_list_row (GbViewStack *self,
+                            GbView      *child)
+{
+  GtkWidget *row;
+  GtkWidget *label;
+
+  g_assert (GB_IS_VIEW_STACK (self));
+  g_assert (GB_IS_VIEW (child));
+
+  row = g_object_new (GTK_TYPE_LIST_BOX_ROW,
+                      "visible", TRUE,
+                      NULL);
+  label = g_object_new (GTK_TYPE_LABEL,
+                        "margin-bottom", 3,
+                        "margin-end", 6,
+                        "margin-start", 6,
+                        "margin-top", 3,
+                        "visible", TRUE,
+                        "xalign", 0.0f,
+                        NULL);
+  g_object_bind_property (child, "title", label, "label", G_BINDING_SYNC_CREATE);
+  g_object_set_data (G_OBJECT (row), "GB_VIEW", child);
+  gtk_container_add (GTK_CONTAINER (row), label);
+  gtk_container_add (GTK_CONTAINER (self->views_listbox), row);
+}
+
+static void
+gb_view_stack_remove_list_row (GbViewStack *self,
+                               GbView      *child)
+{
+  GList *children;
+  GList *iter;
+
+  g_assert (GB_IS_VIEW_STACK (self));
+  g_assert (GB_IS_VIEW (child));
+
+  children = gtk_container_get_children (GTK_CONTAINER (self->views_listbox));
+
+  for (iter = children; iter; iter = iter->next)
+    {
+      GbView *view = g_object_get_data (iter->data, "GB_VIEW");
+
+      if (view == child)
+        {
+          gtk_container_remove (GTK_CONTAINER (self->views_listbox), iter->data);
+          break;
+        }
+    }
+
+  g_list_free (children);
+}
+
+static void
+gb_view_stack_move_top_list_row (GbViewStack *self,
+                                 GbView      *view)
+{
+  GList *children;
+  GList *iter;
+
+  g_assert (GB_IS_VIEW_STACK (self));
+  g_assert (GB_IS_VIEW (view));
+
+  children = gtk_container_get_children (GTK_CONTAINER (self->views_listbox));
+
+  for (iter = children; iter; iter = iter->next)
+    {
+      GtkWidget *row = iter->data;
+      GbView *item = g_object_get_data (G_OBJECT (row), "GB_VIEW");
+
+      if (item == view)
+        {
+          g_object_ref (row);
+          gtk_container_remove (GTK_CONTAINER (self->views_listbox), row);
+          gtk_list_box_prepend (self->views_listbox, row);
+          gtk_list_box_select_row (self->views_listbox, GTK_LIST_BOX_ROW (row));
+          g_object_unref (row);
+          break;
+        }
+    }
+
+  g_list_free (children);
+}
+
+static void
 gb_view_stack_add (GtkContainer *container,
                    GtkWidget    *child)
 {
@@ -59,6 +143,7 @@ gb_view_stack_add (GtkContainer *container,
 
       gtk_widget_set_sensitive (GTK_WIDGET (self->close_button), TRUE);
       gtk_widget_set_sensitive (GTK_WIDGET (self->document_button), TRUE);
+      gtk_widget_set_visible (GTK_WIDGET (self->views_button), TRUE);
 
       self->focus_history = g_list_prepend (self->focus_history, child);
       controls = gb_view_get_controls (GB_VIEW (child));
@@ -66,6 +151,7 @@ gb_view_stack_add (GtkContainer *container,
         gtk_container_add (GTK_CONTAINER (self->controls_stack), controls);
       gtk_container_add (GTK_CONTAINER (self->stack), child);
       gb_view_set_back_forward_list (GB_VIEW (child), self->back_forward_list);
+      gb_view_stack_add_list_row (self, GB_VIEW (child));
       gtk_stack_set_visible_child (self->stack, child);
     }
   else
@@ -83,6 +169,8 @@ gb_view_stack_remove (GbViewStack *self,
   g_assert (GB_IS_VIEW_STACK (self));
   g_assert (GB_IS_VIEW (view));
 
+  gb_view_stack_remove_list_row (self, view);
+
   self->focus_history = g_list_remove (self->focus_history, view);
   controls = gb_view_get_controls (view);
   if (controls)
@@ -162,6 +250,7 @@ gb_view_stack_real_empty (GbViewStack *self)
       gtk_widget_set_sensitive (GTK_WIDGET (self->close_button), FALSE);
       gtk_widget_set_sensitive (GTK_WIDGET (self->document_button), FALSE);
       gtk_widget_set_visible (GTK_WIDGET (self->modified_label), FALSE);
+      gtk_widget_set_visible (GTK_WIDGET (self->views_button), FALSE);
     }
 }
 
@@ -268,6 +357,26 @@ gb_view_stack_hierarchy_changed (GtkWidget *widget,
 }
 
 static void
+gb_view_stack__views_listbox_row_activated_cb (GbViewStack   *self,
+                                               GtkListBoxRow *row,
+                                               GtkListBox    *list_box)
+{
+  GbView *view;
+
+  g_assert (GB_IS_VIEW_STACK (self));
+  g_assert (GTK_IS_LIST_BOX_ROW (row));
+  g_assert (GTK_IS_LIST_BOX (list_box));
+
+  view = g_object_get_data (G_OBJECT (row), "GB_VIEW");
+
+  if (GB_IS_VIEW (view))
+    {
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->views_button), FALSE);
+      gb_view_stack_set_active_view (self, GTK_WIDGET (view));
+    }
+}
+
+static void
 gb_view_stack_destroy (GtkWidget *widget)
 {
   GbViewStack *self = (GbViewStack *)widget;
@@ -284,6 +393,12 @@ gb_view_stack_constructed (GObject *object)
 
   G_OBJECT_CLASS (gb_view_stack_parent_class)->constructed (object);
 
+  g_signal_connect_object (self->views_listbox,
+                           "row-activated",
+                           G_CALLBACK (gb_view_stack__views_listbox_row_activated_cb),
+                           self,
+                           G_CONNECT_SWAPPED);
+
   gb_view_stack_actions_init (self);
 }
 
@@ -397,6 +512,8 @@ gb_view_stack_class_init (GbViewStackClass *klass)
   GB_WIDGET_CLASS_BIND (klass, GbViewStack, popover);
   GB_WIDGET_CLASS_BIND (klass, GbViewStack, stack);
   GB_WIDGET_CLASS_BIND (klass, GbViewStack, title_label);
+  GB_WIDGET_CLASS_BIND (klass, GbViewStack, views_button);
+  GB_WIDGET_CLASS_BIND (klass, GbViewStack, views_listbox);
 }
 
 static void
@@ -455,29 +572,35 @@ gb_view_stack_set_active_view (GbViewStack *self,
           GBinding *binding;
           GActionGroup *group;
 
+          ide_set_weak_pointer (&self->active_view, active_view);
+          if (active_view != gtk_stack_get_visible_child (self->stack))
+            gtk_stack_set_visible_child (self->stack, active_view);
+
           self->focus_history = g_list_remove (self->focus_history, active_view);
           self->focus_history = g_list_prepend (self->focus_history, active_view);
 
-          if (active_view != gtk_stack_get_visible_child (self->stack))
-            gtk_stack_set_visible_child (self->stack, active_view);
           binding = g_object_bind_property (active_view, "title",
                                             self->title_label, "label",
                                             G_BINDING_SYNC_CREATE);
           ide_set_weak_pointer (&self->title_binding, binding);
+
           binding = g_object_bind_property (active_view, "modified",
                                             self->modified_label, "visible",
                                             G_BINDING_SYNC_CREATE);
           ide_set_weak_pointer (&self->modified_binding, binding);
-          ide_set_weak_pointer (&self->active_view, active_view);
+
           controls = gb_view_get_controls (GB_VIEW (active_view));
           if (controls)
             {
               gtk_stack_set_visible_child (self->controls_stack, controls);
               gtk_widget_show (GTK_WIDGET (self->controls_stack));
             }
+
           group = gtk_widget_get_action_group (active_view, "view");
           if (group)
             gtk_widget_insert_action_group (GTK_WIDGET (self), "view", group);
+
+          gb_view_stack_move_top_list_row (self, GB_VIEW (active_view));
         }
 
       g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_ACTIVE_VIEW]);


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