Compare commits
28 Commits
linear-com
...
wip/csoria
Author | SHA1 | Date | |
---|---|---|---|
|
852c89aa5e | ||
|
acf2652f88 | ||
|
36cf8ad173 | ||
|
82c8d2c4b6 | ||
|
973927c2f6 | ||
|
c90bc86dbb | ||
|
f9731434f9 | ||
|
48e971f72e | ||
|
c68cea3292 | ||
|
21f0fddfc9 | ||
|
212a95cafb | ||
|
be7a7577b9 | ||
|
c4980370dc | ||
|
facee991ee | ||
|
0fa8ff0221 | ||
|
871cdf27ec | ||
|
04f1171577 | ||
|
0b044ea55a | ||
|
84844d1c42 | ||
|
f66ab18126 | ||
|
a831aeca08 | ||
|
3ea9ddac3a | ||
|
b8dfa1d749 | ||
|
a1ba8ac410 | ||
|
559ce33238 | ||
|
9a0ac6c47d | ||
|
947bf993de | ||
|
c9903e0d3b |
@@ -2628,7 +2628,7 @@ gdk_display_get_monitor_at_point (GdkDisplay *display,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
GdkMonitor *nearest;
|
||||
GdkMonitor *nearest = NULL;
|
||||
int nearest_dist = G_MAXINT;
|
||||
int n_monitors, i;
|
||||
|
||||
|
@@ -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)
|
||||
{
|
||||
@@ -7842,24 +7840,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
|
||||
@@ -7957,7 +7946,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 */
|
||||
@@ -7966,7 +7955,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 */
|
||||
@@ -8495,7 +8484,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);
|
||||
@@ -8561,10 +8550,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
|
||||
@@ -8631,7 +8618,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)
|
||||
|
920
gtk/gtkhidingbox.c
Normal file
920
gtk/gtkhidingbox.c
Normal file
@@ -0,0 +1,920 @@
|
||||
/*
|
||||
* 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 INVERT_ANIMATION_TIME 500 //ms
|
||||
|
||||
typedef enum {
|
||||
ANIMATION_PHASE_NONE,
|
||||
ANIMATION_PHASE_OUT,
|
||||
ANIMATION_PHASE_MOVE,
|
||||
ANIMATION_PHASE_IN
|
||||
} HidingBoxAnimationPhase;
|
||||
|
||||
struct _GtkHidingBoxPrivate
|
||||
{
|
||||
GList *children;
|
||||
gint16 spacing;
|
||||
gint inverted :1;
|
||||
GList *widgets_to_hide;
|
||||
GList *widgets_to_show;
|
||||
GList *widgets_to_remove;
|
||||
GList *widgets_shown;
|
||||
HidingBoxAnimationPhase animation_phase;
|
||||
gint current_width;
|
||||
gint current_height;
|
||||
guint needs_update :1;
|
||||
|
||||
gboolean invert_animation;
|
||||
|
||||
GtkWidget *scrolled_window;
|
||||
GtkWidget *box;
|
||||
GtkAdjustment *hadjustment;
|
||||
|
||||
guint tick_id;
|
||||
guint64 initial_time;
|
||||
};
|
||||
|
||||
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 (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)
|
||||
{
|
||||
GList *child;
|
||||
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 (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
|
||||
clear_animation_state (GtkHidingBox *self)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (self);
|
||||
|
||||
priv->animation_phase = ANIMATION_PHASE_NONE;
|
||||
g_list_free (priv->widgets_to_show);
|
||||
priv->widgets_to_show = NULL;
|
||||
g_list_free (priv->widgets_to_hide);
|
||||
priv->widgets_to_hide = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_children_visibility (GtkHidingBox *box,
|
||||
GtkAllocation *allocation,
|
||||
GtkRequestedSize *sizes,
|
||||
gboolean update,
|
||||
gint *children_size,
|
||||
gint *n_visible_children_expanding)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
|
||||
GtkWidget *child_widget;
|
||||
GList *child;
|
||||
GtkRequestedSize *sizes_temp;
|
||||
gint i;
|
||||
GList *children;
|
||||
GList *temp_widgets_to_show = NULL;
|
||||
gboolean allocate_more_children = TRUE;
|
||||
gint n_visible_children = 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;
|
||||
|
||||
*n_visible_children_expanding = 0;
|
||||
*children_size = -priv->spacing;
|
||||
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);
|
||||
/* Assert the api is working properly */
|
||||
if (sizes_temp[i].minimum_size < 0)
|
||||
g_error ("GtkHidingBox child %s minimum width: %d < 0 for height %d",
|
||||
gtk_widget_get_name (child_widget),
|
||||
sizes_temp[i].minimum_size, allocation->height);
|
||||
|
||||
if (sizes_temp[i].natural_size < sizes_temp[i].minimum_size)
|
||||
g_error ("GtkHidingBox child %s natural width: %d < minimum %d for height %d",
|
||||
gtk_widget_get_name (child_widget),
|
||||
sizes_temp[i].natural_size, sizes_temp[i].minimum_size,
|
||||
allocation->height);
|
||||
|
||||
*children_size += sizes_temp[i].minimum_size + priv->spacing;
|
||||
sizes_temp[i].data = child_widget;
|
||||
|
||||
if (!allocate_more_children || *children_size > allocation->width)
|
||||
{
|
||||
allocate_more_children = FALSE;
|
||||
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 (gtk_widget_get_hexpand (child_widget))
|
||||
(n_visible_children_expanding)++;
|
||||
(n_visible_children)++;
|
||||
|
||||
if (!g_list_find (priv->widgets_to_remove, child_widget))
|
||||
priv->widgets_to_show = g_list_append (priv->widgets_to_show, child_widget);
|
||||
}
|
||||
|
||||
for (i = 0; i < n_visible_children; i++)
|
||||
{
|
||||
if (priv->inverted)
|
||||
{
|
||||
sizes[n_visible_children - i - 1].minimum_size = sizes_temp[i].minimum_size;
|
||||
sizes[n_visible_children - i - 1].natural_size = sizes_temp[i].natural_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
sizes[i].minimum_size = sizes_temp[i].minimum_size;
|
||||
sizes[i].natural_size = sizes_temp[i].natural_size;
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
needs_update (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;
|
||||
GList *widget_shown;
|
||||
GList *widgets_to_show = NULL;
|
||||
gboolean needs_update = FALSE;
|
||||
gboolean allocate_more_children = TRUE;
|
||||
gint children_size = -priv->spacing;
|
||||
|
||||
if (priv->needs_update)
|
||||
return TRUE;
|
||||
|
||||
if (allocation->width != priv->current_width ||
|
||||
allocation->height != priv->current_height)
|
||||
return TRUE;
|
||||
|
||||
children = g_list_copy (priv->children);
|
||||
sizes_temp = g_newa (GtkRequestedSize, g_list_length (priv->children));
|
||||
if (priv->inverted)
|
||||
children = g_list_reverse (children);
|
||||
|
||||
widget_shown = priv->widgets_shown;
|
||||
/* Retrieve desired size for visible children. */
|
||||
for (i = 0, child = children; child != NULL; i++, child = child->next)
|
||||
{
|
||||
child_widget = GTK_WIDGET (child->data);
|
||||
if (!gtk_widget_get_visible (child_widget) || !allocate_more_children)
|
||||
{
|
||||
needs_update = child->data != widget_shown->data;
|
||||
widgets_to_show = g_list_prepend (widgets_to_show, child->data);
|
||||
widget_shown = widget_shown->next;
|
||||
if (needs_update)
|
||||
{
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
needs_update = child->data == widget_shown->data;
|
||||
if (needs_update)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gtk_widget_get_preferred_width_for_height (child_widget,
|
||||
allocation->height,
|
||||
&sizes_temp[i].minimum_size,
|
||||
&sizes_temp[i].natural_size);
|
||||
/* Assert the api is working properly */
|
||||
if (sizes_temp[i].minimum_size < 0)
|
||||
g_error ("GtkHidingBox child %s minimum width: %d < 0 for height %d",
|
||||
gtk_widget_get_name (child_widget),
|
||||
sizes_temp[i].minimum_size, allocation->height);
|
||||
|
||||
if (sizes_temp[i].natural_size < sizes_temp[i].minimum_size)
|
||||
g_error ("GtkHidingBox child %s natural width: %d < minimum %d for height %d",
|
||||
gtk_widget_get_name (child_widget),
|
||||
sizes_temp[i].natural_size, sizes_temp[i].minimum_size,
|
||||
allocation->height);
|
||||
|
||||
children_size += sizes_temp[i].minimum_size + priv->spacing;
|
||||
sizes_temp[i].data = child_widget;
|
||||
|
||||
if (children_size > allocation->width)
|
||||
{
|
||||
allocate_more_children = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
needs_update = needs_update || widget_shown != NULL;
|
||||
|
||||
g_list_free (children);
|
||||
|
||||
return needs_update;
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
GtkRevealer *revealer;
|
||||
|
||||
g_print ("update revealer hide %s\n", gtk_button_get_label (GTK_BUTTON (l->data)));
|
||||
revealer = GTK_REVEALER (gtk_widget_get_parent (l->data));
|
||||
if (gtk_revealer_get_reveal_child (revealer))
|
||||
{
|
||||
GtkStyleContext *style_context;
|
||||
|
||||
style_context = gtk_widget_get_style_context (GTK_WIDGET (revealer));
|
||||
gtk_style_context_remove_class (style_context, "pathbar-initial-opacity");
|
||||
gtk_style_context_remove_class (style_context, "pathbar-opacity-on");
|
||||
gtk_style_context_add_class (style_context, "pathbar-opacity-off");
|
||||
g_signal_connect (revealer, "notify::child-revealed", (GCallback) opacity_off, box);
|
||||
gtk_revealer_set_reveal_child (revealer, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
for (l = priv->widgets_to_remove; l != NULL; l = l->next)
|
||||
{
|
||||
GtkRevealer *revealer;
|
||||
|
||||
g_print ("update revealer remove %s\n", gtk_button_get_label (GTK_BUTTON (l->data)));
|
||||
revealer = GTK_REVEALER (gtk_widget_get_parent (l->data));
|
||||
if (gtk_revealer_get_child_revealed (revealer))
|
||||
{
|
||||
GtkStyleContext *style_context;
|
||||
|
||||
style_context = gtk_widget_get_style_context (GTK_WIDGET (revealer));
|
||||
gtk_style_context_remove_class (style_context, "pathbar-initial-opacity");
|
||||
gtk_style_context_remove_class (style_context, "pathbar-opacity-on");
|
||||
gtk_style_context_add_class (style_context, "pathbar-opacity-off");
|
||||
g_signal_connect (revealer, "notify::child-revealed",
|
||||
(GCallback) unrevealed_really_remove_child, box);
|
||||
gtk_revealer_set_reveal_child (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)
|
||||
{
|
||||
GtkRevealer *revealer;
|
||||
|
||||
revealer = GTK_REVEALER (gtk_widget_get_parent (l->data));
|
||||
if (!gtk_revealer_get_reveal_child (revealer))
|
||||
{
|
||||
GtkStyleContext *style_context;
|
||||
|
||||
style_context = gtk_widget_get_style_context (GTK_WIDGET (revealer));
|
||||
gtk_style_context_remove_class (style_context, "pathbar-opacity-off");
|
||||
gtk_style_context_remove_class (style_context, "pathbar-initial-opacity");
|
||||
gtk_style_context_add_class (style_context, "pathbar-opacity-on");
|
||||
gtk_revealer_set_reveal_child (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;
|
||||
gint n_visible_children_expanding = 0;
|
||||
gint children_size = 0;
|
||||
|
||||
gtk_widget_set_allocation (widget, allocation);
|
||||
|
||||
sizes = g_newa (GtkRequestedSize, g_list_length (priv->children));
|
||||
update_children_visibility (box, allocation, sizes, FALSE, &children_size,
|
||||
&n_visible_children_expanding);
|
||||
|
||||
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
|
||||
finish_invert_animation (GtkHidingBox *self)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (self);
|
||||
|
||||
priv->invert_animation = FALSE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
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;
|
||||
gfloat progress;
|
||||
gdouble adjustment_value;
|
||||
|
||||
if (!priv->initial_time)
|
||||
priv->initial_time = gdk_frame_clock_get_frame_time (frame_clock);
|
||||
|
||||
elapsed = gdk_frame_clock_get_frame_time (frame_clock) - priv->initial_time;
|
||||
progress = elapsed / INVERT_ANIMATION_TIME;
|
||||
|
||||
if (progress >= 1)
|
||||
{
|
||||
finish_invert_animation (self);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->inverted)
|
||||
adjustment_value = 1 / (progress * (gtk_adjustment_get_lower (priv->hadjustment) - gtk_adjustment_get_upper (priv->hadjustment)));
|
||||
else
|
||||
adjustment_value = progress * (gtk_adjustment_get_lower (priv->hadjustment) - gtk_adjustment_get_upper (priv->hadjustment));
|
||||
|
||||
gtk_adjustment_set_value (priv->hadjustment, adjustment_value);
|
||||
}
|
||||
|
||||
static void
|
||||
start_invert_animation (GtkHidingBox *self)
|
||||
{
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (self);
|
||||
GList *child;
|
||||
|
||||
priv->invert_animation = TRUE;
|
||||
|
||||
for (child = priv->children; child != NULL; child = child->next)
|
||||
{
|
||||
GtkWidget *revealer;
|
||||
|
||||
revealer = gtk_widget_get_parent (GTK_WIDGET (child->data));
|
||||
gtk_revealer_set_transition_duration (GTK_REVEALER (revealer), 0);
|
||||
gtk_revealer_set_reveal_child (GTK_REVEALER (revealer), TRUE);
|
||||
}
|
||||
|
||||
priv->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)
|
||||
{
|
||||
GtkHidingBox *box = GTK_HIDING_BOX (user_data);
|
||||
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
|
||||
|
||||
if (priv->invert_animation)
|
||||
return;
|
||||
|
||||
if (priv->inverted)
|
||||
gtk_adjustment_set_value (hadjustment, gtk_adjustment_get_upper (hadjustment));
|
||||
else
|
||||
gtk_adjustment_set_value (hadjustment, gtk_adjustment_get_lower (hadjustment));
|
||||
}
|
||||
|
||||
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);
|
||||
GtkAdjustment *hadjustment;
|
||||
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->widgets_to_hide = NULL;
|
||||
priv->widgets_to_show = NULL;
|
||||
priv->widgets_to_remove = NULL;
|
||||
priv->widgets_shown = NULL;
|
||||
priv->animation_phase = ANIMATION_PHASE_NONE;
|
||||
|
||||
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");
|
||||
|
||||
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_ */
|
@@ -456,6 +456,7 @@ gtk_revealer_real_size_allocate (GtkWidget *widget,
|
||||
|
||||
g_return_if_fail (allocation != NULL);
|
||||
|
||||
g_print ("revealer allocation %d %d %d %d\n", allocation->height, allocation->width, allocation->x, allocation->y);
|
||||
gtk_widget_set_allocation (widget, allocation);
|
||||
gtk_revealer_get_child_allocation (revealer, allocation, &child_allocation);
|
||||
|
||||
|
@@ -446,6 +446,7 @@ gtk_public_h_sources = \
|
||||
gtkpagesetup.h \
|
||||
gtkpaned.h \
|
||||
gtkpapersize.h \
|
||||
gtkpathbar.h \
|
||||
gtkplug.h \
|
||||
gtkprintcontext.h \
|
||||
gtkprintoperation.h \
|
||||
|
@@ -1594,31 +1594,45 @@ 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;
|
||||
}
|
||||
|
||||
/**************
|
||||
|
@@ -2097,22 +2097,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 *
|
||||
|
@@ -2104,22 +2104,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 = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
|
||||
|
||||
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