Add GtkFlowBox

GtkFlowBox is a container that its children in a reflowing
grid, which can be oriented horizontally or vertically.

It is similar to GtkListBox in that the children can
be sorted and filtered, and by requiring a dedicated child
widget type, GtkFlowBoxChild. It is similar to GtkTreeView
in that is supports a full set of selection modes, including
rubberband selection.

This is the culmination of work that has happened in the
egg-list-box module, and earlier in libegg. The origins of
this code are the EggSpreadTable in libegg, which was written
by Tristan van Berkom. It was moved to egg-list-box and
renamed EggFlowBox by Jon McCann, and I gave it some finishing
touched in the flowbox-improvements branch of that module.
This commit is contained in:
Matthias Clasen 2013-09-29 13:43:27 -04:00
parent 8a85371901
commit 943d575ec3
20 changed files with 6211 additions and 1 deletions

View File

@ -421,7 +421,8 @@ HTML_IMAGES = \
$(srcdir)/images/getting-started-app7.png \
$(srcdir)/images/getting-started-app8.png \
$(srcdir)/images/getting-started-app9.png \
$(srcdir)/images/exampleapp.png
$(srcdir)/images/exampleapp.png \
$(srcdir)/images/flow-box.png
# Extra options to supply to gtkdoc-fixref
FIXXREF_OPTIONS=--extra-dir=../gdk/html \

View File

@ -72,6 +72,7 @@
<xi:include href="xml/gtkgrid.xml" />
<xi:include href="xml/gtkrevealer.xml" />
<xi:include href="xml/gtklistbox.xml" />
<xi:include href="xml/gtkflowbox.xml" />
<xi:include href="xml/gtkstack.xml" />
<xi:include href="xml/gtkstackswitcher.xml" />
<xi:include href="xml/gtkheaderbar.xml" />

View File

@ -7737,3 +7737,52 @@ GtkRevealerTransitionType
gtk_revealer_get_transition_type
gtk_revealer_set_transition_type
</SECTION>
<SECTION>
<FILE>gtkflowbox</FILE>
<TITLE>GtkFlowBox</TITLE>
GtkFlowBox
gtk_flow_box_new
gtk_flow_box_insert
gtk_flow_box_get_child_at_index
gtk_flow_box_set_hadjustment
gtk_flow_box_set_vadjustment
gtk_flow_box_set_homogeneous
gtk_flow_box_get_homogeneous
gtk_flow_box_set_row_spacing
gtk_flow_box_get_row_spacing
gtk_flow_box_set_column_spacing
gtk_flow_box_get_column_spacing
gtk_flow_box_set_min_children_per_line
gtk_flow_box_get_min_children_per_line
gtk_flow_box_set_max_children_per_line
gtk_flow_box_get_max_children_per_line
gtk_flow_box_set_activate_on_single_click
gtk_flow_box_get_activate_on_single_click
GtkFlowBoxForeachFunc
gtk_flow_box_selected_foreach
gtk_flow_box_get_selected_children
gtk_flow_box_select_child
gtk_flow_box_unselect_child
gtk_flow_box_select_all
gtk_flow_box_unselect_all
gtk_flow_box_set_selection_mode
gtk_flow_box_get_selection_mode
GtkFlowBoxFilterFunc
gtk_flow_box_set_filter_func
gtk_flow_box_invalidate_filter
GtkFlowBoxSortFunc
gtk_flow_box_set_sort_func
gtk_flow_box_invalidate_sort
<SUBSECTION GtkFlowBoxChild>
GtkFlowBoxChild
gtk_flow_box_child_new
gtk_flow_box_child_get_index
gtk_flow_box_child_is_selected
gtk_flow_box_child_changed
</SECTION>

View File

@ -70,6 +70,8 @@ gtk_file_chooser_get_type
gtk_file_chooser_widget_get_type
gtk_file_filter_get_type
gtk_fixed_get_type
gtk_flow_box_get_type
gtk_flow_box_child_get_type
gtk_font_button_get_type
gtk_font_chooser_get_type
gtk_font_chooser_dialog_get_type

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -126,6 +126,9 @@
<link linkend="GtkListBox">
<inlinegraphic fileref="list-box.png" format="PNG"></inlinegraphic>
</link>
<link linkend="GtkFlowBox">
<inlinegraphic fileref="flow-box.png" format="PNG"></inlinegraphic>
</link>
<link linkend="GtkStack">
<inlinegraphic fileref="stack.png" format="PNG"></inlinegraphic>
</link>

View File

@ -1430,12 +1430,56 @@ create_list_box (void)
return info;
}
static WidgetInfo *
create_flow_box (void)
{
GtkWidget *widget;
GtkWidget *box;
GtkWidget *vbox;
GtkWidget *child;
GtkWidget *button;
WidgetInfo *info;
widget = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_IN);
box = gtk_flow_box_new ();
gtk_flow_box_set_min_children_per_line (GTK_FLOW_BOX (box), 2);
gtk_flow_box_set_max_children_per_line (GTK_FLOW_BOX (box), 2);
gtk_flow_box_set_selection_mode (GTK_FLOW_BOX (box), GTK_SELECTION_BROWSE);
button = gtk_label_new ("Child One");
gtk_container_add (GTK_CONTAINER (box), button);
button = gtk_button_new_with_label ("Child Two");
gtk_container_add (GTK_CONTAINER (box), button);
child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_container_add (GTK_CONTAINER (child), gtk_label_new ("Child Three"));
button = gtk_check_button_new ();
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
gtk_container_add (GTK_CONTAINER (child), button);
gtk_container_add (GTK_CONTAINER (box), child);
gtk_flow_box_select_child (GTK_FLOW_BOX (box),
GTK_FLOW_BOX_CHILD (gtk_widget_get_parent (child)));
gtk_container_add (GTK_CONTAINER (widget), box);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox), gtk_label_new ("Flow Box"),
FALSE, FALSE, 0);
info = new_widget_info ("flow-box", vbox, ASIS);
info->no_focus = FALSE;
return info;
}
GList *
get_all_widgets (void)
{
GList *retval = NULL;
retval = g_list_prepend (retval, create_list_box());
retval = g_list_prepend (retval, create_flow_box());
retval = g_list_prepend (retval, create_headerbar ());
retval = g_list_prepend (retval, create_placessidebar ());
retval = g_list_prepend (retval, create_stack ());

View File

@ -249,6 +249,7 @@ gtk_public_h_sources = \
gtkfilechooserwidget.h \
gtkfilefilter.h \
gtkfixed.h \
gtkflowbox.h \
gtkfontbutton.h \
gtkfontchooser.h \
gtkfontchooserdialog.h \
@ -741,6 +742,7 @@ gtk_base_c_sources = \
gtkfilesystem.c \
gtkfilesystemmodel.c \
gtkfixed.c \
gtkflowbox.c \
gtkfontbutton.c \
gtkfontchooser.c \
gtkfontchooserdialog.c \

View File

@ -18,6 +18,8 @@ gtka11y_c_sources = \
gtkcontainercellaccessible.c \
gtkentryaccessible.c \
gtkexpanderaccessible.c \
gtkflowboxaccessible.c \
gtkflowboxchildaccessible.c \
gtkframeaccessible.c \
gtkiconviewaccessible.c \
gtkimageaccessible.c \

View File

@ -0,0 +1,254 @@
/*
* Copyright (C) 2013 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkflowboxaccessibleprivate.h"
#include "gtk/gtkflowbox.h"
static void atk_selection_interface_init (AtkSelectionIface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkFlowBoxAccessible, gtk_flow_box_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE,
G_IMPLEMENT_INTERFACE (ATK_TYPE_SELECTION, atk_selection_interface_init))
static void
gtk_flow_box_accessible_init (GtkFlowBoxAccessible *accessible)
{
}
static void
gtk_flow_box_accessible_initialize (AtkObject *obj,
gpointer data)
{
ATK_OBJECT_CLASS (gtk_flow_box_accessible_parent_class)->initialize (obj, data);
obj->role = ATK_ROLE_TABLE;
}
static AtkStateSet*
gtk_flow_box_accessible_ref_state_set (AtkObject *obj)
{
AtkStateSet *state_set;
GtkWidget *widget;
state_set = ATK_OBJECT_CLASS (gtk_flow_box_accessible_parent_class)->ref_state_set (obj);
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
if (widget != NULL)
atk_state_set_add_state (state_set, ATK_STATE_MANAGES_DESCENDANTS);
return state_set;
}
static void
gtk_flow_box_accessible_class_init (GtkFlowBoxAccessibleClass *klass)
{
AtkObjectClass *object_class = ATK_OBJECT_CLASS (klass);
object_class->initialize = gtk_flow_box_accessible_initialize;
object_class->ref_state_set = gtk_flow_box_accessible_ref_state_set;
}
static gboolean
gtk_flow_box_accessible_add_selection (AtkSelection *selection,
gint idx)
{
GtkWidget *box;
GList *children;
GtkWidget *child;
box = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
if (box == NULL)
return FALSE;
children = gtk_container_get_children (GTK_CONTAINER (box));
child = g_list_nth_data (children, idx);
g_list_free (children);
if (child)
{
gtk_flow_box_select_child (GTK_FLOW_BOX (box), GTK_FLOW_BOX_CHILD (child));
return TRUE;
}
return FALSE;
}
static gboolean
gtk_flow_box_accessible_remove_selection (AtkSelection *selection,
gint idx)
{
GtkWidget *box;
GList *children;
GtkWidget *child;
box = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
if (box == NULL)
return FALSE;
children = gtk_container_get_children (GTK_CONTAINER (box));
child = g_list_nth_data (children, idx);
g_list_free (children);
if (child)
{
gtk_flow_box_unselect_child (GTK_FLOW_BOX (box), GTK_FLOW_BOX_CHILD (child));
return TRUE;
}
return FALSE;
}
static gboolean
gtk_flow_box_accessible_clear_selection (AtkSelection *selection)
{
GtkWidget *box;
box = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
if (box == NULL)
return FALSE;
gtk_flow_box_unselect_all (GTK_FLOW_BOX (box));
return TRUE;
}
static gboolean
gtk_flow_box_accessible_select_all (AtkSelection *selection)
{
GtkWidget *box;
box = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
if (box == NULL)
return FALSE;
gtk_flow_box_select_all (GTK_FLOW_BOX (box));
return TRUE;
}
typedef struct
{
gint idx;
GtkWidget *child;
} FindSelectedData;
static void
find_selected_child (GtkFlowBox *box,
GtkFlowBoxChild *child,
gpointer data)
{
FindSelectedData *d = data;
if (d->idx == 0)
{
if (d->child == NULL)
d->child = GTK_WIDGET (child);
}
else
d->idx -= 1;
}
static AtkObject *
gtk_flow_box_accessible_ref_selection (AtkSelection *selection,
gint idx)
{
GtkWidget *box;
AtkObject *accessible;
FindSelectedData data;
box = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
if (box == NULL)
return NULL;
data.idx = idx;
data.child = NULL;
gtk_flow_box_selected_foreach (GTK_FLOW_BOX (box), find_selected_child, &data);
if (data.child == NULL)
return NULL;
accessible = gtk_widget_get_accessible (data.child);
g_object_ref (accessible);
return accessible;
}
static void
count_selected (GtkFlowBox *box,
GtkFlowBoxChild *child,
gpointer data)
{
gint *count = data;
*count += 1;
}
static gint
gtk_flow_box_accessible_get_selection_count (AtkSelection *selection)
{
GtkWidget *box;
gint count;
box = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
if (box == NULL)
return 0;
count = 0;
gtk_flow_box_selected_foreach (GTK_FLOW_BOX (box), count_selected, &count);
return count;
}
static gboolean
gtk_flow_box_accessible_is_child_selected (AtkSelection *selection,
gint idx)
{
GtkWidget *box;
GtkFlowBoxChild *child;
box = gtk_accessible_get_widget (GTK_ACCESSIBLE (selection));
if (box == NULL)
return FALSE;
child = gtk_flow_box_get_child_at_index (GTK_FLOW_BOX (box), idx);
return gtk_flow_box_child_is_selected (child);
}
static void atk_selection_interface_init (AtkSelectionIface *iface)
{
iface->add_selection = gtk_flow_box_accessible_add_selection;
iface->remove_selection = gtk_flow_box_accessible_remove_selection;
iface->clear_selection = gtk_flow_box_accessible_clear_selection;
iface->ref_selection = gtk_flow_box_accessible_ref_selection;
iface->get_selection_count = gtk_flow_box_accessible_get_selection_count;
iface->is_child_selected = gtk_flow_box_accessible_is_child_selected;
iface->select_all_selection = gtk_flow_box_accessible_select_all;
}
void
_gtk_flow_box_accessible_selection_changed (GtkWidget *box)
{
AtkObject *accessible;
accessible = gtk_widget_get_accessible (box);
g_signal_emit_by_name (accessible, "selection-changed");
}
void
_gtk_flow_box_accessible_update_cursor (GtkWidget *box,
GtkWidget *child)
{
AtkObject *accessible;
AtkObject *descendant;
accessible = gtk_widget_get_accessible (box);
descendant = child ? gtk_widget_get_accessible (child) : NULL;
g_signal_emit_by_name (accessible, "active-descendant-changed", descendant);
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2013 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_FLOW_BOX_ACCESSIBLE_H__
#define __GTK_FLOW_BOX_ACCESSIBLE_H__
#if !defined (__GTK_A11Y_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk-a11y.h> can be included directly."
#endif
#include <gtk/gtk.h>
#include <gtk/a11y/gtkcontaineraccessible.h>
G_BEGIN_DECLS
#define GTK_TYPE_FLOW_BOX_ACCESSIBLE (gtk_flow_box_accessible_get_type ())
#define GTK_FLOW_BOX_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FLOW_BOX_ACCESSIBLE, GtkFlowBoxAccessible))
#define GTK_FLOW_BOX_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FLOW_BOX_ACCESSIBLE, GtkFlowBoxAccessibleClass))
#define GTK_IS_FLOW_BOX_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FLOW_BOX_ACCESSIBLE))
#define GTK_IS_FLOW_BOX_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FLOW_BOX_ACCESSIBLE))
#define GTK_FLOW_BOX_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FLOW_BOX_ACCESSIBLE, GtkFlowBoxAccessibleClass))
typedef struct _GtkFlowBoxAccessible GtkFlowBoxAccessible;
typedef struct _GtkFlowBoxAccessibleClass GtkFlowBoxAccessibleClass;
typedef struct _GtkFlowBoxAccessiblePrivate GtkFlowBoxAccessiblePrivate;
struct _GtkFlowBoxAccessible
{
GtkContainerAccessible parent;
GtkFlowBoxAccessiblePrivate *priv;
};
struct _GtkFlowBoxAccessibleClass
{
GtkContainerAccessibleClass parent_class;
};
GDK_AVAILABLE_IN_3_12
GType gtk_flow_box_accessible_get_type (void);
G_END_DECLS
#endif /* __GTK_FLOW_BOX_ACCESSIBLE_H__ */

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2013 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_FLOW_BOX_ACCESSIBLE_PRIVATE_H__
#define __GTK_FLOW_BOX_ACCESSIBLE_PRIVATE_H__
#include <gtk/a11y/gtkflowboxaccessible.h>
G_BEGIN_DECLS
void _gtk_flow_box_accessible_selection_changed (GtkWidget *box);
void _gtk_flow_box_accessible_update_cursor (GtkWidget *box,
GtkWidget *child);
G_END_DECLS
#endif /* __GTK_FLOW_BOX_ACCESSIBLE_PRIVATE_H__ */

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) 2013 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkflowboxchildaccessible.h"
#include "gtk/gtkflowbox.h"
G_DEFINE_TYPE (GtkFlowBoxChildAccessible, gtk_flow_box_child_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE)
static void
gtk_flow_box_child_accessible_init (GtkFlowBoxChildAccessible *accessible)
{
}
static void
gtk_flow_box_child_accessible_initialize (AtkObject *obj,
gpointer data)
{
ATK_OBJECT_CLASS (gtk_flow_box_child_accessible_parent_class)->initialize (obj, data);
obj->role = ATK_ROLE_TABLE_CELL;
}
static AtkStateSet *
gtk_flow_box_child_accessible_ref_state_set (AtkObject *obj)
{
AtkStateSet *state_set;
GtkWidget *widget, *parent;
state_set = ATK_OBJECT_CLASS (gtk_flow_box_child_accessible_parent_class)->ref_state_set (obj);
widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj));
if (widget != NULL)
{
parent = gtk_widget_get_parent (widget);
if (gtk_flow_box_get_selection_mode (GTK_FLOW_BOX (parent)) != GTK_SELECTION_NONE)
atk_state_set_add_state (state_set, ATK_STATE_SELECTABLE);
if (gtk_flow_box_child_is_selected (GTK_FLOW_BOX_CHILD (widget)))
atk_state_set_add_state (state_set, ATK_STATE_SELECTED);
}
return state_set;
}
static void
gtk_flow_box_child_accessible_class_init (GtkFlowBoxChildAccessibleClass *klass)
{
AtkObjectClass *object_class = ATK_OBJECT_CLASS (klass);
object_class->initialize = gtk_flow_box_child_accessible_initialize;
object_class->ref_state_set = gtk_flow_box_child_accessible_ref_state_set;
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2013 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_FLOW_BOX_CHILD_ACCESSIBLE_H__
#define __GTK_FLOW_BOX_CHILD_ACCESSIBLE_H__
#if !defined (__GTK_A11Y_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk-a11y.h> can be included directly."
#endif
#include <gtk/gtk.h>
#include <gtk/a11y/gtkcontaineraccessible.h>
G_BEGIN_DECLS
#define GTK_TYPE_FLOW_BOX_CHILD_ACCESSIBLE (gtk_flow_box_child_accessible_get_type ())
#define GTK_FLOW_BOX_CHILD_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FLOW_BOX_CHILD_ACCESSIBLE, GtkFlowBoxChildAccessible))
#define GTK_FLOW_BOX_CHILD_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FLOW_BOX_CHILD_ACCESSIBLE, GtkFlowBoxChildAccessibleClass))
#define GTK_IS_FLOW_BOX_CHILD_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FLOW_BOX_CHILD_ACCESSIBLE))
#define GTK_IS_FLOW_BOX_CHILD_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FLOW_BOX_CHILD_ACCESSIBLE))
#define GTK_FLOW_BOX_CHILD_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FLOW_BOX_CHILD_ACCESSIBLE, GtkFlowBoxChildAccessibleClass))
typedef struct _GtkFlowBoxChildAccessible GtkFlowBoxChildAccessible;
typedef struct _GtkFlowBoxChildAccessibleClass GtkFlowBoxChildAccessibleClass;
struct _GtkFlowBoxChildAccessible
{
GtkContainerAccessible parent;
};
struct _GtkFlowBoxChildAccessibleClass
{
GtkContainerAccessibleClass parent_class;
};
GDK_AVAILABLE_IN_3_12
GType gtk_flow_box_child_accessible_get_type (void);
G_END_DECLS
#endif /* __GTK_FLOW_BOX_CHILD_ACCESSIBLE_H__ */

View File

@ -39,6 +39,8 @@
#include <gtk/a11y/gtkcontainercellaccessible.h>
#include <gtk/a11y/gtkentryaccessible.h>
#include <gtk/a11y/gtkexpanderaccessible.h>
#include <gtk/a11y/gtkflowboxaccessible.h>
#include <gtk/a11y/gtkflowboxchildaccessible.h>
#include <gtk/a11y/gtkframeaccessible.h>
#include <gtk/a11y/gtkiconviewaccessible.h>
#include <gtk/a11y/gtkimageaccessible.h>

View File

@ -99,6 +99,7 @@
#include <gtk/gtkfilechooserdialog.h>
#include <gtk/gtkfilechooserwidget.h>
#include <gtk/gtkfilefilter.h>
#include <gtk/gtkflowbox.h>
#include <gtk/gtkfontbutton.h>
#include <gtk/gtkfontchooser.h>
#include <gtk/gtkfontchooserdialog.h>

4719
gtk/gtkflowbox.c Normal file

File diff suppressed because it is too large Load Diff

220
gtk/gtkflowbox.h Normal file
View File

@ -0,0 +1,220 @@
/*
* Copyright (C) 2010 Openismus GmbH
* Copyright (C) 2013 Red Hat, Inc.
*
* 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.
*
* This library 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.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors:
* Tristan Van Berkom <tristanvb@openismus.com>
* Matthias Clasen <mclasen@redhat.com>
* William Jon McCann <jmccann@redhat.com>
*/
#ifndef __GTK_FLOW_BOX_H__
#define __GTK_FLOW_BOX_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
#define GTK_TYPE_FLOW_BOX (gtk_flow_box_get_type ())
#define GTK_FLOW_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FLOW_BOX, GtkFlowBox))
#define GTK_FLOW_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FLOW_BOX, GtkFlowBoxClass))
#define GTK_IS_FLOW_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FLOW_BOX))
#define GTK_IS_FLOW_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FLOW_BOX))
#define GTK_FLOW_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FLOW_BOX, GtkFlowBoxClass))
typedef struct _GtkFlowBox GtkFlowBox;
typedef struct _GtkFlowBoxClass GtkFlowBoxClass;
typedef struct _GtkFlowBoxChild GtkFlowBoxChild;
typedef struct _GtkFlowBoxChildClass GtkFlowBoxChildClass;
struct _GtkFlowBox
{
GtkContainer container;
};
struct _GtkFlowBoxClass
{
GtkContainerClass parent_class;
void (*child_activated) (GtkFlowBox *box,
GtkFlowBoxChild *child);
void (*selected_children_changed) (GtkFlowBox *box);
void (*activate_cursor_child) (GtkFlowBox *box);
void (*toggle_cursor_child) (GtkFlowBox *box);
void (*move_cursor) (GtkFlowBox *box,
GtkMovementStep step,
gint count);
void (*select_all) (GtkFlowBox *box);
void (*unselect_all) (GtkFlowBox *box);
/* Padding for future expansion */
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
void (*_gtk_reserved3) (void);
void (*_gtk_reserved4) (void);
void (*_gtk_reserved5) (void);
void (*_gtk_reserved6) (void);
};
#define GTK_TYPE_FLOW_BOX_CHILD (gtk_flow_box_child_get_type ())
#define GTK_FLOW_BOX_CHILD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FLOW_BOX_CHILD, GtkFlowBoxChild))
#define GTK_FLOW_BOX_CHILD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FLOW_BOX_CHILD, GtkFlowBoxChildClass))
#define GTK_IS_FLOW_BOX_CHILD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FLOW_BOX_CHILD))
#define GTK_IS_FLOW_BOX_CHILD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FLOW_BOX_CHILD))
#define GTK_FLOW_BOX_CHILD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EG_TYPE_FLOW_BOX_CHILD, GtkFlowBoxChildClass))
struct _GtkFlowBoxChild
{
GtkBin parent_instance;
};
struct _GtkFlowBoxChildClass
{
GtkBinClass parent_class;
void (* activate) (GtkFlowBoxChild *child);
/* Padding for future expansion */
void (*_gtk_reserved1) (void);
void (*_gtk_reserved2) (void);
};
GDK_AVAILABLE_IN_3_12
GType gtk_flow_box_child_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_3_12
GtkWidget* gtk_flow_box_child_new (void);
GDK_AVAILABLE_IN_3_12
gint gtk_flow_box_child_get_index (GtkFlowBoxChild *child);
GDK_AVAILABLE_IN_3_12
gboolean gtk_flow_box_child_is_selected (GtkFlowBoxChild *child);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_child_changed (GtkFlowBoxChild *child);
GDK_AVAILABLE_IN_3_12
GType gtk_flow_box_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_3_12
GtkWidget *gtk_flow_box_new (void);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_set_homogeneous (GtkFlowBox *box,
gboolean homogeneous);
GDK_AVAILABLE_IN_3_12
gboolean gtk_flow_box_get_homogeneous (GtkFlowBox *box);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_set_row_spacing (GtkFlowBox *box,
guint spacing);
GDK_AVAILABLE_IN_3_12
guint gtk_flow_box_get_row_spacing (GtkFlowBox *box);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_set_column_spacing (GtkFlowBox *box,
guint spacing);
GDK_AVAILABLE_IN_3_12
guint gtk_flow_box_get_column_spacing (GtkFlowBox *box);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_set_min_children_per_line (GtkFlowBox *box,
guint n_children);
GDK_AVAILABLE_IN_3_12
guint gtk_flow_box_get_min_children_per_line (GtkFlowBox *box);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_set_max_children_per_line (GtkFlowBox *box,
guint n_children);
GDK_AVAILABLE_IN_3_12
guint gtk_flow_box_get_max_children_per_line (GtkFlowBox *box);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_set_activate_on_single_click (GtkFlowBox *box,
gboolean single);
GDK_AVAILABLE_IN_3_12
gboolean gtk_flow_box_get_activate_on_single_click (GtkFlowBox *box);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_insert (GtkFlowBox *box,
GtkWidget *widget,
gint position);
GDK_AVAILABLE_IN_3_12
GtkFlowBoxChild *gtk_flow_box_get_child_at_index (GtkFlowBox *box,
gint idx);
typedef void (* GtkFlowBoxForeachFunc) (GtkFlowBox *box,
GtkFlowBoxChild *child,
gpointer user_data);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_selected_foreach (GtkFlowBox *box,
GtkFlowBoxForeachFunc func,
gpointer data);
GDK_AVAILABLE_IN_3_12
GList *gtk_flow_box_get_selected_children (GtkFlowBox *box);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_select_child (GtkFlowBox *box,
GtkFlowBoxChild *child);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_unselect_child (GtkFlowBox *box,
GtkFlowBoxChild *child);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_select_all (GtkFlowBox *box);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_unselect_all (GtkFlowBox *box);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_set_selection_mode (GtkFlowBox *box,
GtkSelectionMode mode);
GDK_AVAILABLE_IN_3_12
GtkSelectionMode gtk_flow_box_get_selection_mode (GtkFlowBox *box);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_set_hadjustment (GtkFlowBox *box,
GtkAdjustment *adjustment);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_set_vadjustment (GtkFlowBox *box,
GtkAdjustment *adjustment);
typedef gboolean (*GtkFlowBoxFilterFunc) (GtkFlowBoxChild *child,
gpointer user_data);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_set_filter_func (GtkFlowBox *box,
GtkFlowBoxFilterFunc filter_func,
gpointer user_data,
GDestroyNotify destroy);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_invalidate_filter (GtkFlowBox *box);
typedef gint (*GtkFlowBoxSortFunc) (GtkFlowBoxChild *child1,
GtkFlowBoxChild *child2,
gpointer user_data);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_set_sort_func (GtkFlowBox *box,
GtkFlowBoxSortFunc sort_func,
gpointer user_data,
GDestroyNotify destroy);
GDK_AVAILABLE_IN_3_12
void gtk_flow_box_invalidate_sort (GtkFlowBox *box);
G_END_DECLS
#endif /* __GTK_FLOW_BOX_H__ */

View File

@ -54,6 +54,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
testentryicons \
testfilechooser \
testfilechooserbutton \
testflowbox \
testfontselection \
testfontselectiondialog \
testfontchooser \
@ -190,6 +191,7 @@ testentryicons_DEPENDENCIES = $(TEST_DEPS)
testerrors_DEPENDENCIES = $(TEST_DEPS)
testfilechooser_DEPENDENCIES = $(TEST_DEPS)
testfilechooserbutton_DEPENDENCIES = $(TEST_DEPS)
testflowbox_DEPENDENCIES = $(TEST_DEPS)
testfontselection_DEPENDENCIES = $(TEST_DEPS)
testfontselectiondialog_DEPENDENCIES = $(TEST_DEPS)
testfontchooser_DEPENDENCIES = $(TEST_DEPS)
@ -310,6 +312,9 @@ testfilechooserbutton_SOURCES = \
prop-editor.c \
testfilechooserbutton.c
testflowbox_SOURCES = \
testflowbox.c
testfontselection_SOURCES = \
testfontselection.c

692
tests/testflowbox.c Normal file
View File

@ -0,0 +1,692 @@
/*
* Copyright (C) 2010 Openismus GmbH
*
* 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.
*
* This library 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.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <gtk/gtk.h>
enum {
SIMPLE_ITEMS = 0,
FOCUS_ITEMS,
WRAPPY_ITEMS,
STOCK_ITEMS,
IMAGE_ITEMS
};
#define INITIAL_HALIGN GTK_ALIGN_FILL
#define INITIAL_VALIGN GTK_ALIGN_START
#define INITIAL_MINIMUM_LENGTH 3
#define INITIAL_MAXIMUM_LENGTH 6
#define INITIAL_CSPACING 2
#define INITIAL_RSPACING 2
#define N_ITEMS 1000
static GtkFlowBox *the_flowbox = NULL;
static gint items_type = SIMPLE_ITEMS;
static GtkOrientation text_orientation = GTK_ORIENTATION_HORIZONTAL;
static void
populate_flowbox_simple (GtkFlowBox *flowbox)
{
GtkWidget *widget, *frame;
gint i;
for (i = 0; i < N_ITEMS; i++)
{
gchar *text = g_strdup_printf ("Item %02d", i);
widget = gtk_label_new (text);
frame = gtk_frame_new (NULL);
gtk_widget_show (widget);
gtk_widget_show (frame);
gtk_container_add (GTK_CONTAINER (frame), widget);
if (text_orientation == GTK_ORIENTATION_VERTICAL)
gtk_label_set_angle (GTK_LABEL (widget), 90);
g_object_set_data_full (G_OBJECT (frame), "id", (gpointer)g_strdup (text), g_free);
gtk_container_add (GTK_CONTAINER (flowbox), frame);
g_free (text);
}
}
static void
populate_flowbox_focus (GtkFlowBox *flowbox)
{
GtkWidget *widget, *frame, *box;
gint i;
gboolean sensitive;
for (i = 0; i < 200; i++)
{
sensitive = TRUE;
frame = gtk_frame_new (NULL);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
gtk_container_add (GTK_CONTAINER (frame), box);
widget = gtk_label_new ("Label");
gtk_container_add (GTK_CONTAINER (box), widget);
switch (i % 4)
{
case 0:
widget = gtk_entry_new ();
break;
case 1:
widget = gtk_button_new_with_label ("Button");
break;
case 2:
widget = gtk_label_new ("bla");
break;
case 3:
widget = gtk_label_new ("bla");
sensitive = FALSE;
break;
}
gtk_container_add (GTK_CONTAINER (box), widget);
if (i % 5 == 0)
gtk_container_add (GTK_CONTAINER (box), gtk_switch_new ());
gtk_widget_show_all (frame);
gtk_container_add (GTK_CONTAINER (flowbox), frame);
if (!sensitive)
gtk_widget_set_sensitive (gtk_widget_get_parent (frame), FALSE);
}
}
static void
populate_flowbox_wrappy (GtkFlowBox *flowbox)
{
GtkWidget *widget, *frame;
gint i;
const gchar *strings[] = {
"These are", "some wrappy label", "texts", "of various", "lengths.",
"They should always be", "shown", "consecutively. Except it's",
"hard to say", "where exactly the", "label", "will wrap", "and where exactly",
"the actual", "container", "will wrap.", "This label is really really really long !",
"Let's add some more", "labels to the",
"mix. Just to", "make sure we", "got something to work", "with here."
};
for (i = 0; i < G_N_ELEMENTS (strings); i++)
{
widget = gtk_label_new (strings[i]);
frame = gtk_frame_new (NULL);
gtk_widget_show (widget);
gtk_widget_show (frame);
if (text_orientation == GTK_ORIENTATION_VERTICAL)
gtk_label_set_angle (GTK_LABEL (widget), 90);
gtk_container_add (GTK_CONTAINER (frame), widget);
gtk_label_set_line_wrap (GTK_LABEL (widget), TRUE);
gtk_label_set_line_wrap_mode (GTK_LABEL (widget), PANGO_WRAP_WORD);
gtk_label_set_width_chars (GTK_LABEL (widget), 10);
g_object_set_data_full (G_OBJECT (frame), "id", (gpointer)g_strdup (strings[i]), g_free);
gtk_container_add (GTK_CONTAINER (flowbox), frame);
}
}
static void
populate_flowbox_stock (GtkFlowBox *flowbox)
{
GtkWidget *widget;
static GSList *stock_ids = NULL;
GSList *l;
gint i;
if (!stock_ids)
stock_ids = gtk_stock_list_ids ();
for (i = 0, l = stock_ids; i < 30 && l != NULL; i++, l = l->next)
{
gchar *stock_id = l->data;
gchar *text = g_strdup_printf ("Item %02d", i);
widget = gtk_button_new_from_stock (stock_id);
gtk_widget_show (widget);
g_object_set_data_full (G_OBJECT (widget), "id", (gpointer)g_strdup (text), g_free);
gtk_container_add (GTK_CONTAINER (flowbox), widget);
}
}
static void
populate_flowbox_images (GtkFlowBox *flowbox)
{
GtkWidget *widget, *image, *label;
gint i;
for (i = 0; i < N_ITEMS; i++)
{
gchar *text = g_strdup_printf ("Item %02d", i);
widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
gtk_widget_set_hexpand (widget, TRUE);
image = gtk_image_new_from_icon_name ("face-wink", GTK_ICON_SIZE_DIALOG);
gtk_widget_set_hexpand (image, TRUE);
gtk_image_set_pixel_size (GTK_IMAGE (image), 256);
label = gtk_label_new (text);
gtk_container_add (GTK_CONTAINER (widget), image);
gtk_container_add (GTK_CONTAINER (widget), label);
gtk_widget_show_all (widget);
if (text_orientation == GTK_ORIENTATION_VERTICAL)
gtk_label_set_angle (GTK_LABEL (widget), 90);
g_object_set_data_full (G_OBJECT (widget), "id", (gpointer)g_strdup (text), g_free);
gtk_container_add (GTK_CONTAINER (flowbox), widget);
g_free (text);
}
}
static void
populate_items (GtkFlowBox *flowbox)
{
GList *children, *l;
/* Remove all children first */
children = gtk_container_get_children (GTK_CONTAINER (flowbox));
for (l = children; l; l = l->next)
{
GtkWidget *child = l->data;
gtk_container_remove (GTK_CONTAINER (flowbox), child);
}
g_list_free (children);
if (items_type == SIMPLE_ITEMS)
populate_flowbox_simple (flowbox);
else if (items_type == FOCUS_ITEMS)
populate_flowbox_focus (flowbox);
else if (items_type == WRAPPY_ITEMS)
populate_flowbox_wrappy (flowbox);
else if (items_type == STOCK_ITEMS)
populate_flowbox_stock (flowbox);
else if (items_type == IMAGE_ITEMS)
populate_flowbox_images (flowbox);
}
static void
horizontal_alignment_changed (GtkComboBox *box,
GtkFlowBox *flowbox)
{
GtkAlign alignment = gtk_combo_box_get_active (box);
gtk_widget_set_halign (GTK_WIDGET (flowbox), alignment);
}
static void
vertical_alignment_changed (GtkComboBox *box,
GtkFlowBox *flowbox)
{
GtkAlign alignment = gtk_combo_box_get_active (box);
gtk_widget_set_valign (GTK_WIDGET (flowbox), alignment);
}
static void
orientation_changed (GtkComboBox *box,
GtkFlowBox *flowbox)
{
GtkOrientation orientation = gtk_combo_box_get_active (box);
gtk_orientable_set_orientation (GTK_ORIENTABLE (flowbox), orientation);
}
static void
selection_mode_changed (GtkComboBox *box,
GtkFlowBox *flowbox)
{
GtkSelectionMode mode = gtk_combo_box_get_active (box);
gtk_flow_box_set_selection_mode (flowbox, mode);
}
static void
line_length_changed (GtkSpinButton *spin,
GtkFlowBox *flowbox)
{
gint length = gtk_spin_button_get_value_as_int (spin);
gtk_flow_box_set_min_children_per_line (flowbox, length);
}
static void
max_line_length_changed (GtkSpinButton *spin,
GtkFlowBox *flowbox)
{
gint length = gtk_spin_button_get_value_as_int (spin);
gtk_flow_box_set_max_children_per_line (flowbox, length);
}
static void
spacing_changed (GtkSpinButton *button,
gpointer data)
{
GtkOrientation orientation = GPOINTER_TO_INT (data);
gint state = gtk_spin_button_get_value_as_int (button);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
gtk_flow_box_set_column_spacing (the_flowbox, state);
else
gtk_flow_box_set_row_spacing (the_flowbox, state);
}
static void
items_changed (GtkComboBox *box,
GtkFlowBox *flowbox)
{
items_type = gtk_combo_box_get_active (box);
populate_items (flowbox);
}
static void
text_orientation_changed (GtkComboBox *box,
GtkFlowBox *flowbox)
{
text_orientation = gtk_combo_box_get_active (box);
populate_items (flowbox);
}
static void
homogeneous_toggled (GtkToggleButton *button,
GtkFlowBox *flowbox)
{
gboolean state = gtk_toggle_button_get_active (button);
gtk_flow_box_set_homogeneous (flowbox, state);
}
static void
on_child_activated (GtkFlowBox *self,
GtkWidget *child)
{
const char *id;
id = g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (child))), "id");
g_message ("Child activated %p: %s", child, id);
}
static void
selection_foreach (GtkFlowBox *self,
GtkFlowBoxChild *child_info,
gpointer data)
{
const char *id;
GtkWidget *child;
child = gtk_bin_get_child (GTK_BIN (child_info));
id = g_object_get_data (G_OBJECT (child), "id");
g_message ("Child selected %p: %s", child, id);
}
static void
on_selected_children_changed (GtkFlowBox *self)
{
g_message ("Selection changed");
//gtk_flow_box_selected_foreach (self, selection_foreach, NULL);
}
static gboolean
filter_func (GtkFlowBoxChild *child, gpointer user_data)
{
gint index;
index = gtk_flow_box_child_get_index (child);
return (index % 3) == 0;
}
static void
filter_toggled (GtkToggleButton *button,
GtkFlowBox *flowbox)
{
gboolean state = gtk_toggle_button_get_active (button);
if (state)
gtk_flow_box_set_filter_func (flowbox, filter_func, NULL, NULL);
else
gtk_flow_box_set_filter_func (flowbox, NULL, NULL, NULL);
}
static gint
sort_func (GtkFlowBoxChild *a,
GtkFlowBoxChild *b,
gpointer data)
{
gchar *ida, *idb;
ida = (gchar *)g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (a))), "id");
idb = (gchar *)g_object_get_data (G_OBJECT (gtk_bin_get_child (GTK_BIN (b))), "id");
return g_strcmp0 (ida, idb);
}
static void
sort_toggled (GtkToggleButton *button,
GtkFlowBox *flowbox)
{
gboolean state = gtk_toggle_button_get_active (button);
if (state)
gtk_flow_box_set_sort_func (flowbox, sort_func, NULL, NULL);
else
gtk_flow_box_set_sort_func (flowbox, NULL, NULL, NULL);
}
static GtkWidget *
create_window (void)
{
GtkWidget *window, *hbox, *vbox, *flowbox_cntl, *items_cntl;
GtkWidget *flowbox, *widget, *expander, *swindow;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
gtk_container_set_border_width (GTK_CONTAINER (window), 8);
gtk_widget_show (vbox);
gtk_widget_show (hbox);
gtk_container_add (GTK_CONTAINER (window), hbox);
gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
swindow = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_widget_show (swindow);
gtk_box_pack_start (GTK_BOX (hbox), swindow, TRUE, TRUE, 0);
flowbox = gtk_flow_box_new ();
gtk_widget_set_halign (flowbox, GTK_ALIGN_END);
the_flowbox = (GtkFlowBox *)flowbox;
gtk_widget_set_halign (flowbox, INITIAL_HALIGN);
gtk_widget_set_valign (flowbox, INITIAL_VALIGN);
gtk_flow_box_set_column_spacing (GTK_FLOW_BOX (flowbox), INITIAL_CSPACING);
gtk_flow_box_set_row_spacing (GTK_FLOW_BOX (flowbox), INITIAL_RSPACING);
gtk_flow_box_set_min_children_per_line (GTK_FLOW_BOX (flowbox), INITIAL_MINIMUM_LENGTH);
gtk_flow_box_set_max_children_per_line (GTK_FLOW_BOX (flowbox), INITIAL_MAXIMUM_LENGTH);
gtk_widget_show (flowbox);
gtk_container_add (GTK_CONTAINER (swindow), flowbox);
gtk_flow_box_set_hadjustment (GTK_FLOW_BOX (flowbox),
gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (swindow)));
gtk_flow_box_set_vadjustment (GTK_FLOW_BOX (flowbox),
gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (swindow)));
g_signal_connect (flowbox, "child-activated", G_CALLBACK (on_child_activated), NULL);
g_signal_connect (flowbox, "selected-children-changed", G_CALLBACK (on_selected_children_changed), NULL);
/* Add Flowbox test control frame */
expander = gtk_expander_new ("Flow Box controls");
gtk_expander_set_expanded (GTK_EXPANDER (expander), TRUE);
flowbox_cntl = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
gtk_widget_show (flowbox_cntl);
gtk_widget_show (expander);
gtk_container_add (GTK_CONTAINER (expander), flowbox_cntl);
gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, FALSE, 0);
widget = gtk_check_button_new_with_label ("Homogeneous");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
gtk_widget_show (widget);
gtk_widget_set_tooltip_text (widget, "Set whether the items should be displayed at the same size");
gtk_box_pack_start (GTK_BOX (flowbox_cntl), widget, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (widget), "toggled",
G_CALLBACK (homogeneous_toggled), flowbox);
widget = gtk_check_button_new_with_label ("Activate on single click");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
g_object_bind_property (widget, "active",
flowbox, "activate-on-single-click",
G_BINDING_SYNC_CREATE);
gtk_widget_show (widget);
gtk_box_pack_start (GTK_BOX (flowbox_cntl), widget, FALSE, FALSE, 0);
/* Add alignment controls */
widget = gtk_combo_box_text_new ();
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Fill");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Start");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "End");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Center");
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), INITIAL_HALIGN);
gtk_widget_show (widget);
gtk_widget_set_tooltip_text (widget, "Set the horizontal alignment policy");
gtk_box_pack_start (GTK_BOX (flowbox_cntl), widget, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (horizontal_alignment_changed), flowbox);
widget = gtk_combo_box_text_new ();
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Fill");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Start");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "End");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Center");
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), INITIAL_VALIGN);
gtk_widget_show (widget);
gtk_widget_set_tooltip_text (widget, "Set the vertical alignment policy");
gtk_box_pack_start (GTK_BOX (flowbox_cntl), widget, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (vertical_alignment_changed), flowbox);
/* Add Orientation control */
widget = gtk_combo_box_text_new ();
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Horizontal");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Vertical");
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
gtk_widget_show (widget);
gtk_widget_set_tooltip_text (widget, "Set the flowbox orientation");
gtk_box_pack_start (GTK_BOX (flowbox_cntl), widget, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (orientation_changed), flowbox);
/* Add selection mode control */
widget = gtk_combo_box_text_new ();
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "None");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Single");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Browse");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Multiple");
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
gtk_widget_show (widget);
gtk_widget_set_tooltip_text (widget, "Set the selection mode");
gtk_box_pack_start (GTK_BOX (flowbox_cntl), widget, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (selection_mode_changed), flowbox);
/* Add minimum line length in items control */
widget = gtk_spin_button_new_with_range (1, 10, 1);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), INITIAL_MINIMUM_LENGTH);
gtk_widget_show (widget);
gtk_widget_set_tooltip_text (widget, "Set the minimum amount of items per line before wrapping");
gtk_box_pack_start (GTK_BOX (flowbox_cntl), widget, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (line_length_changed), flowbox);
g_signal_connect (G_OBJECT (widget), "value-changed",
G_CALLBACK (line_length_changed), flowbox);
/* Add natural line length in items control */
widget = gtk_spin_button_new_with_range (1, 10, 1);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), INITIAL_MAXIMUM_LENGTH);
gtk_widget_show (widget);
gtk_widget_set_tooltip_text (widget, "Set the natural amount of items per line ");
gtk_box_pack_start (GTK_BOX (flowbox_cntl), widget, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (max_line_length_changed), flowbox);
g_signal_connect (G_OBJECT (widget), "value-changed",
G_CALLBACK (max_line_length_changed), flowbox);
/* Add horizontal/vertical spacing controls */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
gtk_widget_show (hbox);
widget = gtk_label_new ("H Spacing");
gtk_widget_show (widget);
gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
widget = gtk_spin_button_new_with_range (0, 30, 1);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), INITIAL_CSPACING);
gtk_widget_show (widget);
gtk_widget_set_tooltip_text (widget, "Set the horizontal spacing between children");
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (spacing_changed), GINT_TO_POINTER (GTK_ORIENTATION_HORIZONTAL));
g_signal_connect (G_OBJECT (widget), "value-changed",
G_CALLBACK (spacing_changed), GINT_TO_POINTER (GTK_ORIENTATION_HORIZONTAL));
gtk_box_pack_start (GTK_BOX (flowbox_cntl), hbox, FALSE, FALSE, 0);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
gtk_widget_show (hbox);
widget = gtk_label_new ("V Spacing");
gtk_widget_show (widget);
gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
widget = gtk_spin_button_new_with_range (0, 30, 1);
gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), INITIAL_RSPACING);
gtk_widget_show (widget);
gtk_widget_set_tooltip_text (widget, "Set the vertical spacing between children");
gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (spacing_changed), GINT_TO_POINTER (GTK_ORIENTATION_VERTICAL));
g_signal_connect (G_OBJECT (widget), "value-changed",
G_CALLBACK (spacing_changed), GINT_TO_POINTER (GTK_ORIENTATION_VERTICAL));
gtk_box_pack_start (GTK_BOX (flowbox_cntl), hbox, FALSE, FALSE, 0);
/* filtering and sorting */
widget = gtk_check_button_new_with_label ("Filter");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
gtk_widget_show (widget);
gtk_widget_set_tooltip_text (widget, "Set whether some items should be filtered out");
gtk_box_pack_start (GTK_BOX (flowbox_cntl), widget, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (widget), "toggled",
G_CALLBACK (filter_toggled), flowbox);
widget = gtk_check_button_new_with_label ("Sort");
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
gtk_widget_show (widget);
gtk_widget_set_tooltip_text (widget, "Set whether items should be sorted");
gtk_box_pack_start (GTK_BOX (flowbox_cntl), widget, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (widget), "toggled",
G_CALLBACK (sort_toggled), flowbox);
/* Add test items control frame */
expander = gtk_expander_new ("Test item controls");
gtk_expander_set_expanded (GTK_EXPANDER (expander), TRUE);
items_cntl = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
gtk_widget_show (items_cntl);
gtk_widget_show (expander);
gtk_container_add (GTK_CONTAINER (expander), items_cntl);
gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, FALSE, 0);
/* Add Items control */
widget = gtk_combo_box_text_new ();
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Simple");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Focus");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Wrappy");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Stock");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Images");
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
gtk_widget_show (widget);
gtk_widget_set_tooltip_text (widget, "Set the item set to use");
gtk_box_pack_start (GTK_BOX (items_cntl), widget, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (items_changed), flowbox);
/* Add Text Orientation control */
widget = gtk_combo_box_text_new ();
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Horizontal");
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Vertical");
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0);
gtk_widget_show (widget);
gtk_widget_set_tooltip_text (widget, "Set the item's text orientation (cant be done for stock buttons)");
gtk_box_pack_start (GTK_BOX (items_cntl), widget, FALSE, FALSE, 0);
g_signal_connect (G_OBJECT (widget), "changed",
G_CALLBACK (text_orientation_changed), flowbox);
populate_items (GTK_FLOW_BOX (flowbox));
/* This line was added only for the convenience of reproducing
* a height-for-width inside GtkScrolledWindow bug (bug 629778).
* -Tristan
*/
gtk_window_set_default_size (GTK_WINDOW (window), 390, -1);
return window;
}
int
main (int argc, char *argv[])
{
GtkWidget *window;
gtk_init (&argc, &argv);
window = create_window ();
g_signal_connect (window, "delete-event",
G_CALLBACK (gtk_main_quit), window);
gtk_widget_show (window);
gtk_main ();
return 0;
}