[libhandy/tabs: 31/62] Added a demo




commit e3ff707f4c2bc04cafde137a4b0fbf455e848208
Author: Alexander Mikhaylenko <alexm gnome org>
Date:   Wed Sep 9 22:49:09 2020 +0500

    Added a demo

 examples/handy-demo.c                          |  14 +
 examples/handy-demo.gresources.xml             |   4 +
 examples/hdy-demo-window.c                     |  14 +
 examples/hdy-demo-window.ui                    |  89 ++++++
 examples/hdy-tab-view-demo-window.c            | 410 +++++++++++++++++++++++++
 examples/hdy-tab-view-demo-window.h            |  15 +
 examples/hdy-tab-view-demo-window.ui           | 130 ++++++++
 examples/icons/ephy-audio-muted-symbolic.svg   |  86 ++++++
 examples/icons/ephy-audio-playing-symbolic.svg |   1 +
 examples/icons/widget-tab-view-symbolic.svg    |   1 +
 examples/meson.build                           |   1 +
 src/hdy-tab-box.c                              |   2 +-
 src/hdy-tab-view.c                             |   3 +-
 13 files changed, 768 insertions(+), 2 deletions(-)
---
diff --git a/examples/handy-demo.c b/examples/handy-demo.c
index 052ce4ce..7225afe9 100644
--- a/examples/handy-demo.c
+++ b/examples/handy-demo.c
@@ -17,6 +17,18 @@ show_preferences (GSimpleAction *action,
   gtk_widget_show (GTK_WIDGET (preferences));
 }
 
+static void
+setup_accels (GtkApplication *app)
+{
+  const char *const new_tab_accels[] = { "<Primary>T", NULL };
+  const char *const new_window_accels[] = { "<Primary>N", NULL };
+  const char *const tab_close_accels[] = { "<Primary>W", NULL };
+
+  gtk_application_set_accels_for_action (app, "win.tab-new", new_tab_accels);
+  gtk_application_set_accels_for_action (app, "win.window-new", new_window_accels);
+  gtk_application_set_accels_for_action (app, "tab.close", tab_close_accels);
+}
+
 static void
 startup (GtkApplication *app)
 {
@@ -24,6 +36,8 @@ startup (GtkApplication *app)
 
   hdy_init ();
 
+  setup_accels (app);
+
   gtk_css_provider_load_from_resource (css_provider, "/sm/puri/Handy/Demo/ui/style.css");
   gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
                                              GTK_STYLE_PROVIDER (css_provider),
diff --git a/examples/handy-demo.gresources.xml b/examples/handy-demo.gresources.xml
index e0825c1d..648ab330 100644
--- a/examples/handy-demo.gresources.xml
+++ b/examples/handy-demo.gresources.xml
@@ -2,6 +2,8 @@
 <gresources>
   <gresource prefix="/sm/puri/Handy/Demo">
     <file preprocess="xml-stripblanks">icons/dark-mode-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/ephy-audio-playing-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/ephy-audio-muted-symbolic.svg</file>
     <file preprocess="xml-stripblanks">icons/gesture-touchscreen-swipe-back-symbolic-rtl.svg</file>
     <file preprocess="xml-stripblanks">icons/gesture-touchscreen-swipe-back-symbolic.svg</file>
     <file preprocess="xml-stripblanks">icons/gesture-touchpad-swipe-back-symbolic-rtl.svg</file>
@@ -15,12 +17,14 @@
     <file preprocess="xml-stripblanks">icons/widget-leaflet-symbolic.svg</file>
     <file preprocess="xml-stripblanks">icons/widget-list-symbolic.svg</file>
     <file preprocess="xml-stripblanks">icons/widget-search-symbolic.svg</file>
+    <file preprocess="xml-stripblanks">icons/widget-tab-view-symbolic.svg</file>
     <file preprocess="xml-stripblanks">icons/widget-view-switcher-symbolic.svg</file>
     <file preprocess="xml-stripblanks">icons/widget-window-symbolic.svg</file>
   </gresource>
   <gresource prefix="/sm/puri/Handy/Demo/ui">
     <file preprocess="xml-stripblanks">hdy-demo-preferences-window.ui</file>
     <file preprocess="xml-stripblanks">hdy-demo-window.ui</file>
+    <file preprocess="xml-stripblanks">hdy-tab-view-demo-window.ui</file>
     <file preprocess="xml-stripblanks">hdy-view-switcher-demo-window.ui</file>
     <file compressed="true">style.css</file>
   </gresource>
diff --git a/examples/hdy-demo-window.c b/examples/hdy-demo-window.c
index ffcab9a1..a5d1091f 100644
--- a/examples/hdy-demo-window.c
+++ b/examples/hdy-demo-window.c
@@ -1,6 +1,7 @@
 #include "hdy-demo-window.h"
 
 #include <glib/gi18n.h>
+#include "hdy-tab-view-demo-window.h"
 #include "hdy-view-switcher-demo-window.h"
 
 struct _HdyDemoWindow
@@ -425,6 +426,18 @@ avatar_update_contacts (HdyDemoWindow *self)
   }
 }
 
+static void
+tab_view_demo_clicked_cb (GtkButton     *btn,
+                          HdyDemoWindow *self)
+{
+  GtkApplication *app = gtk_window_get_application (GTK_WINDOW (self) );
+  HdyTabViewDemoWindow *window = hdy_tab_view_demo_window_new (app);
+
+  hdy_tab_view_demo_window_prepopulate (window);
+
+  gtk_window_present (GTK_WINDOW (window));
+}
+
 static void
 hdy_demo_window_constructed (GObject *object)
 {
@@ -487,6 +500,7 @@ hdy_demo_window_class_init (HdyDemoWindowClass *klass)
   gtk_widget_class_bind_template_callback_full (widget_class, "carousel_return_clicked_cb", 
G_CALLBACK(carousel_return_clicked_cb));
   gtk_widget_class_bind_template_callback_full (widget_class, "avatar_file_remove_cb", 
G_CALLBACK(avatar_file_remove_cb));
   gtk_widget_class_bind_template_callback_full (widget_class, "avatar_file_set_cb", 
G_CALLBACK(avatar_file_set_cb));
+  gtk_widget_class_bind_template_callback_full (widget_class, "tab_view_demo_clicked_cb", 
G_CALLBACK(tab_view_demo_clicked_cb));
 }
 
 static void
diff --git a/examples/hdy-demo-window.ui b/examples/hdy-demo-window.ui
index 9d00588f..2fa86798 100644
--- a/examples/hdy-demo-window.ui
+++ b/examples/hdy-demo-window.ui
@@ -2277,6 +2277,95 @@
                         <property name="title">Window</property>
                       </packing>
                     </child>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="visible">True</property>
+                        <property name="orientation">vertical</property>
+                        <property name="can_focus">False</property>
+                        <property name="valign">center</property>
+                        <property name="expand">True</property>
+                        <child>
+                          <object class="GtkBox">
+                            <property name="visible">True</property>
+                            <property name="orientation">vertical</property>
+                            <property name="can_focus">False</property>
+                            <property name="halign">center</property>
+                            <property name="valign">center</property>
+                            <property name="margin-bottom">32</property>
+                            <child>
+                              <object class="GtkImage">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="valign">center</property>
+                                <property name="pixel_size">128</property>
+                                <property name="icon_name">widget-tab-view-symbolic</property>
+                                <property name="icon-size">0</property>
+                                <property name="margin-bottom">18</property>
+                                <style>
+                                  <class name="dim-label"/>
+                                </style>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                              </packing>
+                            </child>
+                            <child>
+                              <object class="GtkBox">
+                                <property name="visible">True</property>
+                                <property name="orientation">vertical</property>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="opacity">0.5</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" translatable="yes">Tab View</property>
+                                    <property name="halign">center</property>
+                                    <property name="xalign">0</property>
+                                    <property name="margin-bottom">12</property>
+                                    <attributes>
+                                      <attribute name="weight" value="bold"/>
+                                      <attribute name="scale" value="2"/>
+                                    </attributes>
+                                  </object>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="opacity">0.5</property>
+                                    <property name="can_focus">False</property>
+                                    <property name="label" translatable="yes">A modern tab widget.</property>
+                                    <property name="justify">center</property>
+                                    <property name="use_markup">true</property>
+                                    <property name="wrap">True</property>
+                                  </object>
+                                </child>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkBox">
+                            <property name="visible">True</property>
+                            <property name="orientation">vertical</property>
+                            <property name="can_focus">False</property>
+                            <property name="halign">center</property>
+                            <property name="spacing">12</property>
+                            <child>
+                              <object class="GtkButton">
+                                <property name="visible">True</property>
+                                <property name="label" translatable="yes">Run the demo</property>
+                                <signal name="clicked" handler="tab_view_demo_clicked_cb" swapped="no"/>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="name">tab-view</property>
+                        <property name="title">Tab View</property>
+                      </packing>
+                    </child>
                   </object>
                 </child>
               </object>
diff --git a/examples/hdy-tab-view-demo-window.c b/examples/hdy-tab-view-demo-window.c
new file mode 100644
index 00000000..e942d56a
--- /dev/null
+++ b/examples/hdy-tab-view-demo-window.c
@@ -0,0 +1,410 @@
+#include "hdy-tab-view-demo-window.h"
+
+#include <glib/gi18n.h>
+
+struct _HdyTabViewDemoWindow
+{
+  HdyApplicationWindow parent_instance;
+  HdyTabView *view;
+
+  GActionMap *tab_action_group;
+
+  HdyTabPage *menu_page;
+};
+
+G_DEFINE_TYPE (HdyTabViewDemoWindow, hdy_tab_view_demo_window, HDY_TYPE_APPLICATION_WINDOW)
+
+static void
+window_new (GSimpleAction *action,
+            GVariant      *parameter,
+            gpointer       user_data)
+{
+  HdyTabViewDemoWindow *self = HDY_TAB_VIEW_DEMO_WINDOW (user_data);
+  GtkApplication *app = gtk_window_get_application (GTK_WINDOW (self));
+  HdyTabViewDemoWindow *window = hdy_tab_view_demo_window_new (app);
+
+  hdy_tab_view_demo_window_prepopulate (window);
+
+  gtk_window_present (GTK_WINDOW (window));
+}
+
+static GIcon *
+get_random_icon (void)
+{
+  GtkIconTheme *theme = gtk_icon_theme_get_default ();
+  GList *list;
+  gint index;
+  GIcon *icon;
+
+  list = gtk_icon_theme_list_icons (theme, "MimeTypes");
+
+  index = g_random_int_range (0, g_list_length (list));
+  icon = g_themed_icon_new (g_list_nth_data (list, index));
+
+  g_list_free_full (list, g_free);
+
+  return icon;
+}
+
+static gboolean
+text_to_tooltip (GBinding     *binding,
+                 const GValue *input,
+                 GValue       *output,
+                 gpointer      user_data)
+{
+  const gchar *title = g_value_get_string (input);
+  gchar *tooltip = g_markup_printf_escaped ("An elaborate tooltip for <b>%s</b>", title);
+
+  g_value_take_string (output, tooltip);
+
+  return TRUE;
+}
+
+static void
+tab_new (GSimpleAction *action,
+         GVariant      *parameter,
+         gpointer       user_data)
+{
+  HdyTabViewDemoWindow *self = HDY_TAB_VIEW_DEMO_WINDOW (user_data);
+  g_autofree gchar *title = NULL;
+  GtkWidget *content;
+  HdyTabPage *page;
+  GIcon *icon;
+  static gint next_page = 1;
+
+  title = g_strdup_printf ("Page %d", next_page);
+  icon = get_random_icon ();
+
+  content = g_object_new (GTK_TYPE_ENTRY,
+                          "visible", TRUE,
+                          "text", title,
+                          "halign", GTK_ALIGN_CENTER,
+                          "valign", GTK_ALIGN_CENTER,
+                          NULL);
+
+  page = hdy_tab_view_append (self->view, GTK_WIDGET (content));
+
+  g_object_bind_property (content, "text",
+                          page, "title",
+                          G_BINDING_SYNC_CREATE);
+  g_object_bind_property_full (content, "text",
+                               page, "tooltip",
+                               G_BINDING_SYNC_CREATE,
+                               text_to_tooltip, NULL,
+                               NULL, NULL);
+
+  hdy_tab_page_set_icon (page, icon);
+  hdy_tab_page_set_secondary_icon_activatable (page, TRUE);
+
+  hdy_tab_view_set_selected_page (self->view, page);
+
+  next_page++;
+}
+
+static HdyTabPage *
+get_current_page (HdyTabViewDemoWindow *self)
+{
+  if (self->menu_page)
+    return self->menu_page;
+
+  return hdy_tab_view_get_selected_page (self->view);
+}
+
+static void
+tab_pin (GSimpleAction *action,
+         GVariant      *parameter,
+         gpointer       user_data)
+{
+  HdyTabViewDemoWindow *self = HDY_TAB_VIEW_DEMO_WINDOW (user_data);
+
+  hdy_tab_view_set_page_pinned (self->view, get_current_page (self), TRUE);
+}
+
+static void
+tab_unpin (GSimpleAction *action,
+           GVariant      *parameter,
+           gpointer       user_data)
+{
+  HdyTabViewDemoWindow *self = HDY_TAB_VIEW_DEMO_WINDOW (user_data);
+
+  hdy_tab_view_set_page_pinned (self->view, get_current_page (self), FALSE);
+}
+
+static void
+tab_close (GSimpleAction *action,
+           GVariant      *parameter,
+           gpointer       user_data)
+{
+  HdyTabViewDemoWindow *self = HDY_TAB_VIEW_DEMO_WINDOW (user_data);
+
+  hdy_tab_view_close_page (self->view, get_current_page (self));
+}
+
+static void
+tab_close_other (GSimpleAction *action,
+                 GVariant      *parameter,
+                 gpointer       user_data)
+{
+  HdyTabViewDemoWindow *self = HDY_TAB_VIEW_DEMO_WINDOW (user_data);
+
+  hdy_tab_view_close_other_pages (self->view, get_current_page (self));
+}
+
+static void
+tab_close_left (GSimpleAction *action,
+                GVariant      *parameter,
+                gpointer       user_data)
+{
+  HdyTabViewDemoWindow *self = HDY_TAB_VIEW_DEMO_WINDOW (user_data);
+
+  hdy_tab_view_close_pages_before (self->view, get_current_page (self));
+}
+
+static void
+tab_close_right (GSimpleAction *action,
+                 GVariant      *parameter,
+                 gpointer       user_data)
+{
+  HdyTabViewDemoWindow *self = HDY_TAB_VIEW_DEMO_WINDOW (user_data);
+
+  hdy_tab_view_close_pages_after (self->view, get_current_page (self));
+}
+
+static void
+tab_move_to_new_window (GSimpleAction *action,
+                        GVariant      *parameter,
+                        gpointer       user_data)
+{
+  HdyTabViewDemoWindow *self = HDY_TAB_VIEW_DEMO_WINDOW (user_data);
+  GtkApplication *app = gtk_window_get_application (GTK_WINDOW (self));
+  HdyTabViewDemoWindow *window = hdy_tab_view_demo_window_new (app);
+
+  hdy_tab_view_transfer_page (self->view,
+                              self->menu_page,
+                              window->view,
+                              0);
+
+  gtk_window_present (GTK_WINDOW (window));
+}
+
+static void
+tab_change_needs_attention (GSimpleAction *action,
+                            GVariant      *parameter,
+                            gpointer       user_data)
+{
+  HdyTabViewDemoWindow *self = HDY_TAB_VIEW_DEMO_WINDOW (user_data);
+  gboolean need_attention = g_variant_get_boolean (parameter);
+
+  hdy_tab_page_set_needs_attention (get_current_page (self), need_attention);
+  g_simple_action_set_state (action, g_variant_new_boolean (need_attention));
+}
+
+static void
+tab_change_loading (GSimpleAction *action,
+                    GVariant      *parameter,
+                    gpointer       user_data)
+{
+  HdyTabViewDemoWindow *self = HDY_TAB_VIEW_DEMO_WINDOW (user_data);
+  gboolean loading = g_variant_get_boolean (parameter);
+
+  hdy_tab_page_set_loading (get_current_page (self), loading);
+  g_simple_action_set_state (action, g_variant_new_boolean (loading));
+}
+
+static GIcon *
+get_secondary_icon (HdyTabPage *page)
+{
+  gboolean muted;
+
+  muted = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (page),
+                                              "hdy-tab-view-demo-muted"));
+
+  if (muted)
+    return g_themed_icon_new ("ephy-audio-muted-symbolic");
+  else
+    return g_themed_icon_new ("ephy-audio-playing-symbolic");
+}
+
+static void
+tab_change_secondary_icon (GSimpleAction *action,
+                           GVariant      *parameter,
+                           gpointer       user_data)
+{
+  HdyTabViewDemoWindow *self = HDY_TAB_VIEW_DEMO_WINDOW (user_data);
+  gboolean secondary_icon = g_variant_get_boolean (parameter);
+  g_autoptr (GIcon) icon = NULL;
+
+  if (secondary_icon)
+    icon = get_secondary_icon (get_current_page (self));
+
+  hdy_tab_page_set_secondary_icon (get_current_page (self), icon);
+  g_simple_action_set_state (action, g_variant_new_boolean (secondary_icon));
+}
+
+static GActionEntry action_entries[] = {
+  { "window-new", window_new },
+  { "tab-new", tab_new },
+};
+
+static GActionEntry tab_action_entries[] = {
+  { "pin", tab_pin },
+  { "unpin", tab_unpin },
+  { "close", tab_close },
+  { "close-other", tab_close_other },
+  { "close-left", tab_close_left },
+  { "close-right", tab_close_right },
+  { "move-to-new-window", tab_move_to_new_window },
+  { "needs-attention", NULL, NULL, "false", tab_change_needs_attention },
+  { "loading", NULL, NULL, "false", tab_change_loading },
+  { "secondary-icon", NULL, NULL, "false", tab_change_secondary_icon },
+};
+
+static inline void
+set_tab_action_enabled (HdyTabViewDemoWindow *self,
+                        const gchar          *name,
+                        gboolean              enabled)
+{
+  GAction *action = g_action_map_lookup_action (self->tab_action_group, name);
+
+  g_assert (G_IS_SIMPLE_ACTION (action));
+
+  g_simple_action_set_enabled (G_SIMPLE_ACTION (action),
+                               enabled);
+}
+
+static inline void
+set_tab_action_state (HdyTabViewDemoWindow *self,
+                      const gchar          *name,
+                      gboolean              state)
+{
+  GAction *action = g_action_map_lookup_action (self->tab_action_group, name);
+
+  g_assert (G_IS_SIMPLE_ACTION (action));
+
+  g_simple_action_set_state (G_SIMPLE_ACTION (action),
+                             g_variant_new_boolean (state));
+}
+
+static void
+setup_menu_cb (HdyTabViewDemoWindow *self,
+               HdyTabPage           *page,
+               HdyTabView           *view)
+{
+  HdyTabPage *prev = NULL;
+  gboolean can_close_left = TRUE, can_close_right = TRUE;
+  gboolean pinned = FALSE, prev_pinned;
+  guint n_pages, pos;
+
+  self->menu_page = page;
+
+  n_pages = hdy_tab_view_get_n_pages (self->view);
+
+  if (page) {
+    pos = hdy_tab_view_get_page_position (self->view, page);
+
+    if (pos > 0)
+      prev = hdy_tab_view_get_nth_page (self->view, pos - 1);
+
+    pinned = hdy_tab_page_get_pinned (page);
+    prev_pinned = prev && hdy_tab_page_get_pinned (prev);
+
+    can_close_left = !pinned && prev && !prev_pinned;
+    can_close_right = pos < n_pages - 1;
+  }
+
+  set_tab_action_enabled (self, "pin", !page || !pinned);
+  set_tab_action_enabled (self, "unpin", !page || pinned);
+  set_tab_action_enabled (self, "close", !page || !pinned);
+  set_tab_action_enabled (self, "close-left", can_close_left);
+  set_tab_action_enabled (self, "close-right", can_close_right);
+  set_tab_action_enabled (self, "close-other", can_close_left || can_close_right);
+  set_tab_action_enabled (self, "move-to-new-window", !page || (!pinned && n_pages > 1));
+
+  if (page) {
+    set_tab_action_state (self, "loading", hdy_tab_page_get_loading (page));
+    set_tab_action_state (self, "needs-attention", hdy_tab_page_get_needs_attention (page));
+    set_tab_action_state (self, "secondary-icon", hdy_tab_page_get_secondary_icon (page) != NULL);
+  }
+}
+
+static HdyTabView *
+create_window_cb (HdyTabViewDemoWindow *self)
+{
+  GtkApplication *app = gtk_window_get_application (GTK_WINDOW (self));
+  HdyTabViewDemoWindow *window = hdy_tab_view_demo_window_new (app);
+
+  gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
+  gtk_window_present (GTK_WINDOW (window));
+
+  return window->view;
+}
+
+static void
+secondary_icon_activated_cb (HdyTabViewDemoWindow *self,
+                             HdyTabPage           *page)
+{
+  g_autoptr (GIcon) icon = NULL;
+  gboolean muted;
+
+  muted = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (page),
+                                              "hdy-tab-view-demo-muted"));
+
+  g_object_set_data (G_OBJECT (page),
+                     "hdy-tab-view-demo-muted",
+                     GINT_TO_POINTER (!muted));
+
+  icon = get_secondary_icon (page);
+
+  hdy_tab_page_set_secondary_icon (page, icon);
+}
+
+static void
+hdy_tab_view_demo_window_class_init (HdyTabViewDemoWindowClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gtk_widget_class_set_template_from_resource (widget_class, 
"/sm/puri/Handy/Demo/ui/hdy-tab-view-demo-window.ui");
+  gtk_widget_class_bind_template_child (widget_class, HdyTabViewDemoWindow, view);
+  gtk_widget_class_bind_template_callback (widget_class, setup_menu_cb);
+  gtk_widget_class_bind_template_callback (widget_class, create_window_cb);
+  gtk_widget_class_bind_template_callback (widget_class, secondary_icon_activated_cb);
+}
+
+static void
+hdy_tab_view_demo_window_init (HdyTabViewDemoWindow *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  g_action_map_add_action_entries (G_ACTION_MAP (self),
+                                   action_entries,
+                                   G_N_ELEMENTS (action_entries),
+                                   self);
+
+  self->tab_action_group = G_ACTION_MAP (g_simple_action_group_new ());
+  g_action_map_add_action_entries (self->tab_action_group,
+                                   tab_action_entries,
+                                   G_N_ELEMENTS (tab_action_entries),
+                                   self);
+
+  gtk_widget_insert_action_group (GTK_WIDGET (self),
+                                  "tab",
+                                  G_ACTION_GROUP (self->tab_action_group));
+}
+
+HdyTabViewDemoWindow *
+hdy_tab_view_demo_window_new (GtkApplication *app)
+{
+  g_return_val_if_fail (GTK_IS_APPLICATION (app), NULL);
+
+  return g_object_new (HDY_TYPE_TAB_VIEW_DEMO_WINDOW,
+                       "application", app,
+                       NULL);
+}
+
+void
+hdy_tab_view_demo_window_prepopulate (HdyTabViewDemoWindow *self)
+{
+  tab_new (NULL, NULL, self);
+  tab_new (NULL, NULL, self);
+  tab_new (NULL, NULL, self);
+}
diff --git a/examples/hdy-tab-view-demo-window.h b/examples/hdy-tab-view-demo-window.h
new file mode 100644
index 00000000..67bee92f
--- /dev/null
+++ b/examples/hdy-tab-view-demo-window.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <handy.h>
+
+G_BEGIN_DECLS
+
+#define HDY_TYPE_TAB_VIEW_DEMO_WINDOW (hdy_tab_view_demo_window_get_type())
+
+G_DECLARE_FINAL_TYPE (HdyTabViewDemoWindow, hdy_tab_view_demo_window, HDY, TAB_VIEW_DEMO_WINDOW, 
HdyApplicationWindow)
+
+HdyTabViewDemoWindow *hdy_tab_view_demo_window_new (GtkApplication *app);
+
+void hdy_tab_view_demo_window_prepopulate (HdyTabViewDemoWindow *self);
+
+G_END_DECLS
diff --git a/examples/hdy-tab-view-demo-window.ui b/examples/hdy-tab-view-demo-window.ui
new file mode 100644
index 00000000..931518a0
--- /dev/null
+++ b/examples/hdy-tab-view-demo-window.ui
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.0 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <requires lib="libhandy" version="0.0"/>
+  <template class="HdyTabViewDemoWindow" parent="HdyApplicationWindow">
+    <property name="title">Tab View Demo</property>
+    <property name="default-width">800</property>
+    <property name="default-height">600</property>
+    <child>
+      <object class="GtkBox">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <child>
+          <object class="HdyHeaderBar">
+            <property name="visible">True</property>
+            <property name="show_close_button">True</property>
+            <property name="title" bind-source="HdyTabViewDemoWindow" bind-property="title"/>
+            <child>
+              <object class="GtkButton">
+                <property name="visible">True</property>
+                <property name="action-name">win.tab-new</property>
+                <child>
+                  <object class="GtkImage">
+                    <property name="visible">True</property>
+                    <property name="icon-name">tab-new-symbolic</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="GtkMenuButton">
+                <property name="visible">True</property>
+                <property name="menu-model">primary_menu</property>
+                <child>
+                  <object class="GtkImage">
+                    <property name="visible">True</property>
+                    <property name="icon-name">open-menu-symbolic</property>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="pack-type">end</property>
+              </packing>
+            </child>
+          </object>
+        </child>
+        <child>
+          <object class="HdyTabBar">
+            <property name="visible">True</property>
+            <property name="view">view</property>
+          </object>
+        </child>
+        <child>
+          <object class="HdyTabView" id="view">
+            <property name="visible">True</property>
+            <property name="vexpand">True</property>
+            <property name="menu-model">tab_menu</property>
+            <signal name="setup-menu" handler="setup_menu_cb" swapped="true"/>
+            <signal name="create-window" handler="create_window_cb" swapped="true"/>
+            <signal name="secondary-icon-activated" handler="secondary_icon_activated_cb" swapped="true"/>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+  <menu id="primary_menu">
+    <section>
+      <item>
+        <attribute name="label">_New Window</attribute>
+        <attribute name="action">win.window-new</attribute>
+      </item>
+    </section>
+  </menu>
+  <menu id="tab_menu">
+    <section>
+      <item>
+        <attribute name="label">_Move to New Window</attribute>
+        <attribute name="action">tab.move-to-new-window</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label">P_in Tab</attribute>
+        <attribute name="action">tab.pin</attribute>
+        <attribute name="hidden-when">action-disabled</attribute>
+      </item>
+      <item>
+        <attribute name="label">Unp_in Tab</attribute>
+        <attribute name="action">tab.unpin</attribute>
+        <attribute name="hidden-when">action-disabled</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label">Loa_ding</attribute>
+        <attribute name="action">tab.loading</attribute>
+      </item>
+      <item>
+        <attribute name="label">Needs _Attention</attribute>
+        <attribute name="action">tab.needs-attention</attribute>
+      </item>
+      <item>
+        <attribute name="label">_Secondary Icon</attribute>
+        <attribute name="action">tab.secondary-icon</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label">Close _Other Tabs</attribute>
+        <attribute name="action">tab.close-other</attribute>
+      </item>
+      <item>
+        <attribute name="label">Close Tabs to the _Left</attribute>
+        <attribute name="action">tab.close-left</attribute>
+      </item>
+      <item>
+        <attribute name="label">Close Tabs to the _Right</attribute>
+        <attribute name="action">tab.close-right</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label">_Close</attribute>
+        <attribute name="action">tab.close</attribute>
+      </item>
+    </section>
+  </menu>
+</interface>
diff --git a/examples/icons/ephy-audio-muted-symbolic.svg b/examples/icons/ephy-audio-muted-symbolic.svg
new file mode 100644
index 00000000..e838a7b7
--- /dev/null
+++ b/examples/icons/ephy-audio-muted-symbolic.svg
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   width="15.999999"
+   height="15.999999"
+   viewBox="0 0 4.233333 4.2333332"
+   version="1.1"
+   id="svg59656"
+   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+   sodipodi:docname="sound-muted-symbolic.svg">
+  <defs
+     id="defs59650" />
+  <sodipodi:namedview
+     inkscape:snap-midpoints="true"
+     inkscape:snap-smooth-nodes="true"
+     inkscape:snap-intersection-paths="true"
+     inkscape:object-paths="true"
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="4.7332096"
+     inkscape:cx="72.365677"
+     inkscape:cy="-5.9069288"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:document-rotation="0"
+     showgrid="true"
+     units="px"
+     inkscape:window-width="1920"
+     inkscape:window-height="1016"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1">
+    <inkscape:grid
+       type="xygrid"
+       id="grid59669"
+       originx="-414.0729"
+       originy="-67.204172" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata59653">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-414.07291,-67.20417)">
+    <g
+       style="fill:#241f31"
+       transform="matrix(0.26458333,0,0,0.26458333,414.07293,67.204165)"
+       fill="#474747"
+       id="g16">
+      <path
+         transform="translate(-7.5590552e-5,1.8897638e-5)"
+         d="M 7.453125 2 L 4.5214844 4.9609375 L 8 8.4394531 L 8 2 L 7.453125 2 z M 11 3 L 11 5 C 11.607 
5.789 12 6.76 12 8 C 12 9.241 11.607 10.22 11 11 L 11 11.439453 L 12.287109 12.726562 C 13.34008 11.684021 14 
9.952001 14 8 C 14 5.834 13.261 3.98 12 3 L 11 3 z M 2 5 L 2 11 L 4.484375 11 L 7.5253906 14 L 8 14 L 8 
10.5625 L 2.4375 5 L 2 5 z M 9 5 L 9 9.4394531 L 10.226562 10.666016 C 10.734406 9.9178051 11 9.0952939 11 8 
C 11 6.743 10.688 5.784 10 5 L 9 5 z "
+         style="marker:none;fill:#241f31"
+         id="path10" />
+    </g>
+    <path
+       id="path60"
+       d="m 417.90147,71.336914 0.28098,-0.280987 -3.70443,-3.703902 -0.28072,0.280723 z"
+       
style="fill:#241f31;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
 />
+    <g
+       style="fill:#2ec27e"
+       transform="translate(-5.8208332)"
+       id="g72" />
+  </g>
+</svg>
diff --git a/examples/icons/ephy-audio-playing-symbolic.svg b/examples/icons/ephy-audio-playing-symbolic.svg
new file mode 100644
index 00000000..0a641575
--- /dev/null
+++ b/examples/icons/ephy-audio-playing-symbolic.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="16" height="16"><g fill="#474747"><path d="M2 
5h2.484l2.97-3H8v12h-.475l-3.04-3H2z" style="marker:none" color="#bebebe" overflow="visible"/><path d="M14 
8c0-2.166-.739-4.02-2-5h-1v2c.607.789 1 1.76 1 3 0 1.241-.393 2.22-1 3v2h1c1.223-.995 2-2.873 2-5z" 
style="marker:none" color="#000" overflow="visible"/><path d="M11 8c0-1.257-.312-2.216-1-3H9v6h1c.672-.837 
1-1.742 1-3z" 
style="line-height:normal;-inkscape-font-specification:Sans;text-indent:0;text-align:start;text-decoration-line:none;text-transform:none;marker:none"
 color="#000" font-weight="400" font-family="Sans" overflow="visible"/></g></svg>
\ No newline at end of file
diff --git a/examples/icons/widget-tab-view-symbolic.svg b/examples/icons/widget-tab-view-symbolic.svg
new file mode 100644
index 00000000..38230bb0
--- /dev/null
+++ b/examples/icons/widget-tab-view-symbolic.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg"; width="16.009" height="16"><g fill="#2e3436"><path d="M4.003 
1s-.709-.014-1.447.355C1.817 1.725 1.003 2.667 1.003 4v9h-1l-.004 2h.004l3 
.01V15h13v-2h-1V4s.014-.709-.355-1.447C14.278 1.814 13.336 1 12.003 1zm0 2h8c.667 0 
.725.186.855.447.131.262.145.553.145.553v9h-10V4c0-.667.186-.725.447-.855.262-.131.553-.145.553-.145z" 
style="line-height:normal;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000;text-transform:none;text-orientation:mixed;white-space:normal;shape-padding:0;isolation:auto;mix-blend-mode:normal;solid-color:#000;solid-opacity:1"
 color="#000" font-weight="400" font-family="sans-serif" overflow="visible"/><path d="M7.009 
5v2h-2v2h2v2h2V9h2V7h-2V5z"/></g></svg>
\ No newline at end of file
diff --git a/examples/meson.build b/examples/meson.build
index 883607e9..1e59a324 100644
--- a/examples/meson.build
+++ b/examples/meson.build
@@ -12,6 +12,7 @@ handy_demo_sources = [
   'handy-demo.c',
   'hdy-demo-preferences-window.c',
   'hdy-demo-window.c',
+  'hdy-tab-view-demo-window.c',
   'hdy-view-switcher-demo-window.c',
   libhandy_generated_headers,
 ]
diff --git a/src/hdy-tab-box.c b/src/hdy-tab-box.c
index 81129b30..b1479dd3 100644
--- a/src/hdy-tab-box.c
+++ b/src/hdy-tab-box.c
@@ -2629,7 +2629,7 @@ hdy_tab_box_button_press_event (GtkWidget      *widget,
 
   self->pressed_button = event->button;
 
-  if (self->pressed_button == GDK_BUTTON_MIDDLE && !self->pinned) {
+  if (self->pressed_button == GDK_BUTTON_MIDDLE) {
     hdy_tab_view_close_page (self->view, self->hovered_tab->page);
 
     return GDK_EVENT_STOP;
diff --git a/src/hdy-tab-view.c b/src/hdy-tab-view.c
index a8ec7641..b0c3dbdd 100644
--- a/src/hdy-tab-view.c
+++ b/src/hdy-tab-view.c
@@ -615,7 +615,8 @@ static gboolean
 close_page_cb (HdyTabView *self,
                HdyTabPage *page)
 {
-  hdy_tab_view_close_page_finish (self, page, TRUE);
+  hdy_tab_view_close_page_finish (self, page,
+                                  !hdy_tab_page_get_pinned (page));
 
   return GDK_EVENT_PROPAGATE;
 }


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