Compare commits
29 Commits
shader-too
...
wip/csoria
Author | SHA1 | Date | |
---|---|---|---|
|
8d381295d8 | ||
|
47e57e20db | ||
|
fc20d3e4c7 | ||
|
5612244ea2 | ||
|
6c6bc078ee | ||
|
b42658723f | ||
|
17aaf4d611 | ||
|
eb1e01c9d8 | ||
|
25996e4818 | ||
|
a58ca2f686 | ||
|
1760e74eec | ||
|
7bb1c7275f | ||
|
7e751d4c28 | ||
|
a23937f937 | ||
|
ab63949730 | ||
|
be254e2a6a | ||
|
25b2af0928 | ||
|
42d508d7b6 | ||
|
34f9fe4706 | ||
|
12dcce4808 | ||
|
80746fa837 | ||
|
8ef6f596a5 | ||
|
e48961cc07 | ||
|
7bd4acdeee | ||
|
0039b7cf17 | ||
|
cb33fb3478 | ||
|
b9b6e508f1 | ||
|
f3076aa28f | ||
|
0e86f08962 |
@@ -197,6 +197,7 @@ gtk_public_h_sources = \
|
||||
gtkfilechoosernative.h \
|
||||
gtkfilechooserwidget.h \
|
||||
gtkfilefilter.h \
|
||||
gtkfilespathbar.h \
|
||||
gtkfixed.h \
|
||||
gtkflowbox.h \
|
||||
gtkfontbutton.h \
|
||||
@@ -252,6 +253,7 @@ gtk_public_h_sources = \
|
||||
gtkpagesetup.h \
|
||||
gtkpaned.h \
|
||||
gtkpapersize.h \
|
||||
gtkpathbar.h \
|
||||
gtkplacessidebar.h \
|
||||
gtkplug.h \
|
||||
gtkpopover.h \
|
||||
@@ -487,6 +489,7 @@ gtk_private_h_sources = \
|
||||
gtkgestureswipeprivate.h \
|
||||
gtkgesturezoomprivate.h \
|
||||
gtkheaderbarprivate.h \
|
||||
gtkhidingbox.h \
|
||||
gtkhslaprivate.h \
|
||||
gtkiconcache.h \
|
||||
gtkiconhelperprivate.h \
|
||||
@@ -518,8 +521,8 @@ gtk_private_h_sources = \
|
||||
gtkmountoperationprivate.h \
|
||||
gtknativedialogprivate.h \
|
||||
gtkorientableprivate.h \
|
||||
gtkpathbarcontainerprivate.h \
|
||||
gtkpango.h \
|
||||
gtkpathbar.h \
|
||||
gtkplacessidebarprivate.h \
|
||||
gtkplacesviewprivate.h \
|
||||
gtkplacesviewrowprivate.h \
|
||||
@@ -756,6 +759,7 @@ gtk_base_c_sources = \
|
||||
gtkfilechooserutils.c \
|
||||
gtkfilechooserwidget.c \
|
||||
gtkfilefilter.c \
|
||||
gtkfilespathbar.c \
|
||||
gtkfilesystem.c \
|
||||
gtkfilesystemmodel.c \
|
||||
gtkfixed.c \
|
||||
@@ -779,6 +783,7 @@ gtk_base_c_sources = \
|
||||
gtkglarea.c \
|
||||
gtkgrid.c \
|
||||
gtkheaderbar.c \
|
||||
gtkhidingbox.c \
|
||||
gtkhsla.c \
|
||||
gtkicon.c \
|
||||
gtkiconcache.c \
|
||||
@@ -828,6 +833,7 @@ gtk_base_c_sources = \
|
||||
gtkorientable.c \
|
||||
gtkoverlay.c \
|
||||
gtkpagesetup.c \
|
||||
gtkpathbarcontainer.c \
|
||||
gtkpaned.c \
|
||||
gtkpango.c \
|
||||
gtkpapersize.c \
|
||||
|
@@ -6,7 +6,6 @@
|
||||
|
||||
<glade-widget-classes>
|
||||
<!-- base GTK+ private widgets -->
|
||||
<glade-widget-class name="GtkPathBar" generic-name="pathbar" title="Path Bar" icon-name="widget-gtk-toolbar"/>
|
||||
<glade-widget-class name="GtkColorEditor" generic-name="coloreditor" title="Color Editor" icon-name="widget-gtk-colorselection"/>
|
||||
<glade-widget-class name="GtkColorSwatch" generic-name="colorswatch" title="Color Swatch" icon-name="widget-gtk-colorselection"/>
|
||||
<glade-widget-class name="GtkColorPlane" generic-name="colorplane" title="Color Plane" icon-name="widget-gtk-colorselection"/>
|
||||
@@ -23,7 +22,6 @@
|
||||
</glade-widget-classes>
|
||||
|
||||
<glade-widget-group name="gtk-private" title="Private GTK+ Classes">
|
||||
<glade-widget-class-ref name="GtkPathBar"/>
|
||||
<glade-widget-class-ref name="GtkColorEditor"/>
|
||||
<glade-widget-class-ref name="GtkColorSwatch"/>
|
||||
<glade-widget-class-ref name="GtkColorPlane"/>
|
||||
|
@@ -102,6 +102,7 @@
|
||||
#include <gtk/gtkfilechoosernative.h>
|
||||
#include <gtk/gtkfilechooserwidget.h>
|
||||
#include <gtk/gtkfilefilter.h>
|
||||
#include <gtk/gtkfilespathbar.h>
|
||||
#include <gtk/gtkflowbox.h>
|
||||
#include <gtk/gtkfontbutton.h>
|
||||
#include <gtk/gtkfontchooser.h>
|
||||
@@ -120,6 +121,7 @@
|
||||
#include <gtk/gtkglarea.h>
|
||||
#include <gtk/gtkgrid.h>
|
||||
#include <gtk/gtkheaderbar.h>
|
||||
#include <gtk/gtkhidingbox.h>
|
||||
#include <gtk/gtkicontheme.h>
|
||||
#include <gtk/gtkiconview.h>
|
||||
#include <gtk/gtkimage.h>
|
||||
@@ -154,6 +156,7 @@
|
||||
#include <gtk/gtkoverlay.h>
|
||||
#include <gtk/gtkpagesetup.h>
|
||||
#include <gtk/gtkpapersize.h>
|
||||
#include <gtk/gtkpathbar.h>
|
||||
#include <gtk/gtkpaned.h>
|
||||
#include <gtk/gtkplacessidebar.h>
|
||||
#include <gtk/gtkpopover.h>
|
||||
|
@@ -479,7 +479,12 @@ count_expand_children (GtkBox *box,
|
||||
{
|
||||
*visible_children += 1;
|
||||
if (child->expand || gtk_widget_compute_expand (child->widget, private->orientation))
|
||||
{
|
||||
|
||||
if (GTK_IS_REVEALER (child->widget))
|
||||
g_print ("########################## IT IS\n");
|
||||
*expand_children += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -49,7 +49,7 @@
|
||||
#include "gtkmessagedialog.h"
|
||||
#include "gtkmountoperation.h"
|
||||
#include "gtkpaned.h"
|
||||
#include "gtkpathbar.h"
|
||||
#include "gtkfilespathbar.h"
|
||||
#include "gtkplacessidebar.h"
|
||||
#include "gtkplacessidebarprivate.h"
|
||||
#include "gtkplacesviewprivate.h"
|
||||
@@ -550,11 +550,9 @@ static void list_row_activated (GtkTreeView *tree_view,
|
||||
static void list_cursor_changed (GtkTreeView *treeview,
|
||||
GtkFileChooserWidget *impl);
|
||||
|
||||
static void path_bar_clicked (GtkPathBar *path_bar,
|
||||
GFile *file,
|
||||
GFile *child,
|
||||
gboolean child_is_hidden,
|
||||
GtkFileChooserWidget *impl);
|
||||
static void on_path_bar_file (GtkFilesPathBar *path_bar,
|
||||
GParamSpec *pspec,
|
||||
GtkFileChooserWidget *impl);
|
||||
|
||||
static void update_cell_renderer_attributes (GtkFileChooserWidget *impl);
|
||||
|
||||
@@ -3034,7 +3032,7 @@ put_recent_folder_in_pathbar (GtkFileChooserWidget *impl, GtkTreeIter *iter)
|
||||
gtk_tree_model_get (GTK_TREE_MODEL (priv->recent_model), iter,
|
||||
MODEL_COL_FILE, &file,
|
||||
-1);
|
||||
_gtk_path_bar_set_file (GTK_PATH_BAR (priv->browse_path_bar), file, FALSE);
|
||||
gtk_files_path_bar_set_file (GTK_FILES_PATH_BAR (priv->browse_path_bar), file);
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
@@ -5482,7 +5480,7 @@ update_current_folder_get_info_cb (GCancellable *cancellable,
|
||||
if (! _gtk_file_info_consider_as_directory (info))
|
||||
goto out;
|
||||
|
||||
_gtk_path_bar_set_file (GTK_PATH_BAR (priv->browse_path_bar), data->file, data->keep_trail);
|
||||
gtk_files_path_bar_set_file (GTK_FILES_PATH_BAR (priv->browse_path_bar), data->file);
|
||||
|
||||
if (priv->current_folder != data->file)
|
||||
{
|
||||
@@ -7845,24 +7843,15 @@ list_row_activated (GtkTreeView *tree_view,
|
||||
}
|
||||
|
||||
static void
|
||||
path_bar_clicked (GtkPathBar *path_bar,
|
||||
GFile *file,
|
||||
GFile *child_file,
|
||||
gboolean child_is_hidden,
|
||||
on_path_bar_file (GtkFilesPathBar *path_bar,
|
||||
GParamSpec *pspec,
|
||||
GtkFileChooserWidget *impl)
|
||||
{
|
||||
if (child_file)
|
||||
pending_select_files_add (impl, child_file);
|
||||
GFile *file;
|
||||
|
||||
if (!change_folder_and_display_error (impl, file, FALSE))
|
||||
return;
|
||||
file = gtk_files_path_bar_get_file (path_bar);
|
||||
|
||||
/* Say we have "/foo/bar/[.baz]" and the user clicks on "bar". We should then
|
||||
* show hidden files so that ".baz" appears in the file list, as it will still
|
||||
* be shown in the path bar: "/foo/[bar]/.baz"
|
||||
*/
|
||||
if (child_is_hidden)
|
||||
g_object_set (impl, "show-hidden", TRUE, NULL);
|
||||
change_folder_and_display_error (impl, file, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -7960,7 +7949,7 @@ up_folder_handler (GtkFileChooserWidget *impl)
|
||||
{
|
||||
GtkFileChooserWidgetPrivate *priv = impl->priv;
|
||||
|
||||
_gtk_path_bar_up (GTK_PATH_BAR (priv->browse_path_bar));
|
||||
//_gtk_path_bar_up (GTK_PATH_BAR (priv->browse_path_bar));
|
||||
}
|
||||
|
||||
/* Handler for the "down-folder" keybinding signal */
|
||||
@@ -7969,7 +7958,7 @@ down_folder_handler (GtkFileChooserWidget *impl)
|
||||
{
|
||||
GtkFileChooserWidgetPrivate *priv = impl->priv;
|
||||
|
||||
_gtk_path_bar_down (GTK_PATH_BAR (priv->browse_path_bar));
|
||||
//_gtk_path_bar_down (GTK_PATH_BAR (priv->browse_path_bar));
|
||||
}
|
||||
|
||||
/* Handler for the "home-folder" keybinding signal */
|
||||
@@ -8498,7 +8487,7 @@ gtk_file_chooser_widget_class_init (GtkFileChooserWidgetClass *class)
|
||||
gtk_widget_class_bind_template_callback (widget_class, list_selection_changed);
|
||||
gtk_widget_class_bind_template_callback (widget_class, list_cursor_changed);
|
||||
gtk_widget_class_bind_template_callback (widget_class, filter_combo_changed);
|
||||
gtk_widget_class_bind_template_callback (widget_class, path_bar_clicked);
|
||||
gtk_widget_class_bind_template_callback (widget_class, on_path_bar_file);
|
||||
gtk_widget_class_bind_template_callback (widget_class, places_sidebar_open_location_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, places_sidebar_show_error_message_cb);
|
||||
gtk_widget_class_bind_template_callback (widget_class, places_sidebar_show_other_locations_with_flags_cb);
|
||||
@@ -8564,10 +8553,8 @@ post_process_ui (GtkFileChooserWidget *impl)
|
||||
|
||||
g_list_free (cells);
|
||||
|
||||
/* Set the GtkPathBar file system backend */
|
||||
_gtk_path_bar_set_file_system (GTK_PATH_BAR (impl->priv->browse_path_bar), impl->priv->file_system);
|
||||
file = g_file_new_for_path ("/");
|
||||
_gtk_path_bar_set_file (GTK_PATH_BAR (impl->priv->browse_path_bar), file, FALSE);
|
||||
gtk_files_path_bar_set_file (GTK_FILES_PATH_BAR (impl->priv->browse_path_bar), file);
|
||||
g_object_unref (file);
|
||||
|
||||
/* Set the fixed size icon renderer, this requires
|
||||
@@ -8634,7 +8621,7 @@ gtk_file_chooser_widget_init (GtkFileChooserWidget *impl)
|
||||
/* Ensure GTK+ private types used by the template
|
||||
* definition before calling gtk_widget_init_template()
|
||||
*/
|
||||
g_type_ensure (GTK_TYPE_PATH_BAR);
|
||||
g_type_ensure (GTK_TYPE_FILES_PATH_BAR);
|
||||
g_type_ensure (GTK_TYPE_PLACES_VIEW);
|
||||
|
||||
gtk_widget_init_template (GTK_WIDGET (impl));
|
||||
|
541
gtk/gtkfilespathbar.c
Normal file
541
gtk/gtkfilespathbar.c
Normal file
@@ -0,0 +1,541 @@
|
||||
/* gtkfilespathbar.c
|
||||
*
|
||||
* Copyright (C) 2015 Red Hat
|
||||
*
|
||||
* 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 2 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/>.
|
||||
*
|
||||
* Authors: Carlos Soriano <csoriano@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkfilespathbar.h"
|
||||
#include "gtkpathbar.h"
|
||||
#include "gtkpopover.h"
|
||||
|
||||
#include "gtkintl.h"
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
|
||||
#define LOCAL_FILESYSTEM_ROOT_URI "file:///"
|
||||
#define OTHER_LOCATIONS_URI "other-locations:///"
|
||||
/**
|
||||
* SECTION:gtkfilespathbar
|
||||
* @Short_description: Widget that displays a path in UNIX format in a button-like manner
|
||||
* @Title: GtkFilesPathBar
|
||||
* @See_also: #GtkPathBar, #GtkFileChooser
|
||||
*
|
||||
* #GtkFilesPathBar is a stock widget that displays a path in UNIX format in a way that
|
||||
* the user can interact with it, selecting part of it or providing menus for
|
||||
* every part of the path.
|
||||
*
|
||||
* Given the usual big lenght of paths, it conveniently manages the overflow of it,
|
||||
* hiding the parts of the path that doesn't have snouegh space to be displayed
|
||||
* in a overflow popover
|
||||
*/
|
||||
|
||||
struct _GtkFilesPathBarPrivate
|
||||
{
|
||||
GtkWidget *path_bar;
|
||||
|
||||
GFile *file;
|
||||
GCancellable *cancellable;
|
||||
GFileMonitor *monitor;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkFilesPathBar, gtk_files_path_bar, GTK_TYPE_BIN)
|
||||
|
||||
enum {
|
||||
POPULATE_POPUP,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_FILE,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
static GParamSpec *files_path_bar_properties[LAST_PROP] = { NULL, };
|
||||
static guint files_path_bar_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
typedef struct {
|
||||
GtkFilesPathBar *path_bar;
|
||||
GString *display_path;
|
||||
GFile *root_file;
|
||||
gchar *root_label;
|
||||
GIcon *root_icon;
|
||||
GCancellable *cancellable;
|
||||
} PathFilesInfo;
|
||||
|
||||
static GMount*
|
||||
get_mounted_mount_for_root (GFile *file)
|
||||
{
|
||||
GVolumeMonitor *volume_monitor;
|
||||
GList *mounts;
|
||||
GList *l;
|
||||
GMount *mount;
|
||||
GMount *result = NULL;
|
||||
GFile *root = NULL;
|
||||
GFile *default_location = NULL;
|
||||
|
||||
volume_monitor = g_volume_monitor_get ();
|
||||
mounts = g_volume_monitor_get_mounts (volume_monitor);
|
||||
|
||||
for (l = mounts; l != NULL; l = l->next)
|
||||
{
|
||||
mount = l->data;
|
||||
|
||||
if (g_mount_is_shadowed (mount))
|
||||
continue;
|
||||
|
||||
root = g_mount_get_root (mount);
|
||||
if (g_file_equal (file, root))
|
||||
{
|
||||
result = g_object_ref (mount);
|
||||
break;
|
||||
}
|
||||
|
||||
default_location = g_mount_get_default_location (mount);
|
||||
if (!g_file_equal (default_location, root) &&
|
||||
g_file_equal (file, default_location))
|
||||
{
|
||||
result = g_object_ref (mount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_clear_object (&root);
|
||||
g_clear_object (&default_location);
|
||||
g_list_free_full (mounts, g_object_unref);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
file_is_home_dir (GFile *file)
|
||||
{
|
||||
gboolean is_home_dir;
|
||||
gchar *path;
|
||||
|
||||
path = g_file_get_path (file);
|
||||
|
||||
is_home_dir = g_strcmp0 (path, g_get_home_dir ()) == 0;
|
||||
|
||||
if (path)
|
||||
g_free (path);
|
||||
|
||||
return is_home_dir;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
file_is_absolute_root (GFile *file)
|
||||
{
|
||||
gboolean is_filesystem_root;
|
||||
gchar *file_basename;
|
||||
|
||||
file_basename = g_file_get_basename (file);
|
||||
is_filesystem_root = g_strcmp0 (file_basename, G_DIR_SEPARATOR_S) == 0;
|
||||
|
||||
g_free (file_basename);
|
||||
|
||||
return is_filesystem_root;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
file_is_root (GFile *file)
|
||||
{
|
||||
GMount *mount;
|
||||
gboolean is_root = FALSE;
|
||||
|
||||
mount = get_mounted_mount_for_root (file);
|
||||
|
||||
is_root = file_is_absolute_root (file) || file_is_home_dir (file) || mount;
|
||||
|
||||
g_clear_object (&mount);
|
||||
|
||||
return is_root;
|
||||
}
|
||||
|
||||
static GIcon*
|
||||
get_root_icon (GFile *file)
|
||||
{
|
||||
GIcon *icon = NULL;
|
||||
GFile *local_filesystem_file;
|
||||
|
||||
local_filesystem_file = g_file_new_for_uri (LOCAL_FILESYSTEM_ROOT_URI);
|
||||
if (g_file_equal (file, local_filesystem_file))
|
||||
icon = g_themed_icon_new ("drive-harddisk");
|
||||
|
||||
g_object_unref (local_filesystem_file);
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
get_root_label (GFile *file)
|
||||
{
|
||||
gchar *label = NULL;
|
||||
gchar *path;
|
||||
GMount *mount;
|
||||
GFile *other_locations;
|
||||
|
||||
path = g_file_get_path (file);
|
||||
mount = get_mounted_mount_for_root (file);
|
||||
other_locations = g_file_new_for_uri (OTHER_LOCATIONS_URI);
|
||||
if (g_strcmp0 (path, g_get_home_dir ()) == 0)
|
||||
label = g_strdup (_("Home"));
|
||||
else if (g_file_equal (file, other_locations))
|
||||
label = g_strdup (_("Other Locations"));
|
||||
else if (mount)
|
||||
label = g_mount_get_name (mount);
|
||||
|
||||
if (path)
|
||||
g_free (path);
|
||||
g_clear_object (&mount);
|
||||
g_object_unref (other_locations);
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
static void
|
||||
free_path_files_info (PathFilesInfo *path_files_info)
|
||||
{
|
||||
if (path_files_info->display_path)
|
||||
g_string_free (path_files_info->display_path, TRUE);
|
||||
if (path_files_info->root_label)
|
||||
g_free (path_files_info->root_label);
|
||||
|
||||
g_clear_object (&path_files_info->cancellable);
|
||||
g_clear_object (&path_files_info->root_file);
|
||||
g_clear_object (&path_files_info->root_icon);
|
||||
|
||||
g_slice_free (PathFilesInfo, path_files_info);
|
||||
}
|
||||
|
||||
static void
|
||||
on_all_path_files_info_queried (PathFilesInfo *path_files_info)
|
||||
{
|
||||
GtkFilesPathBarPrivate *priv = gtk_files_path_bar_get_instance_private (path_files_info->path_bar);
|
||||
gchar *root_uri;
|
||||
|
||||
root_uri = g_file_get_uri (path_files_info->root_file);
|
||||
gtk_path_bar_set_path_extended (GTK_PATH_BAR (priv->path_bar),
|
||||
path_files_info->display_path->str, root_uri,
|
||||
path_files_info->root_label, path_files_info->root_icon);
|
||||
|
||||
g_free (root_uri);
|
||||
free_path_files_info (path_files_info);
|
||||
}
|
||||
|
||||
static void
|
||||
on_queried_file_info (GObject *object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GFile *file = G_FILE (object);
|
||||
GError *error = NULL;
|
||||
PathFilesInfo *path_files_info = (PathFilesInfo *) user_data;
|
||||
GFileInfo *file_info = NULL;
|
||||
gchar *uri;
|
||||
|
||||
uri = g_file_get_uri (file);
|
||||
if (g_cancellable_is_cancelled (path_files_info->cancellable))
|
||||
{
|
||||
free_path_files_info (path_files_info);
|
||||
goto out;
|
||||
}
|
||||
|
||||
file_info = g_file_query_info_finish (file, result, &error);
|
||||
if (!error || g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
|
||||
{
|
||||
if (file_is_root (file))
|
||||
{
|
||||
|
||||
uri = g_file_get_uri (file);
|
||||
path_files_info->root_icon = get_root_icon (file);
|
||||
path_files_info->root_label = get_root_label (file);
|
||||
path_files_info->root_file = g_object_ref (file);
|
||||
/* If it is not specific root managed by us, just query display name */
|
||||
if (!path_files_info->root_label && !path_files_info->root_icon)
|
||||
{
|
||||
if (!error)
|
||||
{
|
||||
path_files_info->root_label = g_strdup (g_file_info_get_display_name (file_info));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Error trying to get info from %s, location not supported", uri);
|
||||
|
||||
free_path_files_info (path_files_info);
|
||||
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
g_string_prepend (path_files_info->display_path, uri);
|
||||
on_all_path_files_info_queried (path_files_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
GFile *parent;
|
||||
|
||||
parent = g_file_get_parent (file);
|
||||
|
||||
g_string_prepend (path_files_info->display_path, g_file_info_get_display_name (file_info));
|
||||
g_string_prepend (path_files_info->display_path, G_DIR_SEPARATOR_S);
|
||||
g_file_query_info_async (parent,
|
||||
"standard::display-name",
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
G_PRIORITY_DEFAULT,
|
||||
path_files_info->cancellable,
|
||||
on_queried_file_info,
|
||||
path_files_info);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
|
||||
free_path_files_info (path_files_info);
|
||||
}
|
||||
|
||||
out:
|
||||
g_object_unref (file);
|
||||
g_clear_object (&file_info);
|
||||
if (error)
|
||||
g_error_free (error);
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
static void
|
||||
on_path_bar_populate_popup (GtkPathBar *path_bar,
|
||||
GtkWidget *container,
|
||||
const gchar *selected_path,
|
||||
GtkFilesPathBar *self)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
file = g_file_new_for_path (selected_path);
|
||||
g_signal_emit (self, files_path_bar_signals[POPULATE_POPUP], 0,
|
||||
container, file);
|
||||
}
|
||||
|
||||
static void
|
||||
on_path_bar_selected_path (GtkPathBar *path_bar,
|
||||
GParamSpec *pspec,
|
||||
GtkFilesPathBar *self)
|
||||
{
|
||||
GFile *file;
|
||||
|
||||
file = g_file_new_for_uri (gtk_path_bar_get_selected_path (path_bar));
|
||||
|
||||
gtk_files_path_bar_set_file (self, file);
|
||||
|
||||
g_object_unref (file);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_files_path_bar_dispose (GObject *object)
|
||||
{
|
||||
GtkFilesPathBar *self = (GtkFilesPathBar *)object;
|
||||
GtkFilesPathBarPrivate *priv = gtk_files_path_bar_get_instance_private (self);
|
||||
|
||||
g_cancellable_cancel (priv->cancellable);
|
||||
g_clear_object (&priv->cancellable);
|
||||
g_clear_object (&priv->file);
|
||||
|
||||
G_OBJECT_CLASS (gtk_files_path_bar_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_files_path_bar_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFilesPathBar *self = GTK_FILES_PATH_BAR (object);
|
||||
GtkFilesPathBarPrivate *priv = gtk_files_path_bar_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_FILE:
|
||||
g_value_set_object (value, priv->file);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_files_path_bar_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFilesPathBar *self = GTK_FILES_PATH_BAR (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_FILE:
|
||||
gtk_files_path_bar_set_file (self, g_value_get_object (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_files_path_bar_class_init (GtkFilesPathBarClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->dispose = gtk_files_path_bar_dispose;
|
||||
object_class->get_property = gtk_files_path_bar_get_property;
|
||||
object_class->set_property = gtk_files_path_bar_set_property;
|
||||
|
||||
/**
|
||||
* GtkFilesPathBar::populate-popup:
|
||||
* @files_path_bar: the object which received the signal.
|
||||
* @container: (type Gtk.Widget): a #GtkContainer
|
||||
* @path: (type const gchar*): string of the path where the user performed a right click.
|
||||
*
|
||||
* The path bar emits this signal when the user invokes a contextual
|
||||
* popup on one of its items. In the signal handler, the application may
|
||||
* add extra items to the menu as appropriate. For example, a file manager
|
||||
* may want to add a "Properties" command to the menu.
|
||||
*
|
||||
* The @container and all its contents are destroyed after the user
|
||||
* dismisses the popup. The popup is re-created (and thus, this signal is
|
||||
* emitted) every time the user activates the contextual menu.
|
||||
*
|
||||
* Since: 3.20
|
||||
*/
|
||||
files_path_bar_signals [POPULATE_POPUP] =
|
||||
g_signal_new (I_("populate-popup"),
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (GtkFilesPathBarClass, populate_popup),
|
||||
NULL, NULL,
|
||||
_gtk_marshal_VOID__OBJECT_STRING,
|
||||
G_TYPE_NONE, 2,
|
||||
GTK_TYPE_WIDGET,
|
||||
G_TYPE_STRING);
|
||||
|
||||
files_path_bar_properties[PROP_FILE] =
|
||||
g_param_spec_object ("file",
|
||||
P_("File"),
|
||||
P_("The file set in the path bar."),
|
||||
G_TYPE_FILE,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties (object_class, LAST_PROP, files_path_bar_properties);
|
||||
|
||||
gtk_widget_class_set_css_name (widget_class, "files-path-bar");
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_files_path_bar_init (GtkFilesPathBar *self)
|
||||
{
|
||||
GtkFilesPathBarPrivate *priv = gtk_files_path_bar_get_instance_private (self);
|
||||
|
||||
g_type_ensure (GTK_TYPE_FILES_PATH_BAR);
|
||||
|
||||
priv->path_bar = gtk_path_bar_new ();
|
||||
gtk_path_bar_set_inverted (GTK_PATH_BAR (priv->path_bar), TRUE);
|
||||
gtk_widget_show (priv->path_bar);
|
||||
g_signal_connect (GTK_PATH_BAR (priv->path_bar), "populate-popup",
|
||||
G_CALLBACK (on_path_bar_populate_popup), self);
|
||||
g_signal_connect (GTK_PATH_BAR (priv->path_bar), "notify::selected-path",
|
||||
G_CALLBACK (on_path_bar_selected_path), self);
|
||||
gtk_container_add (GTK_CONTAINER (self), priv->path_bar);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_files_path_bar_get_file:
|
||||
* @files_path_bar: a #GtkFilesPathBar
|
||||
*
|
||||
* Get the path represented by the files path bar
|
||||
*
|
||||
* Returns: (transfer none): The current #GFile.
|
||||
*
|
||||
* Since: 3.20
|
||||
*/
|
||||
GFile*
|
||||
gtk_files_path_bar_get_file (GtkFilesPathBar *self)
|
||||
{
|
||||
GtkFilesPathBarPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_FILES_PATH_BAR (self), NULL);
|
||||
|
||||
priv = gtk_files_path_bar_get_instance_private (GTK_FILES_PATH_BAR (self));
|
||||
|
||||
return priv->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_files_path_bar_set_file:
|
||||
* @files_path_bar: a #GtkFilesPathBar
|
||||
* @file: the #GFile.
|
||||
*
|
||||
* Set the #GFile represented by the path bar.
|
||||
*
|
||||
* Since: 3.20
|
||||
*/
|
||||
void
|
||||
gtk_files_path_bar_set_file (GtkFilesPathBar *self,
|
||||
GFile *file)
|
||||
{
|
||||
GtkFilesPathBarPrivate *priv;
|
||||
PathFilesInfo *path_files_info;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILES_PATH_BAR (self));
|
||||
|
||||
priv = gtk_files_path_bar_get_instance_private (GTK_FILES_PATH_BAR (self));
|
||||
|
||||
if (priv->file && g_file_equal (priv->file, file))
|
||||
return;
|
||||
|
||||
g_cancellable_cancel (priv->cancellable);
|
||||
g_clear_object (&priv->cancellable);
|
||||
priv->cancellable = g_cancellable_new ();
|
||||
|
||||
g_clear_object (&priv->file);
|
||||
priv->file = g_object_ref (file);
|
||||
|
||||
path_files_info = g_slice_new (PathFilesInfo);
|
||||
path_files_info->path_bar = self;
|
||||
path_files_info->display_path = g_string_new ("");
|
||||
path_files_info->root_file = NULL;
|
||||
path_files_info->root_label = NULL;
|
||||
path_files_info->root_icon = NULL;
|
||||
path_files_info->cancellable = g_object_ref (priv->cancellable);
|
||||
|
||||
g_file_query_info_async (g_object_ref (file),
|
||||
"standard::display-name",
|
||||
G_FILE_QUERY_INFO_NONE,
|
||||
G_PRIORITY_DEFAULT,
|
||||
path_files_info->cancellable,
|
||||
on_queried_file_info,
|
||||
path_files_info);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), files_path_bar_properties[PROP_FILE]);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_files_path_bar_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_FILES_PATH_BAR, NULL);
|
||||
}
|
83
gtk/gtkfilespathbar.h
Normal file
83
gtk/gtkfilespathbar.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* gtkfilespathbar.h
|
||||
*
|
||||
* Copyright (C) 2015 Red Hat
|
||||
*
|
||||
* 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 2 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/>.
|
||||
*
|
||||
* Authors: Carlos Soriano <csoriano@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_FILES_PATH_BAR_H__
|
||||
#define __GTK_FILES_PATH_BAR_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtkbin.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_FILES_PATH_BAR (gtk_files_path_bar_get_type())
|
||||
#define GTK_FILES_PATH_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILES_PATH_BAR, GtkFilesPathBar))
|
||||
#define GTK_FILES_PATH_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILES_PATH_BAR, GtkFilesPathBarClass))
|
||||
#define GTK_IS_FILES_PATH_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILES_PATH_BAR))
|
||||
#define GTK_IS_FILES_PATH_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILES_PATH_BAR)
|
||||
#define GTK_FILES_PATH_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILES_PATH_BAR, GtkFilesPathBarClass))
|
||||
|
||||
typedef struct _GtkFilesPathBar GtkFilesPathBar;
|
||||
typedef struct _GtkFilesPathBarClass GtkFilesPathBarClass;
|
||||
typedef struct _GtkFilesPathBarPrivate GtkFilesPathBarPrivate;
|
||||
|
||||
struct _GtkFilesPathBarClass
|
||||
{
|
||||
GtkBinClass parent;
|
||||
|
||||
/*< public >*/
|
||||
|
||||
void (* populate_popup) (GtkFilesPathBar *files_path_bar,
|
||||
GFile *selected_file);
|
||||
/*< private >*/
|
||||
|
||||
/* Padding for future expansion */
|
||||
gpointer reserved[10];
|
||||
};
|
||||
|
||||
struct _GtkFilesPathBar
|
||||
{
|
||||
GtkBin parent_instance;
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
GType gtk_files_path_bar_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
GtkWidget* gtk_files_path_bar_new (void);
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
void gtk_files_path_bar_set_file (GtkFilesPathBar *files_path_bar,
|
||||
GFile *file);
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
GFile* gtk_files_path_bar_get_file (GtkFilesPathBar *files_path_bar);
|
||||
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
gboolean gtk_files_path_bar_get_edit_mode_enabled (GtkFilesPathBar *files_path_bar);
|
||||
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
void gtk_files_path_bar_set_edit_mode_enabled (GtkFilesPathBar *files_path_bar,
|
||||
gboolean enable);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_FILES_PATH_BAR_H__ */
|
@@ -29,6 +29,7 @@
|
||||
#include "gtkcontainerprivate.h"
|
||||
#include "gtkcsscustomgadgetprivate.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkrevealer.h"
|
||||
#include "gtkintl.h"
|
||||
|
||||
|
||||
@@ -1000,7 +1001,12 @@ gtk_grid_request_compute_expand (GtkGridRequest *request,
|
||||
line = &lines->lines[attach->pos - lines->min];
|
||||
line->empty = FALSE;
|
||||
if (gtk_widget_compute_expand (child->widget, orientation))
|
||||
{
|
||||
|
||||
if (GTK_IS_REVEALER (child->widget))
|
||||
g_print ("########################## IT IS\n");
|
||||
line->expand = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
for (list = priv->children; list; list = list->next)
|
||||
@@ -1030,6 +1036,8 @@ gtk_grid_request_compute_expand (GtkGridRequest *request,
|
||||
|
||||
if (!has_expand && gtk_widget_compute_expand (child->widget, orientation))
|
||||
{
|
||||
if (GTK_IS_REVEALER (child->widget))
|
||||
g_print ("########################## IT IS\n");
|
||||
for (i = 0; i < attach->span; i++)
|
||||
{
|
||||
if (attach->pos + i >= max || attach->pos + 1 < min)
|
||||
|
875
gtk/gtkhidingbox.c
Normal file
875
gtk/gtkhidingbox.c
Normal file
@@ -0,0 +1,875 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Rafał Lużyński <digitalfreak@lingonborough.com>
|
||||
* Copyright (C) 2015 Red Hat
|
||||
*
|
||||
* Licensed under the GNU General Public License Version 2
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Authors: Rafał Lużyński <digitalfreak@lingonborough.com>
|
||||
* Carlos Soriano <csoriano@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkhidingbox.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtksizerequest.h"
|
||||
#include "gtkbuildable.h"
|
||||
#include "gtkrevealer.h"
|
||||
#include "gtkadjustment.h"
|
||||
#include "gtkscrolledwindow.h"
|
||||
#include "gtkbox.h"
|
||||
|
||||
//TODO remove
|
||||
#include "gtkbutton.h"
|
||||
|
||||
#include "glib.h"
|
||||
|
||||
#define REVEALER_ANIMATION_TIME 250 //ms
|
||||
#define INVERT_ANIMATION_SPEED 0.1 //px/ms
|
||||
|
||||
struct _GtkHidingBoxPrivate
|
||||
{
|
||||
GList *children;
|
||||
gint16 spacing;
|
||||
gint inverted :1;
|
||||
GList *widgets_to_hide;
|
||||
GList *widgets_to_show;
|
||||
GList *widgets_to_remove;
|
||||
gint current_width;
|
||||
gint current_height;
|
||||
guint needs_update :1;
|
||||
|
||||
gboolean invert_animation;
|
||||
|
||||
GtkWidget *scrolled_window;
|
||||
GtkWidget *box;
|
||||
GtkAdjustment *hadjustment;
|
||||
|
||||
guint invert_animation_tick_id;
|
||||
double invert_animation_progress;
|
||||
guint64 invert_animation_initial_time;
|
||||
gint allocated_children_width;
|
||||
gint total_children_width;
|
||||
gint previous_child_width;
|
||||
};
|
||||
|
||||
static void
|
||||
gtk_hiding_box_buildable_init (GtkBuildableIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkHidingBox, gtk_hiding_box, GTK_TYPE_CONTAINER,
|
||||
G_ADD_PRIVATE (GtkHidingBox)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, gtk_hiding_box_buildable_init))
|
||||
|
||||
|
||||
static void
|
||||
gtk_hiding_box_buildable_add_child (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
GObject *child,
|
||||
const gchar *type)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (GTK_HIDING_BOX (buildable));
|
||||
|
||||
if (!type)
|
||||
{
|
||||
gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
|
||||
priv->needs_update = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GTK_BUILDER_WARN_INVALID_CHILD_TYPE (GTK_HIDING_BOX (buildable), type);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_hiding_box_buildable_init (GtkBuildableIface *iface)
|
||||
{
|
||||
iface->add_child = gtk_hiding_box_buildable_add_child;
|
||||
}
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_SPACING,
|
||||
PROP_INVERTED,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
static GParamSpec *hiding_box_properties[LAST_PROP] = { NULL, };
|
||||
|
||||
static void
|
||||
gtk_hiding_box_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkHidingBox *box = GTK_HIDING_BOX (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SPACING:
|
||||
gtk_hiding_box_set_spacing (box, g_value_get_int (value));
|
||||
break;
|
||||
case PROP_INVERTED:
|
||||
gtk_hiding_box_set_inverted (box, g_value_get_boolean (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_hiding_box_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkHidingBox *box = GTK_HIDING_BOX (object);
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SPACING:
|
||||
g_value_set_int (value, priv->spacing);
|
||||
break;
|
||||
case PROP_INVERTED:
|
||||
g_value_set_boolean (value, priv->inverted);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_hiding_box_add (GtkContainer *container,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkHidingBox *box = GTK_HIDING_BOX (container);
|
||||
GtkWidget *revealer;
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
|
||||
GtkStyleContext *style_context;
|
||||
|
||||
revealer = gtk_revealer_new ();
|
||||
style_context = gtk_widget_get_style_context (revealer);
|
||||
gtk_style_context_add_class (style_context, "pathbar-initial-opacity");
|
||||
gtk_revealer_set_transition_type (GTK_REVEALER (revealer),
|
||||
GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT);
|
||||
gtk_container_add (GTK_CONTAINER (revealer), widget);
|
||||
g_print ("box fine? %s \n", G_OBJECT_TYPE_NAME (priv->box));
|
||||
gtk_container_add (GTK_CONTAINER (priv->box), revealer);
|
||||
priv->children = g_list_append (priv->children, widget);
|
||||
gtk_widget_show (revealer);
|
||||
|
||||
g_print ("add\n");
|
||||
}
|
||||
|
||||
static void
|
||||
really_remove_child (GtkHidingBox *self,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GList *child;
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (self);
|
||||
|
||||
g_print ("really remove child %p %s\n", widget, gtk_button_get_label (GTK_BUTTON (widget)));
|
||||
for (child = priv->widgets_to_remove; child != NULL; child = child->next)
|
||||
{
|
||||
GtkWidget *revealer;
|
||||
|
||||
revealer = gtk_widget_get_parent (child->data);
|
||||
g_print ("aver %p\n", child->data);
|
||||
if (child->data == widget && !gtk_revealer_get_child_revealed (GTK_REVEALER (revealer)))
|
||||
{
|
||||
g_print ("############################## INSIDE\n");
|
||||
gboolean was_visible = gtk_widget_get_visible (widget);
|
||||
|
||||
priv->widgets_to_remove = g_list_remove (priv->widgets_to_remove,
|
||||
child->data);
|
||||
gtk_container_remove (GTK_CONTAINER (priv->box), revealer);
|
||||
|
||||
if (was_visible)
|
||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unrevealed_really_remove_child (GObject *widget,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkHidingBox *self = GTK_HIDING_BOX (user_data);
|
||||
|
||||
g_print ("unrevelaed really remove child %p %s\n", widget, G_OBJECT_TYPE_NAME (widget));
|
||||
really_remove_child (self, gtk_bin_get_child (GTK_BIN (widget)));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_hiding_box_remove (GtkContainer *container,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GtkHidingBox *box = GTK_HIDING_BOX (container);
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
|
||||
GtkWidget *to_remove;
|
||||
|
||||
g_print ("remove %p %s\n", widget, G_OBJECT_TYPE_NAME (widget));
|
||||
if (GTK_IS_REVEALER (widget) && gtk_widget_get_parent (widget) == priv->box)
|
||||
to_remove = gtk_bin_get_child (GTK_BIN (widget));
|
||||
else
|
||||
to_remove = widget;
|
||||
|
||||
priv->widgets_to_remove = g_list_append (priv->widgets_to_remove, to_remove);
|
||||
priv->children = g_list_remove (priv->children, to_remove);
|
||||
priv->needs_update = TRUE;
|
||||
gtk_widget_queue_resize (GTK_WIDGET (container));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_hiding_box_forall (GtkContainer *container,
|
||||
gboolean include_internals,
|
||||
GtkCallback callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
GtkHidingBox *box = GTK_HIDING_BOX (container);
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
|
||||
GList *child;
|
||||
|
||||
for (child = priv->children; child != NULL; child = child->next)
|
||||
(* callback) (child->data, callback_data);
|
||||
|
||||
if (include_internals)
|
||||
{
|
||||
(* callback) (priv->scrolled_window, callback_data);
|
||||
|
||||
for (child = priv->widgets_to_remove; child != NULL; child = child->next)
|
||||
(* callback) (child->data, callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_children_visibility (GtkHidingBox *box,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
|
||||
GtkWidget *child_widget;
|
||||
GList *child;
|
||||
GtkRequestedSize *sizes_temp;
|
||||
gint i;
|
||||
GList *children;
|
||||
gboolean allocate_more_children = TRUE;
|
||||
gint current_children_width = 0;
|
||||
|
||||
g_list_free (priv->widgets_to_show);
|
||||
priv->widgets_to_show = NULL;
|
||||
g_list_free (priv->widgets_to_hide);
|
||||
priv->widgets_to_hide = NULL;
|
||||
children = g_list_copy (priv->children);
|
||||
sizes_temp = g_newa (GtkRequestedSize, g_list_length (priv->children));
|
||||
if (priv->inverted)
|
||||
children = g_list_reverse (children);
|
||||
|
||||
/* Retrieve desired size for visible children. */
|
||||
for (i = 0, child = children; child != NULL; i++, child = child->next)
|
||||
{
|
||||
child_widget = GTK_WIDGET (child->data);
|
||||
|
||||
gtk_widget_get_preferred_width_for_height (child_widget,
|
||||
allocation->height,
|
||||
&sizes_temp[i].minimum_size,
|
||||
&sizes_temp[i].natural_size);
|
||||
|
||||
current_children_width += sizes_temp[i].minimum_size;
|
||||
|
||||
if (!allocate_more_children || current_children_width > allocation->width)
|
||||
{
|
||||
if (allocate_more_children)
|
||||
priv->allocated_children_width = current_children_width - sizes_temp[i].minimum_size;
|
||||
allocate_more_children = FALSE;
|
||||
priv->previous_child_width = sizes_temp[i].minimum_size;
|
||||
if (gtk_revealer_get_child_revealed (GTK_REVEALER (gtk_widget_get_parent (child_widget))))
|
||||
priv->widgets_to_hide = g_list_append (priv->widgets_to_hide, child_widget);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!g_list_find (priv->widgets_to_remove, child_widget))
|
||||
priv->widgets_to_show = g_list_append (priv->widgets_to_show, child_widget);
|
||||
}
|
||||
|
||||
priv->total_children_width = current_children_width;
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
static void
|
||||
add_opacity_class (GtkWidget *widget,
|
||||
const gchar *class_name)
|
||||
{
|
||||
GtkStyleContext *style_context;
|
||||
|
||||
style_context = gtk_widget_get_style_context (widget);
|
||||
|
||||
gtk_style_context_add_class (style_context, class_name);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_all_opacity_classes (GtkWidget *widget)
|
||||
{
|
||||
GtkStyleContext *style_context;
|
||||
|
||||
style_context = gtk_widget_get_style_context (widget);
|
||||
|
||||
gtk_style_context_remove_class (style_context, "pathbar-initial-opacity");
|
||||
gtk_style_context_remove_class (style_context, "pathbar-opacity-on");
|
||||
gtk_style_context_remove_class (style_context, "pathbar-opacity-off");
|
||||
gtk_style_context_remove_class (style_context, "pathbar-invert-animation-opacity-off");
|
||||
gtk_style_context_remove_class (style_context, "pathbar-invert-animation-opacity-on");
|
||||
}
|
||||
|
||||
static void
|
||||
opacity_on (GObject *widget,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (GTK_HIDING_BOX (user_data));
|
||||
|
||||
g_print ("opacity on!!!!!\n");
|
||||
g_signal_handlers_disconnect_by_func (widget, opacity_on, user_data);
|
||||
priv->widgets_to_show = g_list_remove (priv->widgets_to_show,
|
||||
gtk_bin_get_child (GTK_BIN (widget)));
|
||||
remove_all_opacity_classes (GTK_WIDGET (widget));
|
||||
}
|
||||
|
||||
static void
|
||||
opacity_off (GObject *widget,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (GTK_HIDING_BOX (user_data));
|
||||
|
||||
g_print ("opacity off!!!!!\n");
|
||||
g_signal_handlers_disconnect_by_func (widget, opacity_off, user_data);
|
||||
priv->widgets_to_hide = g_list_remove (priv->widgets_to_hide,
|
||||
gtk_bin_get_child (GTK_BIN (widget)));
|
||||
remove_all_opacity_classes (GTK_WIDGET (widget));
|
||||
}
|
||||
|
||||
static void
|
||||
idle_update_revealers (GtkHidingBox *box)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
|
||||
GList *l;
|
||||
|
||||
for (l = priv->widgets_to_hide; l != NULL; l = l->next)
|
||||
{
|
||||
GtkWidget *revealer;
|
||||
|
||||
g_print ("update revealer hide %s\n", gtk_button_get_label (GTK_BUTTON (l->data)));
|
||||
revealer = gtk_widget_get_parent (l->data);
|
||||
if (gtk_revealer_get_reveal_child (GTK_REVEALER (revealer)))
|
||||
{
|
||||
remove_all_opacity_classes (revealer);
|
||||
if (priv->invert_animation && priv->invert_animation_progress >= 1)
|
||||
{
|
||||
gdouble velocity = INVERT_ANIMATION_SPEED; // px / ms
|
||||
gint revealer_animation_time;
|
||||
gdouble max_real_adjustment;
|
||||
|
||||
max_real_adjustment = gtk_adjustment_get_upper (priv->hadjustment) -
|
||||
gtk_widget_get_allocated_width (priv->scrolled_window);
|
||||
|
||||
g_print ("animation velocity %f %f\n", max_real_adjustment, velocity);
|
||||
revealer_animation_time = (gtk_widget_get_allocated_width (priv->scrolled_window) -
|
||||
priv->allocated_children_width) /
|
||||
velocity;
|
||||
g_print ("animation time %d %d %d\n", priv->allocated_children_width, gtk_widget_get_allocated_width (priv->scrolled_window), revealer_animation_time);
|
||||
add_opacity_class (revealer, "pathbar-invert-animation-opacity-off");
|
||||
g_signal_connect (revealer, "notify::child-revealed", (GCallback) opacity_off, box);
|
||||
gtk_revealer_set_transition_duration (GTK_REVEALER (revealer), revealer_animation_time);
|
||||
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), FALSE);
|
||||
}
|
||||
else if (!priv->invert_animation)
|
||||
{
|
||||
add_opacity_class (revealer, "pathbar-opacity-off");
|
||||
g_signal_connect (revealer, "notify::child-revealed", (GCallback) opacity_off, box);
|
||||
gtk_revealer_set_transition_duration (GTK_REVEALER (revealer), REVEALER_ANIMATION_TIME);
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), FALSE);
|
||||
}
|
||||
#if 0
|
||||
if (!priv->invert_animation)
|
||||
{
|
||||
add_opacity_class (revealer, "pathbar-opacity-off");
|
||||
g_signal_connect (revealer, "notify::child-revealed", (GCallback) opacity_off, box);
|
||||
gtk_revealer_set_transition_duration (GTK_REVEALER (revealer), REVEALER_ANIMATION_TIME);
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), FALSE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
for (l = priv->widgets_to_remove; l != NULL; l = l->next)
|
||||
{
|
||||
GtkWidget *revealer;
|
||||
|
||||
g_print ("update revealer remove %s\n", gtk_button_get_label (GTK_BUTTON (l->data)));
|
||||
revealer = gtk_widget_get_parent (l->data);
|
||||
if (gtk_revealer_get_child_revealed (GTK_REVEALER (revealer)))
|
||||
{
|
||||
remove_all_opacity_classes (revealer);
|
||||
add_opacity_class (revealer, "pathbar-opacity-off");
|
||||
g_signal_connect (revealer, "notify::child-revealed",
|
||||
(GCallback) unrevealed_really_remove_child, box);
|
||||
gtk_revealer_set_transition_duration (GTK_REVEALER (revealer), REVEALER_ANIMATION_TIME);
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print ("widget to remove NOT revealed %p\n", l->data);
|
||||
really_remove_child (box, l->data);
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->widgets_to_remove || priv->widgets_to_hide)
|
||||
return;
|
||||
|
||||
for (l = priv->widgets_to_show; l != NULL; l = l->next)
|
||||
{
|
||||
GtkWidget *revealer;
|
||||
|
||||
revealer = gtk_widget_get_parent (l->data);
|
||||
if (!gtk_revealer_get_reveal_child (GTK_REVEALER (revealer)))
|
||||
{
|
||||
remove_all_opacity_classes (revealer);
|
||||
add_opacity_class (revealer, "pathbar-opacity-on");
|
||||
if (priv->invert_animation)
|
||||
gtk_revealer_set_transition_duration (GTK_REVEALER (revealer), REVEALER_ANIMATION_TIME);
|
||||
else
|
||||
gtk_revealer_set_transition_duration (GTK_REVEALER (revealer), REVEALER_ANIMATION_TIME);
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), TRUE);
|
||||
g_signal_connect (revealer, "notify::child-revealed", (GCallback) opacity_on, box);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_hiding_box_size_allocate (GtkWidget *widget,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
GtkHidingBox *box = GTK_HIDING_BOX (widget);
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
|
||||
GtkAllocation child_allocation;
|
||||
GtkRequestedSize *sizes;
|
||||
|
||||
gtk_widget_set_allocation (widget, allocation);
|
||||
|
||||
sizes = g_newa (GtkRequestedSize, g_list_length (priv->children));
|
||||
update_children_visibility (box, allocation);
|
||||
|
||||
idle_update_revealers (box);
|
||||
|
||||
child_allocation.x = allocation->x;
|
||||
child_allocation.y = allocation->y;
|
||||
child_allocation.width = allocation->width;
|
||||
child_allocation.height = allocation->height;
|
||||
gtk_widget_size_allocate (priv->scrolled_window, &child_allocation);
|
||||
|
||||
_gtk_widget_set_simple_clip (widget, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
update_hadjustment (GtkHidingBox *self)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (self);
|
||||
gdouble adjustment_value;
|
||||
gdouble max_real_adjustment;
|
||||
|
||||
max_real_adjustment = gtk_adjustment_get_upper (priv->hadjustment) -
|
||||
gtk_widget_get_allocated_width (priv->scrolled_window);
|
||||
|
||||
g_print ("aligment changed %f %f %d %f\n", max_real_adjustment, gtk_adjustment_get_upper (priv->hadjustment), gtk_widget_get_allocated_width (priv->scrolled_window), gtk_adjustment_get_lower (priv->hadjustment));
|
||||
if (priv->invert_animation)
|
||||
{
|
||||
if (priv->inverted)
|
||||
{
|
||||
adjustment_value = (priv->invert_animation_progress) *
|
||||
(max_real_adjustment -
|
||||
gtk_adjustment_get_lower (priv->hadjustment));
|
||||
}
|
||||
else
|
||||
{
|
||||
adjustment_value = ABS (1 - priv->invert_animation_progress) *
|
||||
(max_real_adjustment -
|
||||
gtk_adjustment_get_lower (priv->hadjustment));
|
||||
}
|
||||
|
||||
g_print ("adjustment value %f %f %f\n", adjustment_value, gtk_adjustment_get_upper (priv->hadjustment), priv->invert_animation_progress);
|
||||
gtk_adjustment_set_value (priv->hadjustment, adjustment_value);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (priv->inverted)
|
||||
gtk_adjustment_set_value (priv->hadjustment, max_real_adjustment);
|
||||
else
|
||||
gtk_adjustment_set_value (priv->hadjustment, gtk_adjustment_get_lower (priv->hadjustment));
|
||||
}
|
||||
|
||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
static void
|
||||
finish_invert_animation (GtkHidingBox *self)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (self);
|
||||
|
||||
g_print ("\n\n\n\n\n\n\n\n##################ss#######finish invert animation\n\n\n\n\n\n\n");
|
||||
idle_update_revealers (self);
|
||||
priv->invert_animation = FALSE;
|
||||
priv->invert_animation_initial_time = 0;
|
||||
gtk_widget_remove_tick_callback (priv->scrolled_window,
|
||||
priv->invert_animation_tick_id);
|
||||
priv->invert_animation_tick_id = 0;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
invert_animation_on_tick (GtkWidget *widget,
|
||||
GdkFrameClock *frame_clock,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkHidingBox *self = GTK_HIDING_BOX (user_data);
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (self);
|
||||
guint64 elapsed;
|
||||
gdouble max_real_adjustment;
|
||||
|
||||
max_real_adjustment = gtk_adjustment_get_upper (priv->hadjustment) -
|
||||
(gdouble) gtk_widget_get_allocated_width (priv->scrolled_window);
|
||||
|
||||
if (priv->invert_animation_initial_time == 0)
|
||||
priv->invert_animation_initial_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
|
||||
elapsed = gdk_frame_clock_get_frame_time (frame_clock) - priv->invert_animation_initial_time;
|
||||
priv->invert_animation_progress = elapsed * INVERT_ANIMATION_SPEED / (1000. * max_real_adjustment);
|
||||
g_print ("################animation progres %d %f %f %f\n", gtk_widget_get_allocated_width (priv->scrolled_window), max_real_adjustment, elapsed / 1000., priv->invert_animation_progress);
|
||||
update_hadjustment (self);
|
||||
|
||||
if (priv->invert_animation_progress >= 1)
|
||||
{
|
||||
finish_invert_animation (self);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
start_invert_animation (GtkHidingBox *self)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (self);
|
||||
GList *child;
|
||||
|
||||
priv->invert_animation = TRUE;
|
||||
priv->invert_animation_progress = 0;
|
||||
|
||||
for (child = priv->children; child != NULL; child = child->next)
|
||||
{
|
||||
GtkWidget *revealer;
|
||||
|
||||
revealer = gtk_widget_get_parent (GTK_WIDGET (child->data));
|
||||
|
||||
remove_all_opacity_classes (revealer);
|
||||
add_opacity_class (revealer, "pathbar-invert-animation-opacity-on");
|
||||
|
||||
gtk_revealer_set_transition_duration (GTK_REVEALER (revealer),
|
||||
0);
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), TRUE);
|
||||
}
|
||||
|
||||
priv->invert_animation_tick_id = gtk_widget_add_tick_callback (priv->scrolled_window,
|
||||
(GtkTickCallback) invert_animation_on_tick,
|
||||
self, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
hadjustment_on_changed (GtkAdjustment *hadjustment,
|
||||
gpointer user_data)
|
||||
{
|
||||
update_hadjustment (GTK_HIDING_BOX (user_data));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_hiding_box_get_preferred_width (GtkWidget *widget,
|
||||
gint *minimum_width,
|
||||
gint *natural_width)
|
||||
{
|
||||
GtkHidingBox *box = GTK_HIDING_BOX (widget);
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
|
||||
gint child_minimum_width;
|
||||
gint child_natural_width;
|
||||
GList *child;
|
||||
gint n_visible_children;
|
||||
gboolean have_min = FALSE;
|
||||
GList *children;
|
||||
|
||||
*minimum_width = 0;
|
||||
*natural_width = 0;
|
||||
|
||||
children = g_list_copy (priv->children);
|
||||
if (priv->inverted)
|
||||
children = g_list_reverse (children);
|
||||
|
||||
n_visible_children = 0;
|
||||
for (child = children; child != NULL; child = child->next)
|
||||
{
|
||||
if (!gtk_widget_is_visible (child->data))
|
||||
continue;
|
||||
|
||||
++n_visible_children;
|
||||
gtk_widget_get_preferred_width (child->data, &child_minimum_width, &child_natural_width);
|
||||
/* Minimum is a minimum of the first visible child */
|
||||
if (!have_min)
|
||||
{
|
||||
*minimum_width = child_minimum_width;
|
||||
have_min = TRUE;
|
||||
}
|
||||
/* Natural is a sum of all visible children */
|
||||
*natural_width += child_natural_width;
|
||||
}
|
||||
|
||||
/* Natural must also include the spacing */
|
||||
if (priv->spacing && n_visible_children > 1)
|
||||
*natural_width += priv->spacing * (n_visible_children - 1);
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_hiding_box_get_preferred_height (GtkWidget *widget,
|
||||
gint *minimum_height,
|
||||
gint *natural_height)
|
||||
{
|
||||
GtkHidingBox *box = GTK_HIDING_BOX (widget);
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
|
||||
gint child_minimum_height;
|
||||
gint child_natural_height;
|
||||
GList *child;
|
||||
|
||||
*minimum_height = 0;
|
||||
*natural_height = 0;
|
||||
for (child = priv->children; child != NULL; child = child->next)
|
||||
{
|
||||
if (!gtk_widget_is_visible (child->data))
|
||||
continue;
|
||||
|
||||
gtk_widget_get_preferred_height (child->data, &child_minimum_height, &child_natural_height);
|
||||
*minimum_height = MAX (*minimum_height, child_minimum_height);
|
||||
*natural_height = MAX (*natural_height, child_natural_height);
|
||||
}
|
||||
}
|
||||
|
||||
static GtkSizeRequestMode
|
||||
gtk_hiding_box_get_request_mode (GtkWidget *self)
|
||||
{
|
||||
return GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
|
||||
}
|
||||
|
||||
static void
|
||||
on_what (gpointer data,
|
||||
GObject *where_the_object_was)
|
||||
{
|
||||
G_BREAKPOINT ();
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_hiding_box_init (GtkHidingBox *box)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
|
||||
GtkWidget *hscrollbar;
|
||||
|
||||
gtk_widget_set_has_window (GTK_WIDGET (box), FALSE);
|
||||
priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
|
||||
priv->hadjustment = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (priv->scrolled_window));
|
||||
g_signal_connect (priv->hadjustment, "changed", (GCallback) hadjustment_on_changed, box);
|
||||
hscrollbar = gtk_scrolled_window_get_hscrollbar (GTK_SCROLLED_WINDOW (priv->scrolled_window));
|
||||
gtk_widget_hide (hscrollbar);
|
||||
priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
g_object_weak_ref (G_OBJECT (priv->box), on_what, NULL);
|
||||
gtk_container_add (GTK_CONTAINER (priv->scrolled_window), priv->box);
|
||||
gtk_widget_set_parent (priv->scrolled_window, GTK_WIDGET (box));
|
||||
|
||||
priv->invert_animation = FALSE;
|
||||
priv->spacing = 0;
|
||||
priv->inverted = FALSE;
|
||||
priv->invert_animation_tick_id = 0;
|
||||
priv->widgets_to_hide = NULL;
|
||||
priv->widgets_to_show = NULL;
|
||||
priv->widgets_to_remove = NULL;
|
||||
|
||||
gtk_widget_show_all (priv->scrolled_window);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_hiding_box_class_init (GtkHidingBoxClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
||||
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
|
||||
|
||||
object_class->set_property = gtk_hiding_box_set_property;
|
||||
object_class->get_property = gtk_hiding_box_get_property;
|
||||
|
||||
widget_class->size_allocate = gtk_hiding_box_size_allocate;
|
||||
widget_class->get_preferred_width = gtk_hiding_box_get_preferred_width;
|
||||
widget_class->get_preferred_height = gtk_hiding_box_get_preferred_height;
|
||||
widget_class->get_request_mode = gtk_hiding_box_get_request_mode;
|
||||
|
||||
container_class->add = gtk_hiding_box_add;
|
||||
container_class->remove = gtk_hiding_box_remove;
|
||||
container_class->forall = gtk_hiding_box_forall;
|
||||
|
||||
hiding_box_properties[PROP_SPACING] =
|
||||
g_param_spec_int ("spacing",
|
||||
_("Spacing"),
|
||||
_("The amount of space between children"),
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
hiding_box_properties[PROP_INVERTED] =
|
||||
g_param_spec_int ("inverted",
|
||||
_("Direction of hiding children inverted"),
|
||||
P_("If false the container will start hiding widgets from the end when there is not enough space, and the oposite in case inverted is true."),
|
||||
0, G_MAXINT, 0,
|
||||
G_PARAM_READWRITE);
|
||||
|
||||
g_object_class_install_properties (object_class, LAST_PROP, hiding_box_properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_hiding_box_new:
|
||||
*
|
||||
* Creates a new #GtkHidingBox.
|
||||
*
|
||||
* Returns: a new #GtkHidingBox.
|
||||
**/
|
||||
GtkWidget *
|
||||
gtk_hiding_box_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_HIDING_BOX, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_hiding_box_set_spacing:
|
||||
* @box: a #GtkHidingBox
|
||||
* @spacing: the number of pixels to put between children
|
||||
*
|
||||
* Sets the #GtkHidingBox:spacing property of @box, which is the
|
||||
* number of pixels to place between children of @box.
|
||||
*/
|
||||
void
|
||||
gtk_hiding_box_set_spacing (GtkHidingBox *box,
|
||||
gint spacing)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv ;
|
||||
|
||||
g_return_if_fail (GTK_IS_HIDING_BOX (box));
|
||||
|
||||
priv = gtk_hiding_box_get_instance_private (box);
|
||||
|
||||
if (priv->spacing != spacing)
|
||||
{
|
||||
priv->spacing = spacing;
|
||||
|
||||
g_object_notify (G_OBJECT (box), "spacing");
|
||||
|
||||
gtk_widget_queue_resize (GTK_WIDGET (box));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_hiding_box_get_spacing:
|
||||
* @box: a #GtkHidingBox
|
||||
*
|
||||
* Gets the value set by gtk_hiding_box_set_spacing().
|
||||
*
|
||||
* Returns: spacing between children
|
||||
**/
|
||||
gint
|
||||
gtk_hiding_box_get_spacing (GtkHidingBox *box)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv ;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_HIDING_BOX (box), 0);
|
||||
|
||||
priv = gtk_hiding_box_get_instance_private (box);
|
||||
|
||||
return priv->spacing;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gtk_hiding_box_set_inverted (GtkHidingBox *box,
|
||||
gboolean inverted)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv ;
|
||||
|
||||
g_return_if_fail (GTK_IS_HIDING_BOX (box));
|
||||
|
||||
priv = gtk_hiding_box_get_instance_private (box);
|
||||
|
||||
if (priv->inverted != inverted)
|
||||
{
|
||||
priv->inverted = inverted != FALSE;
|
||||
|
||||
g_object_notify (G_OBJECT (box), "inverted");
|
||||
|
||||
start_invert_animation (box);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (box));
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_hiding_box_get_inverted (GtkHidingBox *box)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv ;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_HIDING_BOX (box), 0);
|
||||
|
||||
priv = gtk_hiding_box_get_instance_private (box);
|
||||
|
||||
return priv->inverted;
|
||||
}
|
||||
|
||||
GList *
|
||||
gtk_hiding_box_get_overflow_children (GtkHidingBox *box)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv ;
|
||||
GList *result = NULL;
|
||||
GList *l;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_HIDING_BOX (box), 0);
|
||||
|
||||
priv = gtk_hiding_box_get_instance_private (box);
|
||||
|
||||
for (l = priv->children; l != NULL; l = l->next)
|
||||
if (gtk_widget_is_visible (l->data) && !gtk_widget_get_child_visible (l->data))
|
||||
result = g_list_append (result, l->data);
|
||||
|
||||
return result;
|
||||
}
|
77
gtk/gtkhidingbox.h
Normal file
77
gtk/gtkhidingbox.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Rafał Lużyński <digitalfreak@lingonborough.com>
|
||||
*
|
||||
* Licensed under the GNU General Public License Version 2
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_HIDING_BOX_H__
|
||||
#define __GTK_HIDING_BOX_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtkcontainer.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_HIDING_BOX (gtk_hiding_box_get_type())
|
||||
#define GTK_HIDING_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_HIDING_BOX, GtkHidingBox))
|
||||
#define GTK_HIDING_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_HIDING_BOX, GtkHidingBoxClass))
|
||||
#define GTK_IS_HIDING_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_HIDING_BOX))
|
||||
#define GTK_IS_HIDING_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_HIDING_BOX)
|
||||
#define GTK_HIDING_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_HIDING_BOX, GtkHidingBoxClass))
|
||||
|
||||
typedef struct _GtkHidingBox GtkHidingBox;
|
||||
typedef struct _GtkHidingBoxClass GtkHidingBoxClass;
|
||||
typedef struct _GtkHidingBoxPrivate GtkHidingBoxPrivate;
|
||||
|
||||
struct _GtkHidingBoxClass
|
||||
{
|
||||
GtkContainerClass parent;
|
||||
|
||||
/* Padding for future expansion */
|
||||
gpointer reserved[10];
|
||||
};
|
||||
|
||||
struct _GtkHidingBox
|
||||
{
|
||||
GtkContainer parent_instance;
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
GType gtk_hiding_box_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
GtkWidget *gtk_hiding_box_new (void);
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
void gtk_hiding_box_set_spacing (GtkHidingBox *box,
|
||||
gint spacing);
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
gint gtk_hiding_box_get_spacing (GtkHidingBox *box);
|
||||
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
void gtk_hiding_box_set_inverted (GtkHidingBox *box,
|
||||
gboolean inverted);
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
gboolean gtk_hiding_box_get_inverted (GtkHidingBox *box);
|
||||
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
GList *gtk_hiding_box_get_overflow_children (GtkHidingBox *box);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GTK_HIDING_BOX_H_ */
|
2514
gtk/gtkpathbar.c
2514
gtk/gtkpathbar.c
File diff suppressed because it is too large
Load Diff
113
gtk/gtkpathbar.h
113
gtk/gtkpathbar.h
@@ -1,67 +1,94 @@
|
||||
/* gtkpathbar.h
|
||||
* Copyright (C) 2004 Red Hat, Inc., Jonathan Blandford <jrb@gnome.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
* Copyright (C) 2015 Red Hat
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* 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 2 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
|
||||
* Library General Public License for more details.
|
||||
* 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 Library General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Carlos Soriano <csoriano@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_PATH_BAR_H__
|
||||
#define __GTK_PATH_BAR_H__
|
||||
|
||||
#include "gtkcontainer.h"
|
||||
#include "gtkfilesystem.h"
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtkbin.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkPathBar GtkPathBar;
|
||||
typedef struct _GtkPathBarClass GtkPathBarClass;
|
||||
#define GTK_TYPE_PATH_BAR (gtk_path_bar_get_type())
|
||||
#define GTK_PATH_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PATH_BAR, GtkPathBar))
|
||||
#define GTK_PATH_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PATH_BAR, GtkPathBarClass))
|
||||
#define GTK_IS_PATH_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PATH_BAR))
|
||||
#define GTK_IS_PATH_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PATH_BAR)
|
||||
#define GTK_PATH_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PATH_BAR, GtkPathBarClass))
|
||||
|
||||
typedef struct _GtkPathBar GtkPathBar;
|
||||
typedef struct _GtkPathBarClass GtkPathBarClass;
|
||||
typedef struct _GtkPathBarPrivate GtkPathBarPrivate;
|
||||
|
||||
|
||||
#define GTK_TYPE_PATH_BAR (gtk_path_bar_get_type ())
|
||||
#define GTK_PATH_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PATH_BAR, GtkPathBar))
|
||||
#define GTK_PATH_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PATH_BAR, GtkPathBarClass))
|
||||
#define GTK_IS_PATH_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PATH_BAR))
|
||||
#define GTK_IS_PATH_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PATH_BAR))
|
||||
#define GTK_PATH_BAR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PATH_BAR, GtkPathBarClass))
|
||||
|
||||
struct _GtkPathBar
|
||||
{
|
||||
GtkContainer parent;
|
||||
|
||||
GtkPathBarPrivate *priv;
|
||||
};
|
||||
|
||||
struct _GtkPathBarClass
|
||||
{
|
||||
GtkContainerClass parent_class;
|
||||
GtkBinClass parent;
|
||||
|
||||
void (* path_clicked) (GtkPathBar *path_bar,
|
||||
GFile *file,
|
||||
GFile *child_file,
|
||||
gboolean child_is_hidden);
|
||||
/*< public >*/
|
||||
|
||||
void (* populate_popup) (GtkPathBar *path_bar,
|
||||
const gchar *selected_path);
|
||||
/*< private >*/
|
||||
|
||||
/* Padding for future expansion */
|
||||
gpointer reserved[10];
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_path_bar_get_type (void) G_GNUC_CONST;
|
||||
void _gtk_path_bar_set_file_system (GtkPathBar *path_bar,
|
||||
GtkFileSystem *file_system);
|
||||
void _gtk_path_bar_set_file (GtkPathBar *path_bar,
|
||||
GFile *file,
|
||||
gboolean keep_trail);
|
||||
void _gtk_path_bar_up (GtkPathBar *path_bar);
|
||||
void _gtk_path_bar_down (GtkPathBar *path_bar);
|
||||
struct _GtkPathBar
|
||||
{
|
||||
GtkBin parent_instance;
|
||||
};
|
||||
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
GType gtk_path_bar_get_type (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
GtkWidget* gtk_path_bar_new (void);
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
void gtk_path_bar_set_path (GtkPathBar *path_bar,
|
||||
const gchar *path);
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
const gchar* gtk_path_bar_get_path (GtkPathBar *path_bar);
|
||||
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
void gtk_path_bar_set_path_extended (GtkPathBar *self,
|
||||
const gchar *path,
|
||||
const gchar *root_path,
|
||||
const gchar *root_label,
|
||||
GIcon *root_icon);
|
||||
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
void gtk_path_bar_set_selected_path (GtkPathBar *path_bar,
|
||||
const gchar *path);
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
const gchar* gtk_path_bar_get_selected_path (GtkPathBar *path_bar);
|
||||
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
void gtk_path_bar_set_inverted (GtkPathBar *path_bar,
|
||||
gboolean inverted);
|
||||
GDK_AVAILABLE_IN_3_20
|
||||
gboolean gtk_path_bar_get_inverted (GtkPathBar *path_bar);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_PATH_BAR_H__ */
|
||||
|
||||
|
260
gtk/gtkpathbarcontainer.c
Normal file
260
gtk/gtkpathbarcontainer.c
Normal file
@@ -0,0 +1,260 @@
|
||||
/* gtkpathbarcontainer.c
|
||||
*
|
||||
* Copyright (C) 2015 Red Hat
|
||||
*
|
||||
* 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 2 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/>.
|
||||
*
|
||||
* Authors: Carlos Soriano <csoriano@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkpathbarcontainerprivate.h"
|
||||
#include "gtkbuildable.h"
|
||||
#include "gtkwidget.h"
|
||||
#include "gtkmenubutton.h"
|
||||
#include "gtksizerequest.h"
|
||||
#include "gtkhidingbox.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
#include "glib-object.h"
|
||||
|
||||
struct _GtkPathBarContainerPrivate
|
||||
{
|
||||
GtkWidget *overflow_button;
|
||||
GtkWidget *path_box;
|
||||
};
|
||||
|
||||
static GtkBuildableIface *parent_buildable_iface;
|
||||
|
||||
static GObject *
|
||||
buildable_get_internal_child (GtkBuildable *buildable,
|
||||
GtkBuilder *builder,
|
||||
const gchar *childname)
|
||||
{
|
||||
if (g_strcmp0 (childname, "overflow_button") == 0)
|
||||
return G_OBJECT (gtk_path_bar_container_get_overflow_button (GTK_PATH_BAR_CONTAINER (buildable)));
|
||||
if (g_strcmp0 (childname, "path_box") == 0)
|
||||
return G_OBJECT (gtk_path_bar_container_get_path_box (GTK_PATH_BAR_CONTAINER (buildable)));
|
||||
|
||||
return parent_buildable_iface->get_internal_child (buildable, builder, childname);
|
||||
}
|
||||
|
||||
static void
|
||||
buildable_init (GtkBuildableIface *iface)
|
||||
{
|
||||
parent_buildable_iface = g_type_interface_peek_parent (iface);
|
||||
iface->get_internal_child = buildable_get_internal_child;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkPathBarContainer, gtk_path_bar_container, GTK_TYPE_CONTAINER,
|
||||
G_ADD_PRIVATE (GtkPathBarContainer)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, buildable_init))
|
||||
static void
|
||||
container_forall (GtkContainer *container,
|
||||
gboolean include_internals,
|
||||
GtkCallback callback,
|
||||
gpointer callback_data)
|
||||
{
|
||||
GtkPathBarContainerPrivate *priv = gtk_path_bar_container_get_instance_private (GTK_PATH_BAR_CONTAINER (container));
|
||||
|
||||
if (include_internals)
|
||||
{
|
||||
(* callback) (priv->overflow_button, callback_data);
|
||||
(* callback) (priv->path_box, callback_data);
|
||||
}
|
||||
}
|
||||
|
||||
static GtkSizeRequestMode
|
||||
get_request_mode (GtkWidget *self)
|
||||
{
|
||||
return GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
|
||||
}
|
||||
|
||||
static void
|
||||
size_allocate (GtkWidget *self,
|
||||
GtkAllocation *allocation)
|
||||
{
|
||||
GtkPathBarContainerPrivate *priv = gtk_path_bar_container_get_instance_private (GTK_PATH_BAR_CONTAINER (self));
|
||||
gint path_min_width;
|
||||
gint path_nat_width;
|
||||
gint overflow_button_min_width;
|
||||
GtkAllocation path_container_allocation;
|
||||
GtkAllocation overflow_button_allocation;
|
||||
GtkTextDirection direction;
|
||||
gboolean overflow;
|
||||
GList *overflow_children;
|
||||
GList *children;
|
||||
|
||||
gtk_widget_set_allocation (self, allocation);
|
||||
|
||||
children = gtk_container_get_children (GTK_CONTAINER (priv->path_box));
|
||||
gtk_widget_set_child_visible (priv->overflow_button, FALSE);
|
||||
|
||||
if (g_list_length (children) == 0)
|
||||
return;
|
||||
|
||||
gtk_widget_get_preferred_width (priv->path_box, &path_min_width, &path_nat_width);
|
||||
|
||||
/* Try to allocate all children with our allocation so we can request if there
|
||||
* is some overflow children */
|
||||
path_container_allocation.x = allocation->x;
|
||||
path_container_allocation.width = allocation->width;
|
||||
path_container_allocation.y = allocation->y;
|
||||
path_container_allocation.height = allocation->height;
|
||||
gtk_widget_size_allocate (priv->path_box, &path_container_allocation);
|
||||
gtk_widget_get_preferred_width (priv->overflow_button, &overflow_button_min_width, NULL);
|
||||
overflow_children = gtk_hiding_box_get_overflow_children (GTK_HIDING_BOX (priv->path_box));
|
||||
overflow = overflow_children != NULL;
|
||||
g_list_free (overflow_children);
|
||||
|
||||
direction = gtk_widget_get_direction (self);
|
||||
|
||||
path_container_allocation.x = allocation->x;
|
||||
path_container_allocation.width = allocation->width;
|
||||
if (overflow)
|
||||
{
|
||||
if (direction == GTK_TEXT_DIR_LTR)
|
||||
{
|
||||
path_container_allocation.x = allocation->x + overflow_button_min_width;
|
||||
path_container_allocation.width = allocation->width - overflow_button_min_width;
|
||||
|
||||
overflow_button_allocation.y = allocation->y;
|
||||
overflow_button_allocation.height = allocation->height;
|
||||
overflow_button_allocation.width = overflow_button_min_width;
|
||||
overflow_button_allocation.x = allocation->x;
|
||||
gtk_widget_set_child_visible (priv->overflow_button, TRUE);
|
||||
gtk_widget_size_allocate (priv->overflow_button, &overflow_button_allocation);
|
||||
}
|
||||
else
|
||||
{
|
||||
path_container_allocation.width = allocation->width - overflow_button_min_width;
|
||||
}
|
||||
}
|
||||
|
||||
path_container_allocation.y = allocation->y;
|
||||
path_container_allocation.height = allocation->height;
|
||||
gtk_widget_size_allocate (priv->path_box, &path_container_allocation);
|
||||
|
||||
if (overflow && direction == GTK_TEXT_DIR_RTL)
|
||||
{
|
||||
overflow_button_allocation.y = allocation->y;
|
||||
overflow_button_allocation.height = allocation->height;
|
||||
overflow_button_allocation.width = overflow_button_min_width;
|
||||
overflow_button_allocation.x = path_container_allocation.x +
|
||||
path_container_allocation.width;
|
||||
gtk_widget_set_child_visible (priv->overflow_button, TRUE);
|
||||
gtk_widget_size_allocate (priv->overflow_button, &overflow_button_allocation);
|
||||
}
|
||||
|
||||
_gtk_widget_set_simple_clip (self, NULL);
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
static void
|
||||
get_preferred_width (GtkWidget *self,
|
||||
gint *minimum_width,
|
||||
gint *natural_width)
|
||||
{
|
||||
GtkPathBarContainerPrivate *priv = gtk_path_bar_container_get_instance_private (GTK_PATH_BAR_CONTAINER (self));
|
||||
|
||||
gtk_widget_get_preferred_width (priv->path_box, minimum_width, natural_width);
|
||||
}
|
||||
|
||||
static void
|
||||
get_preferred_height (GtkWidget *self,
|
||||
gint *minimum_height,
|
||||
gint *natural_height)
|
||||
{
|
||||
GtkPathBarContainerPrivate *priv = gtk_path_bar_container_get_instance_private (GTK_PATH_BAR_CONTAINER (self));
|
||||
|
||||
gtk_widget_get_preferred_height (priv->path_box, minimum_height, natural_height);
|
||||
}
|
||||
|
||||
static void
|
||||
widget_destroy (GtkWidget *object)
|
||||
{
|
||||
GtkPathBarContainerPrivate *priv = gtk_path_bar_container_get_instance_private (GTK_PATH_BAR_CONTAINER (object));
|
||||
|
||||
if (priv->overflow_button && priv->path_box)
|
||||
{
|
||||
gtk_widget_unparent (priv->overflow_button);
|
||||
gtk_widget_unparent (priv->path_box);
|
||||
|
||||
priv->overflow_button = NULL;
|
||||
priv->path_box = NULL;
|
||||
}
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_path_bar_container_parent_class)->destroy (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_path_bar_container_class_init (GtkPathBarContainerClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
|
||||
|
||||
widget_class->get_request_mode = get_request_mode;
|
||||
widget_class->get_preferred_width = get_preferred_width;
|
||||
widget_class->get_preferred_height = get_preferred_height;
|
||||
widget_class->size_allocate = size_allocate;
|
||||
widget_class->destroy = widget_destroy;
|
||||
|
||||
// Neccesary to draw and realize children
|
||||
container_class->forall = container_forall;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_path_bar_container_init (GtkPathBarContainer *self)
|
||||
{
|
||||
GtkPathBarContainerPrivate *priv = gtk_path_bar_container_get_instance_private (self);
|
||||
|
||||
gtk_widget_set_has_window (GTK_WIDGET (self), FALSE);
|
||||
|
||||
priv->overflow_button = gtk_menu_button_new ();
|
||||
priv->path_box = gtk_hiding_box_new ();
|
||||
|
||||
gtk_widget_set_parent (priv->overflow_button, GTK_WIDGET (self));
|
||||
gtk_widget_set_parent (priv->path_box, GTK_WIDGET (self));
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_path_bar_container_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_PATH_BAR_CONTAINER, NULL);
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_path_bar_container_get_overflow_button (GtkPathBarContainer *self)
|
||||
{
|
||||
GtkPathBarContainerPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_PATH_BAR_CONTAINER (self), NULL);
|
||||
|
||||
priv = gtk_path_bar_container_get_instance_private (self);
|
||||
|
||||
return priv->overflow_button;
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
gtk_path_bar_container_get_path_box (GtkPathBarContainer *self)
|
||||
{
|
||||
GtkPathBarContainerPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_PATH_BAR_CONTAINER (self), NULL);
|
||||
|
||||
priv = gtk_path_bar_container_get_instance_private (self);
|
||||
|
||||
return priv->path_box;
|
||||
}
|
66
gtk/gtkpathbarcontainerprivate.h
Normal file
66
gtk/gtkpathbarcontainerprivate.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* gtkpathbarcontainerprivate.h
|
||||
*
|
||||
* Copyright (C) 2015 Red Hat
|
||||
*
|
||||
* 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 2 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/>.
|
||||
*
|
||||
* Authors: Carlos Soriano <csoriano@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_PATH_BAR_CONTAINER_PRIVATE_H__
|
||||
#define __GTK_PATH_BAR_CONTAINER_PRIVATE_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtkcontainer.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_PATH_BAR_CONTAINER (gtk_path_bar_container_get_type())
|
||||
#define GTK_PATH_BAR_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PATH_BAR_CONTAINER, GtkPathBarContainer))
|
||||
#define GTK_PATH_BAR_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PATH_BAR_CONTAINER, GtkPathBarContainerClass))
|
||||
#define GTK_IS_PATH_BAR_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PATH_BAR_CONTAINER))
|
||||
#define GTK_IS_PATH_BAR_CONTAINER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PATH_BAR_CONTAINER)
|
||||
#define GTK_PATH_BAR_CONTAINER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PATH_BAR_CONTAINER, GtkPathBarContainerClass))
|
||||
|
||||
typedef struct _GtkPathBarContainer GtkPathBarContainer;
|
||||
typedef struct _GtkPathBarContainerClass GtkPathBarContainerClass;
|
||||
typedef struct _GtkPathBarContainerPrivate GtkPathBarContainerPrivate;
|
||||
|
||||
struct _GtkPathBarContainerClass
|
||||
{
|
||||
GtkContainerClass parent;
|
||||
|
||||
/* Padding for future expansion */
|
||||
gpointer reserved[10];
|
||||
};
|
||||
|
||||
struct _GtkPathBarContainer
|
||||
{
|
||||
GtkContainer parent_instance;
|
||||
};
|
||||
|
||||
GType gtk_path_bar_container_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GtkWidget *gtk_path_bar_container_new (void);
|
||||
|
||||
GtkWidget *gtk_path_bar_container_get_path_box (GtkPathBarContainer *path_bar_container);
|
||||
|
||||
GtkWidget *gtk_path_bar_container_get_overflow_button (GtkPathBarContainer *path_bar_container);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* GTK_PATH_BAR_CONTAINER_PRIVATE_H_ */
|
@@ -446,6 +446,7 @@ gtk_public_h_sources = \
|
||||
gtkpagesetup.h \
|
||||
gtkpaned.h \
|
||||
gtkpapersize.h \
|
||||
gtkpathbar.h \
|
||||
gtkplug.h \
|
||||
gtkprintcontext.h \
|
||||
gtkprintoperation.h \
|
||||
|
@@ -1570,31 +1570,55 @@ headerbar {
|
||||
/************
|
||||
* Pathbars *
|
||||
************/
|
||||
.path-bar button {
|
||||
&.text-button, &.image-button, & {
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
&.text-button.image-button label {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
path-bar button.flat, .path-bar-overflow-popover button.flat {
|
||||
background-image: none;
|
||||
border-radius: 0px;
|
||||
border-color: transparent;
|
||||
border-width: 2px 0px 2px 0px;
|
||||
box-shadow: 0px 0px 0px;
|
||||
margin: 0px;
|
||||
opacity: 0.55;
|
||||
padding: 3px 8px 4px;
|
||||
background-color: transparent;
|
||||
|
||||
&.text-button.image-button, & {
|
||||
label:last-child { padding-right: 8px; }
|
||||
label:first-child { padding-left: 8px; }
|
||||
}
|
||||
&:checked {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
image {
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
&:hover {
|
||||
border-bottom-color: mix($selected_bg_color, $selected_fg_color, 75%);
|
||||
}
|
||||
|
||||
&.slider-button {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
&:backdrop, &:backdrop:checked {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
background-image: none;
|
||||
}
|
||||
}
|
||||
|
||||
.pathbar-initial-opacity {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.pathbar-opacity-on {
|
||||
opacity: 1;
|
||||
transition-duration: 250ms;
|
||||
}
|
||||
|
||||
.pathbar-opacity-off {
|
||||
opacity: 0;
|
||||
transition-duration: 250ms;
|
||||
}
|
||||
|
||||
.pathbar-invert-animation-opacity-on {
|
||||
opacity: 1;
|
||||
transition-duration: 60ms;
|
||||
}
|
||||
|
||||
.pathbar-invert-animation-opacity-off {
|
||||
opacity: 0;
|
||||
transition-duration: 60ms;
|
||||
}
|
||||
|
||||
/**************
|
||||
|
@@ -2083,22 +2083,35 @@ window.csd > .titlebar:not(headerbar) {
|
||||
/************
|
||||
* Pathbars *
|
||||
************/
|
||||
.path-bar button.text-button, .path-bar button.image-button, .path-bar button {
|
||||
padding-left: 4px;
|
||||
padding-right: 4px; }
|
||||
.path-bar button.text-button.image-button label {
|
||||
padding-left: 0;
|
||||
padding-right: 0; }
|
||||
.path-bar button.text-button.image-button label:last-child, .path-bar button label:last-child {
|
||||
padding-right: 8px; }
|
||||
.path-bar button.text-button.image-button label:first-child, .path-bar button label:first-child {
|
||||
padding-left: 8px; }
|
||||
.path-bar button image {
|
||||
padding-left: 4px;
|
||||
padding-right: 4px; }
|
||||
.path-bar button.slider-button {
|
||||
padding-left: 0;
|
||||
padding-right: 0; }
|
||||
path-bar button.flat, .path-bar-overflow-popover button.flat {
|
||||
background-image: none;
|
||||
border-radius: 0px;
|
||||
border-color: transparent;
|
||||
border-width: 2px 0px 2px 0px;
|
||||
box-shadow: 0px 0px 0px;
|
||||
margin: 0px;
|
||||
opacity: 0.55;
|
||||
padding: 3px 8px 4px;
|
||||
background-color: transparent; }
|
||||
path-bar button.flat:checked, .path-bar-overflow-popover button.flat:checked {
|
||||
opacity: 1; }
|
||||
path-bar button.flat:hover, .path-bar-overflow-popover button.flat:hover {
|
||||
border-bottom-color: #5986b5; }
|
||||
path-bar button.flat:backdrop, path-bar button.flat:backdrop:checked, .path-bar-overflow-popover button.flat:backdrop, .path-bar-overflow-popover button.flat:backdrop:checked {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
background-image: none; }
|
||||
|
||||
.pathbar-initial-opacity {
|
||||
opacity: 0; }
|
||||
|
||||
.pathbar-opacity-on {
|
||||
opacity: 1;
|
||||
transition-duration: 250ms; }
|
||||
|
||||
.pathbar-opacity-off {
|
||||
opacity: 0;
|
||||
transition-duration: 250ms; }
|
||||
|
||||
/**************
|
||||
* Tree Views *
|
||||
|
@@ -2090,22 +2090,35 @@ window.csd > .titlebar:not(headerbar) {
|
||||
/************
|
||||
* Pathbars *
|
||||
************/
|
||||
.path-bar button.text-button, .path-bar button.image-button, .path-bar button {
|
||||
padding-left: 4px;
|
||||
padding-right: 4px; }
|
||||
.path-bar button.text-button.image-button label {
|
||||
padding-left: 0;
|
||||
padding-right: 0; }
|
||||
.path-bar button.text-button.image-button label:last-child, .path-bar button label:last-child {
|
||||
padding-right: 8px; }
|
||||
.path-bar button.text-button.image-button label:first-child, .path-bar button label:first-child {
|
||||
padding-left: 8px; }
|
||||
.path-bar button image {
|
||||
padding-left: 4px;
|
||||
padding-right: 4px; }
|
||||
.path-bar button.slider-button {
|
||||
padding-left: 0;
|
||||
padding-right: 0; }
|
||||
path-bar button.flat, .path-bar-overflow-popover button.flat {
|
||||
background-image: none;
|
||||
border-radius: 0px;
|
||||
border-color: transparent;
|
||||
border-width: 2px 0px 2px 0px;
|
||||
box-shadow: 0px 0px 0px;
|
||||
margin: 0px;
|
||||
opacity: 0.55;
|
||||
padding: 3px 8px 4px;
|
||||
background-color: transparent; }
|
||||
path-bar button.flat:checked, .path-bar-overflow-popover button.flat:checked {
|
||||
opacity: 1; }
|
||||
path-bar button.flat:hover, .path-bar-overflow-popover button.flat:hover {
|
||||
border-bottom-color: #77ace3; }
|
||||
path-bar button.flat:backdrop, path-bar button.flat:backdrop:checked, .path-bar-overflow-popover button.flat:backdrop, .path-bar-overflow-popover button.flat:backdrop:checked {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
background-image: none; }
|
||||
|
||||
.pathbar-initial-opacity {
|
||||
opacity: 0; }
|
||||
|
||||
.pathbar-opacity-on {
|
||||
opacity: 1;
|
||||
transition-duration: 250ms; }
|
||||
|
||||
.pathbar-opacity-off {
|
||||
opacity: 0;
|
||||
transition-duration: 250ms; }
|
||||
|
||||
/**************
|
||||
* Tree Views *
|
||||
|
@@ -56,9 +56,9 @@
|
||||
<property name="spacing">6</property>
|
||||
<property name="border-width">6</property>
|
||||
<child>
|
||||
<object class="GtkPathBar" id="browse_path_bar">
|
||||
<object class="GtkFilesPathBar" id="browse_path_bar">
|
||||
<property name="visible">True</property>
|
||||
<signal name="path-clicked" handler="path_bar_clicked" after="yes" swapped="no"/>
|
||||
<signal name="notify::file" handler="on_path_bar_file"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">1</property>
|
||||
|
@@ -86,6 +86,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
|
||||
testgtk \
|
||||
testheaderbar \
|
||||
testheightforwidth \
|
||||
testhidingbox \
|
||||
testiconview \
|
||||
testiconview-keynav \
|
||||
testicontheme \
|
||||
@@ -108,6 +109,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
|
||||
testorientable \
|
||||
testoverlay \
|
||||
testoverlaystyleclass \
|
||||
testpathbar \
|
||||
testprint \
|
||||
testrecentchooser \
|
||||
testrecentchoosermenu \
|
||||
@@ -291,6 +293,8 @@ testanimation_DEPENDENCIES = $(TEST_DEPS)
|
||||
testpixbuf_save_DEPENDENCIES = $(TEST_DEPS)
|
||||
testpixbuf_color_DEPENDENCIES = $(TEST_DEPS)
|
||||
testpixbuf_scale_DEPENDENCIES = $(TEST_DEPS)
|
||||
testpathbar_DEPENDENCIES = $(TEST_DEPS)
|
||||
testhidingbox_DEPENDENCIES = $(TEST_DEPS)
|
||||
testgmenu_DEPENDENCIES = $(TEST_DEPS)
|
||||
testlogout_DEPENDENCIES = $(TEST_DEPS)
|
||||
teststack_DEPENDENCIES = $(TEST_DEPS)
|
||||
@@ -391,6 +395,12 @@ testtoolbar_SOURCES = \
|
||||
testmenubutton_SOURCES = \
|
||||
testmenubutton.c
|
||||
|
||||
testpathbar_SOURCES = \
|
||||
testpathbar.c
|
||||
|
||||
testhidingbox_SOURCES = \
|
||||
testhidingbox.c
|
||||
|
||||
testprint_SOURCES = \
|
||||
testprint.c \
|
||||
testprintfileoperation.h \
|
||||
|
152
tests/testhidingbox.c
Normal file
152
tests/testhidingbox.c
Normal file
@@ -0,0 +1,152 @@
|
||||
#include "config.h"
|
||||
#include "glib.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define N_BUTTONS 10
|
||||
|
||||
static GtkWidget *hiding_box;
|
||||
static char *lorem_ipsum = "Loremipsumdolorsitamet, consecteturadipisicingelit,";
|
||||
|
||||
static char*
|
||||
get_lorem_ipsum ()
|
||||
{
|
||||
static char **lorem_ipsum_split;
|
||||
static int n_lorem_ipsum_words;
|
||||
|
||||
if (!lorem_ipsum_split)
|
||||
{
|
||||
lorem_ipsum_split = g_strsplit (lorem_ipsum, " ", -1);
|
||||
n_lorem_ipsum_words = g_strv_length (lorem_ipsum_split);
|
||||
}
|
||||
|
||||
return lorem_ipsum_split [g_random_int_range (0, n_lorem_ipsum_words)];
|
||||
}
|
||||
|
||||
static void
|
||||
on_path_selected (GtkPathBar *path_bar,
|
||||
GParamSpec *pspec,
|
||||
gpointer *user_data)
|
||||
{
|
||||
g_print ("Path selected: %s\n", gtk_path_bar_get_selected_path (path_bar));
|
||||
}
|
||||
|
||||
static void
|
||||
on_button_clicked (GtkWidget *button,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("button clicked\n");
|
||||
gtk_container_remove (GTK_CONTAINER (user_data), button);
|
||||
}
|
||||
|
||||
static void
|
||||
on_reset_button_clicked (GtkButton *reset_button)
|
||||
{
|
||||
GtkWidget *button;
|
||||
|
||||
gtk_container_foreach (GTK_CONTAINER (hiding_box), (GtkCallback) gtk_widget_destroy, NULL);
|
||||
|
||||
for (int i = 0; i < N_BUTTONS; i++)
|
||||
{
|
||||
button = gtk_button_new_with_label (get_lorem_ipsum ());
|
||||
g_signal_connect (button, "clicked", (GCallback) on_button_clicked, hiding_box);
|
||||
gtk_container_add (GTK_CONTAINER (hiding_box), button);
|
||||
}
|
||||
|
||||
gtk_widget_show_all (hiding_box);
|
||||
}
|
||||
|
||||
static void
|
||||
on_add_button (gint line)
|
||||
{
|
||||
GtkWidget *button;
|
||||
|
||||
button = gtk_button_new_with_label (get_lorem_ipsum ());
|
||||
gtk_widget_show (button);
|
||||
g_signal_connect (button, "clicked", (GCallback) on_button_clicked, hiding_box);
|
||||
gtk_container_add (GTK_CONTAINER (hiding_box), button);
|
||||
}
|
||||
|
||||
static void
|
||||
on_remove_button (gint line)
|
||||
{
|
||||
GList *children;
|
||||
GList *last;
|
||||
|
||||
children = gtk_container_get_children (hiding_box);
|
||||
last = g_list_last (children);
|
||||
if (last)
|
||||
gtk_container_remove (hiding_box, GTK_WIDGET (last->data));
|
||||
}
|
||||
|
||||
static void
|
||||
on_invert_button (gint line)
|
||||
{
|
||||
gtk_hiding_box_set_inverted (GTK_HIDING_BOX (hiding_box),
|
||||
!gtk_hiding_box_get_inverted (GTK_HIDING_BOX (hiding_box)));
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *grid;
|
||||
GtkWidget *reset_button;
|
||||
GtkWidget *add_button;
|
||||
GtkWidget *remove_button;
|
||||
GtkWidget *invert_button;
|
||||
GtkWidget *label;
|
||||
GFile *file = NULL;
|
||||
GIcon *icon;
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
window = g_object_connect (g_object_new (gtk_window_get_type (),
|
||||
"type", GTK_WINDOW_TOPLEVEL,
|
||||
"title", "Test path bar",
|
||||
"resizable", TRUE,
|
||||
"default-height", 200,
|
||||
NULL),
|
||||
"signal::destroy", gtk_main_quit, NULL,
|
||||
NULL);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
g_type_ensure (GTK_TYPE_HIDING_BOX);
|
||||
|
||||
label = gtk_label_new ("Generic GtkPathBar tests");
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 2, 1);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
hiding_box = gtk_hiding_box_new ();
|
||||
gtk_grid_attach (GTK_GRID (grid), hiding_box, 0, 1, 1, 1);
|
||||
gtk_widget_show_all (hiding_box);
|
||||
/* Add/Remove buttons */
|
||||
add_button = gtk_button_new_with_label ("Add");
|
||||
gtk_widget_set_halign (add_button, GTK_ALIGN_END);
|
||||
remove_button = gtk_button_new_with_label ("Remove");
|
||||
gtk_widget_set_halign (remove_button, GTK_ALIGN_END);
|
||||
gtk_grid_attach_next_to (GTK_GRID (grid), add_button, hiding_box, GTK_POS_RIGHT, 1, 1);
|
||||
g_signal_connect_swapped (add_button, "clicked", (GCallback) on_add_button, GINT_TO_POINTER (0));
|
||||
gtk_grid_attach_next_to (GTK_GRID (grid), remove_button, add_button, GTK_POS_RIGHT, 1, 1);
|
||||
g_signal_connect_swapped (remove_button, "clicked", (GCallback) on_remove_button, GINT_TO_POINTER (0));
|
||||
gtk_widget_show (add_button);
|
||||
gtk_widget_show (remove_button);
|
||||
/* Inverted button */
|
||||
invert_button = gtk_button_new_with_label ("Invert");
|
||||
gtk_widget_set_halign (invert_button, GTK_ALIGN_END);
|
||||
gtk_grid_attach_next_to (GTK_GRID (grid), invert_button, remove_button, GTK_POS_RIGHT, 1, 1);
|
||||
g_signal_connect_swapped (invert_button, "clicked", (GCallback) on_invert_button, GINT_TO_POINTER (0));
|
||||
|
||||
/* Reset button */
|
||||
reset_button = gtk_button_new_with_label ("Reset State");
|
||||
gtk_widget_set_hexpand (reset_button, TRUE);
|
||||
g_signal_connect (GTK_BUTTON (reset_button), "clicked",
|
||||
G_CALLBACK (on_reset_button_clicked), window);
|
||||
gtk_grid_attach (GTK_GRID (grid), reset_button, 0, 11, 2, 1);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (window), grid);
|
||||
gtk_widget_show_all (window);
|
||||
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
}
|
330
tests/testpathbar.c
Normal file
330
tests/testpathbar.c
Normal file
@@ -0,0 +1,330 @@
|
||||
#include "config.h"
|
||||
#include "glib.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static GActionGroup *action_group;
|
||||
static GtkWidget *path_bar;
|
||||
static GtkWidget *path_bar_inverted;
|
||||
static GtkWidget *path_bar_slash;
|
||||
static GtkWidget *path_bar_custom_root_label;
|
||||
static GtkWidget *path_bar_custom_root_icon;
|
||||
static GtkWidget *files_path_bar_random;
|
||||
static GtkWidget *files_path_bar_recent;
|
||||
static const gchar* REAL_LOCATION_RANDOM = "file:///boot/efi/EFI/BOOT";
|
||||
static const gchar* REAL_LOCATION_RECENT = "recent:///";
|
||||
static const gchar* ORIGINAL_PATH = "/test/test 2/test 3/asda lkasdl/pppppppppppppppp/ alskd";
|
||||
static const gchar* ROOT_PATH = "/test/test 2/test 3";
|
||||
static const gchar* DISPLAY_PATH = "/test/test 2/This Is A Root/asda lkasdl/pppppppppppppppp/ alskd";
|
||||
|
||||
static void
|
||||
action_menu_1 (GSimpleAction *action,
|
||||
GVariant *variant,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("Menu 1 action\n");
|
||||
}
|
||||
|
||||
static void
|
||||
action_menu_2 (GSimpleAction *action,
|
||||
GVariant *variant,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("Menu 2 action\n");
|
||||
}
|
||||
|
||||
static void
|
||||
action_special (GSimpleAction *action,
|
||||
GVariant *variant,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("Special action\n");
|
||||
}
|
||||
|
||||
const GActionEntry entries[] = {
|
||||
{ "menu_1", action_menu_1 },
|
||||
{ "menu_2", action_menu_2 },
|
||||
{ "special", action_special },
|
||||
};
|
||||
|
||||
static void
|
||||
on_populate_popup (GtkPathBar *path_bar,
|
||||
GtkWidget *container,
|
||||
const gchar *selected_path)
|
||||
{
|
||||
GtkWidget *menu_item;
|
||||
|
||||
menu_item = gtk_model_button_new ();
|
||||
gtk_actionable_set_action_name (GTK_ACTIONABLE (menu_item),
|
||||
"action_group.menu_1");
|
||||
g_object_set (menu_item, "text", "Menu 1", NULL);
|
||||
gtk_container_add (GTK_CONTAINER (container), menu_item);
|
||||
|
||||
menu_item = gtk_model_button_new ();
|
||||
gtk_actionable_set_action_name (GTK_ACTIONABLE (menu_item),
|
||||
"action_group.menu_2");
|
||||
g_object_set (menu_item, "text", "Menu 2", NULL);
|
||||
gtk_container_add (GTK_CONTAINER (container), menu_item);
|
||||
|
||||
if (g_strcmp0 (selected_path, "/test/test 2/test 3") == 0)
|
||||
{
|
||||
menu_item = gtk_model_button_new ();
|
||||
gtk_actionable_set_action_name (GTK_ACTIONABLE (menu_item),
|
||||
"action_group.special");
|
||||
g_object_set (menu_item, "text", "Special", NULL);
|
||||
gtk_container_add (GTK_CONTAINER (container), menu_item);
|
||||
}
|
||||
|
||||
gtk_widget_show_all (container);
|
||||
|
||||
g_print ("Populate popup\n");
|
||||
}
|
||||
|
||||
static void
|
||||
on_path_selected (GtkPathBar *path_bar,
|
||||
GParamSpec *pspec,
|
||||
gpointer *user_data)
|
||||
{
|
||||
g_print ("Path selected: %s\n", gtk_path_bar_get_selected_path (path_bar));
|
||||
}
|
||||
|
||||
static gchar*
|
||||
get_display_path_from_selected (const gchar *selected_path)
|
||||
{
|
||||
gchar **splitted_path;
|
||||
gchar **display_splitted_path;
|
||||
gint i;
|
||||
GString *display_path;
|
||||
gchar *display_path_gchar;
|
||||
|
||||
splitted_path = g_strsplit (selected_path, "/", -1);
|
||||
display_splitted_path = g_strsplit (DISPLAY_PATH, "/", -1);
|
||||
display_path = g_string_new ("");
|
||||
/* Skip the first empty split part */
|
||||
for (i = 1; i < g_strv_length (splitted_path); i++)
|
||||
{
|
||||
g_string_append (display_path, "/");
|
||||
g_string_append (display_path, display_splitted_path[i]);
|
||||
}
|
||||
|
||||
display_path_gchar = display_path->str;
|
||||
|
||||
g_string_free (display_path, FALSE);
|
||||
g_strfreev (splitted_path);
|
||||
g_strfreev (display_splitted_path);
|
||||
|
||||
return display_path_gchar;
|
||||
}
|
||||
|
||||
static void
|
||||
on_path_selected_set_path (GtkPathBar *path_bar,
|
||||
GParamSpec *pspec,
|
||||
gpointer *user_data)
|
||||
{
|
||||
gchar *selected_path;
|
||||
gchar *new_display_path;
|
||||
|
||||
selected_path = g_strdup (gtk_path_bar_get_selected_path (path_bar));
|
||||
new_display_path = get_display_path_from_selected (selected_path);
|
||||
g_print ("Path selected: %s, setting path to GtkPathBar and new display path %s\n", selected_path, new_display_path);
|
||||
if (path_bar == GTK_PATH_BAR (path_bar_custom_root_label))
|
||||
{
|
||||
gtk_path_bar_set_path_extended (GTK_PATH_BAR (path_bar_custom_root_label),
|
||||
selected_path, ROOT_PATH, "This Is A Root", NULL);
|
||||
}
|
||||
else if (path_bar == GTK_PATH_BAR (path_bar_custom_root_icon))
|
||||
{
|
||||
GIcon *icon;
|
||||
|
||||
icon = g_themed_icon_new ("drive-harddisk");
|
||||
gtk_path_bar_set_path_extended (GTK_PATH_BAR (path_bar_custom_root_icon),
|
||||
selected_path, "/", NULL, icon);
|
||||
g_object_unref (icon);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_path_bar_set_path (path_bar, selected_path);
|
||||
}
|
||||
|
||||
g_free (selected_path);
|
||||
g_free (new_display_path);
|
||||
}
|
||||
|
||||
static void
|
||||
on_file_changed (GtkFilesPathBar *path_bar,
|
||||
GParamSpec *pspec,
|
||||
gpointer *user_data)
|
||||
{
|
||||
GFile *file;
|
||||
gchar *uri;
|
||||
|
||||
file = gtk_files_path_bar_get_file (path_bar);
|
||||
uri = g_file_get_uri (file);
|
||||
g_print ("File selected: %s in GtkFilesPathBar\n", uri);
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
connect_path_bar (GtkPathBar *path_bar)
|
||||
{
|
||||
g_signal_connect (GTK_PATH_BAR (path_bar), "populate-popup",
|
||||
G_CALLBACK (on_populate_popup), NULL);
|
||||
g_signal_connect (GTK_PATH_BAR (path_bar), "notify::selected-path",
|
||||
G_CALLBACK (on_path_selected), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
connect_path_bar_set_path (GtkPathBar *path_bar)
|
||||
{
|
||||
g_signal_connect (GTK_PATH_BAR (path_bar), "populate-popup",
|
||||
G_CALLBACK (on_populate_popup), NULL);
|
||||
g_signal_connect (GTK_PATH_BAR (path_bar), "notify::selected-path",
|
||||
G_CALLBACK (on_path_selected_set_path), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
connect_files_path_bar (GtkFilesPathBar *files_path_bar)
|
||||
{
|
||||
g_signal_connect (GTK_FILES_PATH_BAR (files_path_bar), "populate-popup",
|
||||
G_CALLBACK (on_populate_popup), NULL);
|
||||
g_signal_connect (GTK_FILES_PATH_BAR (files_path_bar), "notify::file",
|
||||
G_CALLBACK (on_file_changed), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
on_reset_button_clicked (GtkButton *reset_button)
|
||||
{
|
||||
GFile *file;
|
||||
GIcon *icon;
|
||||
|
||||
gtk_path_bar_set_path (GTK_PATH_BAR (path_bar), ORIGINAL_PATH);
|
||||
gtk_path_bar_set_path (GTK_PATH_BAR (path_bar_inverted), ORIGINAL_PATH);
|
||||
gtk_path_bar_set_path (GTK_PATH_BAR (path_bar_slash), "/");
|
||||
gtk_path_bar_set_path_extended (GTK_PATH_BAR (path_bar_custom_root_label),
|
||||
ORIGINAL_PATH, ROOT_PATH, "This Is A Root", NULL);
|
||||
icon = g_themed_icon_new ("drive-harddisk");
|
||||
gtk_path_bar_set_path_extended (GTK_PATH_BAR (path_bar_custom_root_icon),
|
||||
ORIGINAL_PATH, "/", NULL, icon);
|
||||
g_object_unref (icon);
|
||||
|
||||
file = g_file_new_for_uri (REAL_LOCATION_RANDOM);
|
||||
gtk_files_path_bar_set_file (GTK_FILES_PATH_BAR (files_path_bar_random), file);
|
||||
g_object_unref (file);
|
||||
file = g_file_new_for_uri (REAL_LOCATION_RECENT);
|
||||
gtk_files_path_bar_set_file (GTK_FILES_PATH_BAR (files_path_bar_recent), file);
|
||||
g_object_unref (file);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *grid;
|
||||
GtkWidget *reset_button;
|
||||
GtkWidget *label;
|
||||
GFile *file = NULL;
|
||||
GIcon *icon;
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
window = g_object_connect (g_object_new (gtk_window_get_type (),
|
||||
"type", GTK_WINDOW_TOPLEVEL,
|
||||
"title", "Test path bar",
|
||||
"resizable", TRUE,
|
||||
"default-height", 200,
|
||||
NULL),
|
||||
"signal::destroy", gtk_main_quit, NULL,
|
||||
NULL);
|
||||
|
||||
action_group = G_ACTION_GROUP (g_simple_action_group_new ());
|
||||
g_action_map_add_action_entries (G_ACTION_MAP (action_group), entries,
|
||||
G_N_ELEMENTS (entries), window);
|
||||
|
||||
gtk_widget_insert_action_group (window, "action_group", action_group);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
g_type_ensure (GTK_TYPE_PATH_BAR);
|
||||
|
||||
label = gtk_label_new ("Generic GtkPathBar tests");
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 2, 1);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
path_bar = gtk_path_bar_new ();
|
||||
gtk_grid_attach (GTK_GRID (grid), path_bar, 0, 1, 1, 1);
|
||||
gtk_path_bar_set_path (GTK_PATH_BAR (path_bar), ORIGINAL_PATH);
|
||||
connect_path_bar (GTK_PATH_BAR (path_bar));
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
path_bar_inverted = gtk_path_bar_new ();
|
||||
gtk_path_bar_set_inverted (GTK_PATH_BAR (path_bar_inverted), TRUE);
|
||||
gtk_path_bar_set_path (GTK_PATH_BAR (path_bar_inverted), ORIGINAL_PATH);
|
||||
connect_path_bar (GTK_PATH_BAR (path_bar_inverted));
|
||||
gtk_grid_attach (GTK_GRID (grid), path_bar_inverted, 0, 2, 1, 1);
|
||||
|
||||
label = gtk_label_new ("“/” a.k.a root, special case");
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 3, 2, 1);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
path_bar_slash = gtk_path_bar_new ();
|
||||
gtk_path_bar_set_inverted (GTK_PATH_BAR (path_bar_slash), TRUE);
|
||||
gtk_path_bar_set_path (GTK_PATH_BAR (path_bar_slash), "/");
|
||||
connect_path_bar_set_path (GTK_PATH_BAR (path_bar_slash));
|
||||
gtk_grid_attach (GTK_GRID (grid), path_bar_slash, 0, 4, 1, 1);
|
||||
|
||||
label = gtk_label_new ("GtkPathBar with special roots");
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 5, 2, 1);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
path_bar_custom_root_label = gtk_path_bar_new ();
|
||||
gtk_path_bar_set_inverted (GTK_PATH_BAR (path_bar_custom_root_label), TRUE);
|
||||
gtk_path_bar_set_path_extended (GTK_PATH_BAR (path_bar_custom_root_label),
|
||||
ORIGINAL_PATH, ROOT_PATH, "This Is A Root", NULL);
|
||||
connect_path_bar_set_path (GTK_PATH_BAR (path_bar_custom_root_label));
|
||||
gtk_grid_attach (GTK_GRID (grid), path_bar_custom_root_label, 0, 6, 1, 1);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
path_bar_custom_root_icon = gtk_path_bar_new ();
|
||||
gtk_path_bar_set_inverted (GTK_PATH_BAR (path_bar_custom_root_icon), TRUE);
|
||||
icon = g_themed_icon_new ("drive-harddisk");
|
||||
gtk_path_bar_set_path_extended (GTK_PATH_BAR (path_bar_custom_root_icon),
|
||||
ORIGINAL_PATH, "/", NULL, icon);
|
||||
g_object_unref (icon);
|
||||
connect_path_bar_set_path (GTK_PATH_BAR (path_bar_custom_root_icon));
|
||||
gtk_grid_attach (GTK_GRID (grid), path_bar_custom_root_icon, 0, 7, 1, 1);
|
||||
|
||||
/* GtkFilesPathBar tests */
|
||||
label = gtk_label_new ("GtkFilesPathBar tests");
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 8, 2, 1);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
files_path_bar_random = gtk_files_path_bar_new ();
|
||||
file = g_file_new_for_uri (REAL_LOCATION_RANDOM);
|
||||
gtk_files_path_bar_set_file (GTK_FILES_PATH_BAR (files_path_bar_random), file);
|
||||
connect_files_path_bar (GTK_FILES_PATH_BAR (files_path_bar_random));
|
||||
gtk_grid_attach (GTK_GRID (grid), files_path_bar_random, 0, 9, 1, 1);
|
||||
|
||||
g_clear_object (&file);
|
||||
|
||||
files_path_bar_recent = gtk_files_path_bar_new ();
|
||||
file = g_file_new_for_uri (REAL_LOCATION_RECENT);
|
||||
gtk_files_path_bar_set_file (GTK_FILES_PATH_BAR (files_path_bar_recent), file);
|
||||
connect_files_path_bar (GTK_FILES_PATH_BAR (files_path_bar_recent));
|
||||
gtk_grid_attach (GTK_GRID (grid), files_path_bar_recent, 0, 10, 1, 1);
|
||||
|
||||
g_clear_object (&file);
|
||||
|
||||
/* Reset button */
|
||||
reset_button = gtk_button_new_with_label ("Reset State");
|
||||
gtk_widget_set_hexpand (reset_button, TRUE);
|
||||
g_signal_connect (GTK_BUTTON (reset_button), "clicked",
|
||||
G_CALLBACK (on_reset_button_clicked), window);
|
||||
gtk_grid_attach (GTK_GRID (grid), reset_button, 0, 11, 2, 1);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (window), grid);
|
||||
gtk_widget_show_all (window);
|
||||
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user