[nautilus/wip/gbsneto/actionbar: 3/5] action-bar: implement NautilusActionBar



commit 8ef611ceea4fe2d0396f3cd5afd4ea3d97eb200e
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Wed Mar 2 00:59:06 2016 -0300

    action-bar: implement NautilusActionBar
    
    The new NautilusActionBar class handles everything
    needed to be an usable actionbar as envisioned by
    the available mockups.

 src/Makefile.am                         |    2 +
 src/nautilus-action-bar.c               |  195 ++++++++++++++++++++++++++++
 src/nautilus-action-bar.h               |   36 +++++
 src/resources/css/Adwaita.css           |    5 +
 src/resources/nautilus.gresource.xml    |    1 +
 src/resources/ui/nautilus-action-bar.ui |  213 +++++++++++++++++++++++++++++++
 6 files changed, 452 insertions(+), 0 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 40329ce..02b1695 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -139,6 +139,8 @@ nautilus_SOURCES = \
        gtk/gtkplacesviewprivate.h              \
        gtk/gtkplacesviewrow.c                  \
        gtk/gtkplacesviewrowprivate.h           \
+       nautilus-action-bar.c                   \
+       nautilus-action-bar.h                   \
        nautilus-application.c                  \
        nautilus-application.h                  \
        nautilus-bookmark-list.c                \
diff --git a/src/nautilus-action-bar.c b/src/nautilus-action-bar.c
new file mode 100644
index 0000000..5af8f5f
--- /dev/null
+++ b/src/nautilus-action-bar.c
@@ -0,0 +1,195 @@
+/* nautilus-action-bar.c
+ *
+ * Copyright (C) 2016 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "nautilus-action-bar.h"
+
+#include <libnautilus-private/nautilus-clipboard.h>
+#include <libnautilus-private/nautilus-clipboard-monitor.h>
+
+#include <glib/gi18n.h>
+
+struct _NautilusActionBar
+{
+  GtkActionBar        parent;
+
+  GtkWidget          *paste_button;
+  GtkWidget          *stack;
+
+  NautilusView       *view;
+};
+
+G_DEFINE_TYPE (NautilusActionBar, nautilus_action_bar, GTK_TYPE_ACTION_BAR)
+
+enum {
+  PROP_0,
+  PROP_VIEW,
+  N_PROPS
+};
+
+static void
+update_paste_button (NautilusActionBar *self)
+{
+  NautilusClipboardMonitor *monitor;
+  NautilusClipboardInfo *info;
+
+  monitor = nautilus_clipboard_monitor_get ();
+  info = nautilus_clipboard_monitor_get_clipboard_info (monitor);
+
+  gtk_widget_set_visible (self->paste_button, info != NULL);
+
+  if (info)
+    {
+      gchar *label;
+      gint length;
+
+      length = g_list_length (info->files);
+
+      if (info->cut)
+        label = g_strdup_printf (g_dngettext(NULL, "Move %d file", "Move %d files", length), length);
+      else
+        label = g_strdup_printf (g_dngettext(NULL, "Paste %d file", "Paste %d files", length), length);
+
+      gtk_button_set_label (GTK_BUTTON (self->paste_button), label);
+
+      g_free (label);
+    }
+}
+
+static void
+selection_changed_cb (NautilusView      *view,
+                      GParamSpec        *pspec,
+                      NautilusActionBar *actionbar)
+{
+  GList *selection;
+
+  selection = nautilus_view_get_selection (view);
+
+  gtk_stack_set_visible_child_name (GTK_STACK (actionbar->stack),
+                                    g_list_length (selection) == 0 ? "normal" : "selection");
+}
+
+static void
+nautilus_action_bar_finalize (GObject *object)
+{
+  NautilusActionBar *self = NAUTILUS_ACTION_BAR (object);
+
+  g_signal_handlers_disconnect_by_func (self->view, selection_changed_cb, self);
+  g_clear_object (&self->view);
+
+  G_OBJECT_CLASS (nautilus_action_bar_parent_class)->finalize (object);
+}
+
+static void
+nautilus_action_bar_get_property (GObject    *object,
+                                  guint       prop_id,
+                                  GValue     *value,
+                                  GParamSpec *pspec)
+{
+  NautilusActionBar *self = NAUTILUS_ACTION_BAR (object);
+
+  switch (prop_id)
+    {
+    case PROP_VIEW:
+      g_value_set_object (value, self->view);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+nautilus_action_bar_set_property (GObject      *object,
+                                  guint         prop_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+{
+  NautilusActionBar *self = NAUTILUS_ACTION_BAR (object);
+
+  switch (prop_id)
+    {
+    case PROP_VIEW:
+      if (g_set_object (&self->view, g_value_get_object (value)))
+        {
+          g_signal_connect (self->view, "notify::selection", G_CALLBACK (selection_changed_cb), self);
+          g_object_notify (object, "view");
+        }
+
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+nautilus_action_bar_class_init (NautilusActionBarClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = nautilus_action_bar_finalize;
+  object_class->get_property = nautilus_action_bar_get_property;
+  object_class->set_property = nautilus_action_bar_set_property;
+
+  /**
+   * NautilusActionBar::view:
+   *
+   * The view related to this actionbar.
+   */
+  g_object_class_install_property (object_class,
+                                   PROP_VIEW,
+                                   g_param_spec_object ("view",
+                                                        "View of the actionbar",
+                                                        "The view related to this actionbar",
+                                                        NAUTILUS_TYPE_VIEW,
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/org/gnome/nautilus/ui/nautilus-action-bar.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, NautilusActionBar, stack);
+  gtk_widget_class_bind_template_child (widget_class, NautilusActionBar, paste_button);
+}
+
+static void
+nautilus_action_bar_init (NautilusActionBar *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  update_paste_button (self);
+
+  g_signal_connect_swapped (nautilus_clipboard_monitor_get (), "clipboard-changed",
+                            G_CALLBACK (update_paste_button), self);
+}
+
+/**
+ * nautilus_action_bar_new:
+ * @view: a #NautilusView
+ *
+ * Creates a new actionbar related to @view.
+ *
+ * Returns: (transfer full): a #NautilusActionBar
+ */
+GtkWidget*
+nautilus_action_bar_new (NautilusView *view)
+{
+  return g_object_new (NAUTILUS_TYPE_ACTION_BAR,
+                       "view", view,
+                       NULL);
+}
+
diff --git a/src/nautilus-action-bar.h b/src/nautilus-action-bar.h
new file mode 100644
index 0000000..3835e3f
--- /dev/null
+++ b/src/nautilus-action-bar.h
@@ -0,0 +1,36 @@
+/* nautilus-action-bar.h
+ *
+ * Copyright (C) 2016 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NAUTILUS_ACTION_BAR_H
+#define NAUTILUS_ACTION_BAR_H
+
+#include <gtk/gtk.h>
+
+#include "nautilus-view.h"
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_ACTION_BAR (nautilus_action_bar_get_type())
+
+G_DECLARE_FINAL_TYPE (NautilusActionBar, nautilus_action_bar, NAUTILUS, ACTION_BAR, GtkActionBar)
+
+GtkWidget*           nautilus_action_bar_new                     (NautilusView      *view);
+
+G_END_DECLS
+
+#endif /* NAUTILUS_ACTION_BAR_H */
diff --git a/src/resources/css/Adwaita.css b/src/resources/css/Adwaita.css
index 87d9501..affad3f 100644
--- a/src/resources/css/Adwaita.css
+++ b/src/resources/css/Adwaita.css
@@ -122,6 +122,11 @@
     border-bottom: 1px solid @theme_bg_color;
 }
 
+actionbar {
+       background-color: @theme_bg_color;
+       border-top: solid 1px @borders;
+}
+
 /* Libgd tag entries in the search. Sadly it requires this copy pasted css style.
  * https://git.gnome.org/browse/libgd/tree/libgd/gd-tagged-entry-default.css
  */
diff --git a/src/resources/nautilus.gresource.xml b/src/resources/nautilus.gresource.xml
index 9463849..25dba10 100644
--- a/src/resources/nautilus.gresource.xml
+++ b/src/resources/nautilus.gresource.xml
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
   <gresource prefix="/org/gnome/nautilus">
+    <file compressed="true">ui/nautilus-action-bar.ui</file>
     <file compressed="true">ui/nautilus-preferences-window.ui</file>
     <file compressed="true">ui/nautilus-search-popover.ui</file>
     <file>gtk/menus.ui</file>
diff --git a/src/resources/ui/nautilus-action-bar.ui b/src/resources/ui/nautilus-action-bar.ui
new file mode 100644
index 0000000..3c501e0
--- /dev/null
+++ b/src/resources/ui/nautilus-action-bar.ui
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.18"/>
+  <template class="NautilusActionBar" parent="GtkActionBar">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <child>
+      <object class="GtkStack" id="stack">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="hexpand">True</property>
+        <property name="valign">center</property>
+        <property name="transition_type">crossfade</property>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkButton" id="paste_button">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="action_name">view.paste</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton">
+                <property name="label" translatable="yes">New Folder…</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="action_name">view.new-folder</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkMenuButton">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="menu_model">actionbar-menu</property>
+                <child>
+                  <object class="GtkImage">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="icon_name">view-more-symbolic</property>
+                  </object>
+                </child>
+                <style>
+                  <class name="image-button"/>
+                </style>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="pack_type">end</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="name">normal</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkButton">
+                <property name="label" translatable="yes">New Folder With Selection…</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="action_name">view.new-folder-with-selection</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton">
+                <property name="label" translatable="yes">Move To…</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="action_name">view.move-to</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton">
+                <property name="label" translatable="yes">Copy To…</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="action_name">view.copy-to</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkMenuButton">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="menu_model">actionbar-selection-menu</property>
+                <child>
+                  <object class="GtkImage">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="icon_name">view-more-symbolic</property>
+                  </object>
+                </child>
+                <style>
+                  <class name="image-button"/>
+                </style>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">3</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">True</property>
+                <property name="action_name">view.move-to-trash</property>
+                <style>
+                  <class name="destructive-action" />
+                </style>
+                <child>
+                  <object class="GtkImage">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="icon_name">user-trash-symbolic</property>
+                  </object>
+                </child>
+                <style>
+                  <class name="image-button"/>
+                </style>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="pack_type">end</property>
+                <property name="position">4</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="name">selection</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </template>
+  <menu id="actionbar-menu">
+    <section>
+      <item>
+        <attribute name="action">view.properties</attribute>
+        <attribute name="label" translatable="yes">Properties</attribute>
+        <attribute name="accel">&lt;Primary&gt;i</attribute>
+      </item>
+    </section>
+  </menu>
+  <menu id="actionbar-selection-menu">
+    <section>
+      <item>
+        <attribute name="action">view.open-item-new-window</attribute>
+        <attribute name="label" translatable="yes">Open in New Window</attribute>
+        <attribute name="accel">&lt;Primary&gt;&lt;Alt&gt;w</attribute>
+      </item>
+      <item>
+        <attribute name="action">view.open-item-new-tab</attribute>
+        <attribute name="label" translatable="yes">Open in New Tab</attribute>
+        <attribute name="accel">&lt;Primary&gt;&lt;Alt&gt;t</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="action">view.properties</attribute>
+        <attribute name="label" translatable="yes">Properties</attribute>
+        <attribute name="accel">&lt;Primary&gt;i</attribute>
+      </item>
+    </section>
+  </menu>
+</interface>


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