Compare commits

..

3 Commits

Author SHA1 Message Date
Matthias Clasen
ef6456261e meson: Cosmetics
Treat the display backend list like other lists in the summary.
2020-05-30 01:42:38 -04:00
Matthias Clasen
a1eefc2b39 Bump the pango dependency
We soon want to rely on the list model apis in
pango 1.45. This commit also fixes a mixup where
using pango as a submodule would break the build
when pangoft2 is required.
2020-05-30 01:38:30 -04:00
Matthias Clasen
db506cc479 test change 2020-05-30 01:23:03 -04:00
636 changed files with 33704 additions and 178823 deletions

View File

@@ -17,12 +17,7 @@ stages:
# Common variables
variables:
COMMON_MESON_FLAGS: "--fatal-meson-warnings --werror"
BACKEND_FLAGS: "-Dx11-backend=true -Dwayland-backend=true -Dbroadway-backend=true -Dvulkan=yes"
FEATURE_FLAGS: "-Dcloudproviders=true"
MESON_TEST_TIMEOUT_MULTIPLIER: 2
FEDORA_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora:v17"
FLATPAK_IMAGE: "registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master"
DOCS_IMAGE: "registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v19"
.only-default:
only:
@@ -32,14 +27,14 @@ variables:
style-check-diff:
extends: .only-default
image: $FEDORA_IMAGE
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v17
stage: .pre
allow_failure: true
script:
- .gitlab-ci/run-style-check-diff.sh
.build-fedora-default:
image: $FEDORA_IMAGE
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v17
artifacts:
when: always
reports:
@@ -71,7 +66,11 @@ fedora-x86_64:
variables:
EXTRA_MESON_FLAGS: "--buildtype=debug --default-library=both"
script:
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS}
-Dx11-backend=true
-Dwayland-backend=true
-Dbroadway-backend=true
-Dvulkan=yes
-Dprofiler=true
_build
- ninja -C _build
@@ -85,7 +84,11 @@ release-build:
variables:
EXTRA_MESON_FLAGS: "--buildtype=release"
script:
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS} ${BACKEND_FLAGS} ${FEATURE_FLAGS}
- meson ${COMMON_MESON_FLAGS} ${EXTRA_MESON_FLAGS}
-Dx11-backend=true
-Dwayland-backend=true
-Dbroadway-backend=true
-Dvulkan=yes
_build
- ninja -C _build
- .gitlab-ci/run-tests.sh _build x11
@@ -107,14 +110,14 @@ release-build:
- subprojects/libepoxy/
- subprojects/pango/
msys2-mingw64:
msys2-mingw32:
extends: .mingw-defaults
variables:
MSYSTEM: "MINGW64"
MSYSTEM: "MINGW32"
CHERE_INVOKING: "yes"
.flatpak-defaults:
image: $FLATPAK_IMAGE
image: registry.gitlab.gnome.org/gnome/gnome-runtime-images/gnome:master
stage: flatpak
allow_failure: true
tags:
@@ -168,7 +171,7 @@ flatpak-master:icon-browser:
APPID: org.gtk.IconBrowser4
static-scan:
image: $FEDORA_IMAGE
image: registry.gitlab.gnome.org/gnome/gtk/fedora:v16
stage: analysis
variables:
EXTRA_MESON_FLAGS: "--buildtype=debug"
@@ -181,7 +184,7 @@ static-scan:
allow_failure: true
reference:
image: $DOCS_IMAGE
image: registry.gitlab.gnome.org/gnome/gtk/fedora-docs:v19
stage: docs
variables:
EXTRA_MESON_FLAGS: "--buildtype=release"

View File

@@ -4,15 +4,8 @@ set -e
# We need to add a new remote for the upstream master, since this script could
# be running in a personal fork of the repository which has out of date branches.
if [ "${CI_PROJECT_NAMESPACE}" != "GNOME" ]; then
echo "Retrieving the current upstream repository from ${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}..."
git remote add upstream https://gitlab.gnome.org/GNOME/gtk.git
git fetch upstream
ORIGIN="upstream"
else
echo "Reusing the existing repository on ${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}"
ORIGIN="origin"
fi
git remote add upstream https://gitlab.gnome.org/GNOME/gtk.git
git fetch upstream
# Work out the newest common ancestor between the detached HEAD that this CI job
# has checked out, and the upstream target branch (which will typically be
@@ -20,7 +13,7 @@ fi
#
# `${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}` is only defined if were running in
# a merge request pipeline; fall back to `${CI_DEFAULT_BRANCH}` otherwise.
newest_common_ancestor_sha=$(diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "${ORIGIN}/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}") <(git rev-list --first-parent HEAD) | head -1)
newest_common_ancestor_sha=$(diff --old-line-format='' --new-line-format='' <(git rev-list --first-parent "upstream/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-${CI_DEFAULT_BRANCH}}") <(git rev-list --first-parent HEAD) | head -1)
git diff -U0 --no-color "${newest_common_ancestor_sha}" | .gitlab-ci/clang-format-diff.py -binary "clang-format" -p1
exit_status=$?

View File

@@ -34,8 +34,8 @@ pacman --noconfirm -S --needed \
mingw-w64-$MSYS2_ARCH-shared-mime-info
# https://gitlab.gnome.org/GNOME/gtk/issues/2243
wget "https://gitlab.gnome.org/creiter/gitlab-ci-win32-runner-v2/raw/master/pango/mingw-w64-$MSYS2_ARCH-pango-git-1.44.7.90.ge48ae523-1-any.pkg.tar.zst"
pacman --noconfirm -U "mingw-w64-$MSYS2_ARCH-pango-git-1.44.7.90.ge48ae523-1-any.pkg.tar.zst"
wget "https://gitlab.gnome.org/creiter/gitlab-ci-win32-runner-v2/raw/master/pango/mingw-w64-$MSYS2_ARCH-pango-1.44.7-1-any.pkg.tar.xz"
pacman --noconfirm -U "mingw-w64-$MSYS2_ARCH-pango-1.44.7-1-any.pkg.tar.xz"
# https://github.com/msys2/MINGW-packages/pull/6465
pacman --noconfirm -S --needed mingw-w64-$MSYS2_ARCH-brotli

90
NEWS
View File

@@ -1,95 +1,7 @@
Overview of Changes in GTK 3.98.5
=================================
* Introduce new list widgets and supporting infrastructure.
The main APIs are:
- GtkListView
- GtkGridView
- GtkColumnView and GtkColumnViewColumn
- GtkDropDown
- GtkListItemFactory and implementations
- GtkExpression
- GtkFilter and subclasses, and GtkFilterListModel
- GtkSorter and subclasses, and GtkSortListModel
- GtkSelectionModel and subclasses
- GtkTreeListModel, GtkTreeExpander and GtkTreeListRowSorter
* GtkFileChooser:
- Add a tracker3-based search engine implementation
- Rate-limit updates from the trash monitor
* GtkWindow:
- Redo the css node setup. There is now a single 'window' node
- Fix rounded corners on tiled windows
* GtkApplication:
- Drop app menu support. Menubar support is still there
* GtkFixed:
- Change coordinate APIs to take doubles
* GtkOverlay:
- Make GtkOverlayLayout public
* GtkTooltips:
- Fix line wrapping of tooltips
* Shortcuts:
- Fix mnemonic cycling
- Fix using '0' as a mnemonic
* Menus:
- Differentiate keypad keys in accelerators
* GtkIMContext:
- Add gtk_im_context_filter_key to allow event reinjection
* Themes:
- Adwaita: Limit the scope of backdrop
* Accessibility:
- Clean up and reorganize the code to prepare for the
dropping of ATK
* GDK:
- Drop unused enum and struct definitions from headers
- Make keymap translation API public again. Still needed
- Frameclock: Always use compositor refresh rate info
- Frameclock: Use quadratic correction for frame time jitter
- Frameclock: Ensure monotonicity
- Frameclock: Track resason for paint
- X11: Improve sync when the Nvidia driver is used
* GSK:
- GL renderer: Fix blurred outset shadows
- GL renderer: handle nested transform nodes properly
- GL renderer: Optimize clip handling
* gtk-demo:
- Improve the Drag-and-Drop demo with proper drag icons
- Don't show the main window if --run is given
- Add demos for list widgets and GtkDropDrown
* Documentation:
- Convert freestanding sections to markdown
- Drop the glossary
- Expand and improve the migration guide
* Build:
- We require pandoc now, for building the documentation
- Require Pango 1.45
* Translation updates:
Polish
Romanian
Slovenian
Turkish
Ukrainian
Overview of Changes in GTK 3.98.4
=================================
* Themes
- Refine menu styling
- Tweak visible focus behavior

View File

@@ -27,6 +27,14 @@
/* Define to 1 if you have the `dcgettext' function. */
#mesondefine HAVE_DCGETTEXT
/* Define to 1 if you have the declaration of `isinf', and to 0 if you don't.
*/
#mesondefine HAVE_DECL_ISINF
/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
*/
#mesondefine HAVE_DECL_ISNAN
/* Define to 1 if you have the <dlfcn.h> header file. */
#mesondefine HAVE_DLFCN_H
@@ -72,6 +80,9 @@
/* Define to 1 if you have a working `mmap' system call. */
#mesondefine HAVE_MMAP
/* Define to 1 if you have the `nearbyint' function. */
#mesondefine HAVE_NEARBYINT
/* Define to 1 if you have the `posix_fallocate' function. */
#mesondefine HAVE_POSIX_FALLOCATE
@@ -81,9 +92,21 @@
/* Have the Xrandr 1.5 extension library */
#mesondefine HAVE_RANDR15
/* Define to 1 if you have the `rint' function. */
#mesondefine HAVE_RINT
/* Define to 1 if you have the `round' function. */
#mesondefine HAVE_ROUND
/* Define to 1 if you have the `sincos' function. */
#mesondefine HAVE_SINCOS
/* Define to 1 if you have the `log2` function */
#mesondefine HAVE_LOG2
/* Define to 1 if you ahve the `exp2` function */
#mesondefine HAVE_EXP2
/* Define to 1 if you have the <stdint.h> header file. */
#mesondefine HAVE_STDINT_H
@@ -123,9 +146,6 @@
/* Have the Xcursor library */
#mesondefine HAVE_XCURSOR
/* Have the XDAMAGE X extension */
#mesondefine HAVE_XDAMAGE
/* Have the XFIXES X extension */
#mesondefine HAVE_XFIXES
@@ -274,4 +294,4 @@
#mesondefine ISO_CODES_PREFIX
/* Define if tracker3 is available */
#mesondefine HAVE_TRACKER3
#mesondefine HAVE_TRACKER3

View File

@@ -169,7 +169,6 @@ constraint_view_init (ConstraintView *self)
GListModel *guides;
GListModel *children;
GListModel *constraints;
GtkFilter *filter;
manager = gtk_constraint_layout_new ();
gtk_widget_set_layout_manager (GTK_WIDGET (self), manager);
@@ -177,12 +176,8 @@ constraint_view_init (ConstraintView *self)
all_children = gtk_widget_observe_children (GTK_WIDGET (self));
all_constraints = gtk_constraint_layout_observe_constraints (GTK_CONSTRAINT_LAYOUT (manager));
guides = gtk_constraint_layout_observe_guides (GTK_CONSTRAINT_LAYOUT (manager));
filter = gtk_custom_filter_new (omit_internal, NULL, NULL);
constraints = (GListModel *)gtk_filter_list_model_new (all_constraints, filter);
g_object_unref (filter);
filter = gtk_custom_filter_new (omit_internal, NULL, NULL);
children = (GListModel *)gtk_filter_list_model_new (all_children, filter);
g_object_unref (filter);
constraints = (GListModel *)gtk_filter_list_model_new (all_constraints, omit_internal, NULL, NULL);
children = (GListModel *)gtk_filter_list_model_new (all_children, omit_internal, NULL, NULL);
list = g_list_store_new (G_TYPE_LIST_MODEL);
g_list_store_append (list, children);

View File

@@ -184,6 +184,58 @@ max_input (GtkSpinButton *spin_button,
return FALSE;
}
static gboolean
min_output (GtkSpinButton *spin_button)
{
GtkAdjustment *adjustment;
double value;
GtkWidget *box, *text;
adjustment = gtk_spin_button_get_adjustment (spin_button);
value = gtk_adjustment_get_value (adjustment);
box = gtk_widget_get_first_child (GTK_WIDGET (spin_button));
text = gtk_widget_get_first_child (box);
if (value == 0.0)
{
gtk_editable_set_text (GTK_EDITABLE (spin_button), "");
gtk_text_set_placeholder_text (GTK_TEXT (text), "unset");
return TRUE;
}
else
{
gtk_text_set_placeholder_text (GTK_TEXT (text), "");
return FALSE;
}
}
static gboolean
max_output (GtkSpinButton *spin_button)
{
GtkAdjustment *adjustment;
double value;
GtkWidget *box, *text;
adjustment = gtk_spin_button_get_adjustment (spin_button);
value = gtk_adjustment_get_value (adjustment);
box = gtk_widget_get_first_child (GTK_WIDGET (spin_button));
text = gtk_widget_get_first_child (box);
if (value == (double)G_MAXINT)
{
gtk_editable_set_text (GTK_EDITABLE (spin_button), "");
gtk_text_set_placeholder_text (GTK_TEXT (text), "unset");
return TRUE;
}
else
{
gtk_text_set_placeholder_text (GTK_TEXT (text), "");
return FALSE;
}
}
static void
guide_editor_constructed (GObject *object)
{
@@ -192,12 +244,16 @@ guide_editor_constructed (GObject *object)
guide_strength_combo (editor->strength);
g_signal_connect (editor->min_width, "input", G_CALLBACK (min_input), NULL);
g_signal_connect (editor->min_width, "output", G_CALLBACK (min_output), NULL);
g_signal_connect (editor->min_height, "input", G_CALLBACK (min_input), NULL);
g_signal_connect (editor->min_height, "output", G_CALLBACK (min_output), NULL);
g_signal_connect (editor->max_width, "input", G_CALLBACK (max_input), NULL);
g_signal_connect (editor->max_width, "output", G_CALLBACK (max_output), NULL);
g_signal_connect (editor->max_height, "input", G_CALLBACK (max_input), NULL);
g_signal_connect (editor->max_height, "output", G_CALLBACK (max_output), NULL);
if (editor->guide)
{

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/* Constraints/Interactive
*
* Demonstrate how constraints can be updates during user interaction.
* The vertical edge between the buttons can be dragged with the mouse.
* Demonstrate how constraints can be updates during
* user interaction.
*/
#include <glib/gi18n.h>

View File

@@ -94,7 +94,7 @@ do_css_basics (GtkWidget *do_widget)
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
container = gtk_scrolled_window_new ();
container = gtk_scrolled_window_new (NULL, NULL);
gtk_window_set_child (GTK_WINDOW (window), container);
child = gtk_text_view_new_with_buffer (text);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (container), child);

View File

@@ -132,7 +132,7 @@ do_css_multiplebgs (GtkWidget *do_widget)
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_paned_set_end_child (GTK_PANED (paned), sw);
child = gtk_text_view_new_with_buffer (text);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), child);

View File

@@ -101,7 +101,7 @@ do_css_pixbufs (GtkWidget *do_widget)
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
container = gtk_scrolled_window_new ();
container = gtk_scrolled_window_new (NULL, NULL);
gtk_paned_set_end_child (GTK_PANED (paned), container);
child = gtk_text_view_new_with_buffer (text);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (container), child);

View File

@@ -119,7 +119,7 @@ do_css_shadows (GtkWidget *do_widget)
provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
container = gtk_scrolled_window_new ();
container = gtk_scrolled_window_new (NULL, NULL);
gtk_paned_set_end_child (GTK_PANED (paned), container);
child = gtk_text_view_new_with_buffer (text);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (container), child);

View File

@@ -1,8 +1,9 @@
/* Cursors
*
* Demonstrates a useful set of available cursors. The cursors shown here are the
* ones defined by CSS, which we assume to be available. The example shows creating
* cursors by name or from an image, with or without a fallback.
* Demonstrates a useful set of available cursors. The cursors shown here are the ones
* defined by CSS, which we assume to be available.
*
* The example shows creating cursors by name or from an image, with or without a fallback.
*/
#include <gtk/gtk.h>

View File

@@ -1,10 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/">
</gresource>
<gresource prefix="/ui">
<file preprocess="xml-stripblanks">main.ui</file>
<file preprocess="xml-stripblanks">main-listitem.ui</file>
</gresource>
<gresource prefix="/application_demo">
<file>application.c</file>
@@ -105,9 +102,6 @@
<file>zoom_in_cursor.png</file>
<file>zoom_out_cursor.png</file>
</gresource>
<gresource prefix="/dnd">
<file>dnd.css</file>
</gresource>
<gresource prefix="/fishbowl">
<file>fishbowl.ui</file>
<file>gtkfishbowl.c</file>
@@ -124,23 +118,6 @@
<file>gnome-fs-directory.png</file>
<file>gnome-fs-regular.png</file>
</gresource>
<gresource prefix="/listview_filebrowser">
<file>listview_filebrowser.ui</file>
<file>listview_filebrowser.css</file>
</gresource>
<gresource prefix="/listview_minesweeper">
<file>listview_minesweeper.ui</file>
<file>listview_minesweeper_cell.ui</file>
</gresource>
<gresource prefix="/listview_settings">
<file>listview_settings.ui</file>
</gresource>
<gresource prefix="/listview_weather">
<file compressed="true">listview_weather.txt</file>
</gresource>
<gresource prefix="/listview_colors">
<file compressed="true">color.names.txt</file>
</gresource>
<gresource prefix="/shortcuts">
<file>shortcuts.ui</file>
<file>shortcuts-builder.ui</file>
@@ -193,7 +170,6 @@
<file>cursors.c</file>
<file>dialog.c</file>
<file>drawingarea.c</file>
<file>dropdown.c</file>
<file>dnd.c</file>
<file>editable_cells.c</file>
<file>entry_completion.c</file>
@@ -218,14 +194,6 @@
<file>infobar.c</file>
<file>links.c</file>
<file>listbox.c</file>
<file>listview_applauncher.c</file>
<file>listview_colors.c</file>
<file>listview_clocks.c</file>
<file>listview_filebrowser.c</file>
<file>listview_minesweeper.c</file>
<file>listview_settings.c</file>
<file>listview_weather.c</file>
<file>listview_words.c</file>
<file>list_store.c</file>
<file>markup.c</file>
<file>modelbutton.c</file>
@@ -300,7 +268,6 @@
</gresource>
<gresource prefix="/transparent">
<file>portland-rose.jpg</file>
<file>bluroverlay.h</file>
<file>bluroverlay.c</file>
</gresource>
<gresource prefix="/markup">

View File

@@ -25,36 +25,31 @@
#include <gtk/gtk.h>
#include <gtk/gtk-a11y.h>
struct _DemoTaggedEntry
{
GtkWidget parent_instance;
typedef struct {
GtkWidget *box;
GtkWidget *entry;
};
struct _DemoTaggedEntryClass
{
GtkWidgetClass parent_class;
};
} DemoTaggedEntryPrivate;
static void demo_tagged_entry_editable_init (GtkEditableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (DemoTaggedEntry, demo_tagged_entry, GTK_TYPE_WIDGET,
G_ADD_PRIVATE (DemoTaggedEntry)
G_IMPLEMENT_INTERFACE (GTK_TYPE_EDITABLE, demo_tagged_entry_editable_init))
static void
demo_tagged_entry_init (DemoTaggedEntry *entry)
{
entry->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_parent (entry->box, GTK_WIDGET (entry));
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
entry->entry = gtk_text_new ();
gtk_widget_set_hexpand (entry->entry, TRUE);
gtk_widget_set_vexpand (entry->entry, TRUE);
gtk_widget_set_hexpand (entry->box, FALSE);
gtk_widget_set_vexpand (entry->box, FALSE);
gtk_box_append (GTK_BOX (entry->box), entry->entry);
priv->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_parent (priv->box, GTK_WIDGET (entry));
priv->entry = gtk_text_new ();
gtk_widget_set_hexpand (priv->entry, TRUE);
gtk_widget_set_vexpand (priv->entry, TRUE);
gtk_widget_set_hexpand (priv->box, FALSE);
gtk_widget_set_vexpand (priv->box, FALSE);
gtk_box_append (GTK_BOX (priv->box), priv->entry);
gtk_editable_init_delegate (GTK_EDITABLE (entry));
}
@@ -62,16 +57,23 @@ static void
demo_tagged_entry_dispose (GObject *object)
{
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (object);
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
if (entry->entry)
if (priv->entry)
gtk_editable_finish_delegate (GTK_EDITABLE (entry));
g_clear_pointer (&entry->entry, gtk_widget_unparent);
g_clear_pointer (&entry->box, gtk_widget_unparent);
g_clear_pointer (&priv->entry, gtk_widget_unparent);
g_clear_pointer (&priv->box, gtk_widget_unparent);
G_OBJECT_CLASS (demo_tagged_entry_parent_class)->dispose (object);
}
static void
demo_tagged_entry_finalize (GObject *object)
{
G_OBJECT_CLASS (demo_tagged_entry_parent_class)->finalize (object);
}
static void
demo_tagged_entry_set_property (GObject *object,
guint prop_id,
@@ -96,12 +98,44 @@ demo_tagged_entry_get_property (GObject *object,
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
static void
demo_tagged_entry_measure (GtkWidget *widget,
GtkOrientation orientation,
int for_size,
int *minimum,
int *natural,
int *minimum_baseline,
int *natural_baseline)
{
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
gtk_widget_measure (priv->box, orientation, for_size,
minimum, natural,
minimum_baseline, natural_baseline);
}
static void
demo_tagged_entry_size_allocate (GtkWidget *widget,
int width,
int height,
int baseline)
{
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
gtk_widget_size_allocate (priv->box,
&(GtkAllocation) { 0, 0, width, height },
baseline);
}
static gboolean
demo_tagged_entry_grab_focus (GtkWidget *widget)
{
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (widget);
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
return gtk_widget_grab_focus (entry->entry);
return gtk_widget_grab_focus (priv->entry);
}
static void
@@ -111,14 +145,16 @@ demo_tagged_entry_class_init (DemoTaggedEntryClass *klass)
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->dispose = demo_tagged_entry_dispose;
object_class->finalize = demo_tagged_entry_finalize;
object_class->get_property = demo_tagged_entry_get_property;
object_class->set_property = demo_tagged_entry_set_property;
widget_class->measure = demo_tagged_entry_measure;
widget_class->size_allocate = demo_tagged_entry_size_allocate;
widget_class->grab_focus = demo_tagged_entry_grab_focus;
gtk_editable_install_properties (object_class, 1);
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_ENTRY_ACCESSIBLE);
gtk_widget_class_set_css_name (widget_class, "entry");
}
@@ -126,7 +162,10 @@ demo_tagged_entry_class_init (DemoTaggedEntryClass *klass)
static GtkEditable *
demo_tagged_entry_get_delegate (GtkEditable *editable)
{
return GTK_EDITABLE (DEMO_TAGGED_ENTRY (editable)->entry);
DemoTaggedEntry *entry = DEMO_TAGGED_ENTRY (editable);
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
return GTK_EDITABLE (priv->entry);
}
static void
@@ -145,9 +184,11 @@ void
demo_tagged_entry_add_tag (DemoTaggedEntry *entry,
GtkWidget *tag)
{
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
gtk_box_append (GTK_BOX (entry->box), tag);
gtk_box_append (GTK_BOX (priv->box), tag);
}
void
@@ -155,27 +196,30 @@ demo_tagged_entry_insert_tag_after (DemoTaggedEntry *entry,
GtkWidget *tag,
GtkWidget *sibling)
{
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
if (sibling == NULL)
gtk_box_append (GTK_BOX (entry->box), tag);
gtk_box_append (GTK_BOX (priv->box), tag);
else
gtk_box_insert_child_after (GTK_BOX (entry->box), tag, sibling);
gtk_box_insert_child_after (GTK_BOX (priv->box), tag, sibling);
}
void
demo_tagged_entry_remove_tag (DemoTaggedEntry *entry,
GtkWidget *tag)
{
DemoTaggedEntryPrivate *priv = demo_tagged_entry_get_instance_private (entry);
g_return_if_fail (DEMO_IS_TAGGED_ENTRY (entry));
gtk_box_remove (GTK_BOX (entry->box), tag);
gtk_box_remove (GTK_BOX (priv->box), tag);
}
struct _DemoTaggedEntryTag
{
GtkWidget parent;
GtkWidget *box;
GtkWidget *label;
GtkWidget *button;
@@ -206,11 +250,11 @@ static guint signals[LAST_SIGNAL] = { 0, };
G_DEFINE_TYPE (DemoTaggedEntryTag, demo_tagged_entry_tag, GTK_TYPE_WIDGET)
static void
on_released (GtkGestureClick *gesture,
int n_press,
double x,
double y,
DemoTaggedEntryTag *tag)
on_released (GtkGestureClick *gesture,
int n_press,
double x,
double y,
DemoTaggedEntryTag *tag)
{
g_signal_emit (tag, signals[SIGNAL_CLICKED], 0);
}
@@ -425,7 +469,7 @@ demo_tagged_entry_tag_set_has_close_button (DemoTaggedEntryTag *tag,
image = gtk_image_new_from_icon_name ("window-close-symbolic");
tag->button = gtk_button_new ();
gtk_button_set_child (GTK_BUTTON (tag->button), image);
gtk_box_append (GTK_BOX (tag->button), image);
gtk_widget_set_halign (tag->button, GTK_ALIGN_CENTER);
gtk_widget_set_valign (tag->button, GTK_ALIGN_CENTER);
gtk_button_set_has_frame (GTK_BUTTON (tag->button), FALSE);

View File

@@ -25,11 +25,39 @@
G_BEGIN_DECLS
#define DEMO_TYPE_TAGGED_ENTRY (demo_tagged_entry_get_type ())
G_DECLARE_FINAL_TYPE (DemoTaggedEntry, demo_tagged_entry, DEMO, TAGGED_ENTRY, GtkWidget)
#define DEMO_TYPE_TAGGED_ENTRY (demo_tagged_entry_get_type ())
#define DEMO_TAGGED_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DEMO_TYPE_TAGGED_ENTRY, DemoTaggedEntry))
#define DEMO_TAGGED_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DEMO_TYPE_TAGGED_ENTRY, DemoTaggedEntryClass))
#define DEMO_IS_TAGGED_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DEMO_TYPE_TAGGED_ENTRY))
#define DEMO_IS_TAGGED_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DEMO_TYPE_TAGGED_ENTRY))
#define DEMO_TAGGED_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEMO_TYPE_TAGGED_ENTRY, DemoTaggedEntryClass))
#define DEMO_TYPE_TAGGED_ENTRY_TAG (demo_tagged_entry_tag_get_type ())
G_DECLARE_FINAL_TYPE (DemoTaggedEntryTag, demo_tagged_entry_tag, DEMO, TAGGED_ENTRY_TAG, GtkWidget)
typedef struct _DemoTaggedEntry DemoTaggedEntry;
typedef struct _DemoTaggedEntryClass DemoTaggedEntryClass;
struct _DemoTaggedEntry
{
GtkWidget parent;
};
struct _DemoTaggedEntryClass
{
GtkWidgetClass parent_class;
};
#define DEMO_TYPE_TAGGED_ENTRY_TAG (demo_tagged_entry_tag_get_type ())
#define DEMO_TAGGED_ENTRY_TAG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTag))
#define DEMO_TAGGED_ENTRY_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTag))
#define DEMO_IS_TAGGED_ENTRY_TAG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DEMO_TYPE_TAGGED_ENTRY_TAG))
#define DEMO_IS_TAGGED_ENTRY_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DEMO_TYPE_TAGGED_ENTRY_TAG))
#define DEMO_TAGGED_ENTRY_TAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEMO_TYPE_TAGGED_ENTRY_TAG, DemoTaggedEntryTagClass))
typedef struct _DemoTaggedEntryTag DemoTaggedEntryTag;
typedef struct _DemoTaggedEntryTagClass DemoTaggedEntryTagClass;
GType demo_tagged_entry_get_type (void) G_GNUC_CONST;
GType demo_tagged_entry_tag_get_type (void) G_GNUC_CONST;
GtkWidget * demo_tagged_entry_new (void);

View File

@@ -1,7 +1,6 @@
/* Dialogs
/* Dialogs and Message Boxes
*
* Dialogs are used to pop up transient windows for information
* and user feedback.
* Dialog widgets are used to pop up a transient window for user feedback.
*/
#include <glib/gi18n.h>
@@ -22,9 +21,10 @@ message_dialog_clicked (GtkButton *button,
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK_CANCEL,
"Test message");
"This message box has been popped up the following\n"
"number of times:");
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
ngettext ("Has been shown once", "Has been shown %d times", i), i);
"%d", i);
g_signal_connect (dialog, "response", G_CALLBACK (gtk_window_destroy), NULL);
gtk_widget_show (dialog);
i++;
@@ -61,6 +61,8 @@ interactive_dialog_clicked (GtkButton *button,
{
GtkWidget *content_area;
GtkWidget *dialog;
GtkWidget *hbox;
GtkWidget *image;
GtkWidget *table;
GtkWidget *local_entry1;
GtkWidget *local_entry2;
@@ -69,24 +71,26 @@ interactive_dialog_clicked (GtkButton *button,
dialog = gtk_dialog_new_with_buttons ("Interactive Dialog",
GTK_WINDOW (window),
GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT|GTK_DIALOG_USE_HEADER_BAR,
_("_OK"), GTK_RESPONSE_OK,
_("_Cancel"), GTK_RESPONSE_CANCEL,
GTK_DIALOG_MODAL| GTK_DIALOG_DESTROY_WITH_PARENT,
_("_OK"),
GTK_RESPONSE_OK,
"_Cancel",
GTK_RESPONSE_CANCEL,
NULL);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
table = gtk_grid_new ();
gtk_widget_set_hexpand (table, TRUE);
gtk_widget_set_vexpand (table, TRUE);
gtk_widget_set_halign (table, GTK_ALIGN_CENTER);
gtk_widget_set_valign (table, GTK_ALIGN_CENTER);
gtk_box_append (GTK_BOX (content_area), table);
gtk_grid_set_row_spacing (GTK_GRID (table), 6);
gtk_grid_set_column_spacing (GTK_GRID (table), 6);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);
gtk_box_append (GTK_BOX (content_area), hbox);
image = gtk_image_new_from_icon_name ("dialog-question");
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
gtk_box_append (GTK_BOX (hbox), image);
table = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (table), 4);
gtk_grid_set_column_spacing (GTK_GRID (table), 4);
gtk_box_append (GTK_BOX (hbox), table);
label = gtk_label_new_with_mnemonic ("_Entry 1");
gtk_grid_attach (GTK_GRID (table), label, 0, 0, 1, 1);
local_entry1 = gtk_entry_new ();
@@ -119,6 +123,7 @@ interactive_dialog_clicked (GtkButton *button,
GtkWidget *
do_dialog (GtkWidget *do_widget)
{
GtkWidget *frame;
GtkWidget *vbox;
GtkWidget *vbox2;
GtkWidget *hbox;
@@ -131,16 +136,22 @@ do_dialog (GtkWidget *do_widget)
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Dialogs");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
gtk_window_set_title (GTK_WINDOW (window), "Dialogs and Message Boxes");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
frame = gtk_frame_new ("Dialogs");
gtk_widget_set_margin_start (frame, 8);
gtk_widget_set_margin_end (frame, 8);
gtk_widget_set_margin_top (frame, 8);
gtk_widget_set_margin_bottom (frame, 8);
gtk_window_set_child (GTK_WINDOW (window), frame);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
gtk_widget_set_margin_start (vbox, 8);
gtk_widget_set_margin_end (vbox, 8);
gtk_widget_set_margin_top (vbox, 8);
gtk_widget_set_margin_bottom (vbox, 8);
gtk_window_set_child (GTK_WINDOW (window), vbox);
gtk_frame_set_child (GTK_FRAME (frame), vbox);
/* Standard message dialog */
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 8);

View File

@@ -38,20 +38,15 @@ set_color (CanvasItem *item,
char *str;
GtkStyleContext *context;
GtkCssProvider *provider;
const char *old_class;
str = gdk_rgba_to_string (color);
css = g_strdup_printf ("* { background: %s; }", str);
css = g_strdup_printf ("* { background: %s; padding: 10px; margin: 1px; }", str);
context = gtk_widget_get_style_context (item->label);
provider = g_object_get_data (G_OBJECT (context), "style-provider");
if (provider)
gtk_style_context_remove_provider (context, GTK_STYLE_PROVIDER (provider));
old_class = (const char *)g_object_get_data (G_OBJECT (item->label), "css-class");
if (old_class)
gtk_widget_remove_css_class (item->label, old_class);
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (provider, css, -1);
gtk_style_context_add_provider (gtk_widget_get_style_context (item->label), GTK_STYLE_PROVIDER (provider), 800);
@@ -61,27 +56,6 @@ set_color (CanvasItem *item,
g_free (css);
}
static void
set_css (CanvasItem *item,
const char *class)
{
GtkStyleContext *context;
GtkCssProvider *provider;
const char *old_class;
context = gtk_widget_get_style_context (item->label);
provider = g_object_get_data (G_OBJECT (context), "style-provider");
if (provider)
gtk_style_context_remove_provider (context, GTK_STYLE_PROVIDER (provider));
old_class = (const char *)g_object_get_data (G_OBJECT (item->label), "css-class");
if (old_class)
gtk_widget_remove_css_class (item->label, old_class);
g_object_set_data_full (G_OBJECT (item->label), "css-class", g_strdup (class), g_free);
gtk_widget_add_css_class (item->label, class);
}
static gboolean
item_drag_drop (GtkDropTarget *dest,
const GValue *value,
@@ -91,10 +65,7 @@ item_drag_drop (GtkDropTarget *dest,
GtkWidget *label = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (dest));
CanvasItem *item = CANVAS_ITEM (gtk_widget_get_parent (gtk_widget_get_parent (label)));
if (G_VALUE_TYPE (value) == GDK_TYPE_RGBA)
set_color (item, g_value_get_boxed (value));
else if (G_VALUE_TYPE (value) == G_TYPE_STRING)
set_css (item, g_value_get_string (value));
set_color (item, g_value_get_boxed (value));
return TRUE;
}
@@ -161,13 +132,11 @@ canvas_item_init (CanvasItem *item)
GdkRGBA rgba;
GtkDropTarget *dest;
GtkGesture *gesture;
GType types[2] = { GDK_TYPE_RGBA, G_TYPE_STRING };
n_items++;
text = g_strdup_printf ("Item %d", n_items);
item->label = gtk_label_new (text);
gtk_widget_add_css_class (item->label, "canvasitem");
g_free (text);
item->fixed = gtk_fixed_new ();
@@ -185,8 +154,7 @@ canvas_item_init (CanvasItem *item)
item->angle = 0;
dest = gtk_drop_target_new (G_TYPE_INVALID, GDK_ACTION_COPY);
gtk_drop_target_set_gtypes (dest, types, G_N_ELEMENTS (types));
dest = gtk_drop_target_new (GDK_TYPE_RGBA, GDK_ACTION_COPY);
g_signal_connect (dest, "drop", G_CALLBACK (item_drag_drop), NULL);
gtk_widget_add_controller (GTK_WIDGET (item->label), GTK_EVENT_CONTROLLER (dest));
@@ -561,42 +529,6 @@ canvas_new (void)
return canvas;
}
static GdkContentProvider *
css_drag_prepare (GtkDragSource *source,
double x,
double y,
GtkWidget *button)
{
const char *class;
GdkPaintable *paintable;
class = (const char *)g_object_get_data (G_OBJECT (button), "css-class");
paintable = gtk_widget_paintable_new (button);
gtk_drag_source_set_icon (source, paintable, 0, 0);
g_object_unref (paintable);
return gdk_content_provider_new_typed (G_TYPE_STRING, class);
}
static GtkWidget *
css_button_new (const char *class)
{
GtkWidget *button;
GtkDragSource *source;
button = gtk_image_new ();
gtk_widget_set_size_request (button, 48, 32);
gtk_widget_add_css_class (button, class);
g_object_set_data (G_OBJECT (button), "css-class", (gpointer)class);
source = gtk_drag_source_new ();
g_signal_connect (source, "prepare", G_CALLBACK (css_drag_prepare), button);
gtk_widget_add_controller (button, GTK_EVENT_CONTROLLER (source));
return button;
}
static GtkWidget *window = NULL;
GtkWidget *
@@ -616,18 +548,10 @@ do_dnd (GtkWidget *do_widget)
};
int i;
int x, y;
GtkCssProvider *provider;
button = gtk_color_button_new ();
g_object_unref (g_object_ref_sink (button));
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/dnd/dnd.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
800);
g_object_unref (provider);
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
@@ -659,7 +583,7 @@ do_dnd (GtkWidget *do_widget)
y += 100;
}
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_NEVER);
@@ -682,10 +606,6 @@ do_dnd (GtkWidget *do_widget)
NULL);
gtk_box_append (GTK_BOX (box3), swatch);
}
gtk_box_append (GTK_BOX (box3), css_button_new ("rainbow1"));
gtk_box_append (GTK_BOX (box3), css_button_new ("rainbow2"));
gtk_box_append (GTK_BOX (box3), css_button_new ("rainbow3"));
}
if (!gtk_widget_get_visible (window))

View File

@@ -1,37 +0,0 @@
label.canvasitem {
padding: 10px;
margin: 1px;
}
.canvasitem.rainbow1,
image.rainbow1 {
background: linear-gradient(140deg,red,orange,yellow,green,blue,purple);
}
.canvasitem.rainbow2,
image.rainbow2 {
animation: rainbow2 1s infinite linear;
}
@keyframes rainbow2 {
0% { background: linear-gradient(0deg,red,orange,yellow,green,blue,purple); }
25% { background: linear-gradient(90deg,red,orange,yellow,green,blue,purple); }
50% { background: linear-gradient(180deg,red,orange,yellow,green,blue,purple); }
75% { background: linear-gradient(270deg,red,orange,yellow,green,blue,purple); }
100% { background: linear-gradient(360deg,red,orange,yellow,green,blue,purple); }
}
.canvasitem.rainbow3,
image.rainbow3 {
animation: rainbow3 1s infinite linear;
}
@keyframes rainbow3 {
0% { background: linear-gradient(140deg,red,orange,yellow,green,blue,purple); }
16.6% { background: linear-gradient(140deg,purple,red,orange,yellow,green,blue); }
33.2% { background: linear-gradient(140deg,blue,purple,red,orange,yellow,green); }
50% { background: linear-gradient(140deg,green,blue,purple,red,orange,yellow); }
66.6% { background: linear-gradient(140deg,yellow,green,blue,purple,red,orange); }
83.2% { background: linear-gradient(140deg,orange,yellow,green,blue,purple,red); }
100% { background: linear-gradient(140deg,red,orange,yellow,green,blue,purple); }
}

View File

@@ -1,305 +0,0 @@
/* Drop Downs
*
* The GtkDropDown widget is a modern alternative to GtkComboBox.
* It uses list models instead of tree models, and the content is
* displayed using widgets instead of cell renderers.
*
* The examples here demonstrate how to use different kinds of
* list models with GtkDropDown, how to use search and how to
* display the selected item differently from the presentation
* in the popup.
*/
#include <gtk/gtk.h>
#define STRING_TYPE_HOLDER (string_holder_get_type ())
G_DECLARE_FINAL_TYPE (StringHolder, string_holder, STRING, HOLDER, GObject)
struct _StringHolder {
GObject parent_instance;
char *title;
char *icon;
char *description;
};
G_DEFINE_TYPE (StringHolder, string_holder, G_TYPE_OBJECT);
static void
string_holder_init (StringHolder *holder)
{
}
static void
string_holder_finalize (GObject *object)
{
StringHolder *holder = STRING_HOLDER (object);
g_free (holder->title);
g_free (holder->icon);
g_free (holder->description);
G_OBJECT_CLASS (string_holder_parent_class)->finalize (object);
}
static void
string_holder_class_init (StringHolderClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->finalize = string_holder_finalize;
}
static StringHolder *
string_holder_new (const char *title, const char *icon, const char *description)
{
StringHolder *holder = g_object_new (STRING_TYPE_HOLDER, NULL);
holder->title = g_strdup (title);
holder->icon = g_strdup (icon);
holder->description = g_strdup (description);
return holder;
}
static void
strings_setup_item_single_line (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkWidget *box, *image, *title;
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
image = gtk_image_new ();
title = gtk_label_new ("");
gtk_label_set_xalign (GTK_LABEL (title), 0.0);
gtk_box_append (GTK_BOX (box), image);
gtk_box_append (GTK_BOX (box), title);
g_object_set_data (G_OBJECT (item), "title", title);
g_object_set_data (G_OBJECT (item), "image", image);
gtk_list_item_set_child (item, box);
}
static void
strings_setup_item_full (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkWidget *box, *box2, *image, *title, *description;
image = gtk_image_new ();
title = gtk_label_new ("");
gtk_label_set_xalign (GTK_LABEL (title), 0.0);
description = gtk_label_new ("");
gtk_label_set_xalign (GTK_LABEL (description), 0.0);
gtk_style_context_add_class (gtk_widget_get_style_context (description), "dim-label");
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
gtk_box_append (GTK_BOX (box), image);
gtk_box_append (GTK_BOX (box), box2);
gtk_box_append (GTK_BOX (box2), title);
gtk_box_append (GTK_BOX (box2), description);
g_object_set_data (G_OBJECT (item), "title", title);
g_object_set_data (G_OBJECT (item), "image", image);
g_object_set_data (G_OBJECT (item), "description", description);
gtk_list_item_set_child (item, box);
}
static void
strings_bind_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkWidget *image, *title, *description;
StringHolder *holder;
holder = gtk_list_item_get_item (item);
title = g_object_get_data (G_OBJECT (item), "title");
image = g_object_get_data (G_OBJECT (item), "image");
description = g_object_get_data (G_OBJECT (item), "description");
gtk_label_set_label (GTK_LABEL (title), holder->title);
if (image)
{
gtk_image_set_from_icon_name (GTK_IMAGE (image), holder->icon);
gtk_widget_set_visible (image, holder->icon != NULL);
}
if (description)
{
gtk_label_set_label (GTK_LABEL (description), holder->description);
gtk_widget_set_visible (description , holder->description != NULL);
}
}
static GtkListItemFactory *
strings_factory_new (gboolean full)
{
GtkListItemFactory *factory;
factory = gtk_signal_list_item_factory_new ();
if (full)
g_signal_connect (factory, "setup", G_CALLBACK (strings_setup_item_full), NULL);
else
g_signal_connect (factory, "setup", G_CALLBACK (strings_setup_item_single_line), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (strings_bind_item), NULL);
return factory;
}
static GListModel *
strings_model_new (const char *const *titles,
const char *const *icons,
const char *const *descriptions)
{
GListStore *store;
int i;
store = g_list_store_new (STRING_TYPE_HOLDER);
for (i = 0; titles[i]; i++)
{
StringHolder *holder = string_holder_new (titles[i],
icons ? icons[i] : NULL,
descriptions ? descriptions[i] : NULL);
g_list_store_append (store, holder);
g_object_unref (holder);
}
return G_LIST_MODEL (store);
}
static GtkWidget *
drop_down_new_from_strings (const char *const *titles,
const char *const *icons,
const char *const *descriptions)
{
GtkWidget *widget;
GListModel *model;
GtkListItemFactory *factory;
GtkListItemFactory *list_factory;
g_return_val_if_fail (titles != NULL, NULL);
g_return_val_if_fail (icons == NULL || g_strv_length ((char **)icons) == g_strv_length ((char **)titles), NULL);
g_return_val_if_fail (descriptions == NULL || g_strv_length ((char **)icons) == g_strv_length ((char **)descriptions), NULL);
model = strings_model_new (titles, icons, descriptions);
factory = strings_factory_new (FALSE);
if (icons != NULL || descriptions != NULL)
list_factory = strings_factory_new (TRUE);
else
list_factory = NULL;
widget = g_object_new (GTK_TYPE_DROP_DOWN,
"model", model,
"factory", factory,
"list-factory", list_factory,
NULL);
g_object_unref (model);
g_object_unref (factory);
if (list_factory)
g_object_unref (list_factory);
return widget;
}
static char *
get_family_name (gpointer item)
{
return g_strdup (pango_font_family_get_name (PANGO_FONT_FAMILY (item)));
}
static char *
get_title (gpointer item)
{
return g_strdup (STRING_HOLDER (item)->title);
}
GtkWidget *
do_dropdown (GtkWidget *do_widget)
{
static GtkWidget *window = NULL;
GtkWidget *button, *box, *spin, *check;
GListModel *model;
GtkExpression *expression;
const char * const times[] = { "1 minute", "2 minutes", "5 minutes", "20 minutes", NULL };
const char * const many_times[] = {
"1 minute", "2 minutes", "5 minutes", "10 minutes", "15 minutes", "20 minutes",
"25 minutes", "30 minutes", "35 minutes", "40 minutes", "45 minutes", "50 minutes",
"55 minutes", "1 hour", "2 hours", "3 hours", "5 hours", "6 hours", "7 hours",
"8 hours", "9 hours", "10 hours", "11 hours", "12 hours", NULL
};
const char * const device_titles[] = { "Digital Output", "Headphones", "Digital Output", "Analog Output", NULL };
const char * const device_icons[] = { "audio-card-symbolic", "audio-headphones-symbolic", "audio-card-symbolic", "audio-card-symbolic", NULL };
const char * const device_descriptions[] = {
"Built-in Audio", "Built-in audio", "Thinkpad Tunderbolt 3 Dock USB Audio", "Thinkpad Tunderbolt 3 Dock USB Audio", NULL
};
if (!window)
{
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Drop Downs");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
gtk_widget_set_margin_start (box, 10);
gtk_widget_set_margin_end (box, 10);
gtk_widget_set_margin_top (box, 10);
gtk_widget_set_margin_bottom (box, 10);
gtk_window_set_child (GTK_WINDOW (window), box);
button = gtk_drop_down_new ();
model = G_LIST_MODEL (pango_cairo_font_map_get_default ());
gtk_drop_down_set_model (GTK_DROP_DOWN (button), model);
gtk_drop_down_set_selected (GTK_DROP_DOWN (button), 0);
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
0, NULL,
(GCallback)get_family_name,
NULL, NULL);
gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);
gtk_expression_unref (expression);
gtk_box_append (GTK_BOX (box), button);
spin = gtk_spin_button_new_with_range (-1, g_list_model_get_n_items (G_LIST_MODEL (model)), 1);
gtk_widget_set_halign (spin, GTK_ALIGN_START);
g_object_bind_property (button, "selected", spin, "value", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
gtk_box_append (GTK_BOX (box), spin);
check = gtk_check_button_new_with_label ("Enable search");
g_object_bind_property (button, "enable-search", check, "active", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL);
gtk_box_append (GTK_BOX (box), check);
g_object_unref (model);
button = drop_down_new_from_strings (times, NULL, NULL);
gtk_box_append (GTK_BOX (box), button);
button = drop_down_new_from_strings (many_times, NULL, NULL);
gtk_drop_down_set_enable_search (GTK_DROP_DOWN (button), TRUE);
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
0, NULL,
(GCallback)get_title,
NULL, NULL);
gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);
gtk_expression_unref (expression);
gtk_box_append (GTK_BOX (box), button);
button = drop_down_new_from_strings (device_titles, device_icons, device_descriptions);
gtk_box_append (GTK_BOX (box), button);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

View File

@@ -364,7 +364,7 @@ do_editable_cells (GtkWidget *do_widget)
gtk_box_append (GTK_BOX (vbox),
gtk_label_new ("Shopping list (you can edit the cells!)"));
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,

View File

@@ -1,4 +1,4 @@
/* Entry/Completion
/* Entry/Entry Completion
*
* GtkEntryCompletion provides a mechanism for adding support for
* completion in GtkEntry.
@@ -12,48 +12,22 @@
static GtkTreeModel *
create_completion_model (void)
{
const char *strings[] = {
"GNOME",
"gnominious",
"Gnomonic projection",
"Gnosophy",
"total",
"totally",
"toto",
"tottery",
"totterer",
"Totten trust",
"Tottenham hotspurs",
"totipotent",
"totipotency",
"totemism",
"totem pole",
"Totara",
"totalizer",
"totalizator",
"totalitarianism",
"total parenteral nutrition",
"total eclipse",
"Totipresence",
"Totipalmi",
"zombie",
"aæx",
"aæy",
"aæz",
NULL
};
int i;
GtkListStore *store;
GtkTreeIter iter;
store = gtk_list_store_new (1, G_TYPE_STRING);
for (i = 0; strings[i]; i++)
{
/* Append one word */
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, strings[i], -1);
}
/* Append one word */
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "GNOME", -1);
/* Append another word */
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "total", -1);
/* And another word */
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, "totally", -1);
return GTK_TREE_MODEL (store);
}
@@ -74,7 +48,7 @@ do_entry_completion (GtkWidget *do_widget)
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Completion");
gtk_window_set_title (GTK_WINDOW (window), "Entry Completion");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
@@ -86,7 +60,7 @@ do_entry_completion (GtkWidget *do_widget)
gtk_window_set_child (GTK_WINDOW (window), vbox);
label = gtk_label_new (NULL);
gtk_label_set_markup (GTK_LABEL (label), "Try writing <b>total</b> or <b>gnome</b> for example.");
gtk_label_set_markup (GTK_LABEL (label), "Completion demo, try writing <b>total</b> or <b>gnome</b> for example.");
gtk_box_append (GTK_BOX (vbox), label);
/* Create our entry */
@@ -107,9 +81,6 @@ do_entry_completion (GtkWidget *do_widget)
/* Use model column 0 as the text column */
gtk_entry_completion_set_text_column (completion, 0);
gtk_entry_completion_set_inline_completion (completion, TRUE);
gtk_entry_completion_set_inline_selection (completion, TRUE);
}
if (!gtk_widget_get_visible (window))

View File

@@ -1,8 +1,8 @@
/* Entry/Undo and Redo
/* Entry/Entry Undo
*
* GtkEntry can provide basic Undo/Redo support using standard keyboard
* accelerators such as Control+z to undo and Control+Shift+z to redo.
* Additionally, Control+y can be used to redo.
* accelerators such as Primary+z to undo and Primary+Shift+z to redo.
* Additionally, Primary+y can be used to redo.
*
* Use gtk_entry_set_enable_undo() to enable undo/redo support.
*/
@@ -23,7 +23,7 @@ do_entry_undo (GtkWidget *do_widget)
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Undo and Redo");
gtk_window_set_title (GTK_WINDOW (window), "Entry Undo");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);

View File

@@ -57,7 +57,7 @@ do_expander (GtkWidget *do_widget)
expander = gtk_expander_new ("Details:");
gtk_widget_set_vexpand (expander, TRUE);
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (sw), 100);
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),

View File

@@ -249,14 +249,6 @@ fishbowl_changes_toggled_cb (GtkToggleButton *button,
gtk_button_set_icon_name (GTK_BUTTON (button), "changes-allow");
}
char *
format_header_cb (GObject *object,
guint count,
double fps)
{
return g_strdup_printf ("%u Icons, %.2f fps", count, fps);
}
GtkWidget *
do_fishbowl (GtkWidget *do_widget)
{

View File

@@ -28,12 +28,22 @@
</child>
<child type="end">
<object class="GtkLabel">
<binding name="label">
<closure type="gchararray" function="format_header_cb">
<lookup name="count">bowl</lookup>
<lookup name="framerate">bowl</lookup>
</closure>
</binding>
<property name="label">fps</property>
</object>
</child>
<child type="end">
<object class="GtkLabel">
<property name="label" bind-source="bowl" bind-property="framerate-string"/>
</object>
</child>
<child type="end">
<object class="GtkLabel">
<property name="label">Icons, </property>
</object>
</child>
<child type="end">
<object class="GtkLabel">
<property name="label" bind-source="bowl" bind-property="count"/>
</object>
</child>
<child type="end">

View File

@@ -1,4 +1,4 @@
/* Fixed Layout
/* Fixed layout
*
* GtkFixed is a container that allows placing and transforming
* widgets manually.
@@ -126,11 +126,11 @@ create_demo_window (GtkWidget *do_widget)
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Fixed Layout");
gtk_window_set_title (GTK_WINDOW (window), "Fixed layout");
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL);
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_window_set_child (GTK_WINDOW (window), sw);
fixed = gtk_fixed_new ();

View File

@@ -1,10 +1,9 @@
/* Flow Box
*
* GtkFlowBox allows flexible and responsive grids which reflow
* as needed and support sorting and filtering. The children of
* a GtkFlowBox are regular widgets
* as needed and support sorting and filtering.
*
* The dataset used here has 665 colors.
* The children of a GtkFlowBox are regular widgets
*/
#include <gtk/gtk.h>
@@ -727,7 +726,7 @@ do_flowbox (GtkWidget *do_widget)
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
scrolled = gtk_scrolled_window_new ();
scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
flowbox = gtk_flow_box_new ();
gtk_widget_set_valign (flowbox, GTK_ALIGN_START);

View File

@@ -13,16 +13,17 @@ in_files = sys.argv[2:]
file_output = """
typedef GtkWidget *(*GDoDemoFunc) (GtkWidget *do_widget);
typedef struct _DemoData DemoData;
typedef struct _Demo Demo;
struct _DemoData
struct _Demo
{
const char *name;
const char *title;
const char *filename;
GDoDemoFunc func;
DemoData *children;
Demo *children;
};
"""
# Demo = namedtuple('Demo', ['name', 'title', 'file', 'func'])
@@ -66,7 +67,7 @@ for demo in demos:
i = 0
for parent in parents:
id = parent_ids[i]
file_output += "\nDemoData child" + str(id) + "[] = {\n"
file_output += "\nDemo child" + str(id) + "[] = {\n"
# iterate over all demos and check if the name starts with the given parent name
for child in demos:
if child[1].startswith(parent + "/"):
@@ -81,7 +82,7 @@ for parent in parents:
# Sort demos by title
demos = sorted(demos, key=lambda x: x[1])
file_output += "\nDemoData gtk_demos[] = {\n"
file_output += "\nDemo gtk_demos[] = {\n"
for demo in demos:
# Do not generate one of these for demos with a parent demo
if "/" not in demo[1]:

View File

@@ -25,7 +25,7 @@ typedef struct _GtkFishbowlChild GtkFishbowlChild;
struct _GtkFishbowlPrivate
{
GtkFishCreationFunc creation_func;
GHashTable *children;
GList *children;
guint count;
gint64 last_frame_time;
@@ -53,6 +53,7 @@ enum {
PROP_BENCHMARK,
PROP_COUNT,
PROP_FRAMERATE,
PROP_FRAMERATE_STRING,
PROP_UPDATE_DELAY,
NUM_PROPERTIES
};
@@ -67,8 +68,6 @@ gtk_fishbowl_init (GtkFishbowl *fishbowl)
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
priv->update_delay = G_USEC_PER_SEC;
priv->children = g_hash_table_new_full (NULL, NULL,
NULL, (GDestroyNotify) g_free);
}
/**
@@ -95,18 +94,20 @@ gtk_fishbowl_measure (GtkWidget *widget,
{
GtkFishbowl *fishbowl = GTK_FISHBOWL (widget);
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
GHashTableIter iter;
gpointer key, value;
GtkFishbowlChild *child;
GList *children;
gint child_min, child_nat;
*minimum = 0;
*natural = 0;
g_hash_table_iter_init (&iter, priv->children);
while (g_hash_table_iter_next (&iter, &key, &value))
for (children = priv->children; children; children = children->next)
{
child = value;
child = children->data;
if (!gtk_widget_get_visible (child->widget))
continue;
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
@@ -136,13 +137,14 @@ gtk_fishbowl_size_allocate (GtkWidget *widget,
GtkFishbowlChild *child;
GtkAllocation child_allocation;
GtkRequisition child_requisition;
GHashTableIter iter;
gpointer key, value;
GList *children;
g_hash_table_iter_init (&iter, priv->children);
while (g_hash_table_iter_next (&iter, &key, &value))
for (children = priv->children; children; children = children->next)
{
child = value;
child = children->data;
if (!gtk_widget_get_visible (child->widget))
continue;
gtk_widget_get_preferred_size (child->widget, &child_requisition, NULL);
child_allocation.x = round (child->x * (width - child_requisition.width));
@@ -180,7 +182,7 @@ gtk_fishbowl_add (GtkFishbowl *fishbowl,
gtk_widget_set_parent (widget, GTK_WIDGET (fishbowl));
g_hash_table_insert (priv->children, widget, child_info);
priv->children = g_list_prepend (priv->children, child_info);
priv->count++;
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_COUNT]);
}
@@ -190,26 +192,34 @@ gtk_fishbowl_remove (GtkFishbowl *fishbowl,
GtkWidget *widget)
{
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
GtkFishbowlChild *child;
GtkWidget *widget_bowl = GTK_WIDGET (fishbowl);
GList *children;
if (g_hash_table_remove (priv->children, widget))
for (children = priv->children; children; children = children->next)
{
gtk_widget_unparent (widget);
child = children->data;
priv->count--;
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_COUNT]);
if (child->widget == widget)
{
gboolean was_visible = gtk_widget_get_visible (widget);
gtk_widget_unparent (widget);
priv->children = g_list_remove_link (priv->children, children);
g_list_free (children);
g_free (child);
if (was_visible && gtk_widget_get_visible (widget_bowl))
gtk_widget_queue_resize (widget_bowl);
priv->count--;
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_COUNT]);
break;
}
}
}
static void
gtk_fishbowl_finalize (GObject *object)
{
GtkFishbowl *fishbowl = GTK_FISHBOWL (object);
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
g_hash_table_destroy (priv->children);
priv->children = NULL;
}
static void
gtk_fishbowl_dispose (GObject *object)
{
@@ -279,6 +289,14 @@ gtk_fishbowl_get_property (GObject *object,
g_value_set_double (value, gtk_fishbowl_get_framerate (fishbowl));
break;
case PROP_FRAMERATE_STRING:
{
char *s = g_strdup_printf ("%.2f", gtk_fishbowl_get_framerate (fishbowl));
g_value_set_string (value, s);
g_free (s);
}
break;
case PROP_UPDATE_DELAY:
g_value_set_int64 (value, gtk_fishbowl_get_update_delay (fishbowl));
break;
@@ -295,7 +313,6 @@ gtk_fishbowl_class_init (GtkFishbowlClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = gtk_fishbowl_finalize;
object_class->dispose = gtk_fishbowl_dispose;
object_class->set_property = gtk_fishbowl_set_property;
object_class->get_property = gtk_fishbowl_get_property;
@@ -333,6 +350,13 @@ gtk_fishbowl_class_init (GtkFishbowlClass *klass)
0,
G_PARAM_READABLE);
props[PROP_FRAMERATE_STRING] =
g_param_spec_string ("framerate-string",
"Framerate as string",
"Framerate as string, with 2 decimals",
NULL,
G_PARAM_READABLE);
props[PROP_UPDATE_DELAY] =
g_param_spec_int64 ("update-delay",
"Update delay",
@@ -484,6 +508,7 @@ gtk_fishbowl_do_update (GtkFishbowl *fishbowl)
priv->framerate = ((int)(priv->framerate * 100))/100.0;
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_FRAMERATE]);
g_object_notify_by_pspec (G_OBJECT (fishbowl), props[PROP_FRAMERATE_STRING]);
if (!priv->benchmark)
return;
@@ -527,9 +552,8 @@ gtk_fishbowl_tick (GtkWidget *widget,
GtkFishbowl *fishbowl = GTK_FISHBOWL (widget);
GtkFishbowlPrivate *priv = gtk_fishbowl_get_instance_private (fishbowl);
GtkFishbowlChild *child;
GList *l;
gint64 frame_time, elapsed;
GHashTableIter iter;
gpointer key, value;
gboolean do_update;
frame_time = gdk_frame_clock_get_frame_time (gtk_widget_get_frame_clock (widget));
@@ -541,10 +565,9 @@ gtk_fishbowl_tick (GtkWidget *widget,
if (elapsed == frame_time)
return G_SOURCE_CONTINUE;
g_hash_table_iter_init (&iter, priv->children);
while (g_hash_table_iter_next (&iter, &key, &value))
for (l = priv->children; l; l = l->next)
{
child = value;
child = l->data;
child->x += child->dx * ((double) elapsed / G_USEC_PER_SEC);
child->y += child->dy * ((double) elapsed / G_USEC_PER_SEC);

View File

@@ -260,7 +260,7 @@ do_hypertext (GtkWidget *do_widget)
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
gtk_text_buffer_set_enable_undo (buffer, TRUE);
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);

View File

@@ -12,7 +12,7 @@ static GtkWidget *window = NULL;
static GtkWidget *scrolledwindow;
static int selected;
#define N_WIDGET_TYPES 6
#define N_WIDGET_TYPES 4
static int hincrement = 5;
@@ -64,7 +64,6 @@ populate_icons (void)
gtk_grid_attach (GTK_GRID (grid), create_icon (), left, top, 1, 1);
hincrement = 0;
vincrement = 5;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_NEVER,
@@ -101,7 +100,6 @@ populate_text (gboolean hilight)
gtk_text_view_set_buffer (GTK_TEXT_VIEW (textview), buffer);
hincrement = 0;
vincrement = 5;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_NEVER,
@@ -126,7 +124,6 @@ populate_image (void)
gtk_picture_set_can_shrink (GTK_PICTURE (image), FALSE);
hincrement = 5;
vincrement = 5;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC,
@@ -134,42 +131,6 @@ populate_image (void)
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), image);
}
extern GtkWidget *create_weather_view (void);
static void
populate_list (void)
{
GtkWidget *list;
list = create_weather_view ();
hincrement = 5;
vincrement = 0;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), list);
}
extern GtkWidget *create_color_grid (void);
static void
populate_grid (void)
{
GtkWidget *list;
list = create_color_grid ();
hincrement = 0;
vincrement = 5;
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolledwindow), list);
}
static void
set_widget_type (int type)
{
@@ -203,16 +164,6 @@ set_widget_type (int type)
populate_image ();
break;
case 4:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a list");
populate_list ();
break;
case 5:
gtk_window_set_title (GTK_WINDOW (window), "Scrolling a grid");
populate_grid ();
break;
default:
g_assert_not_reached ();
}

View File

@@ -276,7 +276,7 @@ do_iconview (GtkWidget *do_widget)
gtk_box_append (GTK_BOX (tool_bar), home_button);
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,

View File

@@ -269,7 +269,7 @@ do_list_store (GtkWidget *do_widget)
label = gtk_label_new ("This is the bug list (note: not based on real data, it would be nice to have a nice ODBC interface to bugzilla or so, though).");
gtk_box_append (GTK_BOX (vbox), label);
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_NEVER,

View File

@@ -236,6 +236,7 @@ reshare_clicked (GtkMessageRow *row,
priv->message->n_reshares++;
gtk_message_row_update (row);
}
static void
@@ -254,12 +255,11 @@ gtk_message_row_state_flags_changed (GtkWidget *widget,
{
GtkMessageRowPrivate *priv = GTK_MESSAGE_ROW (widget)->priv;
GtkStateFlags flags;
gboolean visible;
flags = gtk_widget_get_state_flags (widget);
visible = flags & (GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_SELECTED) ? TRUE : FALSE;
gtk_widget_set_visible (priv->extra_buttons_box, visible);
gtk_widget_set_visible (priv->extra_buttons_box,
flags & (GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_SELECTED));
GTK_WIDGET_CLASS (gtk_message_row_parent_class)->state_flags_changed (widget, previous_state_flags);
}
@@ -358,7 +358,7 @@ do_listbox (GtkWidget *do_widget)
gtk_window_set_child (GTK_WINDOW (window), vbox);
label = gtk_label_new ("Messages from GTK and friends");
gtk_box_append (GTK_BOX (vbox), label);
scrolled = gtk_scrolled_window_new ();
scrolled = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
gtk_widget_set_vexpand (scrolled, TRUE);
gtk_box_append (GTK_BOX (vbox), scrolled);

View File

@@ -1,202 +0,0 @@
/* Lists/Application launcher
*
* This demo uses the GtkListView widget as a fancy application launcher.
*
* It is also a very small introduction to listviews.
*/
#include <gtk/gtk.h>
/* This is the function that creates the #GListModel that we need.
* GTK list widgets need a #GListModel to display, as models support change
* notifications.
* Unfortunately various older APIs do not provide list models, so we create
* our own.
*/
static GListModel *
create_application_list (void)
{
GListStore *store;
GList *apps, *l;
/* We use a #GListStore here, which is a simple array-like list implementation
* for manual management.
* List models need to know what type of data they provide, so we need to
* provide the type here. As we want to do a list of applications, #GAppInfo
* is the object we provide.
*/
store = g_list_store_new (G_TYPE_APP_INFO);
apps = g_app_info_get_all ();
for (l = apps; l; l = l->next)
g_list_store_append (store, l->data);
g_list_free_full (apps, g_object_unref);
return G_LIST_MODEL (store);
}
/* This is the function we use for setting up new listitems to display.
* We add just an #GtkImage and a #GtkKabel here to display the application's
* icon and name, as this is just a simple demo.
*/
static void
setup_listitem_cb (GtkListItemFactory *factory,
GtkListItem *list_item)
{
GtkWidget *box;
GtkWidget *image;
GtkWidget *label;
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
image = gtk_image_new ();
gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE);
gtk_box_append (GTK_BOX (box), image);
label = gtk_label_new ("");
gtk_box_append (GTK_BOX (box), label);
gtk_list_item_set_child (list_item, box);
}
/* Here we need to prepare the listitem for displaying its item. We get the
* listitem already set up from the previous function, so we can reuse the
* #GtkImage widget we set up above.
* We get the item - which we know is a #GAppInfo because it comes out of
* the model we set up above, grab its icon and display it.
*/
static void
bind_listitem_cb (GtkListItemFactory *factory,
GtkListItem *list_item)
{
GtkWidget *image;
GtkWidget *label;
GAppInfo *app_info;
image = gtk_widget_get_first_child (gtk_list_item_get_child (list_item));
label = gtk_widget_get_next_sibling (image);
app_info = gtk_list_item_get_item (list_item);
gtk_image_set_from_gicon (GTK_IMAGE (image), g_app_info_get_icon (app_info));
gtk_label_set_label (GTK_LABEL (label), g_app_info_get_display_name (app_info));
}
/* In more complex code, we would also need functions to unbind and teardown
* the listitem, but this is simple code, so the default implementations are
* enough. If we had connected signals, this step would have been necessary.
*
* The #GtkSignalListItemFactory documentation contains more information about
* this step.
*/
/* This function is called whenever an item in the list is activated. This is
* the simple way to allow reacting to the Enter key or double-clicking on a
* listitem.
* Of course, it is possible to use far more complex interactions by turning
* off activation and adding buttons or other widgets in the setup function
* above, but this is a simple demo, so we'll use the simple way.
*/
static void
activate_cb (GtkListView *list,
guint position,
gpointer unused)
{
GAppInfo *app_info;
GdkAppLaunchContext *context;
GError *error = NULL;
app_info = g_list_model_get_item (gtk_list_view_get_model (list), position);
/* Prepare the context for launching the application and launch it. This
* code is explained in detail in the documentation for #GdkAppLaunchContext
* and #GAppInfo.
*/
context = gdk_display_get_app_launch_context (gtk_widget_get_display (GTK_WIDGET (list)));
if (!g_app_info_launch (app_info,
NULL,
G_APP_LAUNCH_CONTEXT (context),
&error))
{
GtkWidget *dialog;
/* And because error handling is important, even a simple demo has it:
* We display an error dialog that something went wrong.
*/
dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_root (GTK_WIDGET (list))),
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_CLOSE,
"Could not launch %s", g_app_info_get_display_name (app_info));
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", error->message);
g_clear_error (&error);
gtk_widget_show (dialog);
}
g_object_unref (context);
g_object_unref (app_info);
}
static GtkWidget *window = NULL;
GtkWidget *
do_listview_applauncher (GtkWidget *do_widget)
{
if (window == NULL)
{
GtkWidget *list, *sw;
GListModel *model;
GtkListItemFactory *factory;
/* Create a window and set a few defaults */
window = gtk_window_new ();
gtk_window_set_default_size (GTK_WINDOW (window), 640, 320);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Application Launcher");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
/* The #GtkListitemFactory is what is used to create #GtkListItems
* to display the data from the model. So it is absolutely necessary
* to create one.
* We will use a #GtkSignalListItemFactory because it is the simplest
* one to use. Different ones are available for different use cases.
* The most powerful one is #GtkBuilderListItemFactory which uses
* #GtkBuilder .ui files, so it requires little code.
*/
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_listitem_cb), NULL);
/* Create the list widget here.
*/
list = gtk_list_view_new_with_factory (factory);
/* We connect the activate signal here. It's the function we defined
* above for launching the selected application.
*/
g_signal_connect (list, "activate", G_CALLBACK (activate_cb), NULL);
/* And of course we need to set the data model. Here we call the function
* we wrote above that gives us the list of applications. Then we set
* it on the list widget.
* The list will now take items from the model and use the factory
* to create as many listitems as it needs to show itself to the user.
*/
model = create_application_list ();
gtk_list_view_set_model (GTK_LIST_VIEW (list), model);
g_object_unref (model);
/* List widgets should always be contained in a #GtkScrolledWindow,
* because otherwise they might get too large or they might not
* be scrollable.
*/
sw = gtk_scrolled_window_new ();
gtk_window_set_child (GTK_WINDOW (window), sw);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), list);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

View File

@@ -1,506 +0,0 @@
/* Lists/Clocks
*
* This demo displays the time in different timezones.
*
* The goal is to show how to set up expressions that track changes
* in objects and make them update widgets. For that, we create a
* GtkClock object that updates its time every second and then use
* various ways to display that time.
*
* Typically, this will be done using GtkBuilder .ui files with the
* help of the <binding> tag, but this demo shows the code that runs
* behind that.
*/
#include <gtk/gtk.h>
#define GTK_TYPE_CLOCK (gtk_clock_get_type ())
G_DECLARE_FINAL_TYPE (GtkClock, gtk_clock, GTK, CLOCK, GObject)
/* This is our object. It's just a timezone */
typedef struct _GtkClock GtkClock;
struct _GtkClock
{
GObject parent_instance;
/* We allow this to be NULL for the local timezone */
GTimeZone *timezone;
/* Name of the location we're displaying time for */
char *location;
};
enum {
PROP_0,
PROP_LOCATION,
PROP_TIME,
PROP_TIMEZONE,
N_PROPS
};
/* This function returns the current time in the clock's timezone.
* Note that this returns a new object every time, so we need to
* remember to unref it after use.
*/
static GDateTime *
gtk_clock_get_time (GtkClock *clock)
{
if (clock->timezone)
return g_date_time_new_now (clock->timezone);
else
return g_date_time_new_now_local ();
}
/* Here, we implement the functionality required by the GdkPaintable
* interface. This way we have a trivial way to display an analog clock.
* It also allows demonstrating how to directly use objects in the
* listview later by making this object do something interesting.
*/
static void
gtk_clock_snapshot (GdkPaintable *paintable,
GdkSnapshot *snapshot,
double width,
double height)
{
GtkClock *self = GTK_CLOCK (paintable);
GDateTime *time;
GskRoundedRect outline;
#define BLACK ((GdkRGBA) { 0, 0, 0, 1 })
/* save/restore() is necessary so we can undo the transforms we start
* out with.
*/
gtk_snapshot_save (snapshot);
/* First, we move the (0, 0) point to the center of the area so
* we can draw everything relative to it.
*/
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (width / 2, height / 2));
/* Next we scale it, so that we can pretend that the clock is
* 100px in size. That way, we don't need to do any complicated
* math later. We use MIN() here so that we use the smaller
* dimension for sizing. That way we don't overdraw but keep
* the aspect ratio.
*/
gtk_snapshot_scale (snapshot, MIN (width, height) / 100.0, MIN (width, height) / 100.0);
/* Now we have a circle with diameter 100px (and radius 50px) that
* has its (0, 0) point at the center. Let's draw a simple clock into it.
*/
time = gtk_clock_get_time (self);
/* First, draw a circle. This is a neat little trick to draw a circle
* without requiring Cairo.
*/
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-50, -50, 100, 100), 50);
gtk_snapshot_append_border (snapshot,
&outline,
(float[4]) { 4, 4, 4, 4 },
(GdkRGBA [4]) { BLACK, BLACK, BLACK, BLACK });
/* Next, draw the hour hand.
* We do this using tranforms again: Instead of computing where the angle
* points to, we just rotate everything and then draw the hand as if it
* was :00. We don't even need to care about am/pm here because rotations
* just work.
*/
gtk_snapshot_save (snapshot);
gtk_snapshot_rotate (snapshot, 30 * g_date_time_get_hour (time) + 0.5 * g_date_time_get_minute (time));
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-2, -23, 4, 25), 2);
gtk_snapshot_push_rounded_clip (snapshot, &outline);
gtk_snapshot_append_color (snapshot, &BLACK, &outline.bounds);
gtk_snapshot_pop (snapshot);
gtk_snapshot_restore (snapshot);
/* And the same as above for the minute hand. Just make this one longer
* so people can tell the hands apart.
*/
gtk_snapshot_save (snapshot);
gtk_snapshot_rotate (snapshot, 6 * g_date_time_get_minute (time));
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-2, -43, 4, 45), 2);
gtk_snapshot_push_rounded_clip (snapshot, &outline);
gtk_snapshot_append_color (snapshot, &BLACK, &outline.bounds);
gtk_snapshot_pop (snapshot);
gtk_snapshot_restore (snapshot);
/* and finally, the second indicator. */
gtk_snapshot_save (snapshot);
gtk_snapshot_rotate (snapshot, 6 * g_date_time_get_second (time));
gsk_rounded_rect_init_from_rect (&outline, &GRAPHENE_RECT_INIT(-2, -43, 4, 10), 2);
gtk_snapshot_push_rounded_clip (snapshot, &outline);
gtk_snapshot_append_color (snapshot, &BLACK, &outline.bounds);
gtk_snapshot_pop (snapshot);
gtk_snapshot_restore (snapshot);
/* And finally, don't forget to restore the initial save() that
* we did for the initial transformations.
*/
gtk_snapshot_restore (snapshot);
g_date_time_unref (time);
}
/* Our desired size is 100px. That sounds okay for an analog clock */
static int
gtk_clock_get_intrinsic_width (GdkPaintable *paintable)
{
return 100;
}
static int
gtk_clock_get_intrinsic_height (GdkPaintable *paintable)
{
return 100;
}
/* Initialize the paintable interface. This way we turn our clocks
* into objects that can be drawn. There are more functions to this
* interface to define desired size, but this is enough.
*/
static void
gtk_clock_paintable_init (GdkPaintableInterface *iface)
{
iface->snapshot = gtk_clock_snapshot;
iface->get_intrinsic_width = gtk_clock_get_intrinsic_width;
iface->get_intrinsic_height = gtk_clock_get_intrinsic_height;
}
/* Finally, we define the type. The important part is adding the
* paintable interface, so GTK knows that this object can indeed
* be drawn.
*/
G_DEFINE_TYPE_WITH_CODE (GtkClock, gtk_clock, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
gtk_clock_paintable_init))
static GParamSpec *properties[N_PROPS] = { NULL, };
static void
gtk_clock_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GtkClock *self = GTK_CLOCK (object);
switch (property_id)
{
case PROP_LOCATION:
g_value_set_string (value, self->location);
break;
case PROP_TIME:
g_value_take_boxed (value, gtk_clock_get_time (self));
break;
case PROP_TIMEZONE:
g_value_set_boxed (value, self->timezone);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gtk_clock_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GtkClock *self = GTK_CLOCK (object);
switch (property_id)
{
case PROP_LOCATION:
self->location = g_value_dup_string (value);
break;
case PROP_TIMEZONE:
self->timezone = g_value_dup_boxed (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
/* This is the list of all the ticking clocks */
static GSList *ticking_clocks = NULL;
/* This is the ID of the timeout source that is updating all
* ticking clocks.
*/
static guint ticking_clock_id = 0;
/* Every second, this function is called to tell everybody that
* the clocks are ticking.
*/
static gboolean
gtk_clock_tick (gpointer unused)
{
GSList *l;
for (l = ticking_clocks; l; l = l->next)
{
GtkClock *clock = l->data;
/* We will now return a different value for the time property,
* so notify about that.
*/
g_object_notify_by_pspec (G_OBJECT (clock), properties[PROP_TIME]);
/* We will also draw the hands of the clock differently.
* So notify about that, too.
*/
gdk_paintable_invalidate_contents (GDK_PAINTABLE (clock));
}
return G_SOURCE_CONTINUE;
}
static void
gtk_clock_stop_ticking (GtkClock *self)
{
ticking_clocks = g_slist_remove (ticking_clocks, self);
/* If no clock is remaining, stop running the tick updates */
if (ticking_clocks == NULL && ticking_clock_id != 0)
g_clear_handle_id (&ticking_clock_id, g_source_remove);
}
static void
gtk_clock_start_ticking (GtkClock *self)
{
/* if no clock is ticking yet, start */
if (ticking_clock_id == 0)
ticking_clock_id = g_timeout_add_seconds (1, gtk_clock_tick, NULL);
ticking_clocks = g_slist_prepend (ticking_clocks, self);
}
static void
gtk_clock_finalize (GObject *object)
{
GtkClock *self = GTK_CLOCK (object);
gtk_clock_stop_ticking (self);
g_free (self->location);
g_clear_pointer (&self->timezone, g_time_zone_unref);
G_OBJECT_CLASS (gtk_clock_parent_class)->finalize (object);
}
static void
gtk_clock_class_init (GtkClockClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gtk_clock_get_property;
gobject_class->set_property = gtk_clock_set_property;
gobject_class->finalize = gtk_clock_finalize;
properties[PROP_LOCATION] =
g_param_spec_string ("location", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
properties[PROP_TIME] =
g_param_spec_boxed ("time", NULL, NULL, G_TYPE_DATE_TIME, G_PARAM_READABLE);
properties[PROP_TIMEZONE] =
g_param_spec_boxed ("timezone", NULL, NULL, G_TYPE_TIME_ZONE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
static void
gtk_clock_init (GtkClock *self)
{
gtk_clock_start_ticking (self);
}
static GtkClock *
gtk_clock_new (const char *location,
GTimeZone *_tz)
{
GtkClock *result;
result = g_object_new (GTK_TYPE_CLOCK,
"location", location,
"timezone", _tz,
NULL);
g_clear_pointer (&_tz, g_time_zone_unref);
return result;
}
static GListModel *
create_clocks_model (void)
{
GListStore *result;
GtkClock *clock;
result = g_list_store_new (GTK_TYPE_CLOCK);
/* local time */
clock = gtk_clock_new ("local", NULL);
g_list_store_append (result, clock);
g_object_unref (clock);
/* UTC time */
clock = gtk_clock_new ("UTC", g_time_zone_new_utc ());
g_list_store_append (result, clock);
g_object_unref (clock);
/* A bunch of timezones with GTK hackers */
clock = gtk_clock_new ("San Francisco", g_time_zone_new ("America/Los_Angeles"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("Xalapa", g_time_zone_new ("America/Mexico_City"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("Boston", g_time_zone_new ("America/New_York"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("London", g_time_zone_new ("Europe/London"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("Berlin", g_time_zone_new ("Europe/Berlin"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("Moscow", g_time_zone_new ("Europe/Moscow"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("New Delhi", g_time_zone_new ("Asia/Kolkata"));
g_list_store_append (result, clock);
g_object_unref (clock);
clock = gtk_clock_new ("Shanghai", g_time_zone_new ("Asia/Shanghai"));
g_list_store_append (result, clock);
g_object_unref (clock);
return G_LIST_MODEL (result);
}
static char *
convert_time_to_string (GObject *image,
GDateTime *time,
gpointer unused)
{
return g_date_time_format (time, "%x\n%X");
}
/* And this function is the crux for this whole demo.
* It shows how to use expressions to set up bindings.
*/
static void
setup_listitem_cb (GtkListItemFactory *factory,
GtkListItem *list_item)
{
GtkWidget *box, *picture, *location_label, *time_label;
GtkExpression *clock_expression, *expression;
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_list_item_set_child (list_item, box);
/* First, we create an expression that gets us the clock from the listitem:
* 1. Create an expression that gets the list item.
* 2. Use that expression's "item" property to get the clock
*/
expression = gtk_constant_expression_new (GTK_TYPE_LIST_ITEM, list_item);
clock_expression = gtk_property_expression_new (GTK_TYPE_LIST_ITEM, expression, "item");
/* Bind the clock's location to a label.
* This is easy: We just get the "location" property of the clock.
*/
expression = gtk_property_expression_new (GTK_TYPE_CLOCK,
gtk_expression_ref (clock_expression),
"location");
/* Now create the label and bind the expression to it. */
location_label = gtk_label_new (NULL);
gtk_expression_bind (expression, location_label, "label", location_label);
gtk_box_append (GTK_BOX (box), location_label);
/* Here we bind the item itself to a GdkPicture.
* This is simply done by using the clock expression itself.
*/
expression = gtk_expression_ref (clock_expression);
/* Now create the widget and bind the expression to it. */
picture = gtk_picture_new ();
gtk_expression_bind (expression, picture, "paintable", picture);
gtk_box_append (GTK_BOX (box), picture);
/* And finally, everything comes together.
* We create a label for displaying the time as text.
* For that, we need to transform the "GDateTime" of the
* time property into a string so that the label can display it.
*/
expression = gtk_property_expression_new (GTK_TYPE_CLOCK,
gtk_expression_ref (clock_expression),
"time");
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
NULL,
1, (GtkExpression *[1]) { expression },
G_CALLBACK (convert_time_to_string),
NULL, NULL);
/* Now create the label and bind the expression to it. */
time_label = gtk_label_new (NULL);
gtk_expression_bind (expression, time_label, "label", time_label);
gtk_box_append (GTK_BOX (box), time_label);
gtk_expression_unref (clock_expression);
}
static GtkWidget *window = NULL;
GtkWidget *
do_listview_clocks (GtkWidget *do_widget)
{
if (window == NULL)
{
GtkWidget *gridview, *sw;
GtkListItemFactory *factory;
GListModel *model;
GtkNoSelection *selection;
/* This is the normal window setup code every demo does */
window = gtk_window_new ();
gtk_window_set_title (GTK_WINDOW (window), "Clocks");
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
/* List widgets go into a scrolled window. Always. */
sw = gtk_scrolled_window_new ();
gtk_window_set_child (GTK_WINDOW (window), sw);
/* Create the factory that creates the listitems. Because we
* used bindings above during setup, we only need to connect
* to the setup signal.
* The bindings take care of the bind step.
*/
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
gridview = gtk_grid_view_new_with_factory (factory);
gtk_scrollable_set_hscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
gtk_scrollable_set_vscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
model = create_clocks_model ();
selection = gtk_no_selection_new (model);
gtk_grid_view_set_model (GTK_GRID_VIEW (gridview), G_LIST_MODEL (selection));
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), gridview);
g_object_unref (selection);
g_object_unref (model);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

View File

@@ -1,979 +0,0 @@
/* Lists/Colors
*
* This demo displays a grid of colors.
*
* It is using a GtkGridView, and shows how to display
* and sort the data in various ways. The controls for
* this are implemented using GtkDropDown.
*
* The dataset used here has up to 16777216 items.
*
* Note that this demo also functions as a performance
* test for some of the list model machinery, and the
* biggest sizes here can lock up the application for
* extended times when used with sorting.
*/
#include <gtk/gtk.h>
#include <stdlib.h>
#define GTK_TYPE_COLOR (gtk_color_get_type ())
G_DECLARE_FINAL_TYPE (GtkColor, gtk_color, GTK, COLOR, GObject)
/* This is our object. It's just a color */
typedef struct _GtkColor GtkColor;
struct _GtkColor
{
GObject parent_instance;
char *name;
GdkRGBA color;
int h, s, v;
};
enum {
PROP_0,
PROP_NAME,
PROP_COLOR,
PROP_RED,
PROP_GREEN,
PROP_BLUE,
PROP_HUE,
PROP_SATURATION,
PROP_VALUE,
N_COLOR_PROPS
};
static void
gtk_color_snapshot (GdkPaintable *paintable,
GdkSnapshot *snapshot,
double width,
double height)
{
GtkColor *self = GTK_COLOR (paintable);
gtk_snapshot_append_color (snapshot, &self->color, &GRAPHENE_RECT_INIT (0, 0, width, height));
}
static int
gtk_color_get_intrinsic_width (GdkPaintable *paintable)
{
return 32;
}
static int
gtk_color_get_intrinsic_height (GdkPaintable *paintable)
{
return 32;
}
static void
gtk_color_paintable_init (GdkPaintableInterface *iface)
{
iface->snapshot = gtk_color_snapshot;
iface->get_intrinsic_width = gtk_color_get_intrinsic_width;
iface->get_intrinsic_height = gtk_color_get_intrinsic_height;
}
/*
* Finally, we define the type. The important part is adding the paintable
* interface, so GTK knows that this object can indeed be drawm.
*/
G_DEFINE_TYPE_WITH_CODE (GtkColor, gtk_color, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
gtk_color_paintable_init))
static GParamSpec *color_properties[N_COLOR_PROPS] = { NULL, };
static void
rgb_to_hsv (GdkRGBA *rgba,
gdouble *h_out,
gdouble *s_out,
gdouble *v_out)
{
gdouble red, green, blue;
gdouble h, s, v;
gdouble min, max;
gdouble delta;
red = rgba->red;
green = rgba->green;
blue = rgba->blue;
h = 0.0;
if (red > green)
{
if (red > blue)
max = red;
else
max = blue;
if (green < blue)
min = green;
else
min = blue;
}
else
{
if (green > blue)
max = green;
else
max = blue;
if (red < blue)
min = red;
else
min = blue;
}
v = max;
if (max != 0.0)
s = (max - min) / max;
else
s = 0.0;
if (s == 0.0)
h = 0.0;
else
{
delta = max - min;
if (red == max)
h = (green - blue) / delta;
else if (green == max)
h = 2 + (blue - red) / delta;
else if (blue == max)
h = 4 + (red - green) / delta;
h /= 6.0;
if (h < 0.0)
h += 1.0;
else if (h > 1.0)
h -= 1.0;
}
*h_out = h;
*s_out = s;
*v_out = v;
}
static void
gtk_color_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GtkColor *self = GTK_COLOR (object);
switch (property_id)
{
case PROP_NAME:
g_value_set_string (value, self->name);
break;
case PROP_COLOR:
g_value_set_boxed (value, &self->color);
break;
case PROP_RED:
g_value_set_float (value, self->color.red);
break;
case PROP_GREEN:
g_value_set_float (value, self->color.green);
break;
case PROP_BLUE:
g_value_set_float (value, self->color.blue);
break;
case PROP_HUE:
g_value_set_int (value, self->h);
break;
case PROP_SATURATION:
g_value_set_int (value, self->s);
break;
case PROP_VALUE:
g_value_set_int (value, self->v);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gtk_color_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GtkColor *self = GTK_COLOR (object);
double h, s, v;
switch (property_id)
{
case PROP_NAME:
self->name = g_value_dup_string (value);
break;
case PROP_COLOR:
self->color = *(GdkRGBA *) g_value_dup_boxed (value);
rgb_to_hsv (&self->color, &h, &s, &v);
self->h = round (360 * h);
self->s = round (100 * s);
self->v = round (100 * v);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gtk_color_finalize (GObject *object)
{
GtkColor *self = GTK_COLOR (object);
g_free (self->name);
G_OBJECT_CLASS (gtk_color_parent_class)->finalize (object);
}
static void
gtk_color_class_init (GtkColorClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gtk_color_get_property;
gobject_class->set_property = gtk_color_set_property;
gobject_class->finalize = gtk_color_finalize;
color_properties[PROP_NAME] =
g_param_spec_string ("name", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
color_properties[PROP_COLOR] =
g_param_spec_boxed ("color", NULL, NULL, GDK_TYPE_RGBA, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
color_properties[PROP_RED] =
g_param_spec_float ("red", NULL, NULL, 0, 1, 0, G_PARAM_READABLE);
color_properties[PROP_GREEN] =
g_param_spec_float ("green", NULL, NULL, 0, 1, 0, G_PARAM_READABLE);
color_properties[PROP_BLUE] =
g_param_spec_float ("blue", NULL, NULL, 0, 1, 0, G_PARAM_READABLE);
color_properties[PROP_HUE] =
g_param_spec_int ("hue", NULL, NULL, 0, 360, 0, G_PARAM_READABLE);
color_properties[PROP_SATURATION] =
g_param_spec_int ("saturation", NULL, NULL, 0, 100, 0, G_PARAM_READABLE);
color_properties[PROP_VALUE] =
g_param_spec_int ("value", NULL, NULL, 0, 100, 0, G_PARAM_READABLE);
g_object_class_install_properties (gobject_class, N_COLOR_PROPS, color_properties);
}
static void
gtk_color_init (GtkColor *self)
{
}
static GtkColor *
gtk_color_new (const char *name,
float r, float g, float b)
{
GtkColor *result;
GdkRGBA color = { r, g, b, 1.0 };
result = g_object_new (GTK_TYPE_COLOR,
"name", name,
"color", &color,
NULL);
return result;
}
#define N_COLORS (256 * 256 * 256)
#define GTK_TYPE_COLOR_LIST (gtk_color_list_get_type ())
G_DECLARE_FINAL_TYPE (GtkColorList, gtk_color_list, GTK, COLOR_LIST, GObject)
enum {
LIST_PROP_0,
LIST_PROP_SIZE,
N_LIST_PROPS
};
typedef struct _GtkColorList GtkColorList;
struct _GtkColorList
{
GObject parent_instance;
GtkColor **colors; /* Always N_COLORS */
guint size; /* How many colors we allow */
};
static GType
gtk_color_list_get_item_type (GListModel *list)
{
return GTK_TYPE_COLOR;
}
static guint
gtk_color_list_get_n_items (GListModel *list)
{
GtkColorList *self = GTK_COLOR_LIST (list);
return self->size;
}
static guint
position_to_color (guint position)
{
static guint map[] = {
0xFF0000, 0x00FF00, 0x0000FF,
0x7F0000, 0x007F00, 0x00007F,
0x3F0000, 0x003F00, 0x00003F,
0x1F0000, 0x001F00, 0x00001F,
0x0F0000, 0x000F00, 0x00000F,
0x070000, 0x000700, 0x000007,
0x030000, 0x000300, 0x000003,
0x010000, 0x000100, 0x000001
};
guint result, i;
result = 0;
for (i = 0; i < G_N_ELEMENTS (map); i++)
{
if (position & (1 << i))
result ^= map[i];
}
return result;
}
static gpointer
gtk_color_list_get_item (GListModel *list,
guint position)
{
GtkColorList *self = GTK_COLOR_LIST (list);
if (position >= self->size)
return NULL;
position = position_to_color (position);
if (self->colors[position] == NULL)
{
guint red, green, blue;
red = (position >> 16) & 0xFF;
green = (position >> 8) & 0xFF;
blue = position & 0xFF;
self->colors[position] = gtk_color_new ("", red / 255., green / 255., blue / 255.);
}
return g_object_ref (self->colors[position]);
}
static void
gtk_color_list_model_init (GListModelInterface *iface)
{
iface->get_item_type = gtk_color_list_get_item_type;
iface->get_n_items = gtk_color_list_get_n_items;
iface->get_item = gtk_color_list_get_item;
}
G_DEFINE_TYPE_WITH_CODE (GtkColorList, gtk_color_list, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL,
gtk_color_list_model_init))
static GParamSpec *list_properties[N_LIST_PROPS] = { NULL, };
static void
gtk_color_list_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GtkColorList *self = GTK_COLOR_LIST (object);
switch (property_id)
{
case LIST_PROP_SIZE:
g_value_set_uint (value, self->size);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gtk_color_list_set_size (GtkColorList *self,
guint size)
{
guint old_size = self->size;
self->size = size;
if (self->size > old_size)
g_list_model_items_changed (G_LIST_MODEL (self), old_size, 0, self->size - old_size);
else if (old_size > self->size)
g_list_model_items_changed (G_LIST_MODEL (self), self->size, old_size - self->size, 0);
g_object_notify_by_pspec (G_OBJECT (self), list_properties[LIST_PROP_SIZE]);
}
static void
gtk_color_list_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GtkColorList *self = GTK_COLOR_LIST (object);
switch (property_id)
{
case LIST_PROP_SIZE:
gtk_color_list_set_size (self, g_value_get_uint (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
gtk_color_list_dispose (GObject *object)
{
GtkColorList *self = GTK_COLOR_LIST (object);
guint i;
for (i = 0; i < N_COLORS; i++)
{
g_clear_object (&self->colors[i]);
}
g_free (self->colors);
G_OBJECT_CLASS (gtk_color_parent_class)->finalize (object);
}
static void
gtk_color_list_class_init (GtkColorListClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gtk_color_list_get_property;
gobject_class->set_property = gtk_color_list_set_property;
gobject_class->dispose = gtk_color_list_dispose;
list_properties[LIST_PROP_SIZE] =
g_param_spec_uint ("size", NULL, NULL, 0, N_COLORS, 0, G_PARAM_READWRITE);
g_object_class_install_properties (gobject_class, N_LIST_PROPS, list_properties);
}
static void
gtk_color_list_init (GtkColorList *self)
{
GBytes *data;
char **lines;
guint i;
self->colors = g_new0 (GtkColor *, N_COLORS);
data = g_resources_lookup_data ("/listview_colors/color.names.txt", 0, NULL);
lines = g_strsplit (g_bytes_get_data (data, NULL), "\n", 0);
for (i = 0; lines[i]; i++)
{
const char *name;
char **fields;
int red, green, blue;
guint pos;
if (lines[i][0] == '#' || lines[i][0] == '\0')
continue;
fields = g_strsplit (lines[i], " ", 0);
name = fields[1];
red = atoi (fields[3]);
green = atoi (fields[4]);
blue = atoi (fields[5]);
pos = ((red & 0xFF) << 16) | ((green & 0xFF) << 8) | blue;
if (self->colors[pos] == NULL)
self->colors[pos] = gtk_color_new (name, red / 255., green / 255., blue / 255.);
g_strfreev (fields);
}
g_strfreev (lines);
g_bytes_unref (data);
}
static GListModel *
gtk_color_list_new (guint size)
{
return g_object_new (GTK_TYPE_COLOR_LIST,
"size", size,
NULL);
}
static char *
get_rgb_markup (gpointer this,
GtkColor *color)
{
if (!color)
return NULL;
return g_strdup_printf ("<b>R:</b> %d <b>G:</b> %d <b>B:</b> %d",
(int)(color->color.red * 255),
(int)(color->color.green * 255),
(int)(color->color.blue * 255));
}
static char *
get_hsv_markup (gpointer this,
GtkColor *color)
{
if (!color)
return NULL;
return g_strdup_printf ("<b>H:</b> %d <b>S:</b> %d <b>V:</b> %d",
color->h,
color->s,
color->v);
}
static void
setup_simple_listitem_cb (GtkListItemFactory *factory,
GtkListItem *list_item)
{
GtkWidget *picture;
GtkExpression *color_expression, *expression;
expression = gtk_constant_expression_new (GTK_TYPE_LIST_ITEM, list_item);
color_expression = gtk_property_expression_new (GTK_TYPE_LIST_ITEM, expression, "item");
picture = gtk_picture_new ();
gtk_widget_set_size_request (picture, 32, 32);
gtk_expression_bind (color_expression, picture, "paintable", NULL);
gtk_list_item_set_child (list_item, picture);
}
static void
setup_listitem_cb (GtkListItemFactory *factory,
GtkListItem *list_item)
{
GtkWidget *box, *picture, *name_label, *rgb_label, *hsv_label;
GtkExpression *color_expression, *expression;
GtkExpression *params[1];
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_list_item_set_child (list_item, box);
expression = gtk_constant_expression_new (GTK_TYPE_LIST_ITEM, list_item);
color_expression = gtk_property_expression_new (GTK_TYPE_LIST_ITEM, expression, "item");
expression = gtk_property_expression_new (GTK_TYPE_COLOR,
gtk_expression_ref (color_expression),
"name");
name_label = gtk_label_new (NULL);
gtk_expression_bind (expression, name_label, "label", NULL);
gtk_box_append (GTK_BOX (box), name_label);
expression = gtk_expression_ref (color_expression);
picture = gtk_picture_new ();
gtk_expression_bind (expression, picture, "paintable", NULL);
gtk_box_append (GTK_BOX (box), picture);
params[0] = gtk_expression_ref (color_expression);
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
NULL,
1, params,
(GCallback)get_rgb_markup,
NULL, NULL);
rgb_label = gtk_label_new (NULL);
gtk_label_set_use_markup (GTK_LABEL (rgb_label), TRUE);
gtk_expression_bind (expression, rgb_label, "label", NULL);
gtk_box_append (GTK_BOX (box), rgb_label);
params[0] = gtk_expression_ref (color_expression);
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
NULL,
1, params,
(GCallback)get_hsv_markup,
NULL, NULL);
hsv_label = gtk_label_new (NULL);
gtk_label_set_use_markup (GTK_LABEL (hsv_label), TRUE);
gtk_expression_bind (expression, hsv_label, "label", NULL);
gtk_box_append (GTK_BOX (box), hsv_label);
gtk_expression_unref (color_expression);
}
static void
set_title (gpointer item,
const char *title)
{
g_object_set_data (G_OBJECT (item), "title", (gpointer)title);
}
static char *
get_title (gpointer item)
{
return g_strdup ((char *)g_object_get_data (G_OBJECT (item), "title"));
}
GtkWidget *
create_color_grid (void)
{
GtkWidget *gridview;
GtkListItemFactory *factory;
GListModel *model, *selection;
gridview = gtk_grid_view_new ();
gtk_scrollable_set_hscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
gtk_scrollable_set_vscroll_policy (GTK_SCROLLABLE (gridview), GTK_SCROLL_NATURAL);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_simple_listitem_cb), NULL);
gtk_grid_view_set_factory (GTK_GRID_VIEW (gridview), factory);
g_object_unref (factory);
gtk_grid_view_set_max_columns (GTK_GRID_VIEW (gridview), 24);
gtk_grid_view_set_enable_rubberband (GTK_GRID_VIEW (gridview), TRUE);
model = G_LIST_MODEL (gtk_sort_list_model_new (gtk_color_list_new (0), NULL));
selection = G_LIST_MODEL (gtk_multi_selection_new (model));
gtk_grid_view_set_model (GTK_GRID_VIEW (gridview), selection);
g_object_unref (selection);
g_object_unref (model);
return gridview;
}
static gboolean
add_colors (GtkWidget *widget,
GdkFrameClock *clock,
gpointer data)
{
GtkColorList *colors = data;
guint limit;
limit = GPOINTER_TO_UINT (g_object_get_data (data, "limit"));
gtk_color_list_set_size (colors, MIN (limit, colors->size + MAX (1, limit / 4096)));
if (colors->size >= limit)
return G_SOURCE_REMOVE;
else
return G_SOURCE_CONTINUE;
}
static void
refill (GtkWidget *button,
GtkColorList *colors)
{
gtk_color_list_set_size (colors, 0);
gtk_widget_add_tick_callback (button, add_colors, g_object_ref (colors), g_object_unref);
}
static void
limit_changed_cb (GtkDropDown *dropdown,
GParamSpec *pspec,
GtkColorList *colors)
{
guint new_limit, old_limit;
old_limit = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (colors), "limit"));
new_limit = 1 << (3 * (gtk_drop_down_get_selected (dropdown) + 1));
g_object_set_data (G_OBJECT (colors), "limit", GUINT_TO_POINTER (new_limit));
if (old_limit == colors->size)
gtk_color_list_set_size (colors, new_limit);
}
static void
limit_changed_cb2 (GtkDropDown *dropdown,
GParamSpec *pspec,
GtkLabel *label)
{
char *string;
int len;
guint limit;
limit = 1 << (3 * (gtk_drop_down_get_selected (dropdown) + 1));
string = g_strdup_printf ("%'u", limit);
len = g_utf8_strlen (string, -1);
g_free (string);
gtk_label_set_width_chars (label, len + 2); /* for " /" */
}
static void
items_changed_cb (GListModel *model,
guint position,
guint removed,
guint added,
GtkWidget *label)
{
guint n = g_list_model_get_n_items (model);
char *text;
text = g_strdup_printf ("%'u /", n);
gtk_label_set_label (GTK_LABEL (label), text);
g_free (text);
}
static void
setup_number_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkWidget *label;
PangoAttrList *attrs;
label = gtk_label_new ("");
gtk_label_set_xalign (GTK_LABEL (label), 1);
attrs = pango_attr_list_new ();
pango_attr_list_insert (attrs, pango_attr_font_features_new ("tnum"));
gtk_label_set_attributes (GTK_LABEL (label), attrs);
pango_attr_list_unref (attrs);
gtk_list_item_set_child (item, label);
}
static void
bind_number_item (GtkSignalListItemFactory *factory,
GtkListItem *item)
{
GtkWidget *label;
guint limit;
char *string;
label = gtk_list_item_get_child (item);
limit = 1 << (3 * (gtk_list_item_get_position (item) + 1));
string = g_strdup_printf ("%'u", limit);
gtk_label_set_label (GTK_LABEL (label), string);
g_free (string);
}
static GtkWidget *window = NULL;
GtkWidget *
do_listview_colors (GtkWidget *do_widget)
{
if (window == NULL)
{
GtkWidget *header, *gridview, *sw, *box, *dropdown;
GtkListItemFactory *factory;
GListStore *factories;
GListModel *model;
GtkSorter *sorter;
GtkSorter *multi_sorter;
GListStore *sorters;
GtkExpression *expression;
GtkWidget *button;
GtkWidget *label;
PangoAttrList *attrs;
char *string;
guint len;
window = gtk_window_new ();
gtk_window_set_title (GTK_WINDOW (window), "Colors");
header = gtk_header_bar_new ();
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer*)&window);
sw = gtk_scrolled_window_new ();
gtk_window_set_child (GTK_WINDOW (window), sw);
gridview = create_color_grid ();
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), gridview);
model = gtk_grid_view_get_model (GTK_GRID_VIEW (gridview));
g_object_get (model, "model", &model, NULL);
button = gtk_button_new_with_mnemonic ("_Refill");
g_signal_connect (button, "clicked",
G_CALLBACK (refill),
gtk_sort_list_model_get_model (GTK_SORT_LIST_MODEL (model)));
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button);
label = gtk_label_new ("0 /");
attrs = pango_attr_list_new ();
pango_attr_list_insert (attrs, pango_attr_font_features_new ("tnum"));
gtk_label_set_attributes (GTK_LABEL (label), attrs);
pango_attr_list_unref (attrs);
string = g_strdup_printf ("%'u", 4096);
len = g_utf8_strlen (string, -1);
g_free (string);
gtk_label_set_width_chars (GTK_LABEL (label), len + 2);
gtk_label_set_xalign (GTK_LABEL (label), 1);
g_signal_connect (gtk_grid_view_get_model (GTK_GRID_VIEW (gridview)),
"items-changed", G_CALLBACK (items_changed_cb), label);
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), label);
dropdown = gtk_drop_down_new ();
gtk_drop_down_set_from_strings (GTK_DROP_DOWN (dropdown), (const char *[]) { "8", "64", "512", "4096", "32768", "262144", "2097152", "16777216", NULL });
g_signal_connect (dropdown, "notify::selected",
G_CALLBACK (limit_changed_cb),
gtk_sort_list_model_get_model (GTK_SORT_LIST_MODEL (model)));
g_signal_connect (dropdown, "notify::selected",
G_CALLBACK (limit_changed_cb2),
label);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_number_item), NULL);
g_signal_connect (factory, "bind", G_CALLBACK (bind_number_item), NULL);
gtk_drop_down_set_factory (GTK_DROP_DOWN (dropdown), factory);
g_object_unref (factory);
gtk_drop_down_set_selected (GTK_DROP_DOWN (dropdown), 3); /* 4096 */
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), dropdown);
sorters = g_list_store_new (GTK_TYPE_SORTER);
/* An empty multisorter doesn't do any sorting and the sortmodel is
* smart enough to know that.
*/
sorter = gtk_multi_sorter_new ();
set_title (sorter, "Unsorted");
g_list_store_append (sorters, sorter);
g_object_unref (sorter);
sorter = gtk_string_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "name"));
set_title (sorter, "Name");
g_list_store_append (sorters, sorter);
g_object_unref (sorter);
multi_sorter = gtk_multi_sorter_new ();
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "red"));
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
set_title (sorter, "Red");
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "green"));
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
set_title (sorter, "Green");
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "blue"));
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
set_title (sorter, "Blue");
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
set_title (multi_sorter, "RGB");
g_list_store_append (sorters, multi_sorter);
g_object_unref (multi_sorter);
multi_sorter = gtk_multi_sorter_new ();
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "hue"));
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
set_title (sorter, "Hue");
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "saturation"));
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
set_title (sorter, "Saturation");
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
sorter = gtk_numeric_sorter_new (gtk_property_expression_new (GTK_TYPE_COLOR, NULL, "value"));
gtk_numeric_sorter_set_sort_order (GTK_NUMERIC_SORTER (sorter), GTK_SORT_DESCENDING);
set_title (sorter, "Value");
g_list_store_append (sorters, sorter);
gtk_multi_sorter_append (GTK_MULTI_SORTER (multi_sorter), sorter);
set_title (multi_sorter, "HSV");
g_list_store_append (sorters, multi_sorter);
g_object_unref (multi_sorter);
dropdown = gtk_drop_down_new ();
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_box_append (GTK_BOX (box), gtk_label_new ("Sort by:"));
gtk_box_append (GTK_BOX (box), dropdown);
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), box);
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
NULL,
0, NULL,
(GCallback)get_title,
NULL, NULL);
gtk_drop_down_set_expression (GTK_DROP_DOWN (dropdown), expression);
gtk_expression_unref (expression);
gtk_drop_down_set_model (GTK_DROP_DOWN (dropdown), G_LIST_MODEL (sorters));
g_object_unref (sorters);
g_object_bind_property (dropdown, "selected-item", model, "sorter", G_BINDING_SYNC_CREATE);
factories = g_list_store_new (GTK_TYPE_LIST_ITEM_FACTORY);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_simple_listitem_cb), NULL);
set_title (factory, "Colors");
g_list_store_append (factories, factory);
factory = gtk_signal_list_item_factory_new ();
g_signal_connect (factory, "setup", G_CALLBACK (setup_listitem_cb), NULL);
set_title (factory, "Everything");
g_list_store_append (factories, factory);
dropdown = gtk_drop_down_new ();
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_box_append (GTK_BOX (box), gtk_label_new ("Show:"));
gtk_box_append (GTK_BOX (box), dropdown);
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), box);
expression = gtk_cclosure_expression_new (G_TYPE_STRING,
NULL,
0, NULL,
(GCallback)get_title,
NULL, NULL);
gtk_drop_down_set_expression (GTK_DROP_DOWN (dropdown), expression);
gtk_expression_unref (expression);
gtk_drop_down_set_model (GTK_DROP_DOWN (dropdown), G_LIST_MODEL (factories));
g_object_unref (factories);
g_object_bind_property (dropdown, "selected-item", gridview, "factory", G_BINDING_SYNC_CREATE);
g_object_unref (model);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

View File

@@ -1,281 +0,0 @@
/* Lists/File browser
*
* This demo shows off the different layouts that are quickly achievable
* with GtkListview and GtkGridView by implementing a file browser with
* different views.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
static GtkWidget *window = NULL;
/* Create a simple object that holds the data for the different views */
typedef struct _FileBrowserView FileBrowserView;
struct _FileBrowserView
{
GObject parent_instance;
GtkListItemFactory *factory;
char *icon_name;
char *title;
GtkOrientation orientation;
};
enum {
PROP_0,
PROP_FACTORY,
PROP_ICON_NAME,
PROP_TITLE,
PROP_ORIENTATION,
N_PROPS
};
#define FILE_BROWSER_TYPE_VIEW (file_browser_view_get_type ())
G_DECLARE_FINAL_TYPE (FileBrowserView, file_browser_view, FILE_BROWSER, VIEW, GObject);
G_DEFINE_TYPE (FileBrowserView, file_browser_view, G_TYPE_OBJECT);
static GParamSpec *properties[N_PROPS] = { NULL, };
static void
file_browser_view_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
FileBrowserView *self = FILE_BROWSER_VIEW (object);
switch (property_id)
{
case PROP_FACTORY:
g_value_set_object (value, self->factory);
break;
case PROP_ICON_NAME:
g_value_set_string (value, self->icon_name);
break;
case PROP_TITLE:
g_value_set_string (value, self->title);
break;
case PROP_ORIENTATION:
g_value_set_enum (value, self->orientation);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
file_browser_view_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
FileBrowserView *self = FILE_BROWSER_VIEW (object);
switch (prop_id)
{
case PROP_FACTORY:
g_set_object (&self->factory, g_value_get_object (value));
break;
case PROP_ICON_NAME:
g_free (self->icon_name);
self->icon_name = g_value_dup_string (value);
break;
case PROP_TITLE:
g_free (self->title);
self->title = g_value_dup_string (value);
break;
case PROP_ORIENTATION:
self->orientation = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
file_browser_view_finalize (GObject *object)
{
FileBrowserView *self = FILE_BROWSER_VIEW (object);
g_object_unref (self->factory);
g_free (self->icon_name);
g_free (self->title);
G_OBJECT_CLASS (file_browser_view_parent_class)->dispose (object);
}
static void
file_browser_view_class_init (FileBrowserViewClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = file_browser_view_get_property;
gobject_class->set_property = file_browser_view_set_property;
gobject_class->finalize = file_browser_view_finalize;
properties[PROP_FACTORY] =
g_param_spec_object ("factory",
"factory",
"factory to use in the main view",
GTK_TYPE_LIST_ITEM_FACTORY,
G_PARAM_READWRITE);
properties[PROP_ICON_NAME] =
g_param_spec_string ("icon-name",
"icon name",
"icon to display for selecting this view",
NULL,
G_PARAM_READWRITE);
properties[PROP_TITLE] =
g_param_spec_string ("title",
"title",
"title to display for selecting this view",
NULL,
G_PARAM_READWRITE);
properties[PROP_ORIENTATION] =
g_param_spec_enum ("orientation",
"orientation",
"orientation of the view",
GTK_TYPE_ORIENTATION,
GTK_ORIENTATION_VERTICAL,
G_PARAM_READWRITE);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
static void file_browser_view_init (FileBrowserView *self)
{
}
char *
filebrowser_get_display_name (GObject *object,
GFileInfo *info)
{
if (!info)
return NULL;
return g_strdup (g_file_info_get_attribute_string (info, "standard::display-name"));
}
char *
filebrowser_get_content_type (GObject *object,
GFileInfo *info)
{
if (!info)
return NULL;
return g_strdup (g_file_info_get_attribute_string (info, "standard::content-type"));
}
char *
filebrowser_get_size (GObject *object,
GFileInfo *info)
{
if (!info)
return NULL;
return g_format_size (g_file_info_get_attribute_uint64 (info, "standard::size"));
}
GIcon *
filebrowser_get_icon (GObject *object,
GFileInfo *info)
{
GIcon *icon;
if (info)
icon = G_ICON (g_file_info_get_attribute_object (info, "standard::icon"));
else
icon = NULL;
if (icon)
g_object_ref (icon);
return icon;
}
void
filebrowser_up_clicked_cb (GtkButton *button,
GtkDirectoryList *list)
{
GFile *file;
file = g_file_get_parent (gtk_directory_list_get_file (list));
if (file == NULL)
return;
gtk_directory_list_set_file (list, file);
}
void
filebrowser_view_activated_cb (GtkGridView *view,
guint pos,
GtkDirectoryList *list)
{
GFileInfo *info;
info = g_list_model_get_item (gtk_grid_view_get_model (view), pos);
if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
gtk_directory_list_set_file (list, G_FILE (g_file_info_get_attribute_object (info, "standard::file")));
g_object_unref (info);
}
GtkWidget *
do_listview_filebrowser (GtkWidget *do_widget)
{
if (!window)
{
GtkWidget *view;
GtkBuilder *builder;
GtkDirectoryList *dirlist;
GFile *file;
char *cwd;
GtkCssProvider *provider;
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/listview_filebrowser/listview_filebrowser.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
800);
g_object_unref (provider);
builder = gtk_builder_new_from_resource ("/listview_filebrowser/listview_filebrowser.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
/* Create the model and fill it with the contents of the current directory */
cwd = g_get_current_dir ();
file = g_file_new_for_path (cwd);
g_free (cwd);
dirlist = GTK_DIRECTORY_LIST (gtk_builder_get_object (builder, "dirlist"));
gtk_directory_list_set_file (dirlist, file);
g_object_unref (file);
/* grab focus in the view */
view = GTK_WIDGET (gtk_builder_get_object (builder, "view"));
gtk_widget_grab_focus (view);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

View File

@@ -1,11 +0,0 @@
list.viewswitcher {
border: 1px solid gray;
}
list.viewswitcher > row {
padding: 5px;
}
list.viewswitcher row:selected {
background: gray;
}

View File

@@ -1,249 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GListStore" id="viewlist">
<property name="item-type">FileBrowserView</property>
<child>
<object class="FileBrowserView">
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkBox">
<child>
<object class="GtkImage">
<binding name="gicon">
<closure type="GIcon" function="filebrowser_get_icon">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="halign">start</property>
<binding name="label">
<closure type="gchararray" function="filebrowser_get_display_name">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
</object>
</child>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
<property name="icon-name">view-list-symbolic</property>
<property name="title" translatable="yes">List</property>
<property name="orientation">horizontal</property>
</object>
</child>
<child>
<object class="FileBrowserView">
<property name="icon-name">view-grid-symbolic</property>
<property name="title" translatable="yes">Grid</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkImage">
<property name="icon-size">large</property>
<binding name="gicon">
<closure type="GIcon" function="filebrowser_get_icon">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="wrap">1</property>
<property name="wrap-mode">word-char</property>
<property name="lines">2</property>
<property name="ellipsize">end</property>
<property name="width-chars">10</property>
<property name="max-width-chars">30</property>
<binding name="label">
<closure type="gchararray" function="filebrowser_get_display_name">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
</object>
</child>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
<property name="orientation">vertical</property>
</object>
</child>
<child>
<object class="FileBrowserView">
<property name="icon-name">view-paged-symbolic</property>
<property name="title" translatable="yes">Paged</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkBox">
<child>
<object class="GtkImage">
<property name="icon-size">large</property>
<binding name="gicon">
<closure type="GIcon" function="filebrowser_get_icon">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="halign">start</property>
<binding name="label">
<closure type="gchararray" function="filebrowser_get_display_name">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="halign">start</property>
<binding name="label">
<closure type="gchararray" function="filebrowser_get_size">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel">
<property name="halign">start</property>
<binding name="label">
<closure type="gchararray" function="filebrowser_get_content_type">
<lookup name="item">GtkListItem</lookup>
</closure>
</binding>
<style>
<class name="dim-label"/>
</style>
</object>
</child>
</object>
</child>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
<property name="orientation">horizontal</property>
</object>
</child>
</object>
<object class="GtkDirectoryList" id="dirlist">
<property name="attributes">standard::name,standard::display-name,standard::icon,standard::size,standard::content-type</property>
</object>
<object class="GtkWindow" id="window">
<property name="title" translatable="yes">File browser</property>
<property name="default-width">600</property>
<property name="default-height">400</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="">
<property name="show-title-buttons">1</property>
<child>
<object class="GtkButton">
<property name="icon-name">go-up-symbolic</property>
<signal name="clicked" handler="filebrowser_up_clicked_cb" object="dirlist" swapped="no"/>
</object>
</child>
<child type="end">
<object class="GtkListView">
<property name="valign">center</property>
<property name="orientation">horizontal</property>
<style>
<class name="linked"/>
<class name="viewswitcher"/>
</style>
<property name="model">
<object class="GtkSingleSelection" id="selected-view">
<property name="model">viewlist</property>
</object>
</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkImage">
<binding name="icon-name">
<lookup type="FileBrowserView" name="icon-name">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
<binding name="tooltip-text">
<lookup type="FileBrowserView" name="title">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="can-focus">1</property>
<child>
<object class="GtkGridView" id="view">
<property name="model">dirlist</property>
<property name="max-columns">15</property>
<binding name="factory">
<lookup name="factory" type="FileBrowserView">
<lookup name="selected-item">selected-view</lookup>
</lookup>
</binding>
<binding name="orientation">
<lookup name="orientation" type="FileBrowserView">
<lookup name="selected-item">selected-view</lookup>
</lookup>
</binding>
<signal name="activate" handler="filebrowser_view_activated_cb" object="dirlist" swapped="no"/>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -1,472 +0,0 @@
/* Lists/Minesweeper
*
* This demo shows how to develop a user interface for small game using a
* gridview.
*
* It demonstrates how to use the activate signal and single-press behavior
* to implement rather different interaction behavior to a typical list.
*/
#include <glib/gi18n.h>
#include <gtk/gtk.h>
/*** The cell object ***/
/* Create an object that holds the data for a cell in the game */
typedef struct _SweeperCell SweeperCell;
struct _SweeperCell
{
GObject parent_instance;
gboolean is_mine;
gboolean is_visible;
guint neighbor_mines;
};
enum {
CELL_PROP_0,
CELL_PROP_LABEL,
N_CELL_PROPS
};
#define SWEEPER_TYPE_CELL (sweeper_cell_get_type ())
G_DECLARE_FINAL_TYPE (SweeperCell, sweeper_cell, SWEEPER, CELL, GObject);
G_DEFINE_TYPE (SweeperCell, sweeper_cell, G_TYPE_OBJECT);
static GParamSpec *cell_properties[N_CELL_PROPS] = { NULL, };
static const char *
sweeper_cell_get_label (SweeperCell *self)
{
static const char *minecount_labels[10] = { "", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
if (!self->is_visible)
return "?";
if (self->is_mine)
return "💣";
return minecount_labels[self->neighbor_mines];
}
static void
sweeper_cell_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
SweeperCell *self = SWEEPER_CELL (object);
switch (property_id)
{
case CELL_PROP_LABEL:
g_value_set_string (value, sweeper_cell_get_label (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
sweeper_cell_class_init (SweeperCellClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = sweeper_cell_get_property;
cell_properties[CELL_PROP_LABEL] =
g_param_spec_string ("label",
"label",
"label to display for this row",
NULL,
G_PARAM_READABLE);
g_object_class_install_properties (gobject_class, N_CELL_PROPS, cell_properties);
}
static void
sweeper_cell_init (SweeperCell *self)
{
}
static void
sweeper_cell_reveal (SweeperCell *self)
{
if (self->is_visible)
return;
self->is_visible = TRUE;
g_object_notify_by_pspec (G_OBJECT (self), cell_properties[CELL_PROP_LABEL]);
}
static SweeperCell *
sweeper_cell_new (void)
{
return g_object_new (SWEEPER_TYPE_CELL, NULL);
}
/*** The board object ***/
/* Create an object that holds the data for the game */
typedef struct _SweeperGame SweeperGame;
struct _SweeperGame
{
GObject parent_instance;
GPtrArray *cells;
guint width;
guint height;
gboolean playing;
gboolean win;
};
enum {
GAME_PROP_0,
GAME_PROP_HEIGHT,
GAME_PROP_PLAYING,
GAME_PROP_WIDTH,
GAME_PROP_WIN,
N_GAME_PROPS
};
#define SWEEPER_TYPE_GAME (sweeper_game_get_type ())
G_DECLARE_FINAL_TYPE (SweeperGame, sweeper_game, SWEEPER, GAME, GObject);
static GType
sweeper_game_list_model_get_item_type (GListModel *model)
{
return SWEEPER_TYPE_GAME;
}
static guint
sweeper_game_list_model_get_n_items (GListModel *model)
{
SweeperGame *self = SWEEPER_GAME (model);
return self->width * self->height;
}
static gpointer
sweeper_game_list_model_get_item (GListModel *model,
guint position)
{
SweeperGame *self = SWEEPER_GAME (model);
return g_object_ref (g_ptr_array_index (self->cells, position));
}
static void
sweeper_game_list_model_init (GListModelInterface *iface)
{
iface->get_item_type = sweeper_game_list_model_get_item_type;
iface->get_n_items = sweeper_game_list_model_get_n_items;
iface->get_item = sweeper_game_list_model_get_item;
}
G_DEFINE_TYPE_WITH_CODE (SweeperGame, sweeper_game, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, sweeper_game_list_model_init))
static GParamSpec *game_properties[N_GAME_PROPS] = { NULL, };
static void
sweeper_game_dispose (GObject *object)
{
SweeperGame *self = SWEEPER_GAME (object);
g_clear_pointer (&self->cells, g_ptr_array_unref);
G_OBJECT_CLASS (sweeper_game_parent_class)->dispose (object);
}
static void
sweeper_game_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
SweeperGame *self = SWEEPER_GAME (object);
switch (property_id)
{
case GAME_PROP_HEIGHT:
g_value_set_uint (value, self->height);
break;
case GAME_PROP_PLAYING:
g_value_set_boolean (value, self->playing);
break;
case GAME_PROP_WIDTH:
g_value_set_uint (value, self->width);
break;
case GAME_PROP_WIN:
g_value_set_boolean (value, self->win);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
sweeper_game_class_init (SweeperGameClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = sweeper_game_dispose;
gobject_class->get_property = sweeper_game_get_property;
game_properties[GAME_PROP_HEIGHT] =
g_param_spec_uint ("height",
"height",
"height of the game grid",
1, G_MAXUINT, 8,
G_PARAM_READABLE);
game_properties[GAME_PROP_PLAYING] =
g_param_spec_boolean ("playing",
"playing",
"if the game is still going on",
FALSE,
G_PARAM_READABLE);
game_properties[GAME_PROP_WIDTH] =
g_param_spec_uint ("width",
"width",
"width of the game grid",
1, G_MAXUINT, 8,
G_PARAM_READABLE);
game_properties[GAME_PROP_WIN] =
g_param_spec_boolean ("win",
"win",
"if the game was won",
FALSE,
G_PARAM_READABLE);
g_object_class_install_properties (gobject_class, N_GAME_PROPS, game_properties);
}
static void
sweeper_game_reset_board (SweeperGame *self,
guint width,
guint height)
{
guint i;
g_ptr_array_set_size (self->cells, 0);
for (i = 0; i < width * height; i++)
{
g_ptr_array_add (self->cells, sweeper_cell_new ());
}
if (self->width != width)
{
self->width = width;
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_WIDTH]);
}
if (self->height != height)
{
self->height = height;
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_HEIGHT]);
}
if (!self->playing)
{
self->playing = TRUE;
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_PLAYING]);
}
if (self->win)
{
self->win = FALSE;
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_WIN]);
}
}
static void
sweeper_game_place_mines (SweeperGame *self,
guint n_mines)
{
guint i;
for (i = 0; i < n_mines; i++)
{
SweeperCell *cell;
do {
cell = g_ptr_array_index (self->cells, g_random_int_range (0, self->cells->len));
} while (cell->is_mine);
cell->is_mine = TRUE;
}
}
static SweeperCell *
get_cell (SweeperGame *self,
guint x,
guint y)
{
return g_ptr_array_index (self->cells, y * self->width + x);
}
static void
sweeper_game_count_neighbor_mines (SweeperGame *self,
guint width,
guint height)
{
guint x, y, x2, y2;
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
SweeperCell *cell = get_cell (self, x, y);
for (y2 = MAX (1, y) - 1; y2 < MIN (height, y + 2); y2++)
{
for (x2 = MAX (1, x) - 1; x2 < MIN (width, x + 2); x2++)
{
SweeperCell *other = get_cell (self, x2, y2);
if (other->is_mine)
cell->neighbor_mines++;
}
}
}
}
}
static void
sweeper_game_new_game (SweeperGame *self,
guint width,
guint height,
guint n_mines)
{
guint n_items_before;
g_return_if_fail (n_mines <= width * height);
n_items_before = self->width * self->height;
g_object_freeze_notify (G_OBJECT (self));
sweeper_game_reset_board (self, width, height);
sweeper_game_place_mines (self, n_mines);
sweeper_game_count_neighbor_mines (self, width, height);
g_list_model_items_changed (G_LIST_MODEL (self), 0, n_items_before, width * height);
g_object_thaw_notify (G_OBJECT (self));
}
static void
sweeper_game_init (SweeperGame *self)
{
self->cells = g_ptr_array_new_with_free_func (g_object_unref);
sweeper_game_new_game (self, 8, 8, 10);
}
static void
sweeper_game_end (SweeperGame *self,
gboolean win)
{
if (self->playing)
{
self->playing = FALSE;
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_PLAYING]);
}
if (self->win != win)
{
self->win = win;
g_object_notify_by_pspec (G_OBJECT (self), game_properties[GAME_PROP_WIN]);
}
}
static void
sweeper_game_check_finished (SweeperGame *self)
{
guint i;
if (!self->playing)
return;
for (i = 0; i < self->cells->len; i++)
{
SweeperCell *cell = g_ptr_array_index (self->cells, i);
/* There's still a non-revealed cell that isn't a mine */
if (!cell->is_visible && !cell->is_mine)
return;
}
sweeper_game_end (self, TRUE);
}
static void
sweeper_game_reveal_cell (SweeperGame *self,
guint position)
{
SweeperCell *cell;
if (!self->playing)
return;
cell = g_ptr_array_index (self->cells, position);
sweeper_cell_reveal (cell);
if (cell->is_mine)
sweeper_game_end (self, FALSE);
sweeper_game_check_finished (self);
}
void
minesweeper_cell_clicked_cb (GtkGridView *gridview,
guint pos,
SweeperGame *game)
{
sweeper_game_reveal_cell (game, pos);
}
void
minesweeper_new_game_cb (GtkButton *button,
SweeperGame *game)
{
sweeper_game_new_game (game, 8, 8, 10);
}
static GtkWidget *window = NULL;
GtkWidget *
do_listview_minesweeper (GtkWidget *do_widget)
{
if (window == NULL)
{
GtkBuilder *builder;
g_type_ensure (SWEEPER_TYPE_GAME);
builder = gtk_builder_new_from_resource ("/listview_minesweeper/listview_minesweeper.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

View File

@@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="SweeperGame" id="game">
</object>
<object class="GtkWindow" id="window">
<property name="title" translatable="yes">Minesweeper</property>
<child type="titlebar">
<object class="GtkHeaderBar" id="">
<property name="show-title-buttons">1</property>
<child>
<object class="GtkButton">
<property name="label">New Game</property>
<signal name="clicked" handler="minesweeper_new_game_cb" object="game" swapped="no"/>
</object>
</child>
<child type="title">
<object class="GtkImage">
<property name="icon-name">trophy-gold</property>
<binding name="visible">
<lookup name="win">game</lookup>
</binding>
</object>
</child>
</object>
</child>
<child>
<object class="GtkGridView" id="view">
<property name="model">
<object class="GtkNoSelection">
<property name="model">game</property>
</object>
</property>
<property name="single-click-activate">1</property>
<binding name="max-columns">
<lookup name="width">game</lookup>
</binding>
<binding name="min-columns">
<lookup name="width">game</lookup>
</binding>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="resource">/listview_minesweeper/listview_minesweeper_cell.ui</property>
</object>
</property>
<signal name="activate" handler="minesweeper_cell_clicked_cb" object="game" swapped="no"/>
</object>
</child>
</object>
</interface>

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<property name="halign">center</property>
<property name="valign">center</property>
<binding name="label">
<lookup name="label" type="SweeperCell">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>

View File

@@ -1,442 +0,0 @@
/* Lists/Settings
*
* This demo shows a settings viewer for GSettings.
*
* It demonstrates how to implement support for trees with GtkListView.
* It also shows how to set up sorting and filtering for columns in a
* GtkColumnView.
*/
#include <gtk/gtk.h>
#include <stdlib.h>
/* Create an object that wraps GSettingsSchemaKey because that's a boxed type */
typedef struct _SettingsKey SettingsKey;
struct _SettingsKey
{
GObject parent_instance;
GSettings *settings;
GSettingsSchemaKey *key;
};
enum {
PROP_0,
PROP_NAME,
PROP_SUMMARY,
PROP_DESCRIPTION,
PROP_VALUE,
PROP_TYPE,
PROP_DEFAULT_VALUE,
N_PROPS
};
#define SETTINGS_TYPE_KEY (settings_key_get_type ())
G_DECLARE_FINAL_TYPE (SettingsKey, settings_key, SETTINGS, KEY, GObject);
G_DEFINE_TYPE (SettingsKey, settings_key, G_TYPE_OBJECT);
static GParamSpec *properties[N_PROPS] = { NULL, };
static void
settings_key_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
SettingsKey *self = SETTINGS_KEY (object);
switch (property_id)
{
case PROP_DESCRIPTION:
g_value_set_string (value, g_settings_schema_key_get_description (self->key));
break;
case PROP_NAME:
g_value_set_string (value, g_settings_schema_key_get_name (self->key));
break;
case PROP_SUMMARY:
g_value_set_string (value, g_settings_schema_key_get_summary (self->key));
break;
case PROP_VALUE:
{
GVariant *variant = g_settings_get_value (self->settings, g_settings_schema_key_get_name (self->key));
g_value_take_string (value, g_variant_print (variant, FALSE));
g_variant_unref (variant);
}
break;
case PROP_TYPE:
{
const GVariantType *type = g_settings_schema_key_get_value_type (self->key);
g_value_set_string (value, g_variant_type_peek_string (type));
}
break;
case PROP_DEFAULT_VALUE:
{
GVariant *variant = g_settings_schema_key_get_default_value (self->key);
g_value_take_string (value, g_variant_print (variant, FALSE));
g_variant_unref (variant);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
settings_key_finalize (GObject *object)
{
SettingsKey *self = SETTINGS_KEY (object);
g_object_unref (self->settings);
g_settings_schema_key_unref (self->key);
G_OBJECT_CLASS (settings_key_parent_class)->finalize (object);
}
static void
settings_key_class_init (SettingsKeyClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = settings_key_finalize;
gobject_class->get_property = settings_key_get_property;
properties[PROP_DESCRIPTION] =
g_param_spec_string ("description", NULL, NULL, NULL, G_PARAM_READABLE);
properties[PROP_NAME] =
g_param_spec_string ("name", NULL, NULL, NULL, G_PARAM_READABLE);
properties[PROP_SUMMARY] =
g_param_spec_string ("summary", NULL, NULL, NULL, G_PARAM_READABLE);
properties[PROP_VALUE] =
g_param_spec_string ("value", NULL, NULL, NULL, G_PARAM_READABLE);
properties[PROP_TYPE] =
g_param_spec_string ("type", NULL, NULL, NULL, G_PARAM_READABLE);
properties[PROP_DEFAULT_VALUE] =
g_param_spec_string ("default-value", NULL, NULL, NULL, G_PARAM_READABLE);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
static void
settings_key_init (SettingsKey *self)
{
}
static SettingsKey *
settings_key_new (GSettings *settings,
GSettingsSchemaKey *key)
{
SettingsKey *result = g_object_new (SETTINGS_TYPE_KEY, NULL);
result->settings = g_object_ref (settings);
result->key = g_settings_schema_key_ref (key);
return result;
}
static void
item_value_changed (GtkEditableLabel *label,
GParamSpec *pspec,
GtkListItem *item)
{
SettingsKey *self;
const char *text;
const GVariantType *type;
GVariant *variant;
GError *error = NULL;
const char *name;
char *value;
text = gtk_editable_get_text (GTK_EDITABLE (label));
g_object_get (item, "item", &self, NULL);
g_object_unref (self);
type = g_settings_schema_key_get_value_type (self->key);
name = g_settings_schema_key_get_name (self->key);
variant = g_variant_parse (type, text, NULL, NULL, &error);
if (!variant)
{
g_warning ("%s", error->message);
g_clear_error (&error);
goto revert;
}
if (!g_settings_schema_key_range_check (self->key, variant))
{
g_warning ("Not a valid value for %s", name);
goto revert;
}
g_settings_set_value (self->settings, name, variant);
g_variant_unref (variant);
return;
revert:
gtk_widget_error_bell (GTK_WIDGET (label));
g_object_get (self, "value", &value, NULL);
gtk_editable_set_text (GTK_EDITABLE (label), value);
g_free (value);
}
static int
strvcmp (gconstpointer p1,
gconstpointer p2)
{
const char * const *s1 = p1;
const char * const *s2 = p2;
return strcmp (*s1, *s2);
}
static GtkFilter *current_filter;
static gboolean
transform_settings_to_keys (GBinding *binding,
const GValue *from_value,
GValue *to_value,
gpointer data)
{
GtkTreeListRow *treelistrow;
GSettings *settings;
GSettingsSchema *schema;
GListStore *store;
GtkSortListModel *sort_model;
GtkFilterListModel *filter_model;
GtkFilter *filter;
GtkNoSelection *selection_model;
GtkExpression *expression;
char **keys;
guint i;
treelistrow = g_value_get_object (from_value);
if (treelistrow == NULL)
return TRUE;
settings = gtk_tree_list_row_get_item (treelistrow);
g_object_get (settings, "settings-schema", &schema, NULL);
store = g_list_store_new (SETTINGS_TYPE_KEY);
keys = g_settings_schema_list_keys (schema);
for (i = 0; keys[i] != NULL; i++)
{
GSettingsSchemaKey *almost_there = g_settings_schema_get_key (schema, keys[i]);
SettingsKey *finally = settings_key_new (settings, almost_there);
g_list_store_append (store, finally);
g_object_unref (finally);
g_settings_schema_key_unref (almost_there);
}
g_strfreev (keys);
g_settings_schema_unref (schema);
g_object_unref (settings);
sort_model = gtk_sort_list_model_new (G_LIST_MODEL (store),
gtk_column_view_get_sorter (GTK_COLUMN_VIEW (data)));
g_object_unref (store);
expression = gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name");
filter = gtk_string_filter_new ();
gtk_string_filter_set_expression (GTK_STRING_FILTER (filter), expression);
filter_model = gtk_filter_list_model_new (G_LIST_MODEL (sort_model), filter);
gtk_expression_unref (expression);
g_object_unref (sort_model);
g_set_object (&current_filter, filter);
g_object_unref (filter);
selection_model = gtk_no_selection_new (G_LIST_MODEL (filter_model));
g_object_unref (filter_model);
g_value_take_object (to_value, selection_model);
return TRUE;
}
static GListModel *
create_settings_model (gpointer item,
gpointer unused)
{
GSettings *settings = item;
char **schemas;
GListStore *result;
guint i;
if (settings == NULL)
{
g_settings_schema_source_list_schemas (g_settings_schema_source_get_default (),
TRUE,
&schemas,
NULL);
}
else
{
schemas = g_settings_list_children (settings);
}
if (schemas == NULL || schemas[0] == NULL)
{
g_free (schemas);
return NULL;
}
qsort (schemas, g_strv_length (schemas), sizeof (char *), strvcmp);
result = g_list_store_new (G_TYPE_SETTINGS);
for (i = 0; schemas[i] != NULL; i++)
{
GSettings *child;
if (settings == NULL)
child = g_settings_new (schemas[i]);
else
child = g_settings_get_child (settings, schemas[i]);
g_list_store_append (result, child);
g_object_unref (child);
}
g_strfreev (schemas);
return G_LIST_MODEL (result);
}
static void
search_enabled (GtkSearchEntry *entry)
{
gtk_editable_set_text (GTK_EDITABLE (entry), "");
}
static void
search_changed (GtkSearchEntry *entry,
gpointer data)
{
const char *text = gtk_editable_get_text (GTK_EDITABLE (entry));
if (current_filter)
gtk_string_filter_set_search (GTK_STRING_FILTER (current_filter), text);
}
static void
stop_search (GtkSearchEntry *entry,
gpointer data)
{
gtk_editable_set_text (GTK_EDITABLE (entry), "");
if (current_filter)
gtk_string_filter_set_search (GTK_STRING_FILTER (current_filter), "");
}
static GtkWidget *window = NULL;
GtkWidget *
do_listview_settings (GtkWidget *do_widget)
{
if (window == NULL)
{
GtkWidget *listview, *columnview;
GListModel *model;
GtkTreeListModel *treemodel;
GtkSingleSelection *selection;
GtkBuilderScope *scope;
GtkBuilder *builder;
GtkColumnViewColumn *name_column;
GtkColumnViewColumn *type_column;
GtkColumnViewColumn *default_column;
GtkColumnViewColumn *summary_column;
GtkColumnViewColumn *description_column;
GtkSorter *sorter;
GActionGroup *actions;
GAction *action;
g_type_ensure (SETTINGS_TYPE_KEY);
scope = gtk_builder_cscope_new ();
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "search_enabled", (GCallback)search_enabled);
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "search_changed", (GCallback)search_changed);
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "stop_search", (GCallback)stop_search);
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope), "item_value_changed", (GCallback)item_value_changed);
builder = gtk_builder_new ();
gtk_builder_set_scope (builder, scope);
gtk_builder_add_from_resource (builder, "/listview_settings/listview_settings.ui", NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
listview = GTK_WIDGET (gtk_builder_get_object (builder, "listview"));
columnview = GTK_WIDGET (gtk_builder_get_object (builder, "columnview"));
type_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "type_column"));
default_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "default_column"));
summary_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "summary_column"));
description_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "description_column"));
actions = G_ACTION_GROUP (g_simple_action_group_new ());
action = G_ACTION (g_property_action_new ("show-type", type_column, "visible"));
g_action_map_add_action (G_ACTION_MAP (actions), action);
g_object_unref (action);
action = G_ACTION (g_property_action_new ("show-default", default_column, "visible"));
g_action_map_add_action (G_ACTION_MAP (actions), action);
g_object_unref (action);
action = G_ACTION (g_property_action_new ("show-summary", summary_column, "visible"));
g_action_map_add_action (G_ACTION_MAP (actions), action);
g_object_unref (action);
action = G_ACTION (g_property_action_new ("show-description", description_column, "visible"));
g_action_map_add_action (G_ACTION_MAP (actions), action);
g_object_unref (action);
gtk_widget_insert_action_group (columnview, "columnview", actions);
g_object_unref (actions);
model = create_settings_model (NULL, NULL);
treemodel = gtk_tree_list_model_new (FALSE,
model,
TRUE,
create_settings_model,
NULL,
NULL);
selection = gtk_single_selection_new (G_LIST_MODEL (treemodel));
g_object_bind_property_full (selection, "selected-item",
columnview, "model",
G_BINDING_SYNC_CREATE,
transform_settings_to_keys,
NULL,
columnview, NULL);
gtk_list_view_set_model (GTK_LIST_VIEW (listview), G_LIST_MODEL (selection));
g_object_unref (selection);
g_object_unref (treemodel);
g_object_unref (model);
name_column = GTK_COLUMN_VIEW_COLUMN (gtk_builder_get_object (builder, "name_column"));
sorter = gtk_string_sorter_new (gtk_property_expression_new (SETTINGS_TYPE_KEY, NULL, "name"));
gtk_column_view_column_set_sorter (name_column, sorter);
g_object_unref (sorter);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

View File

@@ -1,280 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window">
<property name="title" translatable="yes">Settings</property>
<property name="default-width">640</property>
<property name="default-height">480</property>
<child type="titlebar">
<object class="GtkHeaderBar">
<property name="show-title-buttons">1</property>
<child type="end">
<object class="GtkToggleButton" id="search_button">
<property name="icon-name">system-search-symbolic</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkPaned">
<property name="position">300</property>
<child>
<object class="GtkScrolledWindow">
<child>
<object class="GtkListView" id="listview">
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkTreeExpander" id="expander">
<binding name="list-row">
<lookup name="item">GtkListItem</lookup>
</binding>
<property name="child">
<object class="GtkLabel">
<property name="xalign">0</property>
<binding name="label">
<lookup name="schema" type="GSettings">
<lookup name="item">expander</lookup>
</lookup>
</binding>
</object>
</property>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkSearchBar">
<property name="search-mode-enabled" bind-source="search_button" bind-property="active" bind-flags="bidirectional"/>
<signal name="notify::search-mode-enabled" handler="search_enabled" object="entry"/>
<child>
<object class="GtkSearchEntry" id="entry">
<signal name="search-changed" handler="search_changed"/>
<signal name="stop-search" handler="stop_search"/>
</object>
</child>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="hexpand">1</property>
<property name="vexpand">1</property>
<child>
<object class="GtkColumnView" id="columnview">
<child>
<object class="GtkColumnViewColumn" id="name_column">
<property name="title">Name</property>
<property name="header-menu">header_menu</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<property name="xalign">0</property>
<binding name="label">
<lookup name="name" type="SettingsKey">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkColumnViewColumn">
<property name="title">Value</property>
<property name="resizable">1</property>
<property name="header-menu">header_menu</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkEditableLabel">
<binding name="text">
<lookup name="value" type="SettingsKey">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
<signal name="notify::label" handler="item_value_changed"/>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkColumnViewColumn" id="type_column">
<property name="title">Type</property>
<property name="resizable">1</property>
<property name="header-menu">header_menu</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<property name="xalign">0</property>
<binding name="label">
<lookup name="type" type="SettingsKey">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkColumnViewColumn" id="default_column">
<property name="title">Default</property>
<property name="resizable">1</property>
<property name="expand">1</property>
<property name="header-menu">header_menu</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<property name="xalign">0</property>
<binding name="label">
<lookup name="default-value" type="SettingsKey">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkColumnViewColumn" id="summary_column">
<property name="title">Summary</property>
<property name="resizable">1</property>
<property name="visible">0</property>
<property name="expand">1</property>
<property name="header-menu">header_menu</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<property name="xalign">0</property>
<property name="wrap">1</property>
<binding name="label">
<lookup name="summary" type="SettingsKey">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
</object>
</child>
<child>
<object class="GtkColumnViewColumn" id="description_column">
<property name="title">Description</property>
<property name="resizable">1</property>
<property name="visible">0</property>
<property name="expand">1</property>
<property name="header-menu">header_menu</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes"><![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<property name="xalign">0</property>
<property name="wrap">1</property>
<binding name="label">
<lookup name="description" type="SettingsKey">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>
]]></property>
</object>
</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
<menu id="header_menu">
<section>
<item>
<attribute name="label" translatable="yes">Type</attribute>
<attribute name="action">columnview.show-type</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Default value</attribute>
<attribute name="action">columnview.show-default</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Summary</attribute>
<attribute name="action">columnview.show-summary</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Description</attribute>
<attribute name="action">columnview.show-description</attribute>
</item>
</section>
</menu>
</interface>

View File

@@ -1,328 +0,0 @@
/* Lists/Weather
*
* This demo shows a few of the rarer features of GtkListView and
* how they can be used to display weather information.
*
* The hourly weather info uses a horizontal listview. This is easy
* to achieve because GtkListView implements the GtkOrientable interface.
* To make the items in the list stand out more, the listview uses
* separators.
*
* A GtkNoSelectionModel is used to make sure no item in the list can be
* selected. All other interactions with the items is still possible.
*
* The dataset used here has 70000 items.
*/
#include <gtk/gtk.h>
#define GTK_TYPE_WEATHER_INFO (gtk_weather_info_get_type ())
G_DECLARE_FINAL_TYPE (GtkWeatherInfo, gtk_weather_info, GTK, WEATHER_INFO, GObject)
typedef enum {
GTK_WEATHER_CLEAR,
GTK_WEATHER_FEW_CLOUDS,
GTK_WEATHER_FOG,
GTK_WEATHER_OVERCAST,
GTK_WEATHER_SCATTERED_SHOWERS,
GTK_WEATHER_SHOWERS,
GTK_WEATHER_SNOW,
GTK_WEATHER_STORM
} GtkWeatherType;
struct _GtkWeatherInfo
{
GObject parent_instance;
gint64 timestamp;
int temperature;
GtkWeatherType weather_type;
};
struct _GtkWeatherInfoClass
{
GObjectClass parent_class;
};
G_DEFINE_TYPE (GtkWeatherInfo, gtk_weather_info, G_TYPE_OBJECT)
static void
gtk_weather_info_class_init (GtkWeatherInfoClass *klass)
{
}
static void
gtk_weather_info_init (GtkWeatherInfo *self)
{
}
static GtkWeatherInfo *
gtk_weather_info_new (GDateTime *timestamp,
GtkWeatherInfo *copy_from)
{
GtkWeatherInfo *result;
result = g_object_new (GTK_TYPE_WEATHER_INFO, NULL);
result->timestamp = g_date_time_to_unix (timestamp);
if (copy_from)
{
result->temperature = copy_from->temperature;
result->weather_type = copy_from->weather_type;
}
return result;
}
static GDateTime *
parse_timestamp (const char *string,
GTimeZone *_tz)
{
char *with_seconds;
GDateTime *result;
with_seconds = g_strconcat (string, ":00", NULL);
result = g_date_time_new_from_iso8601 (with_seconds, _tz);
g_free (with_seconds);
return result;
}
static GtkWeatherType
parse_weather_type (const char *clouds,
const char *precip,
GtkWeatherType fallback)
{
if (strstr (precip, "SN"))
return GTK_WEATHER_SNOW;
if (strstr (precip, "TS"))
return GTK_WEATHER_STORM;
if (strstr (precip, "DZ"))
return GTK_WEATHER_SCATTERED_SHOWERS;
if (strstr (precip, "SH") || strstr (precip, "RA"))
return GTK_WEATHER_SHOWERS;
if (strstr (precip, "FG"))
return GTK_WEATHER_FOG;
if (g_str_equal (clouds, "M") ||
g_str_equal (clouds, ""))
return fallback;
if (strstr (clouds, "OVC") ||
strstr (clouds, "BKN"))
return GTK_WEATHER_OVERCAST;
if (strstr (clouds, "BKN") ||
strstr (clouds, "SCT"))
return GTK_WEATHER_FEW_CLOUDS;
if (strstr (clouds, "VV"))
return GTK_WEATHER_FOG;
return GTK_WEATHER_CLEAR;
}
static double
parse_temperature (const char *s,
double fallback)
{
char *endptr;
double d;
d = g_ascii_strtod (s, &endptr);
if (*endptr != '\0')
return fallback;
return d;
}
static GListModel *
create_weather_model (void)
{
GListStore *store;
GTimeZone *utc;
GDateTime *timestamp;
GtkWeatherInfo *info;
GBytes *data;
char **lines;
guint i;
store = g_list_store_new (GTK_TYPE_WEATHER_INFO);
data = g_resources_lookup_data ("/listview_weather/listview_weather.txt", 0, NULL);
lines = g_strsplit (g_bytes_get_data (data, NULL), "\n", 0);
utc = g_time_zone_new_utc ();
timestamp = g_date_time_new (utc, 2011, 1, 1, 0, 0, 0);
info = gtk_weather_info_new (timestamp, NULL);
g_list_store_append (store, info);
g_object_unref (info);
for (i = 0; lines[i] != NULL && *lines[i]; i++)
{
char **fields;
GDateTime *date;
fields = g_strsplit (lines[i], ",", 0);
date = parse_timestamp (fields[0], utc);
while (g_date_time_difference (date, timestamp) > 30 * G_TIME_SPAN_MINUTE)
{
GDateTime *new_timestamp = g_date_time_add_hours (timestamp, 1);
g_date_time_unref (timestamp);
timestamp = new_timestamp;
info = gtk_weather_info_new (timestamp, info);
g_list_store_append (store, info);
g_object_unref (info);
}
info->temperature = parse_temperature (fields[1], info->temperature);
info->weather_type = parse_weather_type (fields[2], fields[3], info->weather_type);
g_date_time_unref (date);
g_strfreev (fields);
}
g_date_time_unref (timestamp);
g_strfreev (lines);
g_bytes_unref (data);
g_time_zone_unref (utc);
return G_LIST_MODEL (store);
}
static void
setup_widget (GtkListItem *list_item,
gpointer unused)
{
GtkWidget *box, *child;
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_list_item_set_child (list_item, box);
child = gtk_label_new (NULL);
gtk_label_set_width_chars (GTK_LABEL (child), 5);
gtk_box_append (GTK_BOX (box), child);
child = gtk_image_new ();
gtk_image_set_icon_size (GTK_IMAGE (child), GTK_ICON_SIZE_LARGE);
gtk_box_append (GTK_BOX (box), child);
child = gtk_label_new (NULL);
gtk_widget_set_vexpand (child, TRUE);
gtk_widget_set_valign (child, GTK_ALIGN_END);
gtk_label_set_width_chars (GTK_LABEL (child), 4);
gtk_box_append (GTK_BOX (box), child);
}
static void
bind_widget (GtkListItem *list_item,
gpointer unused)
{
GtkWidget *box, *child;
GtkWeatherInfo *info;
GDateTime *timestamp;
char *s;
box = gtk_list_item_get_child (list_item);
info = gtk_list_item_get_item (list_item);
child = gtk_widget_get_first_child (box);
timestamp = g_date_time_new_from_unix_utc (info->timestamp);
s = g_date_time_format (timestamp, "%R");
gtk_label_set_text (GTK_LABEL (child), s);
g_free (s);
g_date_time_unref (timestamp);
child = gtk_widget_get_next_sibling (child);
switch (info->weather_type)
{
case GTK_WEATHER_CLEAR:
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-clear-symbolic");
break;
case GTK_WEATHER_FEW_CLOUDS:
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-few-clouds-symbolic");
break;
case GTK_WEATHER_FOG:
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-fog-symbolic");
break;
case GTK_WEATHER_OVERCAST:
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-overcast-symbolic");
break;
case GTK_WEATHER_SCATTERED_SHOWERS:
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-showers-scattered-symbolic");
break;
case GTK_WEATHER_SHOWERS:
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-showers-symbolic");
break;
case GTK_WEATHER_SNOW:
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-snow-symbolic");
break;
case GTK_WEATHER_STORM:
gtk_image_set_from_icon_name (GTK_IMAGE (child), "weather-storm-symbolic");
break;
default:
gtk_image_clear (GTK_IMAGE (child));
break;
}
child = gtk_widget_get_next_sibling (child);
s = g_strdup_printf ("%d°", info->temperature);
gtk_label_set_text (GTK_LABEL (child), s);
g_free (s);
}
static GtkWidget *window = NULL;
GtkWidget *
create_weather_view (void)
{
GtkWidget *listview;
GListModel *model, *selection;
listview = gtk_list_view_new_with_factory (
gtk_functions_list_item_factory_new (setup_widget,
bind_widget,
NULL, NULL));
gtk_orientable_set_orientation (GTK_ORIENTABLE (listview), GTK_ORIENTATION_HORIZONTAL);
gtk_list_view_set_show_separators (GTK_LIST_VIEW (listview), TRUE);
model = create_weather_model ();
selection = G_LIST_MODEL (gtk_no_selection_new (model));
gtk_list_view_set_model (GTK_LIST_VIEW (listview), selection);
g_object_unref (selection);
g_object_unref (model);
return listview;
}
GtkWidget *
do_listview_weather (GtkWidget *do_widget)
{
if (window == NULL)
{
GtkWidget *listview, *sw;
window = gtk_window_new ();
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
gtk_window_set_title (GTK_WINDOW (window), "Weather");
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Weather");
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
sw = gtk_scrolled_window_new ();
gtk_window_set_child (GTK_WINDOW (window), sw);
listview = create_weather_view ();
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), listview);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,241 +0,0 @@
/* Lists/Words
*
* This demo shows filtering a long list - of words.
*
* You should have the file `/usr/share/dict/words` installed for
* this demo to work.
*/
#include <gtk/gtk.h>
static GtkWidget *window = NULL;
static GtkWidget *progress;
const char *factory_text =
"<?xml version='1.0' encoding='UTF-8'?>\n"
"<interface>\n"
" <template class='GtkListItem'>\n"
" <property name='child'>\n"
" <object class='GtkLabel'>\n"
" <property name='ellipsize'>end</property>\n"
" <property name='xalign'>0</property>\n"
" <binding name='label'>\n"
" <lookup name='string' type='GtkStringObject'>\n"
" <lookup name='item'>GtkListItem</lookup>\n"
" </lookup>\n"
" </binding>\n"
" </object>\n"
" </property>\n"
" </template>\n"
"</interface>\n";
static void
update_title_cb (GtkFilterListModel *model)
{
guint total;
char *title;
guint pending;
total = g_list_model_get_n_items (gtk_filter_list_model_get_model (model));
pending = gtk_filter_list_model_get_pending (model);
title = g_strdup_printf ("%u lines", g_list_model_get_n_items (G_LIST_MODEL (model)));
gtk_widget_set_visible (progress, pending != 0);
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (progress), (total - pending) / (double) total);
gtk_window_set_title (GTK_WINDOW (window), title);
g_free (title);
}
static void
read_lines_cb (GObject *object,
GAsyncResult *result,
gpointer data)
{
GBufferedInputStream *stream = G_BUFFERED_INPUT_STREAM (object);
GtkStringList *stringlist = data;
GError *error = NULL;
gsize size;
GPtrArray *lines;
gssize n_filled;
const char *buffer, *newline;
n_filled = g_buffered_input_stream_fill_finish (stream, result, &error);
if (n_filled < 0)
{
g_print ("Could not read data: %s\n", error->message);
g_clear_error (&error);
return;
}
buffer = g_buffered_input_stream_peek_buffer (stream, &size);
if (n_filled == 0)
{
if (size)
gtk_string_list_take (stringlist, g_utf8_make_valid (buffer, size));
return;
}
lines = NULL;
while ((newline = memchr (buffer, '\n', size)))
{
if (newline > buffer)
{
if (lines == NULL)
lines = g_ptr_array_new_with_free_func (g_free);
g_ptr_array_add (lines, g_utf8_make_valid (buffer, newline - buffer));
}
if (g_input_stream_skip (G_INPUT_STREAM (stream), newline - buffer + 1, NULL, &error) < 0)
{
g_clear_error (&error);
break;
}
buffer = g_buffered_input_stream_peek_buffer (stream, &size);
}
if (lines == NULL)
{
g_buffered_input_stream_set_buffer_size (stream, g_buffered_input_stream_get_buffer_size (stream) + 4096);
}
else
{
g_ptr_array_add (lines, NULL);
gtk_string_list_splice (stringlist, g_list_model_get_n_items (G_LIST_MODEL (stringlist)), 0, (const char **) lines->pdata);
g_ptr_array_free (lines, TRUE);
}
g_buffered_input_stream_fill_async (stream, -1, G_PRIORITY_HIGH_IDLE, NULL, read_lines_cb, data);
}
static void
file_is_open_cb (GObject *file,
GAsyncResult *result,
gpointer data)
{
GError *error = NULL;
GFileInputStream *file_stream;
GBufferedInputStream *stream;
file_stream = g_file_read_finish (G_FILE (file), result, &error);
if (file_stream == NULL)
{
g_print ("Could not open file: %s\n", error->message);
g_error_free (error);
return;
}
stream = G_BUFFERED_INPUT_STREAM (g_buffered_input_stream_new (G_INPUT_STREAM (file_stream)));
g_buffered_input_stream_fill_async (stream, -1, G_PRIORITY_HIGH_IDLE, NULL, read_lines_cb, data);
g_object_unref (stream);
}
static void
load_file (GtkStringList *list,
GFile *file)
{
gtk_string_list_splice (list, 0, g_list_model_get_n_items (G_LIST_MODEL (list)), NULL);
g_file_read_async (file, G_PRIORITY_HIGH_IDLE, NULL, file_is_open_cb, list);
}
static void
file_selected_cb (GtkWidget *button,
GtkStringList *stringlist)
{
GFile *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (button));
if (file)
{
load_file (stringlist, file);
g_object_unref (file);
}
}
GtkWidget *
do_listview_words (GtkWidget *do_widget)
{
if (window == NULL)
{
GtkWidget *header, *listview, *sw, *vbox, *search_entry, *open_button, *overlay;
GtkFilterListModel *filter_model;
GtkNoSelection *selection;
GtkStringList *stringlist;
GtkFilter *filter;
GtkExpression *expression;
GFile *file;
file = g_file_new_for_path ("/usr/share/dict/words");
if (g_file_query_exists (file, NULL))
{
stringlist = gtk_string_list_new (NULL);
load_file (stringlist, file);
}
else
{
char **words;
words = g_strsplit ("lorem ipsum dolor sit amet consectetur adipisci elit sed eiusmod tempor incidunt labore et dolore magna aliqua ut enim ad minim veniam quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat", " ", -1);
stringlist = gtk_string_list_new ((const char **) words);
g_strfreev (words);
}
filter = gtk_string_filter_new ();
expression = gtk_property_expression_new (GTK_TYPE_STRING_OBJECT, NULL, "string");
gtk_string_filter_set_expression (GTK_STRING_FILTER (filter), expression);
gtk_expression_unref (expression);
filter_model = gtk_filter_list_model_new (G_LIST_MODEL (stringlist), filter);
gtk_filter_list_model_set_incremental (filter_model, TRUE);
window = gtk_window_new ();
gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
header = gtk_header_bar_new ();
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
open_button = gtk_file_chooser_button_new ("_Open", GTK_FILE_CHOOSER_ACTION_OPEN);
g_signal_connect (open_button, "file-set", G_CALLBACK (file_selected_cb), stringlist);
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), open_button);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer*)&window);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_window_set_child (GTK_WINDOW (window), vbox);
search_entry = gtk_search_entry_new ();
g_object_bind_property (search_entry, "text", filter, "search", 0);
gtk_box_append (GTK_BOX (vbox), search_entry);
overlay = gtk_overlay_new ();
gtk_box_append (GTK_BOX (vbox), overlay);
progress = gtk_progress_bar_new ();
gtk_widget_set_halign (progress, GTK_ALIGN_FILL);
gtk_widget_set_valign (progress, GTK_ALIGN_START);
gtk_widget_set_hexpand (progress, TRUE);
gtk_overlay_add_overlay (GTK_OVERLAY (overlay), progress);
sw = gtk_scrolled_window_new ();
gtk_overlay_set_child (GTK_OVERLAY (overlay), sw);
listview = gtk_list_view_new_with_factory (
gtk_builder_list_item_factory_new_from_bytes (NULL,
g_bytes_new_static (factory_text, strlen (factory_text))));
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), listview);
selection = gtk_no_selection_new (G_LIST_MODEL (filter_model));
gtk_list_view_set_model (GTK_LIST_VIEW (listview), G_LIST_MODEL (selection));
g_object_unref (selection);
g_signal_connect (filter_model, "items-changed", G_CALLBACK (update_title_cb), progress);
g_signal_connect (filter_model, "notify::pending", G_CALLBACK (update_title_cb), progress);
update_title_cb (filter_model);
g_object_unref (filter_model);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkTreeExpander" id="expander">
<binding name="list-row">
<lookup name="item">GtkListItem</lookup>
</binding>
<property name="child">
<object class="GtkLabel">
<property name="halign">start</property>
<binding name="label">
<lookup name="title" type="GtkDemo">
<lookup name="item">expander</lookup>
</lookup>
</binding>
</object>
</property>
</object>
</property>
</template>
</interface>

View File

@@ -16,96 +16,18 @@ static GtkWidget *source_view;
static gchar *current_file = NULL;
static GtkWidget *notebook;
static GtkSingleSelection *selection;
static GtkWidget *treeview;
static GtkWidget *toplevel;
typedef struct _GtkDemo GtkDemo;
struct _GtkDemo
{
GObject parent_instance;
const char *name;
const char *title;
const char *filename;
GDoDemoFunc func;
GListModel *children_model;
};
enum {
PROP_0,
PROP_FILENAME,
PROP_NAME,
PROP_TITLE,
N_PROPS
NAME_COLUMN,
TITLE_COLUMN,
FILENAME_COLUMN,
FUNC_COLUMN,
STYLE_COLUMN,
NUM_COLUMNS
};
# define GTK_TYPE_DEMO (gtk_demo_get_type ())
G_DECLARE_FINAL_TYPE (GtkDemo, gtk_demo, GTK, DEMO, GObject);
G_DEFINE_TYPE (GtkDemo, gtk_demo, G_TYPE_OBJECT);
static GParamSpec *properties[N_PROPS] = { NULL, };
static void
gtk_demo_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GtkDemo *self = GTK_DEMO (object);
switch (property_id)
{
case PROP_FILENAME:
g_value_set_string (value, self->filename);
break;
case PROP_NAME:
g_value_set_string (value, self->name);
break;
case PROP_TITLE:
g_value_set_string (value, self->title);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void gtk_demo_class_init (GtkDemoClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->get_property = gtk_demo_get_property;
properties[PROP_FILENAME] =
g_param_spec_string ("filename",
"filename",
"filename",
NULL,
G_PARAM_READABLE);
properties[PROP_NAME] =
g_param_spec_string ("name",
"name",
"name",
NULL,
G_PARAM_READABLE);
properties[PROP_TITLE] =
g_param_spec_string ("title",
"title",
"title",
NULL,
G_PARAM_READABLE);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
static void gtk_demo_init (GtkDemo *self)
{
}
typedef struct _CallbackData CallbackData;
struct _CallbackData
{
@@ -113,27 +35,6 @@ struct _CallbackData
GtkTreePath *path;
};
static gboolean
gtk_demo_run (GtkDemo *self,
GtkWidget *window)
{
GtkWidget *result;
if (!self->func)
return FALSE;
result = self->func (window);
if (result == NULL)
return FALSE;
if (GTK_IS_WINDOW (result))
{
gtk_window_set_transient_for (GTK_WINDOW (result), GTK_WINDOW (window));
gtk_window_set_modal (GTK_WINDOW (result), TRUE);
}
return TRUE;
}
static void
activate_about (GSimpleAction *action,
GVariant *parameter,
@@ -214,15 +115,82 @@ activate_inspector (GSimpleAction *action,
gtk_window_set_interactive_debugging (TRUE);
}
static void
window_closed_cb (GtkWidget *window, gpointer data)
{
CallbackData *cbdata = data;
GtkTreeIter iter;
PangoStyle style;
gtk_tree_model_get_iter (cbdata->model, &iter, cbdata->path);
gtk_tree_model_get (GTK_TREE_MODEL (cbdata->model), &iter,
STYLE_COLUMN, &style,
-1);
if (style == PANGO_STYLE_ITALIC)
gtk_tree_store_set (GTK_TREE_STORE (cbdata->model), &iter,
STYLE_COLUMN, PANGO_STYLE_NORMAL,
-1);
gtk_tree_path_free (cbdata->path);
g_free (cbdata);
}
static void
run_example_for_row (GtkWidget *window,
GtkTreeModel *model,
GtkTreeIter *iter)
{
PangoStyle style;
GDoDemoFunc func;
GtkWidget *demo;
gtk_tree_model_get (GTK_TREE_MODEL (model),
iter,
FUNC_COLUMN, &func,
STYLE_COLUMN, &style,
-1);
if (func)
{
gtk_tree_store_set (GTK_TREE_STORE (model),
iter,
STYLE_COLUMN, (style == PANGO_STYLE_ITALIC ? PANGO_STYLE_NORMAL : PANGO_STYLE_ITALIC),
-1);
demo = (func) (window);
if (demo != NULL)
{
CallbackData *cbdata;
cbdata = g_new (CallbackData, 1);
cbdata->model = model;
cbdata->path = gtk_tree_model_get_path (model, iter);
if (GTK_IS_WINDOW (demo))
{
gtk_window_set_transient_for (GTK_WINDOW (demo), GTK_WINDOW (window));
gtk_window_set_modal (GTK_WINDOW (demo), TRUE);
}
g_signal_connect (demo, "destroy",
G_CALLBACK (window_closed_cb), cbdata);
}
}
}
static void
activate_run (GSimpleAction *action,
GVariant *parameter,
gpointer window)
gpointer user_data)
{
GtkTreeListRow *row = gtk_single_selection_get_selected_item (selection);
GtkDemo *demo = gtk_tree_list_row_get_item (row);
GtkWidget *window = user_data;
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
gtk_demo_run (demo, window);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
if (gtk_tree_selection_get_selected (selection, &model, &iter))
run_example_for_row (window, model, &iter);
}
/* Stupid syntax highlighting.
@@ -599,10 +567,10 @@ display_image (const char *resource)
{
GtkWidget *sw, *image;
image = gtk_picture_new_for_resource (resource);
image = gtk_image_new_from_resource (resource);
gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
gtk_widget_set_valign (image, GTK_ALIGN_CENTER);
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), image);
return sw;
@@ -642,7 +610,7 @@ display_text (const char *resource)
g_bytes_unref (bytes);
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
@@ -927,93 +895,107 @@ load_file (const gchar *demoname,
}
static void
activate_cb (GtkWidget *widget,
guint position,
gpointer window)
selection_cb (GtkTreeSelection *selection,
GtkTreeModel *model)
{
GtkTreeListRow *row = g_list_model_get_item (gtk_list_view_get_model (GTK_LIST_VIEW (widget)), position);
GtkDemo *demo = gtk_tree_list_row_get_item (row);
GtkTreeIter iter;
char *name;
char *filename;
char *title;
gtk_demo_run (demo, window);
if (! gtk_tree_selection_get_selected (selection, NULL, &iter))
return;
g_object_unref (row);
gtk_tree_model_get (model, &iter,
NAME_COLUMN, &name,
TITLE_COLUMN, &title,
FILENAME_COLUMN, &filename,
-1);
if (filename)
load_file (name, filename);
gtk_window_set_title (GTK_WINDOW (toplevel), title);
g_free (name);
g_free (title);
g_free (filename);
}
static void
selection_cb (GtkSingleSelection *sel,
GParamSpec *pspec,
gpointer user_data)
populate_model (GtkTreeModel *model)
{
GtkTreeListRow *row = gtk_single_selection_get_selected_item (sel);
GtkDemo *demo = gtk_tree_list_row_get_item (row);
Demo *d = gtk_demos;
if (demo->filename)
load_file (demo->name, demo->filename);
gtk_window_set_title (GTK_WINDOW (toplevel), demo->title);
}
static GListModel *
create_demo_model (void)
{
GListStore *store = g_list_store_new (GTK_TYPE_DEMO);
DemoData *demo = gtk_demos;
while (demo->title)
/* this code only supports 1 level of children. If we
* want more we probably have to use a recursing function.
*/
while (d->title)
{
GtkDemo *d = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
DemoData *children = demo->children;
Demo *children = d->children;
GtkTreeIter iter;
d->name = demo->name;
d->title = demo->title;
d->filename = demo->filename;
d->func = demo->func;
gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
g_list_store_append (store, d);
gtk_tree_store_set (GTK_TREE_STORE (model),
&iter,
NAME_COLUMN, d->name,
TITLE_COLUMN, d->title,
FILENAME_COLUMN, d->filename,
FUNC_COLUMN, d->func,
STYLE_COLUMN, PANGO_STYLE_NORMAL,
-1);
if (children)
d++;
if (!children)
continue;
while (children->title)
{
d->children_model = G_LIST_MODEL (g_list_store_new (GTK_TYPE_DEMO));
GtkTreeIter child_iter;
while (children->title)
{
GtkDemo *child = GTK_DEMO (g_object_new (GTK_TYPE_DEMO, NULL));
gtk_tree_store_append (GTK_TREE_STORE (model), &child_iter, &iter);
child->name = children->name;
child->title = children->title;
child->filename = children->filename;
child->func = children->func;
gtk_tree_store_set (GTK_TREE_STORE (model),
&child_iter,
NAME_COLUMN, children->name,
TITLE_COLUMN, children->title,
FILENAME_COLUMN, children->filename,
FUNC_COLUMN, children->func,
STYLE_COLUMN, PANGO_STYLE_NORMAL,
-1);
g_list_store_append (G_LIST_STORE (d->children_model), child);
children++;
}
children++;
}
demo++;
}
return G_LIST_MODEL (store);
}
static GListModel *
get_child_model (gpointer item,
gpointer user_data)
static void
row_activated_cb (GtkWidget *tree_view,
GtkTreePath *path,
GtkTreeViewColumn *column)
{
GtkDemo *demo = item;
GtkTreeIter iter;
GtkWidget *window;
GtkTreeModel *model;
if (demo->children_model)
return g_object_ref (G_LIST_MODEL (demo->children_model));
window = GTK_WIDGET (gtk_widget_get_root (tree_view));
model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
gtk_tree_model_get_iter (model, &iter, path);
return NULL;
run_example_for_row (window, model, &iter);
}
static void
activate (GApplication *app)
{
GtkBuilder *builder;
GListModel *listmodel;
GtkTreeListModel *treemodel;
GtkWidget *window, *listview;
GtkWindow *window;
GtkWidget *widget;
GtkTreeModel *model;
GtkTreeIter iter;
static GActionEntry win_entries[] = {
{ "run", activate_run, NULL, NULL, NULL }
@@ -1021,32 +1003,35 @@ activate (GApplication *app)
builder = gtk_builder_new_from_resource ("/ui/main.ui");
window = (GtkWidget *)gtk_builder_get_object (builder, "window");
gtk_application_add_window (GTK_APPLICATION (app), GTK_WINDOW (window));
window = (GtkWindow *)gtk_builder_get_object (builder, "window");
gtk_application_add_window (GTK_APPLICATION (app), window);
g_action_map_add_action_entries (G_ACTION_MAP (window),
win_entries, G_N_ELEMENTS (win_entries),
window);
notebook = GTK_WIDGET (gtk_builder_get_object (builder, "notebook"));
notebook = (GtkWidget *)gtk_builder_get_object (builder, "notebook");
info_view = GTK_WIDGET (gtk_builder_get_object (builder, "info-textview"));
source_view = GTK_WIDGET (gtk_builder_get_object (builder, "source-textview"));
info_view = (GtkWidget *)gtk_builder_get_object (builder, "info-textview");
source_view = (GtkWidget *)gtk_builder_get_object (builder, "source-textview");
treeview = (GtkWidget *)gtk_builder_get_object (builder, "treeview");
model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
toplevel = GTK_WIDGET (window);
listview = GTK_WIDGET (gtk_builder_get_object (builder, "listview"));
g_signal_connect (listview, "activate", G_CALLBACK (activate_cb), window);
listmodel = create_demo_model ();
treemodel = gtk_tree_list_model_new (FALSE,
G_LIST_MODEL (listmodel),
TRUE,
get_child_model,
NULL,
NULL);
selection = gtk_single_selection_new (G_LIST_MODEL (treemodel));
g_signal_connect (selection, "notify::selected-item", G_CALLBACK (selection_cb), NULL);
gtk_list_view_set_model (GTK_LIST_VIEW (listview), G_LIST_MODEL (selection));
load_file (gtk_demos[0].name, gtk_demos[0].filename);
selection_cb (selection, NULL, NULL);
populate_model (model);
g_signal_connect (treeview, "row-activated", G_CALLBACK (row_activated_cb), model);
widget = (GtkWidget *)gtk_builder_get_object (builder, "treeview-selection");
g_signal_connect (widget, "changed", G_CALLBACK (selection_cb), model);
gtk_tree_model_get_iter_first (gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)), &iter);
gtk_tree_selection_select_iter (GTK_TREE_SELECTION (widget), &iter);
gtk_tree_view_collapse_all (GTK_TREE_VIEW (treeview));
gtk_widget_show (GTK_WIDGET (window));
g_object_unref (builder);
}
@@ -1061,7 +1046,7 @@ auto_quit (gpointer data)
static void
list_demos (void)
{
DemoData *d, *c;
Demo *d, *c;
d = gtk_demos;
@@ -1088,7 +1073,7 @@ command_line (GApplication *app,
const gchar *name = NULL;
gboolean autoquit = FALSE;
gboolean list = FALSE;
DemoData *d, *c;
Demo *d, *c;
GDoDemoFunc func = 0;
GtkWidget *window, *demo;
@@ -1106,11 +1091,11 @@ command_line (GApplication *app,
return 0;
}
window = gtk_application_get_windows (GTK_APPLICATION (app))->data;
if (name == NULL)
goto out;
window = gtk_application_get_windows (GTK_APPLICATION (app))->data;
d = gtk_demos;
while (d->title)
@@ -1140,11 +1125,7 @@ out:
gtk_window_set_transient_for (GTK_WINDOW (demo), GTK_WINDOW (window));
gtk_window_set_modal (GTK_WINDOW (demo), TRUE);
g_signal_connect_swapped (G_OBJECT (demo), "destroy", G_CALLBACK (g_application_quit), app);
}
else
gtk_widget_show (GTK_WIDGET (window));
if (autoquit)
g_timeout_add_seconds (1, auto_quit, app);
@@ -1155,7 +1136,7 @@ out:
static void
print_version (void)
{
g_print ("gtk4-demo %d.%d.%d\n",
g_print ("gtk3-demo %d.%d.%d\n",
gtk_get_major_version (),
gtk_get_minor_version (),
gtk_get_micro_version ());
@@ -1197,6 +1178,16 @@ main (int argc, char **argv)
};
int i;
/* Most code in gtk-demo is intended to be exemplary, but not
* these few lines, which are just a hack so gtk-demo will work
* in the GTK tree without installing it.
*/
if (g_file_test ("../../modules/input/immodules.cache", G_FILE_TEST_EXISTS))
{
g_setenv ("GTK_IM_MODULE_FILE", "../../modules/input/immodules.cache", TRUE);
}
/* -- End of hack -- */
app = gtk_application_new ("org.gtk.Demo4", G_APPLICATION_NON_UNIQUE|G_APPLICATION_HANDLES_COMMAND_LINE);
g_action_map_add_action_entries (G_ACTION_MAP (app),

View File

@@ -16,6 +16,15 @@
</item>
</section>
</menu>
<object class="GtkTreeStore" id="treestore">
<columns>
<column type="gchararray"/>
<column type="gchararray"/>
<column type="gchararray"/>
<column type="gpointer"/>
<column type="gint"/>
</columns>
</object>
<object class="GtkApplicationWindow" id="window">
<style>
<class name="devel"/>
@@ -56,12 +65,30 @@
<property name="hscrollbar-policy">never</property>
<property name="min-content-width">150</property>
<child>
<object class="GtkListView" id="listview">
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="resource">/ui/main-listitem.ui</property>
<object class="GtkTreeView" id="treeview">
<property name="model">treestore</property>
<property name="headers-visible">0</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection">
<property name="mode">browse</property>
</object>
</property>
</child>
<child>
<object class="GtkTreeViewColumn">
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="style">4</attribute>
<attribute name="text">1</attribute>
</attributes>
</child>
<child>
<object class="GtkCellRendererText">
<property name="text"> </property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>

View File

@@ -81,7 +81,7 @@ do_markup (GtkWidget *do_widget)
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 10);
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (view), 10);
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
@@ -94,7 +94,7 @@ do_markup (GtkWidget *do_widget)
gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view2), 10);
gtk_text_view_set_right_margin (GTK_TEXT_VIEW (view2), 10);
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);

View File

@@ -5,7 +5,7 @@ Text <span color="gray">c<span color="green">o</span>l<span color="tomato">o</sp
Colorful <span underline="low" underline-color="blue"><span underline="double" underline-color="red">under</span>lines</span> and <span background="pink"><span underline="error">mo</span><span underline="error" underline-color="green">re</span></span>
Colorful <span strikethrough="true" strikethrough-color="magenta">strikethroughs</span> and <span overline="single" overline_color="green">overlines</span>
Colorful <span strikethrough="true" strikethrough-color="magenta">strikethroughs</span>
Superscripts and subscripts: 𝜀<span rise="-6000" size="x-small" font_desc="italic">0</span> = 𝜔<span rise="8000" size="smaller">𝜔<span rise="14000" size="smaller">𝜔<span rise="20000">.<span rise="23000">.<span rise="26000">.</span></span></span></span></span>

View File

@@ -18,7 +18,6 @@ demos = files([
'cursors.c',
'dialog.c',
'drawingarea.c',
'dropdown.c',
'dnd.c',
'editable_cells.c',
'entry_completion.c',
@@ -42,14 +41,6 @@ demos = files([
'listbox.c',
'flowbox.c',
'list_store.c',
'listview_applauncher.c',
'listview_clocks.c',
'listview_colors.c',
'listview_filebrowser.c',
'listview_minesweeper.c',
'listview_settings.c',
'listview_weather.c',
'listview_words.c',
'markup.c',
'modelbutton.c',
'overlay.c',
@@ -104,7 +95,7 @@ extra_demo_sources = files(['main.c',
if harfbuzz_dep.found() and pangoft_dep.found()
demos += files('font_features.c')
extra_demo_sources += files(['script-names.c', 'language-names.c'])
gtkdemo_deps += [ harfbuzz_dep, epoxy_dep ]
gtkdemo_deps += [ harfbuzz_dep, ]
endif
if os_unix

View File

@@ -259,7 +259,7 @@
259|GTK+ and friends|GTKtoolkit|#java bindings version 4.0.16 released: http://article.gmane.org/gmane.comp.gnome.bindings.java/1796 #gtk|1276885917|0||0|0
260|GTK+ and friends|GTKtoolkit|RT @cwiiis: MxIconTheme and MxIcon respect system's icon theme (and changes) now in #mx master :) Made possible by @thosw's XSettings work|1276883019|0||0|0
261|GTK+ and friends|GTKtoolkit|#javascript mailing list just created. Discuss its usage in GObject libraries: GTK+, Glib ... http://ur1.ca/08lwz by @jwendell #gtk|1276842639|0||0|0
262|GTK+ and friends|GTKtoolkit|Note for Win32 users: XP theming is back in 2.90.3 . Please test. #gtk|1276829697|0||0|0
262|GTK+ and friends|GTKtoolkit|Note fot Win32 users: XP theming is back in 2.90.3 . Please test. #gtk|1276829697|0||0|0
263|GTK+ and friends|GTKtoolkit|GTK+ 2.90.3 (unstable) released: http://mail.gnome.org/archives/gtk-devel-list/2010-June/msg00137.html #gtk|1276829633|0||0|0
264|GTK+ and friends|GTKtoolkit|GLib 2.25.9 (unstable) released: http://ur1.ca/08hrl WARNING: API changes in GDBus, GSettings and GApplication #gtk|1276829581|0||0|0
265|scaroo|scaroo|RT @scaroo: #SeedKit does RGBA window with css shadows and stuff : http://dl.dropbox.com/u/5746554/seedkit-does-rgba.png|1276734086|0|GTKtoolkit|0|1

View File

@@ -40,7 +40,7 @@ do_overlay2 (GtkWidget *do_widget)
gtk_window_set_title (GTK_WINDOW (window), "Decorative Overlay");
overlay = gtk_overlay_new ();
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);

View File

@@ -11,7 +11,6 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
static GtkWidget *entry;
static GtkWidget *entry2;
static GtkWidget *button;
@@ -28,13 +27,6 @@ update_button (GObject *object,
text[0] != '\0' && g_str_equal (text, text2));
}
static void
button_pressed (GtkButton *widget,
GtkWidget *window)
{
gtk_window_destroy (GTK_WINDOW (window));
}
GtkWidget *
do_password_entry (GtkWidget *do_widget)
{
@@ -82,7 +74,7 @@ do_password_entry (GtkWidget *do_widget)
button = gtk_button_new_with_mnemonic ("_Done");
gtk_widget_add_css_class (button, "suggested-action");
g_signal_connect (button, "clicked", G_CALLBACK (button_pressed), window);
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_window_destroy), window);
gtk_widget_set_sensitive (button, FALSE);
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), button);

View File

@@ -1,4 +1,4 @@
/* Sliding Puzzle
/* Sliding puzzle
*
* This demo demonstrates how to use gestures and paintables to create a
* small sliding puzzle game.
@@ -11,7 +11,6 @@
#include "puzzlepiece.h"
#include "paintable.h"
static GtkWidget *window = NULL;
static GtkWidget *frame = NULL;
static GtkWidget *choices = NULL;
@@ -241,8 +240,6 @@ puzzle_button_pressed (GtkGestureClick *gesture,
{
gtk_widget_error_bell (grid);
}
check_solved (grid);
}
static void
@@ -283,8 +280,6 @@ start_puzzle (GdkPaintable *paintable)
/* Add shortcuts so people can use the arrow
* keys to move the puzzle */
controller = gtk_shortcut_controller_new ();
gtk_shortcut_controller_set_scope (GTK_SHORTCUT_CONTROLLER (controller),
GTK_SHORTCUT_SCOPE_GLOBAL);
add_move_binding (GTK_SHORTCUT_CONTROLLER (controller),
GDK_KEY_Left, GDK_KEY_KP_Left,
-1, 0);
@@ -345,16 +340,11 @@ reshuffle (void)
{
GtkWidget *grid;
grid = gtk_aspect_frame_get_child (GTK_ASPECT_FRAME (frame));
if (solved)
{
start_puzzle (puzzle);
grid = gtk_aspect_frame_get_child (GTK_ASPECT_FRAME (frame));
}
start_puzzle (puzzle);
else
{
grid = gtk_aspect_frame_get_child (GTK_ASPECT_FRAME (frame));
shuffle_puzzle (grid);
}
shuffle_puzzle (grid);
gtk_widget_grab_focus (grid);
}
@@ -400,15 +390,6 @@ add_choice (GtkWidget *container,
gtk_flow_box_insert (GTK_FLOW_BOX (container), icon, -1);
}
static void
widget_destroyed (gpointer data,
GObject *widget)
{
if (data)
*(gpointer *) data = NULL;
}
GtkWidget *
do_sliding_puzzle (GtkWidget *do_widget)
{
@@ -443,7 +424,7 @@ do_sliding_puzzle (GtkWidget *do_widget)
gtk_media_stream_set_muted (media, TRUE);
gtk_media_stream_play (media);
add_choice (choices, GDK_PAINTABLE (media));
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), choices);
gtk_grid_attach (GTK_GRID (tweaks), sw, 0, 0, 2, 1);
@@ -479,7 +460,7 @@ do_sliding_puzzle (GtkWidget *do_widget)
gtk_window_set_title (GTK_WINDOW (window), "Sliding Puzzle");
gtk_window_set_titlebar (GTK_WINDOW (window), header);
gtk_window_set_default_size (GTK_WINDOW (window), 400, 300);
g_object_weak_ref (G_OBJECT (window), widget_destroyed, &window);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
frame = gtk_aspect_frame_new (0.5, 0.5, (float) gdk_paintable_get_intrinsic_aspect_ratio (puzzle), FALSE);
gtk_window_set_child (GTK_WINDOW (window), frame);

View File

@@ -40,7 +40,7 @@ do_tabs (GtkWidget *do_widget)
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
gtk_text_buffer_set_text (buffer, "one\ttwo\tthree\nfour\tfive\tsix\nseven\teight\tnine", -1);
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);

View File

@@ -57,6 +57,7 @@ do_tagged_entry (GtkWidget *do_widget)
static GtkWidget *window = NULL;
GtkWidget *box;
GtkWidget *box2;
GtkWidget *header;
GtkWidget *entry;
GtkWidget *button;
@@ -65,9 +66,12 @@ do_tagged_entry (GtkWidget *do_widget)
window = gtk_window_new ();
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
gtk_window_set_title (GTK_WINDOW (window), "Tagged Entry");
gtk_window_set_resizable (GTK_WINDOW (window), FALSE);
header = gtk_header_bar_new ();
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), FALSE);
gtk_window_set_titlebar (GTK_WINDOW (window), header);
gtk_window_set_title (GTK_WINDOW (window), "A tagged entry");
gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
gtk_window_set_deletable (GTK_WINDOW (window), FALSE);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
@@ -91,6 +95,13 @@ do_tagged_entry (GtkWidget *do_widget)
button = gtk_check_button_new_with_mnemonic ("_Spinner");
g_signal_connect (button, "toggled", G_CALLBACK (toggle_spinner), entry);
gtk_box_append (GTK_BOX (box2), button);
button = gtk_button_new_with_mnemonic ("_Done");
gtk_widget_add_css_class (button, "suggested-action");
g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_window_destroy), window);
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), button);
gtk_window_set_default_widget (GTK_WINDOW (window), button);
}
if (!gtk_widget_get_visible (window))

View File

@@ -156,7 +156,7 @@ create_text_view (GtkWidget *hbox,
GtkWidget *textview;
guint timeout;
swindow = gtk_scrolled_window_new ();
swindow = gtk_scrolled_window_new (NULL, NULL);
gtk_box_append (GTK_BOX (hbox), swindow);
textview = gtk_text_view_new ();
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (swindow), textview);

View File

@@ -4,7 +4,7 @@
* GtkTextBuffer. You can enable or disable undo support using
* gtk_text_buffer_set_enable_undo().
*
* Use Control+z to undo and Control+Shift+z or Control+y to
* Use Primary+Z to undo and Primary+Shift+Z or Primary+Y to
* redo previously undone operations.
*/
@@ -29,7 +29,7 @@ do_textundo (GtkWidget *do_widget)
gtk_window_set_default_size (GTK_WINDOW (window), 450, 450);
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
gtk_window_set_title (GTK_WINDOW (window), "Undo and Redo");
gtk_window_set_title (GTK_WINDOW (window), "TextView Undo");
view = gtk_text_view_new ();
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
@@ -46,7 +46,7 @@ do_textundo (GtkWidget *do_widget)
-1);
gtk_text_buffer_end_irreversible_action (buffer);
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);

View File

@@ -494,7 +494,7 @@ do_textview (GtkWidget *do_widget)
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view1));
view2 = gtk_text_view_new_with_buffer (buffer);
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
@@ -504,7 +504,7 @@ do_textview (GtkWidget *do_widget)
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), view1);
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
@@ -590,7 +590,7 @@ easter_egg_callback (GtkWidget *button,
g_object_unref (buffer);
window = gtk_window_new ();
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);

View File

@@ -92,11 +92,12 @@ static Theme themes[] = {
static int theme;
static gboolean
change_theme (GtkWidget *widget,
change_theme (GtkWidget *widget,
GdkFrameClock *frame_clock,
gpointer data)
gpointer data)
{
GtkWidget *label = data;
GtkBuilder *builder = data;
GtkWidget *label;
Theme next = themes[theme++ % G_N_ELEMENTS (themes)];
char *name;
@@ -109,6 +110,7 @@ change_theme (GtkWidget *widget,
gtk_window_set_title (GTK_WINDOW (widget), name);
g_free (name);
label = GTK_WIDGET (gtk_builder_get_object (builder, "fps"));
if (frame_clock)
{
char *fps;
@@ -125,10 +127,10 @@ change_theme (GtkWidget *widget,
static void
clicked (GtkGestureClick *gesture,
int n_press,
double x,
double y,
gpointer data)
int n_press,
double x,
double y,
gpointer data)
{
GtkWidget *window;
GdkEvent *event;
@@ -163,29 +165,6 @@ clicked (GtkGestureClick *gesture,
}
}
static void
toggle_cycle (GObject *button,
GParamSpec *pspec,
gpointer data)
{
gboolean active;
GtkWidget *window;
g_object_get (button, "active", &active, NULL);
window = gtk_widget_get_ancestor (GTK_WIDGET (button), GTK_TYPE_WINDOW);
if (active && !tick_cb)
{
tick_cb = gtk_widget_add_tick_callback (window, change_theme, data, NULL);
}
else if (!active && tick_cb)
{
gtk_widget_remove_tick_callback (window, tick_cb);
tick_cb = 0;
}
}
GtkWidget *
do_themes (GtkWidget *do_widget)
{
@@ -195,8 +174,6 @@ do_themes (GtkWidget *do_widget)
{
GtkBuilder *builder;
GtkWidget *header;
GtkWidget *button;
GtkWidget *label;
GtkGesture *gesture;
builder = gtk_builder_new_from_resource ("/themes/themes.ui");
@@ -206,17 +183,11 @@ do_themes (GtkWidget *do_widget)
gtk_widget_get_display (do_widget));
header = GTK_WIDGET (gtk_builder_get_object (builder, "header"));
label = GTK_WIDGET (gtk_builder_get_object (builder, "fps"));
gesture = gtk_gesture_click_new ();
g_signal_connect (gesture, "pressed", G_CALLBACK (clicked), label);
g_signal_connect (gesture, "pressed", G_CALLBACK (clicked), builder);
gtk_widget_add_controller (header, GTK_EVENT_CONTROLLER (gesture));
button = GTK_WIDGET (gtk_builder_get_object (builder, "toggle"));
g_signal_connect (button, "notify::active", G_CALLBACK (toggle_cycle), label);
gtk_widget_realize (window);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))

View File

@@ -5,11 +5,6 @@
<child type="titlebar">
<object class="GtkHeaderBar" id="header">
<property name="show-title-buttons">1</property>
<child type="start">
<object class="GtkToggleButton" id="toggle">
<property name="label">Cycle</property>
</object>
</child>
<child type="end">
<object class="GtkLabel" id="fps"/>
</child>

View File

@@ -84,7 +84,7 @@ static TreeItem may[] =
static TreeItem june[] =
{
{ "June Fathers' Day", FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, NULL },
{ "Juneteenth (Liberation Day)", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
{ "Juneteenth (Liberation of Slaves)", FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, NULL },
{ "Flag Day", FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, NULL },
{ NULL }
};
@@ -406,7 +406,7 @@ do_tree_store (GtkWidget *do_widget)
gtk_box_append (GTK_BOX (vbox),
gtk_label_new ("Jonathan's Holiday Card Planning Sheet"));
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (sw), TRUE);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,

View File

@@ -2,6 +2,7 @@
<gresources>
<gresource prefix="/org/gtk/iconbrowser/gtk">
<file preprocess="xml-stripblanks">window.ui</file>
<file preprocess="xml-stripblanks">menus.ui</file>
<file>icon.list</file>
</gresource>
</gresources>

View File

@@ -1,156 +0,0 @@
#include "iconbrowsercontext.h"
struct _IbContext
{
GObject parent_instance;
char *id;
char *name;
char *description;
};
struct _IbContextClass
{
GObjectClass parent_class;
};
enum {
PROP_ID = 1,
PROP_NAME,
PROP_DESCRIPTION,
PROP_NUM_PROPERTIES
};
G_DEFINE_TYPE (IbContext, ib_context, G_TYPE_OBJECT)
static void
ib_context_init (IbContext *context)
{
}
static void
ib_context_finalize (GObject *object)
{
IbContext *context = IB_CONTEXT (object);
g_free (context->id);
g_free (context->name);
g_free (context->description);
G_OBJECT_CLASS (ib_context_parent_class)->finalize (object);
}
static void
ib_context_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
IbContext *context = IB_CONTEXT (object);
switch (property_id)
{
case PROP_ID:
g_free (context->id);
context->id = g_value_dup_string (value);
break;
case PROP_NAME:
g_free (context->name);
context->name = g_value_dup_string (value);
break;
case PROP_DESCRIPTION:
g_free (context->description);
context->description = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ib_context_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
IbContext *context = IB_CONTEXT (object);
switch (property_id)
{
case PROP_ID:
g_value_set_string (value, context->id);
break;
case PROP_NAME:
g_value_set_string (value, context->name);
break;
case PROP_DESCRIPTION:
g_value_set_string (value, context->description);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ib_context_class_init (IbContextClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GParamSpec *pspec;
object_class->finalize = ib_context_finalize;
object_class->set_property = ib_context_set_property;
object_class->get_property = ib_context_get_property;
pspec = g_param_spec_string ("id", "Id", "Id",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_ID, pspec);
pspec = g_param_spec_string ("name", "Name", "Name",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_NAME, pspec);
pspec = g_param_spec_string ("description", "Description", "Description",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_DESCRIPTION, pspec);
}
IbContext *
ib_context_new (const char *id,
const char *name,
const char *description)
{
return g_object_new (IB_TYPE_CONTEXT,
"id", id,
"name", name,
"description", description,
NULL);
}
const char *
ib_context_get_id (IbContext *context)
{
return context->id;
}
const char *
ib_context_get_name (IbContext *context)
{
return context->name;
}
const char *
ib_context_get_description (IbContext *context)
{
return context->description;
}

View File

@@ -1,14 +0,0 @@
#pragma once
#include <gtk.h>
#define IB_TYPE_CONTEXT (ib_context_get_type ())
G_DECLARE_FINAL_TYPE (IbContext, ib_context, IB, CONTEXT, GObject)
IbContext *ib_context_new (const char *id,
const char *name,
const char *description);
const char *ib_context_get_id (IbContext *context);
const char *ib_context_get_name (IbContext *context);
const char *ib_context_get_description (IbContext *context);

View File

@@ -1,228 +0,0 @@
#include "iconbrowsericon.h"
struct _IbIcon
{
GObject parent_instance;
gboolean use_symbolic;
char *regular_name;
char *symbolic_name;
char *description;
char *context;
};
struct _IbIconClass
{
GObjectClass parent_class;
};
enum {
PROP_NAME = 1,
PROP_REGULAR_NAME,
PROP_SYMBOLIC_NAME,
PROP_USE_SYMBOLIC,
PROP_DESCRIPTION,
PROP_CONTEXT,
PROP_NUM_PROPERTIES
};
G_DEFINE_TYPE (IbIcon, ib_icon, G_TYPE_OBJECT)
static void
ib_icon_init (IbIcon *icon)
{
}
static void
ib_icon_finalize (GObject *object)
{
IbIcon *icon = IB_ICON (object);
g_free (icon->regular_name);
g_free (icon->symbolic_name);
g_free (icon->description);
g_free (icon->context);
G_OBJECT_CLASS (ib_icon_parent_class)->finalize (object);
}
static void
ib_icon_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
IbIcon *icon = IB_ICON (object);
switch (property_id)
{
case PROP_REGULAR_NAME:
g_free (icon->regular_name);
icon->regular_name = g_value_dup_string (value);
if (!icon->use_symbolic)
g_object_notify (object, "name");
break;
case PROP_SYMBOLIC_NAME:
g_free (icon->symbolic_name);
icon->symbolic_name = g_value_dup_string (value);
if (icon->use_symbolic)
g_object_notify (object, "name");
break;
case PROP_USE_SYMBOLIC:
icon->use_symbolic = g_value_get_boolean (value);
g_object_notify (object, "name");
break;
case PROP_DESCRIPTION:
g_free (icon->description);
icon->description = g_value_dup_string (value);
break;
case PROP_CONTEXT:
g_free (icon->context);
icon->context = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ib_icon_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
IbIcon *icon = IB_ICON (object);
switch (property_id)
{
case PROP_NAME:
g_value_set_string (value, ib_icon_get_name (icon));
break;
case PROP_REGULAR_NAME:
g_value_set_string (value, icon->regular_name);
break;
case PROP_SYMBOLIC_NAME:
g_value_set_string (value, icon->symbolic_name);
break;
case PROP_USE_SYMBOLIC:
g_value_set_boolean (value, icon->use_symbolic);
break;
case PROP_DESCRIPTION:
g_value_set_string (value, icon->description);
break;
case PROP_CONTEXT:
g_value_set_string (value, icon->context);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
ib_icon_class_init (IbIconClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GParamSpec *pspec;
object_class->finalize = ib_icon_finalize;
object_class->set_property = ib_icon_set_property;
object_class->get_property = ib_icon_get_property;
pspec = g_param_spec_string ("name", "Name", "Name",
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_NAME, pspec);
pspec = g_param_spec_string ("regular-name", "Regular Name", "Regular Name",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_REGULAR_NAME, pspec);
pspec = g_param_spec_string ("symbolic-name", "Symbolic Name", "Symbolic Name",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_SYMBOLIC_NAME, pspec);
pspec = g_param_spec_boolean ("use-symbolic", "Use Symbolic", "Use Symbolic",
FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_USE_SYMBOLIC, pspec);
pspec = g_param_spec_string ("description", "Description", "Description",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_DESCRIPTION, pspec);
pspec = g_param_spec_string ("context", "Context", "Context",
NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_CONTEXT, pspec);
}
IbIcon *
ib_icon_new (const char *regular_name,
const char *symbolic_name,
const char *description,
const char *context)
{
return g_object_new (IB_TYPE_ICON,
"regular-name", regular_name,
"symbolic-name", symbolic_name,
"description", description,
"context", context,
NULL);
}
const char *
ib_icon_get_name (IbIcon *icon)
{
if (icon->use_symbolic)
return icon->symbolic_name;
else
return icon->regular_name;
}
const char *
ib_icon_get_regular_name (IbIcon *icon)
{
return icon->regular_name;
}
const char *
ib_icon_get_symbolic_name (IbIcon *icon)
{
return icon->symbolic_name;
}
gboolean
ib_icon_get_use_symbolic (IbIcon *icon)
{
return icon->use_symbolic;
}
const char *
ib_icon_get_description (IbIcon *icon)
{
return icon->description;
}
const char *
ib_icon_get_context (IbIcon *icon)
{
return icon->context;
}

View File

@@ -1,18 +0,0 @@
#pragma once
#include <gtk.h>
#define IB_TYPE_ICON (ib_icon_get_type ())
G_DECLARE_FINAL_TYPE (IbIcon, ib_icon, IB, ICON, GObject)
IbIcon *ib_icon_new (const char *regular_name,
const char *symbolic_name,
const char *description,
const char *context);
const char *ib_icon_get_name (IbIcon *icon);
const char *ib_icon_get_regular_name (IbIcon *icon);
const char *ib_icon_get_symbolic_name (IbIcon *icon);
gboolean ib_icon_get_use_symbolic (IbIcon *icon);
const char *ib_icon_get_description (IbIcon *icon);
const char *ib_icon_get_context (IbIcon *icon);

View File

@@ -1,22 +1,48 @@
#include <string.h>
#include "iconbrowserapp.h"
#include "iconbrowserwin.h"
#include "iconbrowsericon.h"
#include "iconbrowsercontext.h"
#include "iconstore.h"
#include <gtk/gtk.h>
/* Drag 'n Drop */
typedef struct
{
gchar *id;
gchar *name;
gchar *description;
} Context;
static void
context_free (gpointer data)
{
Context *context = data;
g_free (context->id);
g_free (context->name);
g_free (context->description);
g_free (context);
}
struct _IconBrowserWindow
{
GtkApplicationWindow parent;
GHashTable *contexts;
GtkWidget *context_list;
Context *current_context;
gboolean symbolic;
GtkWidget *symbolic_radio;
GtkWidget *searchbar;
GListModel *icon_filter_model;
GListStore *icon_store;
GListStore *context_store;
GtkFilter *name_filter;
GtkTreeModelFilter *filter_model;
GtkWidget *details;
GtkListStore *store;
GtkCellRenderer *cell;
GtkCellRenderer *text_cell;
GtkWidget *search;
GtkWidget *searchbar;
GtkWidget *searchentry;
GtkWidget *list;
GtkWidget *image1;
GtkWidget *image2;
GtkWidget *image3;
@@ -42,6 +68,87 @@ icon_browser_window_get_icon_theme (IconBrowserWindow *win)
return gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (win)));
}
static void
search_text_changed (GtkEntry *entry, IconBrowserWindow *win)
{
const gchar *text;
text = gtk_editable_get_text (GTK_EDITABLE (entry));
if (text[0] == '\0')
return;
gtk_tree_model_filter_refilter (win->filter_model);
}
static void
set_image (GtkWidget *image, const gchar *name, gint size)
{
gtk_image_set_from_icon_name (GTK_IMAGE (image), name);
gtk_image_set_pixel_size (GTK_IMAGE (image), size);
}
static void
item_activated (GtkIconView *icon_view, GtkTreePath *path, IconBrowserWindow *win)
{
GtkIconTheme *icon_theme = icon_browser_window_get_icon_theme (win);
GtkTreeIter iter;
gchar *name;
gchar *description;
gint column;
gtk_tree_model_get_iter (GTK_TREE_MODEL (win->filter_model), &iter, path);
if (win->symbolic)
column = ICON_STORE_SYMBOLIC_NAME_COLUMN;
else
column = ICON_STORE_NAME_COLUMN;
gtk_tree_model_get (GTK_TREE_MODEL (win->filter_model), &iter,
column, &name,
ICON_STORE_DESCRIPTION_COLUMN, &description,
-1);
if (name == NULL || !gtk_icon_theme_has_icon (icon_theme, name))
{
g_free (description);
return;
}
gtk_window_set_title (GTK_WINDOW (win->details), name);
set_image (win->image1, name, 8);
set_image (win->image2, name, 16);
set_image (win->image3, name, 18);
set_image (win->image4, name, 24);
set_image (win->image5, name, 32);
set_image (win->image6, name, 48);
set_image (win->image7, name, 64);
if (win->symbolic)
{
gtk_widget_show (win->image8);
gtk_widget_show (win->label8);
set_image (win->image8, name, 64);
}
else
{
gtk_widget_hide (win->image8);
gtk_widget_hide (win->label8);
}
if (description && description[0])
{
gtk_label_set_text (GTK_LABEL (win->description), description);
gtk_widget_show (win->description);
}
else
{
gtk_widget_hide (win->description);
}
gtk_window_present (GTK_WINDOW (win->details));
g_free (name);
g_free (description);
}
static void
add_icon (IconBrowserWindow *win,
const gchar *name,
@@ -51,7 +158,6 @@ add_icon (IconBrowserWindow *win,
GtkIconTheme *icon_theme = icon_browser_window_get_icon_theme (win);
gchar *regular_name;
gchar *symbolic_name;
IbIcon *icon;
regular_name = g_strdup (name);
if (!gtk_icon_theme_has_icon (icon_theme, regular_name))
@@ -67,12 +173,12 @@ add_icon (IconBrowserWindow *win,
symbolic_name = NULL;
}
icon = ib_icon_new (regular_name, symbolic_name, description, context);
g_object_bind_property (win->symbolic_radio, "active",
icon, "use-symbolic",
G_BINDING_DEFAULT);
g_list_store_append (win->icon_store, icon);
g_object_unref (icon);
gtk_list_store_insert_with_values (win->store, NULL, -1,
ICON_STORE_NAME_COLUMN, regular_name,
ICON_STORE_SYMBOLIC_NAME_COLUMN, symbolic_name,
ICON_STORE_DESCRIPTION_COLUMN, description,
ICON_STORE_CONTEXT_COLUMN, context,
-1);
}
static void
@@ -81,11 +187,50 @@ add_context (IconBrowserWindow *win,
const gchar *name,
const gchar *description)
{
IbContext *context;
Context *c;
GtkWidget *row;
context = ib_context_new (id, name, description);
g_list_store_append (win->context_store, context);
g_object_unref (context);
c = g_new (Context, 1);
c->id = g_strdup (id);
c->name = g_strdup (name);
c->description = g_strdup (description);
g_hash_table_insert (win->contexts, c->id, c);
row = gtk_label_new (name);
gtk_label_set_xalign (GTK_LABEL (row), 0);
g_object_set_data (G_OBJECT (row), "context", c);
gtk_widget_show (row);
gtk_widget_set_margin_start (row, 10);
gtk_widget_set_margin_end (row, 10);
gtk_widget_set_margin_top (row, 10);
gtk_widget_set_margin_bottom (row, 10);
gtk_list_box_insert (GTK_LIST_BOX (win->context_list), row, -1);
/* set the tooltip on the list box row */
row = gtk_widget_get_parent (row);
gtk_widget_set_tooltip_text (row, description);
if (win->current_context == NULL)
win->current_context = c;
}
static void
selected_context_changed (GtkListBox *list, IconBrowserWindow *win)
{
GtkWidget *row;
GtkWidget *label;
row = GTK_WIDGET (gtk_list_box_get_selected_row (list));
if (row == NULL)
return;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (win->search), FALSE);
label = gtk_list_box_row_get_child (GTK_LIST_BOX_ROW (row));
win->current_context = g_object_get_data (G_OBJECT (label), "context");
gtk_tree_model_filter_refilter (win->filter_model);
}
static void
@@ -137,19 +282,6 @@ populate (IconBrowserWindow *win)
g_strfreev (groups);
}
static gboolean
filter_by_icon_name (gpointer item,
gpointer data)
{
return ib_icon_get_name (IB_ICON (item)) != NULL;
}
static void
symbolic_toggled (IconBrowserWindow *win)
{
gtk_filter_changed (win->name_filter, GTK_FILTER_CHANGE_DIFFERENT);
}
static void
copy_to_clipboard (GtkButton *button,
IconBrowserWindow *win)
@@ -160,60 +292,70 @@ copy_to_clipboard (GtkButton *button,
gdk_clipboard_set_text (clipboard, gtk_window_get_title (GTK_WINDOW (win->details)));
}
static void
set_image (GtkWidget *image, const gchar *name, gint size)
static gboolean
icon_visible_func (GtkTreeModel *model,
GtkTreeIter *iter,
gpointer data)
{
gtk_image_set_from_icon_name (GTK_IMAGE (image), name);
gtk_image_set_pixel_size (GTK_IMAGE (image), size);
IconBrowserWindow *win = data;
gchar *context;
gchar *name;
gint column;
gboolean search;
const gchar *search_text;
gboolean visible;
search = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (win->search));
search_text = gtk_editable_get_text (GTK_EDITABLE (win->searchentry));
if (win->symbolic)
column = ICON_STORE_SYMBOLIC_NAME_COLUMN;
else
column = ICON_STORE_NAME_COLUMN;
gtk_tree_model_get (model, iter,
column, &name,
ICON_STORE_CONTEXT_COLUMN, &context,
-1);
if (!name)
visible = FALSE;
else if (search)
visible = strstr (name, search_text) != NULL;
else
visible = win->current_context != NULL && g_strcmp0 (context, win->current_context->id) == 0;
g_free (name);
g_free (context);
return visible;
}
static void
item_activated (GtkGridView *view,
guint position,
IconBrowserWindow *win)
symbolic_toggled (GtkToggleButton *toggle, IconBrowserWindow *win)
{
GListModel *model = gtk_grid_view_get_model (view);
IbIcon *icon = g_list_model_get_item (model, position);
const char *name;
const char *description;
gboolean symbolic;
gint column;
name = ib_icon_get_name (icon);
description = ib_icon_get_description (icon);
symbolic = ib_icon_get_use_symbolic (icon);
win->symbolic = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (toggle));
gtk_window_set_title (GTK_WINDOW (win->details), name);
set_image (win->image1, name, 8);
set_image (win->image2, name, 16);
set_image (win->image3, name, 18);
set_image (win->image4, name, 24);
set_image (win->image5, name, 32);
set_image (win->image6, name, 48);
set_image (win->image7, name, 64);
if (symbolic)
{
gtk_widget_show (win->image8);
gtk_widget_show (win->label8);
set_image (win->image8, name, 64);
}
if (win->symbolic)
column = ICON_STORE_SYMBOLIC_NAME_COLUMN;
else
{
gtk_widget_hide (win->image8);
gtk_widget_hide (win->label8);
}
if (description && description[0])
{
gtk_label_set_text (GTK_LABEL (win->description), description);
gtk_widget_show (win->description);
}
else
{
gtk_widget_hide (win->description);
}
column = ICON_STORE_NAME_COLUMN;
gtk_window_present (GTK_WINDOW (win->details));
icon_store_set_text_column (ICON_STORE (win->store), column);
g_object_unref (icon);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (win->list), win->cell, "icon-name", column, NULL);
gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (win->list), win->text_cell, "text", column, NULL);
gtk_tree_model_filter_refilter (win->filter_model);
gtk_widget_queue_draw (win->list);
}
static void
search_mode_toggled (GObject *searchbar, GParamSpec *pspec, IconBrowserWindow *win)
{
if (gtk_search_bar_get_search_mode (GTK_SEARCH_BAR (searchbar)))
gtk_list_box_unselect_all (GTK_LIST_BOX (win->context_list));
}
static GdkPaintable *
@@ -239,10 +381,7 @@ get_image_paintable (GtkImage *image)
gtk_widget_get_direction (GTK_WIDGET (image)),
0);
if (icon == NULL)
{
g_print ("no icon for %s\n", icon_name);
return NULL;
}
return NULL;
return GDK_PAINTABLE (icon);
case GTK_IMAGE_GICON:
case GTK_IMAGE_EMPTY:
@@ -280,10 +419,10 @@ drag_prepare_texture (GtkDragSource *source,
{
GdkPaintable *paintable = get_image_paintable (GTK_IMAGE (widget));
if (!GDK_IS_PAINTABLE (paintable))
if (!GDK_IS_TEXTURE (paintable))
return NULL;
return gdk_content_provider_new_typed (GDK_TYPE_PAINTABLE, paintable);
return gdk_content_provider_new_typed (GDK_TYPE_TEXTURE, paintable);
}
static GdkContentProvider *
@@ -337,10 +476,17 @@ setup_scalable_image_dnd (GtkWidget *image)
static void
icon_browser_window_init (IconBrowserWindow *win)
{
GtkFilter *filter;
GdkContentFormats *list;
gtk_widget_init_template (GTK_WIDGET (win));
list = gdk_content_formats_new_for_gtype (G_TYPE_STRING);
gtk_icon_view_enable_model_drag_source (GTK_ICON_VIEW (win->list),
GDK_BUTTON1_MASK,
list,
GDK_ACTION_COPY);
gdk_content_formats_unref (list);
setup_image_dnd (win->image1);
setup_image_dnd (win->image2);
setup_image_dnd (win->image3);
@@ -350,16 +496,19 @@ icon_browser_window_init (IconBrowserWindow *win)
setup_image_dnd (win->image7);
setup_scalable_image_dnd (win->image8);
win->contexts = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, context_free);
gtk_tree_model_filter_set_visible_func (win->filter_model, icon_visible_func, win, NULL);
gtk_window_set_transient_for (GTK_WINDOW (win->details), GTK_WINDOW (win));
gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (win->searchbar), GTK_WIDGET (win));
g_signal_connect (win->searchbar, "notify::search-mode-enabled",
G_CALLBACK (search_mode_toggled), win);
gtk_search_bar_set_key_capture_widget (GTK_SEARCH_BAR (win->searchbar),
GTK_WIDGET (win));
symbolic_toggled (GTK_TOGGLE_BUTTON (win->symbolic_radio), win);
populate (win);
filter = gtk_filter_list_model_get_filter (GTK_FILTER_LIST_MODEL (win->icon_filter_model));
win->name_filter = gtk_custom_filter_new (filter_by_icon_name, NULL, NULL);
gtk_multi_filter_append (GTK_MULTI_FILTER (filter), g_object_ref (win->name_filter));
}
static void
@@ -367,7 +516,7 @@ icon_browser_window_finalize (GObject *object)
{
IconBrowserWindow *win = ICON_BROWSER_WINDOW (object);
g_clear_object (&win->name_filter);
g_hash_table_unref (win->contexts);
G_OBJECT_CLASS (icon_browser_window_parent_class)->finalize (object);
}
@@ -379,19 +528,23 @@ icon_browser_window_class_init (IconBrowserWindowClass *class)
object_class->finalize = icon_browser_window_finalize;
g_type_ensure (IB_TYPE_ICON);
g_type_ensure (IB_TYPE_CONTEXT);
g_type_ensure (ICON_STORE_TYPE);
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
"/org/gtk/iconbrowser/gtk/window.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, context_list);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, filter_model);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, symbolic_radio);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, searchbar);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, icon_store);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, icon_filter_model);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, context_store);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, details);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, store);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, cell);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, text_cell);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, search);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, searchbar);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, searchentry);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, list);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image1);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image2);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, image3);
@@ -403,9 +556,11 @@ icon_browser_window_class_init (IconBrowserWindowClass *class)
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, label8);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), IconBrowserWindow, description);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), search_text_changed);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), item_activated);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), copy_to_clipboard);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), selected_context_changed);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), symbolic_toggled);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), copy_to_clipboard);
}
IconBrowserWindow *

View File

@@ -0,0 +1,91 @@
#include "iconstore.h"
#include <gtk/gtk.h>
struct _IconStore
{
GtkListStore parent;
gint text_column;
};
struct _IconStoreClass
{
GtkListStoreClass parent_class;
};
static void icon_store_drag_source_init (GtkTreeDragSourceIface *iface);
G_DEFINE_TYPE_WITH_CODE (IconStore, icon_store, GTK_TYPE_LIST_STORE,
G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
icon_store_drag_source_init))
static void
icon_store_init (IconStore *store)
{
GType types[4] = { G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING };
gtk_list_store_set_column_types (GTK_LIST_STORE (store), 4, types);
store->text_column = ICON_STORE_NAME_COLUMN;
}
static void
icon_store_class_init (IconStoreClass *class)
{
}
static gboolean
row_draggable (GtkTreeDragSource *drag_source,
GtkTreePath *path)
{
return TRUE;
}
static gboolean
drag_data_delete (GtkTreeDragSource *drag_source,
GtkTreePath *path)
{
GtkTreeIter iter;
if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source), &iter, path))
return gtk_list_store_remove (GTK_LIST_STORE (drag_source), &iter);
return FALSE;
}
static GdkContentProvider *
drag_data_get (GtkTreeDragSource *drag_source,
GtkTreePath *path)
{
GdkContentProvider *content;
GtkTreeIter iter;
gchar *text;
if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source), &iter, path))
return NULL;
gtk_tree_model_get (GTK_TREE_MODEL (drag_source), &iter,
ICON_STORE (drag_source)->text_column, &text,
-1);
content = gdk_content_provider_new_typed (G_TYPE_STRING, text);
g_free (text);
return content;
}
static void
icon_store_drag_source_init (GtkTreeDragSourceIface *iface)
{
iface->row_draggable = row_draggable;
iface->drag_data_delete = drag_data_delete;
iface->drag_data_get = drag_data_get;
}
void
icon_store_set_text_column (IconStore *store, gint text_column)
{
store->text_column = text_column;
}

View File

@@ -0,0 +1,26 @@
#ifndef __ICON_STORE_H
#define __ICON_STORE_H
#include <gtk/gtk.h>
#define ICON_STORE_TYPE (icon_store_get_type ())
#define ICON_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ICON_STORE_TYPE, IconStore))
typedef struct _IconStore IconStore;
typedef struct _IconStoreClass IconStoreClass;
enum {
ICON_STORE_NAME_COLUMN,
ICON_STORE_SYMBOLIC_NAME_COLUMN,
ICON_STORE_DESCRIPTION_COLUMN,
ICON_STORE_CONTEXT_COLUMN
};
GType icon_store_get_type (void);
void icon_store_set_text_column (IconStore *store,
gint column);
#endif /* __ICON_STORE_H */

View File

@@ -0,0 +1,10 @@
<interface>
<menu id="app-menu">
<section>
<item>
<attribute name="label" translatable="yes">_Quit</attribute>
<attribute name="action">app.quit</attribute>
</item>
</section>
</menu>
</interface>

View File

@@ -2,8 +2,7 @@ iconbrowser_sources = [
'main.c',
'iconbrowserapp.c',
'iconbrowserwin.c',
'iconbrowsericon.c',
'iconbrowsercontext.c'
'iconstore.c'
]
iconbrowser_resources = gnome.compile_resources('iconbrowser_resources',
@@ -18,3 +17,14 @@ executable('gtk4-icon-browser',
gui_app: true,
link_args: extra_demo_ldflags,
install: true)
install_data('org.gtk.IconBrowser4.desktop', install_dir: gtk_applicationsdir)
# icons
icontheme_dir = join_paths(gtk_datadir, 'icons/hicolor')
foreach size: ['scalable', 'symbolic']
install_subdir('data/' + size,
install_dir: icontheme_dir
)
endforeach

View File

@@ -12,6 +12,10 @@
</item>
</section>
</menu>
<object class="IconStore" id="store"/>
<object class="GtkTreeModelFilter" id="filter_model">
<property name="child-model">store</property>
</object>
<template class="IconBrowserWindow" parent="GtkApplicationWindow">
<style>
<class name="devel"/>
@@ -38,7 +42,7 @@
<property name="draw-indicator">0</property>
<property name="label" translatable="yes">Symbolic</property>
<property name="group">normal_radio</property>
<signal name="notify::active" handler="symbolic_toggled" swapped="yes" after="yes"/>
<signal name="toggled" handler="symbolic_toggled"/>
</object>
</child>
</object>
@@ -67,44 +71,8 @@
<child>
<object class="GtkBox">
<child>
<object class="GtkScrolledWindow">
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkListView">
<property name="model">
<object class="GtkSingleSelection" id="context_model">
<property name="model">
<object class="GListStore" id="context_store">
<property name="item-type">IbContext</property>
</object>
</property>
</object>
</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes">
<![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkLabel">
<property name="xalign">0</property>
<binding name="label">
<lookup name="name" type="IbContext">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</property>
</template>
</interface>
]]>
</property>
</object>
</property>
</object>
</child>
<object class="GtkListBox" id="context_list">
<signal name="selected-rows-changed" handler="selected_context_changed"/>
</object>
</child>
<child>
@@ -120,6 +88,7 @@
<property name="search-mode-enabled" bind-source="search" bind-property="active" bind-flags="bidirectional"/>
<child>
<object class="GtkSearchEntry" id="searchentry">
<signal name="search-changed" handler="search_text_changed"/>
</object>
</child>
</object>
@@ -130,91 +99,23 @@
<property name="vexpand">1</property>
<property name="hscrollbar-policy">never</property>
<child>
<object class="GtkGridView" id="list">
<signal name="activate" handler="item_activated"/>
<property name="single-click-activate">1</property>
<property name="model">
<object class="GtkNoSelection">
<property name="model">
<object class="GtkFilterListModel" id="icon_filter_model">
<property name="filter">
<object class="GtkEveryFilter">
<child>
<object class="GtkStringFilter">
<property name="expression">
<lookup name="name" type="IbIcon"/>
</property>
<binding name="search">
<lookup name="text" type="GtkSearchEntry">
searchentry
</lookup>
</binding>
</object>
</child>
<child>
<object class="GtkStringFilter">
<property name="ignore-case">0</property>
<property name="match-mode">exact</property>
<property name="expression">
<lookup name="context" type="IbIcon"/>
</property>
<binding name="search">
<lookup name="id" type="IbContext">
<lookup name="selected-item" type="GtkSingleSelection">
context_model
</lookup>
</lookup>
</binding>
</object>
</child>
</object>
</property>
<property name="model">
<object class="GListStore" id="icon_store">
<property name="item-type">IbIcon</property>
</object>
</property>
</object>
</property>
<object class="GtkIconView" id="list">
<property name="model">filter_model</property>
<property name="selection-mode">none</property>
<property name="activate-on-single-click">1</property>
<signal name="item_activated" handler="item_activated"/>
<child>
<object class="GtkCellRendererPixbuf" id="cell">
<property name="xpad">10</property>
<property name="ypad">10</property>
</object>
</property>
<property name="factory">
<object class="GtkBuilderListItemFactory">
<property name="bytes">
<![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="GtkListItem">
<property name="child">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkImage">
<property name="pixel-size">48</property>
<binding name="icon-name">
<lookup name="name" type="IbIcon">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</child>
<child>
<object class="GtkLabel">
<binding name="label">
<lookup name="name" type="IbIcon">
<lookup name="item">GtkListItem</lookup>
</lookup>
</binding>
</object>
</child>
</object>
</property>
</template>
</interface>
]]>
</property>
</child>
<child>
<object class="GtkCellRendererText" id="text_cell">
<property name="xpad">10</property>
<property name="ypad">10</property>
</object>
</property>
</child>
</object>
</child>
</object>
@@ -224,7 +125,14 @@
</object>
</child>
</template>
<object class="GtkSizeGroup">
<property name="mode">vertical</property>
<widgets>
<widget name="normal_radio"/>
<widget name="symbolic_radio"/>
<widget name="search"/>
</widgets>
</object>
<object class="GtkDialog" id="details">
<property name="modal">1</property>
<property name="use-header-bar">1</property>
@@ -256,7 +164,7 @@
</object>
</child>
<child>
<object class="GtkImage" id="image2">
<object class="GtkImage" id="image2">
<property name="halign">center</property>
<property name="valign">end</property>
<accessibility>
@@ -465,7 +373,7 @@
</layout>
</object>
</child>
<child>
<child>
<object class="GtkLabel" id="label8">
<property name="halign">center</property>
<property name="valign">baseline</property>
@@ -496,7 +404,7 @@
<signal name="clicked" handler="copy_to_clipboard"/>
</object>
</child>
<child>
<child>
<object class="GtkLabel" id="description">
<property name="margin-start">10</property>
<property name="margin-end">10</property>
@@ -511,4 +419,3 @@
</child>
</object>
</interface>

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkWindow" id="window">
<style>
<class name="devel"/>
</style>
<property name="title" translatable="yes">Help</property>
<property name="default-width">720</property>
<property name="default-height">520</property>
<child>
<object class="GtkScrolledWindow">
<child>
<object class="GtkTextView" id="text_view">
<property name="wrap-mode">word</property>
<property name="left-margin">20</property>
<property name="right-margin">20</property>
<property name="top-margin">20</property>
<property name="bottom-margin">20</property>
<property name="buffer">
<object class="GtkTextBuffer" id="buffer"/>
</property>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -51,121 +51,21 @@ node_editor_application_init (NodeEditorApplication *app)
}
static void
activate_about (GSimpleAction *action,
quit_activated (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkApplication *app = user_data;
char *version;
GString *s;
GskRenderer *gsk_renderer;
const char *renderer;
s = g_string_new ("");
g_string_append (s, "System libraries\n");
g_string_append_printf (s, "\tGLib\t%d.%d.%d\n",
glib_major_version,
glib_minor_version,
glib_micro_version);
g_string_append_printf (s, "\tPango\t%s\n",
pango_version_string ());
g_string_append_printf (s, "\tGTK\t%d.%d.%d\n",
gtk_get_major_version (),
gtk_get_minor_version (),
gtk_get_micro_version ());
gsk_renderer = gtk_native_get_renderer (GTK_NATIVE (gtk_application_get_active_window (app)));
if (strcmp (G_OBJECT_TYPE_NAME (gsk_renderer), "GskVulkanRenderer") == 0)
renderer = "Vulkan";
else if (strcmp (G_OBJECT_TYPE_NAME (gsk_renderer), "GskGLRenderer") == 0)
renderer = "OpenGL";
else if (strcmp (G_OBJECT_TYPE_NAME (gsk_renderer), "GskCairoRenderer") == 0)
renderer = "Cairo";
else
renderer = "Unknown";
g_string_append_printf (s, "\nRenderer\n\t%s", renderer);
version = g_strdup_printf ("%s\nRunning against GTK %d.%d.%d",
PACKAGE_VERSION,
gtk_get_major_version (),
gtk_get_minor_version (),
gtk_get_micro_version ());
gtk_show_about_dialog (GTK_WINDOW (gtk_application_get_active_window (app)),
"program-name", "GTK Node Editor",
"version", version,
"copyright", "©2019—2020 The GTK Team",
"license-type", GTK_LICENSE_LGPL_2_1,
"website", "http://www.gtk.org",
"comments", "Program to test GTK rendering",
"authors", (const char *[]){ "Benjamin Otte", "Timm Bäder", NULL},
"logo-icon-name", "text-editor-symbolic",
"title", "About GTK Node Editor",
"system-information", s->str,
NULL);
g_string_free (s, TRUE);
g_free (version);
}
static void
activate_quit (GSimpleAction *action,
GVariant *parameter,
gpointer data)
gpointer data)
{
g_application_quit (G_APPLICATION (data));
}
static void
activate_inspector (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
gtk_window_set_interactive_debugging (TRUE);
}
static void
activate_help (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkBuilder *builder;
GtkWidget *window;
GtkTextBuffer *buffer;
GBytes *bytes;
const char *text;
gsize len;
builder = gtk_builder_new ();
gtk_builder_add_from_resource (builder, "/org/gtk/gtk4/node-editor/help-window.ui", NULL);
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
buffer = GTK_TEXT_BUFFER (gtk_builder_get_object (builder, "buffer"));
bytes = g_resources_lookup_data ("/org/gtk/gtk4/node-editor/node-format.md",
G_RESOURCE_LOOKUP_FLAGS_NONE,
NULL);
text = g_bytes_get_data (bytes, &len);
gtk_text_buffer_set_text (buffer, text, len);
g_bytes_unref (bytes);
gtk_window_present (GTK_WINDOW (window));
g_object_unref (builder);
}
static GActionEntry app_entries[] =
{
{ "about", activate_about, NULL, NULL, NULL },
{ "quit", activate_quit, NULL, NULL, NULL },
{ "inspector", activate_inspector, NULL, NULL, NULL },
{ "help", activate_help, NULL, NULL, NULL },
{ "quit", quit_activated, NULL, NULL, NULL }
};
static void
node_editor_application_startup (GApplication *app)
{
const char *help_accels[2] = { "F1", NULL };
const char *quit_accels[2] = { "<Ctrl>Q", NULL };
const char *open_accels[2] = { "<Ctrl>O", NULL };
GtkCssProvider *provider;
@@ -175,7 +75,6 @@ node_editor_application_startup (GApplication *app)
g_action_map_add_action_entries (G_ACTION_MAP (app),
app_entries, G_N_ELEMENTS (app_entries),
app);
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "app.help", help_accels);
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "app.quit", quit_accels);
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "win.open", open_accels);

View File

@@ -825,7 +825,6 @@ node_editor_window_create_renderer_widget (gpointer item,
gtk_widget_set_size_request (box, 120, 90);
label = gtk_label_new (g_object_get_data (G_OBJECT (paintable), "description"));
gtk_widget_add_css_class (label, "title-4");
gtk_box_append (GTK_BOX (box), label);
picture = gtk_picture_new_for_paintable (paintable);

View File

@@ -1,22 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<menu id="gear_menu">
<section>
<item>
<attribute name="label" translatable="yes">_Help</attribute>
<attribute name="action">app.help</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Inspector</attribute>
<attribute name="action">app.inspector</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_About Node Editor</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
</menu>
<object class="GtkPopover" id="testcase_popover">
<child>
<object class="GtkGrid">
@@ -136,13 +119,6 @@
<property name="popover">testcase_popover</property>
</object>
</child>
<child type="end">
<object class="GtkMenuButton" id="gear_menu_button">
<property name="valign">center</property>
<property name="menu-model">gear_menu</property>
<property name="icon-name">open-menu-symbolic</property>
</object>
</child>
</object>
</child>
<child>

View File

@@ -2,7 +2,5 @@
<gresources>
<gresource prefix="/org/gtk/gtk4/node-editor">
<file preprocess="xml-stripblanks">node-editor-window.ui</file>
<file preprocess="xml-stripblanks">help-window.ui</file>
<file>node-format.md</file>
</gresource>
</gresources>

View File

@@ -1,213 +0,0 @@
# The Node file format
GSK render nodes can be serialized and deserialized using APIs such as `gsk_render_node_serialize()` and `gsk_render_node_deserialize()`. The intended use for this is development - primarily the development of GTK - by allowing things such as creating testsuites and benchmarks, exchanging nodes in bug reports. GTK includes the `gtk4-node-editor` application for creating such test files.
The format is a text format that follows the [CSS syntax rules](https://drafts.csswg.org/css-syntax-3/). In particular, this means that every array of bytes will produce a render node when parsed, as there is a defined error recovery method. For more details on error handling, please refer to the documentation of the aprsing APIs.
The grammar of a node text representation using [the CSS value definition syntax](https://drafts.csswg.org/css-values-3/#value-defs) looks like this:
**document**: `<node>\*`
**node**: container { <document> } | `<node-name> { <property>* }`
**property**: `<property-name>: <node> | <value> ;`
Each node has its own `<node-name>` and supports a custom set of properties, each with their own `<property-name>` and syntax. The following paragraphs document each of the nodes and their properties.
When serializing and the value of a property equals the default value, this value will not be serialized. Serialization aims to produce an output as small as possible.
# Nodes
### container
The **container** node is a special node that allows specifying a list of child nodes. Its contents follow the same rules as an empty document.
### blend
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| bottom | `<node>` | color { color: #AF0; } | always |
| mode | `<blend-mode>` | normal | non-default |
| top | `<node>` | color { } | always |
Creates a node like `gsk_blend_node_new()` with the given properties.
### blur
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| blur | `<number>` | 1 | non-default |
| child | `<node>` | color { } | always |
Creates a node like `gsk_blur_node_new()` with the given properties.
### border
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| color | `<color>{1,4}` | black | non-default |
| outline | `<rounded-rect>` | 50 | always |
| width | `<number>{1,4}` | 1 | non-default |
Creates a node like `gsk_border_node_new()` with the given properties.
For the color and width properties, the values follow the typical CSS order of top, right, bottom, left. If the last/left value isn't given, the 2nd/right value is used. If the 3rd/bottom value isn't given, the 1st/top value is used. And if the 2nd/right value also isn't given, the 1st/top value is used for every 4 values.
### clip
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| child | `<node>` | color { } | always |
| clip | `<rounded-rect>` | 50 | always |
Creates a node like `gsk_clip_node_new()` with the given properties.
As an extension, this node allows specifying a rounded rectangle for the clip property. If that rectangle is indeed rounded, a node like `gsk_rounded_clip_node_new()` will be created instead.
### color
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| bounds | `<rect>` | 50 | always |
| color | `<color>` | #FF00CC | always |
Creates a node like `gsk_color_node_new()` with the given properties.
The color is chosen as an error pink so it is visible while also reminding people to change it.
### color-matrix
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| child | `<node>` | color { } | always |
| matrix | `<transform>` | none | non-default |
| offset | `<number>{4}` | 0 0 0 0 | non-default |
Creates a node like `gsk_color_matrix_node_new()` with the given properties.
The matrix property accepts a <transform> for compatibility purposes, but you should be aware that the allowed values are meant to be used on 3D transformations, so their naming might appear awkward. However, it is always possible to use the matrix3d() production to specify all 16 values individually.
### cross-fade
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| end | `<node>` | color { } | always |
| mode | `<number>` | 0.5 | non-default |
| start | `<node>` | color { color: #AF0; } | always |
Creates a node like `gsk_cross_fade_node_new()` with the given properties.
### debug
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| child | `<node>` | color { } | always |
| message | `<string>` | "" | non-default |
Creates a node like `gsk_debug_node_new()` with the given properties.
### inset-shadow
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| blur | `<number>` | 0 | non-default |
| color | `<color>` | black | non-default |
| dx | `<number>` | 1 | non-default |
| dy | `<number>` | 1 | non-default |
| outline | `<rounded-rect>` | 50 | always |
| spread | `<number>` | 0 | non-default |
Creates a node like `gsk_inset_shadow_node_new()` with the given properties.
### linear-gradient
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| bounds | `<rect>` | 50 | always |
| end | `<point>` | 0 50 | always |
| start | `<point>` | 0 0 | always |
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
Creates a node like `gsk_linear_gradient_node_new()` with the given properties.
### opacity
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| child | `<node>` | color { } | always |
| opacity | `<number>` | 0.5 | non-default |
Creates a node like `gsk_transform_node_new()` with the given properties.
### outset-shadow
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| blur | `<number>` | 0 | non-default |
| color | `<color>` | black | non-default |
| dx | `<number>` | 1 | non-default |
| dy | `<number>` | 1 | non-default |
| outline | `<rounded-rect>` | 50 | always |
| spread | `<number>` | 0 | non-default |
Creates a node like `gsk_outset_shadow_node_new()` with the given properties.
### repeat
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| bounds | `<rect>` | *bounds of child node* | non-default |
| child | `<node>` | color { } | always |
| child-bounds| `<rect>` | *bounds of child node* | non-default |
Creates a node like `gsk_repeat_node_new()` with the given properties.
### rounded-clip
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| child | `<node>` | color { } | always |
| clip | `<rounded-rect>` | 50 | always |
Creates a node like `gsk_rounded_clip_node_new()` with the given properties.
### shadow
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| child | `<node>` | color { } | always |
| shadow | `<shadow>` | black 1 1 | always |
Creates a node like `gsk_shadow_node_new()` with the given properties.
### text
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| color | `<color>` | black | non-default |
| font | `<string>` | "Cantarell 11" | always |
| glyphs | `<glyphs>` | "Hello" | always |
| offset | `<point>` | 0 0 | non-default |
Creates a node like `gsk_text_node_new()` with the given properties.
If the given font does not exist or the given glyphs are invalid for the given font, an error node will be returned.
### texture
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| bounds | `<rect>` | 50 | always |
| texture | `<url>` | *see below* | always |
Creates a node like `gsk_texture_node_new()` with the given properties.
The default texture is a 10x10 checkerboard with the top left and bottom right 5x5 being in the color #FF00CC and the other part being transparent. A possible representation for this texture is `url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABmJLR0QA/wD/AP+gvaeTAAAAKUlEQVQYlWP8z3DmPwMaYGQwYUQXY0IXwAUGUCGGoxkYGBiweXAoeAYAz44F3e3U1xUAAAAASUVORK5CYII=")
`.
### transform
| property | syntax | default | printed |
| -------- | ---------------- | ---------------------- | ----------- |
| child | `<node>` | color { } | always |
| transform| `<transform>` | none | non-default |
Creates a node like `gsk_transform_node_new()` with the given properties.

View File

@@ -1,14 +1,7 @@
executable('gtk4-print-editor',
executable('print-editor',
['print-editor.c'],
c_args: common_cflags,
dependencies: libgtk_dep,
include_directories: confinc,
gui_app: true,
link_args: extra_demo_ldflags,
install: true)
# desktop file
install_data('org.gtk.PrintEditor4.desktop', install_dir: gtk_applicationsdir)
# appdata
install_data('org.gtk.PrintEditor4.appdata.xml', install_dir: gtk_appdatadir)
link_args: extra_demo_ldflags)

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
<id>org.gtk.PrintEditor4.desktop</id>
<metadata_license>CC0-1.0</metadata_license>
<project_license>LGPL-2.0+</project_license>
<name>GTK Print Editor</name>
<summary>Program to demonstrate GTK printing</summary>
<description>
<p>
GTK Print Editor is a simple editor to demonstrate GTK printing.
</p>
</description>
<screenshots>
<screenshot>
<image>https://static.gnome.org/appdata/gtk4-print-editor/gtk-print-editor1.png</image>
<caption>Print Editor</caption>
</screenshot>
</screenshots>
<kudos>
<kudo>HiDpiIcon</kudo>
<kudo>ModernToolkit</kudo>
</kudos>
<url type="homepage">https://www.gtk.org</url>
<translation type="gettext">gtk-4.0</translation>
<update_contact>matthias.clasen_at_gmail.com</update_contact>
<developer_name>Matthias Clasen and others</developer_name>
<releases>
<release version="3.99.0" date="2020">
<description>
<p>A new developers snapshot towards GTK 4.0.</p>
</description>
</release>
</releases>
</component>

View File

@@ -1,10 +0,0 @@
[Desktop Entry]
Name=Print Editor
Comment=A simple editor demonstrating GTK printing
Exec=gtk4-print-editor %f
Icon=text-editor-symbolic
Terminal=false
Type=Application
StartupNotify=true
Categories=Development;GTK;
NoDisplay=true

View File

@@ -23,7 +23,7 @@ update_title (GtkWindow *window)
else
basename = g_file_get_basename (filename);
title = g_strdup_printf ("GTK Print Editor — %s", basename);
title = g_strdup_printf ("Simple Editor with printing - %s", basename);
g_free (basename);
gtk_window_set_title (window, title);
@@ -592,54 +592,18 @@ activate_about (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
char *version;
GString *sysinfo;
char *setting;
char **backends;
int i;
sysinfo = g_string_new ("System libraries\n");
g_string_append_printf (sysinfo, "\tGLib\t%d.%d.%d\n",
glib_major_version,
glib_minor_version,
glib_micro_version);
g_string_append_printf (sysinfo, "\tPango\t%s\n",
pango_version_string ());
g_string_append_printf (sysinfo, "\tGTK\t%d.%d.%d\n",
gtk_get_major_version (),
gtk_get_minor_version (),
gtk_get_micro_version ());
g_string_append (sysinfo, "\nPrint backends\n");
g_object_get (gtk_settings_get_default (), "gtk-print-backends", &setting, NULL);
backends = g_strsplit (setting, ",", -1);
for (i = 0; backends[i]; i++)
g_string_append_printf (sysinfo, "\t%s\n", backends[i]);
g_strfreev (backends);
g_free (setting);
version = g_strdup_printf ("%s\nRunning against GTK %d.%d.%d",
PACKAGE_VERSION,
gtk_get_major_version (),
gtk_get_minor_version (),
gtk_get_micro_version ());
const gchar *authors[] = {
"Alexander Larsson",
NULL
};
gtk_show_about_dialog (GTK_WINDOW (main_window),
"program-name", "GTK Print Editor",
"version", version,
"copyright", "© 2006-2020 Red Hat, Inc",
"license-type", GTK_LICENSE_LGPL_2_1,
"website", "http://www.gtk.org",
"comments", "Program to demonstrate GTK printing",
"authors", (const char *[]){ "Alexander Larsson", NULL },
"name", "Print Test Editor",
"logo-icon-name", "text-editor-symbolic",
"title", "About GTK Print Editor",
"system-information", sysinfo->str,
"version", PACKAGE_VERSION,
"copyright", "© 2006-2020 Red Hat, Inc",
"comments", "Program to demonstrate GTK printing.",
"authors", authors,
NULL);
g_string_free (sysinfo, TRUE);
g_free (version);
}
static void
@@ -679,6 +643,23 @@ static const gchar ui_info[] =
"<interface>"
" <menu id='menubar'>"
" <submenu>"
" <attribute name='label'>_Application</attribute>"
" <section>"
" <item>"
" <attribute name='label'>_About</attribute>"
" <attribute name='action'>app.about</attribute>"
" <attribute name='accel'>&lt;Primary&gt;a</attribute>"
" </item>"
" </section>"
" <section>"
" <item>"
" <attribute name='label'>_Quit</attribute>"
" <attribute name='action'>app.quit</attribute>"
" <attribute name='accel'>&lt;Primary&gt;q</attribute>"
" </item>"
" </section>"
" </submenu>"
" <submenu>"
" <attribute name='label'>_File</attribute>"
" <section>"
" <item>"
@@ -715,23 +696,6 @@ static const gchar ui_info[] =
" <attribute name='action'>app.print</attribute>"
" </item>"
" </section>"
" <section>"
" <item>"
" <attribute name='label'>_Quit</attribute>"
" <attribute name='action'>app.quit</attribute>"
" <attribute name='accel'>&lt;Primary&gt;q</attribute>"
" </item>"
" </section>"
" </submenu>"
" <submenu>"
" <attribute name='label'>_Help</attribute>"
" <section>"
" <item>"
" <attribute name='label'>_About Print Editor</attribute>"
" <attribute name='action'>app.about</attribute>"
" <attribute name='accel'>&lt;Primary&gt;a</attribute>"
" </item>"
" </section>"
" </submenu>"
" </menu>"
"</interface>";
@@ -752,6 +716,25 @@ mark_set_callback (GtkTextBuffer *text_buffer,
update_statusbar ();
}
static gint
command_line (GApplication *application,
GApplicationCommandLine *command_line)
{
int argc;
char **argv;
argv = g_application_command_line_get_arguments (command_line, &argc);
if (argc == 2)
{
GFile *file = g_file_new_for_commandline_arg (argv[1]);
load_file (file);
g_object_unref (file);
}
return 0;
}
static void
startup (GApplication *app)
{
@@ -785,7 +768,7 @@ activate (GApplication *app)
gtk_window_set_child (GTK_WINDOW (main_window), box);
/* Create document */
sw = gtk_scrolled_window_new ();
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
@@ -826,20 +809,6 @@ activate (GApplication *app)
gtk_widget_show (main_window);
}
static void
open (GApplication *application,
GFile **files,
int n_files,
const char *hint)
{
if (n_files > 1)
g_warning ("Can only open a single file");
activate (application);
load_file (files[0]);
}
int
main (int argc, char **argv)
{
@@ -863,7 +832,7 @@ main (int argc, char **argv)
g_clear_error (&error);
}
app = gtk_application_new ("org.gtk.PrintEditor4", G_APPLICATION_HANDLES_OPEN);
app = gtk_application_new ("org.gtk.PrintEditor", 0);
g_action_map_add_action_entries (G_ACTION_MAP (app),
app_entries, G_N_ELEMENTS (app_entries),
@@ -871,7 +840,7 @@ main (int argc, char **argv)
g_signal_connect (app, "startup", G_CALLBACK (startup), NULL);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
g_signal_connect (app, "open", G_CALLBACK (open), NULL);
g_signal_connect (app, "command-line", G_CALLBACK (command_line), NULL);
g_application_run (G_APPLICATION (app), argc, argv);

View File

@@ -408,8 +408,6 @@ activate_print (GSimpleAction *action,
g_signal_connect (op, "draw-page", G_CALLBACK (print_operation_page), window);
g_signal_connect (op, "done", G_CALLBACK (print_operation_done), NULL);
gtk_print_operation_set_embed_page_setup (op, TRUE);
res = gtk_print_operation_run (op, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, window, NULL);
if (res == GTK_PRINT_OPERATION_RESULT_IN_PROGRESS)

View File

@@ -93,6 +93,7 @@ gdk_display_get_clipboard
gdk_display_get_primary_clipboard
gdk_display_get_setting
gdk_display_get_startup_notification_id
gdk_display_setup_window_visual
<SUBSECTION>
gdk_display_put_event
@@ -207,6 +208,8 @@ GdkModifierType
GDK_MODIFIER_MASK
<SUBSECTION>
gdk_surface_get_support_multidevice
gdk_surface_set_support_multidevice
gdk_surface_get_device_cursor
gdk_surface_set_device_cursor
@@ -355,13 +358,17 @@ gdk_device_get_name
gdk_device_get_vendor_id
gdk_device_get_product_id
gdk_device_get_source
gdk_device_set_key
gdk_device_get_key
gdk_device_set_axis_use
gdk_device_get_axis_use
gdk_device_get_associated_device
gdk_device_list_physical_devices
gdk_device_list_slave_devices
gdk_device_get_device_type
gdk_device_get_display
gdk_device_get_has_cursor
gdk_device_get_n_axes
gdk_device_get_n_keys
gdk_device_get_axes
gdk_device_get_seat
gdk_device_get_num_touches
@@ -376,8 +383,13 @@ gdk_device_has_bidi_layouts
<SUBSECTION>
gdk_device_get_state
gdk_device_get_surface_at_position
gdk_device_get_history
gdk_device_free_history
GdkTimeCoord
gdk_device_get_axis
gdk_device_get_axis_names
gdk_device_get_axis_value
gdk_device_get_last_event_surface
<SUBSECTION>
gdk_device_tool_get_serial
@@ -438,7 +450,8 @@ gdk_seat_get_display
gdk_seat_get_capabilities
gdk_seat_get_pointer
gdk_seat_get_keyboard
gdk_seat_get_physical_devices
gdk_seat_get_slaves
gdk_seat_get_master_pointers
<SUBSECTION Standard>
GDK_SEAT
@@ -482,16 +495,13 @@ gdk_event_get_source_device
gdk_event_get_device_tool
gdk_event_get_time
gdk_event_get_display
gdk_event_get_seat
GdkEventSequence
gdk_event_get_event_sequence
gdk_event_get_modifier_state
gdk_event_get_position
gdk_event_get_axes
gdk_event_get_axis
gdk_event_get_history
gdk_event_get_pointer_emulated
gdk_event_triggers_context_menu
gdk_button_event_get_button
gdk_scroll_event_get_direction
gdk_scroll_event_get_deltas
@@ -510,7 +520,6 @@ gdk_crossing_event_get_mode
gdk_crossing_event_get_detail
gdk_crossing_event_get_focus
gdk_grab_broken_event_get_grab_surface
gdk_grab_broken_event_get_implicit
gdk_dnd_event_get_drop
gdk_configure_event_get_size
gdk_touchpad_event_get_gesture_phase
@@ -521,6 +530,7 @@ gdk_touchpad_event_get_pinch_scale
gdk_pad_event_get_axis_value
gdk_pad_event_get_button
gdk_pad_event_get_group_mode
gdk_motion_event_get_history
<SUBSECTION>
gdk_events_get_angle
@@ -535,23 +545,8 @@ GDK_TYPE_CROSSING_MODE
GDK_TYPE_SCROLL_DIRECTION
GDK_TYPE_NOTIFY_TYPE
GDK_IS_EVENT
gdk_event_get_type
gdk_event_sequence_get_type
gdk_button_event_get_type
gdk_configure_event_get_type
gdk_crossing_event_get_type
gdk_delete_event_get_type
gdk_dnd_event_get_type
gdk_focus_event_get_type
gdk_grab_broken_event_get_type
gdk_key_event_get_type
gdk_motion_event_get_type
gdk_pad_event_get_type
gdk_proximity_event_get_type
gdk_scroll_event_get_type
gdk_touch_event_get_type
gdk_touchpad_event_get_type
</SECTION>
<SECTION>

View File

@@ -27,19 +27,15 @@ private_headers = [
'gdkmonitorprivate.h',
'gdkmemorytextureprivate.h',
'gdkpipeiostreamprivate.h',
'gdkpopupprivate.h',
'gdkprofilerprivate.h',
'gdkscreenprivate.h',
'gdkseatdefaultprivate.h',
'gdkseatprivate.h',
'gdksnapshotprivate.h',
'gdksurfaceimpl.h',
'gdksurfaceprivate.h',
'gdktextureprivate.h',
'gdktoplevelprivate.h',
'gdkvulkancontextprivate.h',
'keyname-table.h',
'x11/gdkprivate-x11.h',
'gdkprivate-x11.h',
'x11/gdkeventsource.h',
'gtk-primary-selection-client-protocol.h',
'gtk-shell-client-protocol.h',

View File

@@ -236,6 +236,7 @@ gsk_transform_to_translate
gsk_transform_transform
gsk_transform_invert
gsk_transform_matrix
gsk_transform_matrix_with_category
gsk_transform_translate
gsk_transform_translate_3d
gsk_transform_rotate

View File

@@ -9,11 +9,9 @@ private_headers = [
'gskprofilerprivate.h',
'gskrendererprivate.h',
'gskrendernodeprivate.h',
'gskrendernodeparserprivate.h',
'gskroundedrectprivate.h',
'gskshaderbuilderprivate.h',
'gsktextureprivate.h',
'gsktransformprivate.h',
'gskvulkanblendpipelineprivate.h',
'gskvulkanborderpipelineprivate.h',
'gskvulkanboxshadowpipelineprivate.h',

View File

@@ -37,7 +37,7 @@ this range will trigger compiler warnings.
Here is how you would compile hello.c if you want to allow it
to use symbols that were not deprecated in 4.2:
```
$ cc `pkg-config --cflags gtk4` -DGDK_VERSION_MIN_REQUIRED=GDK_VERSION_4_2 hello.c -o hello `pkg-config --libs gtk4`
$ cc `pkg-config --cflags gtk4` -DGDK_VERSION_MIN_REQIRED=GDK_VERSION_4_2 hello.c -o hello `pkg-config --libs gtk4`
```
And here is how you would compile hello.c if you don't want

View File

@@ -48,61 +48,19 @@
<chapter id="Lists">
<title>GListModel support</title>
<xi:include href="xml/gtkbitset.xml" />
<xi:include href="xml/gtkexpression.xml" />
<xi:include href="xml/gtkfilterlistmodel.xml" />
<section>
<xi:include href="xml/gtkfilter.xml" />
<xi:include href="xml/gtkcustomfilter.xml" />
<xi:include href="xml/gtkstringfilter.xml" />
<xi:include href="xml/gtkmultifilter.xml" />
</section>
<xi:include href="xml/gtkflattenlistmodel.xml" />
<xi:include href="xml/gtkmaplistmodel.xml" />
<xi:include href="xml/gtkslicelistmodel.xml" />
<xi:include href="xml/gtksortlistmodel.xml" />
<section>
<xi:include href="xml/gtksorter.xml" />
<xi:include href="xml/gtkcustomsorter.xml" />
<xi:include href="xml/gtkstringsorter.xml" />
<xi:include href="xml/gtknumericsorter.xml" />
<xi:include href="xml/gtkmultisorter.xml" />
</section>
<xi:include href="xml/gtkselectionmodel.xml" />
<section>
<xi:include href="xml/gtknoselection.xml" />
<xi:include href="xml/gtksingleselection.xml" />
<xi:include href="xml/gtkmultiselection.xml" />
</section>
<xi:include href="xml/gtkbookmarklist.xml" />
<xi:include href="xml/gtkdirectorylist.xml" />
<xi:include href="xml/gtkstringlist.xml" />
</chapter>
<chapter id="ListContainers">
<title>List-based Widgets</title>
<xi:include href="section-list-widget.xml"/>
<xi:include href="xml/gtklistitem.xml" />
<xi:include href="xml/gtklistitemfactory.xml" />
<section>
<xi:include href="xml/gtksignallistitemfactory.xml" />
<xi:include href="xml/gtkbuilderlistitemfactory.xml" />
</section>
<xi:include href="xml/gtklistview.xml" />
<xi:include href="xml/gtkgridview.xml" />
<xi:include href="xml/gtkcolumnview.xml" />
<xi:include href="xml/gtkcolumnviewcolumn.xml" />
<xi:include href="xml/gtkdropdown.xml" />
<xi:include href="xml/gtknoselection.xml" />
<xi:include href="xml/gtksingleselection.xml" />
</chapter>
<chapter id="Trees">
<title>Tree support</title>
<xi:include href="xml/gtktreelistrow.xml" />
<xi:include href="xml/gtktreelistmodel.xml" />
<section>
<xi:include href="xml/gtktreelistrow.xml" />
</section>
<xi:include href="xml/gtktreelistrowsorter.xml" />
<xi:include href="xml/gtktreeexpander.xml" />
</chapter>
<chapter id="Application">
@@ -129,7 +87,6 @@
<xi:include href="xml/gtkaboutdialog.xml" />
<xi:include href="xml/gtkassistant.xml" />
<xi:include href="xml/gtkwindowgroup.xml" />
<xi:include href="xml/gtknativedialog.xml" />
</chapter>
<chapter id="LayoutContainers">
@@ -218,7 +175,6 @@
<xi:include href="xml/gtkspinbutton.xml" />
<xi:include href="xml/gtksearchentry.xml" />
<xi:include href="xml/gtksearchbar.xml" />
<xi:include href="xml/gtkeditablelabel.xml" />
</chapter>
<chapter id="TextWidgetObjects">
@@ -270,7 +226,6 @@
<xi:include href="xml/gtkpopover.xml" />
<xi:include href="xml/gtkpopovermenu.xml" />
<xi:include href="xml/gtkpopovermenubar.xml" />
<xi:include href="xml/gtkdropdown.xml" />
</chapter>
<chapter id="SelectorWidgets">

View File

@@ -312,8 +312,6 @@ gtk_list_box_bind_model
gtk_list_box_row_new
gtk_list_box_row_changed
gtk_list_box_row_is_selected
gtk_list_box_row_get_child
gtk_list_box_row_set_child
gtk_list_box_row_get_header
gtk_list_box_row_set_header
gtk_list_box_row_get_index
@@ -341,69 +339,18 @@ gtk_list_box_get_type
gtk_list_box_row_get_type
</SECTION>
<SECTION>
<FILE>gtkbitset</FILE>
<TITLE>GtkBitset</TITLE>
GtkBitset
gtk_bitset_ref
gtk_bitset_unref
gtk_bitset_new_empty
gtk_bitset_new_range
gtk_bitset_copy
<SUBSECTION>
gtk_bitset_contains
gtk_bitset_is_empty
gtk_bitset_equals
gtk_bitset_get_minimum
gtk_bitset_get_maximum
gtk_bitset_get_size
gtk_bitset_get_size_in_range
gtk_bitset_get_nth
<SUBSECTION>
gtk_bitset_remove_all
gtk_bitset_add
gtk_bitset_remove
gtk_bitset_add_range
gtk_bitset_remove_range
gtk_bitset_add_range_closed
gtk_bitset_remove_range_closed
gtk_bitset_add_rectangle
gtk_bitset_remove_rectangle
gtk_bitset_union
gtk_bitset_intersect
gtk_bitset_subtract
gtk_bitset_difference
gtk_bitset_shift_left
gtk_bitset_shift_right
gtk_bitset_slice
<SUBSECTION>
GtkBitsetIter
gtk_bitset_iter_init_first
gtk_bitset_iter_init_last
gtk_bitset_iter_init_at
gtk_bitset_iter_next
gtk_bitset_iter_previous
gtk_bitset_iter_get_value
gtk_bitset_iter_is_valid
<SUBSECTION Private>
GTK_TYPE_BITSET
gtk_bitset_get_type
</SECTION>
<SECTION>
<FILE>gtkselectionmodel</FILE>
<TITLE>GtkSelectionModel</TITLE>
GtkSelectionModel
gtk_selection_model_is_selected
gtk_selection_model_get_selection
gtk_selection_model_get_selection_in_range
gtk_selection_model_select_item
gtk_selection_model_unselect_item
gtk_selection_model_select_range
gtk_selection_model_unselect_range
gtk_selection_model_select_all
gtk_selection_model_unselect_all
gtk_selection_model_set_selection
gtk_selection_model_query_range
<SUBSECTION>
gtk_selection_model_selection_changed
<SUBSECTION Standard>
@@ -445,215 +392,6 @@ gtk_single_selection_set_can_unselect
gtk_single_selection_get_type
</SECTION>
<SECTION>
<FILE>gtkmultiselection</FILE>
<TITLE>GtkMultiSeledction</TITLE>
GtkMultiSelection
gtk_multi_selection_new
<SUBSECTION Private>
gtk_multi_selection_get_type
</SECTION>
<SECTION>
<FILE>gtklistitem</FILE>
<TITLE>GtkListItem</TITLE>
GtkListItem
gtk_list_item_get_item
gtk_list_item_get_position
gtk_list_item_get_child
gtk_list_item_set_child
gtk_list_item_get_selected
gtk_list_item_get_selectable
gtk_list_item_set_selectable
gtk_list_item_get_activatable
gtk_list_item_set_activatable
<SUBSECTION Standard>
GTK_LIST_ITEM
GTK_LIST_ITEM_CLASS
GTK_LIST_ITEM_GET_CLASS
GTK_IS_LIST_ITEM
GTK_IS_LIST_ITEM_CLASS
GTK_TYPE_LIST_ITEM
<SUBSECTION Private>
gtk_list_item_get_type
</SECTION>
<SECTION>
<FILE>gtklistitemfactory</FILE>
<TITLE>GtkListItemFactory</TITLE>
GtkListItemFactory
<SUBSECTION Standard>
GTK_LIST_ITEM_FACTORY
GTK_LIST_ITEM_FACTORY_CLASS
GTK_LIST_ITEM_FACTORY_GET_CLASS
GTK_IS_LIST_ITEM_FACTORY
GTK_IS_LIST_ITEM_FACTORY_CLASS
GTK_TYPE_LIST_ITEM_FACTORY
<SUBSECTION Private>
gtk_list_item_factory_get_type
</SECTION>
<SECTION>
<FILE>gtkbuilderlistitemfactory</FILE>
<TITLE>GtkBuilderListItemFactory</TITLE>
GtkBuilderListItemFactory
gtk_builder_list_item_factory_new_from_bytes
gtk_builder_list_item_factory_new_from_resource
gtk_builder_list_item_factory_get_bytes
gtk_builder_list_item_factory_get_resource
gtk_builder_list_item_factory_get_scope
<SUBSECTION Standard>
GTK_BUILDER_LIST_ITEM_FACTORY
GTK_BUILDER_LIST_ITEM_FACTORY_CLASS
GTK_BUILDER_LIST_ITEM_FACTORY_GET_CLASS
GTK_IS_BUILDER_LIST_ITEM_FACTORY
GTK_IS_BUILDER_LIST_ITEM_FACTORY_CLASS
GTK_TYPE_BUILDER_LIST_ITEM_FACTORY
<SUBSECTION Private>
gtk_builder_list_item_factory_get_type
</SECTION>
<SECTION>
<FILE>gtksignallistitemfactory</FILE>
<TITLE>GtkSignalListItemFactory</TITLE>
GtkSignalListItemFactory
gtk_signal_list_item_factory_new
<SUBSECTION Standard>
GTK_SIGNAL_LIST_ITEM_FACTORY
GTK_SIGNAL_LIST_ITEM_FACTORY_CLASS
GTK_SIGNAL_LIST_ITEM_FACTORY_GET_CLASS
GTK_IS_SIGNAL_LIST_ITEM_FACTORY
GTK_IS_SIGNAL_LIST_ITEM_FACTORY_CLASS
GTK_TYPE_SIGNAL_LIST_ITEM_FACTORY
<SUBSECTION Private>
gtk_signal_list_item_factory_get_type
</SECTION>
<SECTION>
<FILE>gtklistview</FILE>
<TITLE>GtkListView</TITLE>
GtkListView
gtk_list_view_new
gtk_list_view_new_with_factory
gtk_list_view_set_factory
gtk_list_view_get_factory
gtk_list_view_set_model
gtk_list_view_get_model
gtk_list_view_set_show_separators
gtk_list_view_get_show_separators
gtk_list_view_set_single_click_activate
gtk_list_view_get_single_click_activate
gtk_list_view_set_enable_rubberband
gtk_list_view_get_enable_rubberband
<SUBSECTION Standard>
GTK_LIST_VIEW
GTK_LIST_VIEW_CLASS
GTK_LIST_VIEW_GET_CLASS
GTK_IS_LIST_VIEW
GTK_IS_LIST_VIEW_CLASS
GTK_TYPE_LIST_VIEW
<SUBSECTION Private>
gtk_list_view_get_type
</SECTION>
<SECTION>
<FILE>gtkcolumnview</FILE>
<TITLE>GtkColumnView</TITLE>
GtkColumnView
gtk_column_view_new
gtk_column_view_append_column
gtk_column_view_insert_column
gtk_column_view_remove_column
gtk_column_view_get_columns
gtk_column_view_get_model
gtk_column_view_set_model
gtk_column_view_get_sorter
gtk_column_view_get_show_row_separators
gtk_column_view_set_show_row_separators
gtk_column_view_get_show_column_separators
gtk_column_view_set_show_column_separators
gtk_column_view_sort_by_column
gtk_column_view_set_single_click_activate
gtk_column_view_get_single_click_activate
gtk_column_view_set_reorderable
gtk_column_view_get_reorderable
gtk_column_view_set_enable_rubberband
gtk_column_view_get_enable_rubberband
<SUBSECTION Standard>
GTK_COLUMN_VIEW
GTK_COLUMN_VIEW_CLASS
GTK_COLUMN_VIEW_GET_CLASS
GTK_IS_COLUMN_VIEW
GTK_IS_COLUMN_VIEW_CLASS
GTK_TYPE_COLUMN_VIEW
<SUBSECTION Private>
gtk_column_view_get_type
</SECTION>
<SECTION>
<FILE>gtkcolumnviewcolumn</FILE>
<TITLE>GtkColumnViewColumn</TITLE>
GtkColumnViewColumn
gtk_column_view_column_new
gtk_column_view_column_new_with_factory
gtk_column_view_column_get_column_view
gtk_column_view_column_set_factory
gtk_column_view_column_get_factory
gtk_column_view_column_set_title
gtk_column_view_column_get_title
gtk_column_view_column_set_sorter
gtk_column_view_column_get_sorter
gtk_column_view_column_set_visible
gtk_column_view_column_get_visible
gtk_column_view_column_set_resizable
gtk_column_view_column_get_resizable
gtk_column_view_column_set_header_menu
gtk_column_view_column_get_header_menu
gtk_column_view_column_set_fixed_width
gtk_column_view_column_get_fixed_width
gtk_column_view_column_set_expand
gtk_column_view_column_get_expand
<SUBSECTION Standard>
GTK_COLUMN_VIEW_COLUMN
GTK_COLUMN_VIEW_COLUMN_CLASS
GTK_COLUMN_VIEW_COLUMN_GET_CLASS
GTK_IS_COLUMN_VIEW_COLUMN
GTK_IS_COLUMN_VIEW_COLUMN_CLASS
GTK_TYPE_COLUMN_VIEW_COLUMN
<SUBSECTION Private>
gtk_column_view_column_get_type
</SECTION>
<SECTION>
<FILE>gtkgridview</FILE>
<TITLE>GtkGridView</TITLE>
GtkGridView
gtk_grid_view_new
gtk_grid_view_new_with_factory
gtk_grid_view_set_model
gtk_grid_view_get_model
gtk_grid_view_set_max_columns
gtk_grid_view_get_max_columns
gtk_grid_view_set_min_columns
gtk_grid_view_get_min_columns
gtk_grid_view_set_single_click_activate
gtk_grid_view_get_single_click_activate
gtk_grid_view_set_enable_rubberband
gtk_grid_view_get_enable_rubberband
gtk_grid_view_set_factory
gtk_grid_view_get_factory
<SUBSECTION Standard>
GTK_GRID_VIEW
GTK_GRID_VIEW_CLASS
GTK_GRID_VIEW_GET_CLASS
GTK_IS_GRID_VIEW
GTK_IS_GRID_VIEW_CLASS
GTK_TYPE_GRID_VIEW
<SUBSECTION Private>
gtk_grid_view_get_type
</SECTION>
<SECTION>
<FILE>gtkbuildable</FILE>
GtkBuildable
@@ -1026,18 +764,6 @@ GTK_EDITABLE_GET_IFACE
gtk_editable_get_type
</SECTION>
<SECTION>
<FILE>gtkeditablelabel</FILE>
<TITLE>GtkEditableLabel</TITLE>
GtkEditableLabel
gtk_editable_label_new
gtk_editable_label_get_editing
gtk_editable_label_start_editing
gtk_editable_label_stop_editing
<SUBSECTION Private>
gtk_editable_label_get_type
</SECTION>
<SECTION>
<FILE>gtktext</FILE>
<TITLE>GtkText</TITLE>
@@ -1434,119 +1160,18 @@ GTK_TYPE_FILE_FILTER
gtk_file_filter_get_type
</SECTION>
<SECTION>
<FILE>gtkdirectorylist</FILE>
<TITLE>GtkDirectoryList</TITLE>
GtkDirectoryList
gtk_directory_list_new
gtk_directory_list_get_attributes
gtk_directory_list_set_attributes
gtk_directory_list_get_file
gtk_directory_list_set_file
gtk_directory_list_get_io_priority
gtk_directory_list_set_io_priority
gtk_directory_list_is_loading
gtk_directory_list_get_error
<SUBSECTION Standard>
GTK_DIRECTORY_LIST
GTK_IS_DIRECTORY_LIST
GTK_TYPE_DIRECTORY_LIST
GTK_DIRECTORY_LIST_CLASS
GTK_IS_DIRECTORY_LIST_CLASS
GTK_DIRECTORY_LIST_GET_CLASS
<SUBSECTION Private>
gtk_directory_list_get_type
</SECTION>
<SECTION>
<FILE>gtkbookmarklist</FILE>
<TITLE>GtkBookmarkList</TITLE>
GtkBookmarkList
gtk_bookmark_list_new
gtk_bookmark_list_get_filename
gtk_bookmark_list_set_attributes
gtk_bookmark_list_get_attributes
gtk_bookmark_list_set_io_priority
gtk_bookmark_list_get_io_priority
gtk_bookmark_list_is_loading
<SUBSECTION Standard>
GTK_TYPE_BOOKMARK_LIST
</SECTION>
<SECTION>
<FILE>gtkfilter</FILE>
<TITLE>GtkFilter</TITLE>
GtkFilter
gtk_filter_match
gtk_filter_get_strictness
<SUBSECTION>
GtkFilterChange
gtk_filter_changed
<SUBSECTION Standard>
GTK_FILTER
GTK_IS_FILTER
GTK_TYPE_FILTER
GTK_FILTER_CLASS
GTK_IS_FILTER_CLASS
GTK_FILTER_GET_CLASS
<SUBSECTION Private>
gtk_filter_get_type
</SECTION>
<SECTION>
<FILE>gtkcustomfilter</FILE>
<TITLE>GtkCustomFilter</TITLE>
GtkCustomFilter
GtkCustomFilterFunc
gtk_custom_filter_new
gtk_custom_filter_set_filter_func
<SUBSECTION Standard>
GTK_CUSTOM_FILTER
GTK_IS_CUSTOM_FILTER
GTK_TYPE_CUSTOM_FILTER
GTK_CUSTOM_FILTER_CLASS
GTK_IS_CUSTOM_FILTER_CLASS
GTK_CUSTOM_FILTER_GET_CLASS
<SUBSECTION Private>
gtk_custom_filter_get_type
</SECTION>
<SECTION>
<FILE>gtkmultifilter</FILE>
<TITLE>GtkMultiFilter</TITLE>
GtkMultiFilter
gtk_multi_filter_append
gtk_multi_filter_remove
<SUBSECTION>
GtkAnyFilter
gtk_any_filter_new
<SUBSECTION>
GtkEveryFilter
gtk_every_filter_new
<SUBSECTION Standard>
GTK_CUSTOM_FILTER
GTK_IS_CUSTOM_FILTER
GTK_TYPE_CUSTOM_FILTER
GTK_CUSTOM_FILTER_CLASS
GTK_IS_CUSTOM_FILTER_CLASS
GTK_CUSTOM_FILTER_GET_CLASS
<SUBSECTION Private>
gtk_custom_filter_get_type
</SECTION>
<SECTION>
<FILE>gtkfilterlistmodel</FILE>
<TITLE>GtkFilterListModel</TITLE>
GtkFilterListModel
GtkFilterListModelFilterFunc
gtk_filter_list_model_new
gtk_filter_list_model_new_for_type
gtk_filter_list_model_set_model
gtk_filter_list_model_get_model
gtk_filter_list_model_set_filter
gtk_filter_list_model_get_filter
gtk_filter_list_model_set_incremental
gtk_filter_list_model_get_incremental
gtk_filter_list_model_get_pending
gtk_filter_list_model_set_filter_func
gtk_filter_list_model_has_filter
gtk_filter_list_model_refilter
<SUBSECTION Standard>
GTK_FILTER_LIST_MODEL
GTK_IS_FILTER_LIST_MODEL
@@ -1566,9 +1191,6 @@ gtk_fixed_new
gtk_fixed_put
gtk_fixed_remove
gtk_fixed_move
gtk_fixed_get_child_position
gtk_fixed_get_child_transform
gtk_fixed_set_child_transform
<SUBSECTION Standard>
GTK_FIXED
GTK_IS_FIXED
@@ -2133,7 +1755,7 @@ gtk_info_bar_get_type
<SECTION>
<FILE>gtknativedialog</FILE>
<TITLE>GtkNativeDialog</TITLE>
GtkNativeDialog
GTK_TYPE_NATIVE_DIALOG
GtkNativeDialogClass
gtk_native_dialog_show
gtk_native_dialog_hide
@@ -2145,8 +1767,9 @@ gtk_native_dialog_set_title
gtk_native_dialog_get_title
gtk_native_dialog_set_transient_for
gtk_native_dialog_get_transient_for
<SUBSECTION Standard>
GtkNativeDialog
<SUBSECTION Private>
GTK_TYPE_NATIVE_DIALOG
gtk_native_dialog_get_type
</SECTION>
@@ -2220,18 +1843,12 @@ GtkNotebookPrivate
<TITLE>GtkPaned</TITLE>
GtkPaned
gtk_paned_new
gtk_paned_set_start_child
gtk_paned_get_start_child
gtk_paned_set_end_child
gtk_paned_get_end_child
gtk_paned_set_resize_start_child
gtk_paned_get_resize_start_child
gtk_paned_set_resize_end_child
gtk_paned_get_resize_end_child
gtk_paned_set_shrink_start_child
gtk_paned_get_shrink_start_child
gtk_paned_set_shrink_end_child
gtk_paned_get_shrink_end_child
gtk_paned_add1
gtk_paned_add2
gtk_paned_pack1
gtk_paned_pack2
gtk_paned_get_child1
gtk_paned_get_child2
gtk_paned_set_position
gtk_paned_get_position
gtk_paned_set_wide_handle
@@ -2719,125 +2336,17 @@ GTK_SLICE_LIST_MODEL_GET_CLASS
gtk_slice_list_model_get_type
</SECTION>
<SECTION>
<FILE>gtksorter</FILE>
<TITLE>GtkSorter</TITLE>
GtkSorter
GtkSorterOrder
GtkSorterChange
gtk_sorter_compare
gtk_sorter_get_order
gtk_sorter_changed
<SUBSECTION Standard>
GTK_SORTER
GTK_IS_SORTER
GTK_TYPE_SORTER
GTK_SORTER_CLASS
GTK_IS_SORTER_CLASS
GTK_SORTER_GET_CLASS
<SUBSECTION Private>
gtk_sorter_get_type
</SECTION>
<SECTION>
<FILE>gtkstringsorter</FILE>
<TITLE>GtkStringSorter</TITLE>
GtkStringSorter
gtk_string_sorter_new
gtk_string_sorter_get_expression
gtk_string_sorter_set_expression
gtk_string_sorter_get_ignore_case
gtk_string_sorter_set_ignore_case
<SUBSECTION Standard>
GTK_STRING_SORTER
GTK_IS_STRING_SORTER
GTK_TYPE_STRING_SORTER
GTK_IS_STRING_SORTER_CLASS
GTK_STRING_SORTER_GET_CLASS
<SUBSECTION Private>
gtk_string_sorter_get_type
</SECTION>
<SECTION>
<FILE>gtknumericsorter</FILE>
<TITLE>GtkNumericSorter</TITLE>
GtkNumericSorter
gtk_numeric_sorter_new
gtk_numeric_sorter_get_expression
gtk_numeric_sorter_set_expression
gtk_numeric_sorter_get_sort_order
gtk_numeric_sorter_set_sort_order
<SUBSECTION Standard>
GTK_NUMERIC_SORTER
GTK_IS_NUMERIC_SORTER
GTK_TYPE_NUMERIC_SORTER
GTK_IS_NUMERIC_SORTER_CLASS
GTK_NUMERIC_SORTER_GET_CLASS
<SUBSECTION Private>
gtk_numeric_sorter_get_type
</SECTION>
<SECTION>
<FILE>gtkcustomsorter</FILE>
<TITLE>GtkCustomSorter</TITLE>
GtkCustomSorter
gtk_custom_sorter_new
gtk_custom_sorter_set_sort_func
<SUBSECTION Standard>
GTK_CUSTOM_SORTER
GTK_IS_CUSTOM_SORTER
GTK_TYPE_CUSTOM_SORTER
GTK_IS_CUSTOM_SORTER_CLASS
GTK_CUSTOM_SORTER_GET_CLASS
<SUBSECTION Private>
gtk_custom_sorter_get_type
</SECTION>
<SECTION>
<FILE>gtkmultisorter</FILE>
<TITLE>GtkMultiSorter</TITLE>
GtkMultiSorter
gtk_multi_sorter_new
gtk_multi_sorter_append
gtk_multi_sorter_remove
<SUBSECTION Standard>
GTK_MULTI_SORTER
GTK_IS_MULTI_SORTER
GTK_TYPE_MULTI_SORTER
GTK_IS_MULTI_SORTER_CLASS
GTK_MULTI_SORTER_GET_CLASS
<SUBSECTION Private>
gtk_multi_sorter_get_type
</SECTION>
<SECTION>
<FILE>gtktreelistrowsorter</FILE>
<TITLE>GtkTreeListRowSorter</TITLE>
GtkTreeListRowSorter
gtk_tree_list_row_sorter_new
gtk_tree_list_row_sorter_get_sorter
gtk_tree_list_row_sorter_set_sorter
<SUBSECTION Standard>
GTK_TREE_LIST_ROW_SORTER
GTK_IS_TREE_LIST_ROW_SORTER
GTK_TYPE_TREE_LIST_ROW_SORTER
GTK_IS_TREE_LIST_ROW_SORTER_CLASS
GTK_TREE_LIST_ROW_SORTER_GET_CLASS
<SUBSECTION Private>
gtk_tree_list_row_sorter_get_type
</SECTION>
<SECTION>
<FILE>gtksortlistmodel</FILE>
<TITLE>GtkSortListModel</TITLE>
GtkSortListModel
gtk_sort_list_model_new
gtk_sort_list_model_new_for_type
gtk_sort_list_model_set_sorter
gtk_sort_list_model_get_sorter
gtk_sort_list_model_set_sort_func
gtk_sort_list_model_has_sort
gtk_sort_list_model_set_model
gtk_sort_list_model_get_model
gtk_sort_list_model_resort
<SUBSECTION Standard>
GTK_SORT_LIST_MODEL
GTK_IS_SORT_LIST_MODEL
@@ -3423,26 +2932,6 @@ GTK_TREE_LIST_MODEL_GET_CLASS
gtk_tree_list_row_get_type
</SECTION>
<SECTION>
<FILE>gtktreeexpander</FILE>
<TITLE>GtkTreeExpander</TITLE>
gtk_tree_expander_new
gtk_tree_expander_get_child
gtk_tree_expander_set_child
gtk_tree_expander_get_item
gtk_tree_expander_get_list_row
gtk_tree_expander_set_list_row
<SUBSECTION Standard>
GTK_TREE_EXPANDER
GTK_IS_TREE_EXPANDER
GTK_TYPE_TREE_EXPANDER
GTK_TREE_EXPANDER_CLASS
GTK_IS_TREE_EXPANDER_CLASS
GTK_TREE_EXPANDER_GET_CLASS
<SUBSECTION Private>
gtk_tree_expander_get_type
</SECTION>
<SECTION>
<FILE>gtktreemodel</FILE>
<TITLE>GtkTreeModel</TITLE>
@@ -4522,7 +4011,6 @@ gtk_widget_get_allocation
gtk_widget_get_allocated_baseline
gtk_widget_get_width
gtk_widget_get_height
gtk_widget_get_size
gtk_widget_compute_bounds
gtk_widget_compute_transform
gtk_widget_compute_point
@@ -4552,8 +4040,11 @@ gtk_widget_has_visible_focus
gtk_widget_is_drawable
gtk_widget_set_receives_default
gtk_widget_get_receives_default
gtk_widget_set_support_multidevice
gtk_widget_get_support_multidevice
gtk_widget_get_realized
gtk_widget_get_mapped
gtk_widget_device_is_shadowed
gtk_widget_get_opacity
gtk_widget_set_opacity
gtk_widget_get_overflow
@@ -5061,8 +4552,6 @@ GtkDeleteType
GtkDirectionType
GtkJustification
GtkMovementStep
GtkOrdering
gtk_ordering_from_cmpfunc
GtkOrientation
GtkPackType
GtkPositionType
@@ -6108,16 +5597,6 @@ gtk_header_bar_get_type
GtkStackPage
gtk_stack_page_get_visible
gtk_stack_page_set_visible
gtk_stack_page_get_title
gtk_stack_page_set_title
gtk_stack_page_get_name
gtk_stack_page_set_name
gtk_stack_page_get_needs_attention
gtk_stack_page_set_needs_attention
gtk_stack_page_get_use_underline
gtk_stack_page_set_use_underline
gtk_stack_page_get_icon_name
gtk_stack_page_set_icon_name
gtk_stack_page_get_child
GtkStack
gtk_stack_new
@@ -7524,95 +7003,6 @@ gtk_overlay_layout_child_get_clip_overlay
GTK_TYPE_OVERLAY_LAYOUT
gtk_overlay_layout_get_type
GTK_TYPE_OVERLAY_LAYOUT_CHLD
gtk_overlay_layout_child_get_type
</SECTION>
<SECTION>
<FILE>gtkexpression</FILE>
GtkExpression
GtkExpressionWatch
GtkExpressionNotify
gtk_expression_ref
gtk_expression_unref
gtk_expression_get_value_type
gtk_expression_is_static
gtk_expression_evaluate
gtk_expression_watch
gtk_expression_bind
gtk_expression_watch_ref
gtk_expression_watch_unref
gtk_expression_watch_evaluate
gtk_expression_watch_unwatch
<SUBSECTION>
gtk_property_expression_new
gtk_property_expression_new_for_pspec
gtk_constant_expression_new
gtk_constant_expression_new_for_value
gtk_object_expression_new
gtk_closure_expression_new
gtk_cclosure_expression_new
<SUBSECTION Standard>
GTK_IS_EXPRESSION
GTK_TYPE_EXPRESSION
<SUBSECTION Private>
gtk_expression_get_type
</SECTION>
<SECTION>
<FILE>gtkstringfilter</FILE>
GtkStringFilter
GtkStringFilterMatchMode
gtk_string_filter_new
gtk_string_filter_get_search
gtk_string_filter_set_search
gtk_string_filter_get_expression
gtk_string_filter_set_expression
gtk_string_filter_get_ignore_case
gtk_string_filter_set_ignore_case
gtk_string_filter_get_match_mode
gtk_string_filter_set_match_mode
<SUBSECTION Private>
gtk_string_filter_get_type
</SECTION>
<SECTION>
<FILE>gtkdropdown</FILE>
<TITLE>GtkDropDown</TITLE>
GtkDropDown
gtk_drop_down_new
gtk_drop_down_set_from_strings
gtk_drop_down_set_model
gtk_drop_down_get_model
gtk_drop_down_set_selected
gtk_drop_down_get_selected
gtk_drop_down_get_selected_item
gtk_drop_down_set_factory
gtk_drop_down_get_factory
gtk_drop_down_set_list_factory
gtk_drop_down_get_list_factory
gtk_drop_down_set_expression
gtk_drop_down_get_expression
gtk_drop_down_set_enable_search
gtk_drop_down_get_enable_search
<SUBSECTION Standard>
GTK_TYPE_DROP_DOWN
<SUBSECTION Private>
gtk_drop_down_get_type
</SECTION>
<SECTION>
<FILE>gtkstringlist</FILE>
<TITLE>GtkStringList</TITLE>
GtkStringList
gtk_string_list_new
gtk_string_list_append
gtk_string_list_take
gtk_string_list_remove
gtk_string_list_splice
gtk_string_list_get_string
GtkStringObject
gtk_string_object_get_string
gtk_overlay_layout_child_
get_type
</SECTION>

View File

@@ -7,7 +7,6 @@ gtk_accessible_get_type
gtk_actionable_get_type
gtk_action_bar_get_type
gtk_adjustment_get_type
gtk_any_filter_get_type
gtk_app_chooser_get_type
gtk_app_chooser_button_get_type
gtk_app_chooser_dialog_get_type
@@ -18,15 +17,12 @@ gtk_aspect_frame_get_type
gtk_assistant_get_type
gtk_assistant_page_get_type
gtk_bin_layout_get_type
gtk_bitset_get_type
gtk_bookmark_list_get_type
gtk_box_get_type
gtk_box_layout_get_type
gtk_buildable_get_type
gtk_builder_cscope_get_type
gtk_builder_get_type
gtk_builder_list_item_factory_get_type
gtk_builder_scope_get_type
gtk_buildable_get_type
gtk_button_get_type
gtk_calendar_get_type
gtk_cell_area_get_type
@@ -50,8 +46,6 @@ gtk_color_button_get_type
gtk_color_chooser_get_type
gtk_color_chooser_dialog_get_type
gtk_color_chooser_widget_get_type
gtk_column_view_get_type
gtk_column_view_column_get_type
gtk_combo_box_get_type
gtk_combo_box_text_get_type
gtk_constraint_get_type
@@ -59,18 +53,13 @@ gtk_constraint_guide_get_type
gtk_constraint_layout_get_type
gtk_constraint_target_get_type
gtk_css_provider_get_type
gtk_custom_filter_get_type
gtk_custom_sorter_get_type
gtk_dialog_get_type
gtk_directory_list_get_type
gtk_drag_icon_get_type
gtk_drag_source_get_type
gtk_drawing_area_get_type
gtk_drop_target_get_type
gtk_drop_target_async_get_type
gtk_drop_down_get_type
gtk_editable_get_type
gtk_editable_label_get_type
gtk_emoji_chooser_get_type
gtk_entry_buffer_get_type
gtk_entry_completion_get_type
@@ -81,14 +70,12 @@ gtk_event_controller_focus_get_type
gtk_event_controller_legacy_get_type
gtk_event_controller_motion_get_type
gtk_event_controller_scroll_get_type
gtk_every_filter_get_type
gtk_expander_get_type
gtk_file_chooser_button_get_type
gtk_file_chooser_dialog_get_type
gtk_file_chooser_get_type
gtk_file_chooser_widget_get_type
gtk_file_filter_get_type
gtk_filter_get_type
gtk_filter_list_model_get_type
gtk_fixed_get_type
gtk_fixed_layout_get_type
@@ -114,7 +101,6 @@ gtk_gl_area_get_type
gtk_grid_get_type
gtk_grid_layout_child_get_type
gtk_grid_layout_get_type
gtk_grid_view_get_type
gtk_header_bar_get_type
gtk_icon_theme_get_type
gtk_icon_view_get_type
@@ -127,12 +113,9 @@ gtk_label_get_type
gtk_layout_child_get_type
gtk_layout_manager_get_type
gtk_link_button_get_type
gtk_list_item_get_type
gtk_list_item_factory_get_type
gtk_list_store_get_type
gtk_list_box_get_type
gtk_list_box_row_get_type
gtk_list_view_get_type
gtk_lock_button_get_type
gtk_map_list_model_get_type
gtk_media_controls_get_type
@@ -141,15 +124,11 @@ gtk_media_stream_get_type
gtk_menu_button_get_type
gtk_message_dialog_get_type
gtk_mount_operation_get_type
gtk_multi_filter_get_type
gtk_multi_selection_get_type
gtk_multi_sorter_get_type
gtk_native_get_type
gtk_native_dialog_get_type
gtk_no_selection_get_type
gtk_notebook_get_type
gtk_notebook_page_get_type
gtk_numeric_sorter_get_type
gtk_orientable_get_type
gtk_overlay_get_type
gtk_overlay_layout_get_type
@@ -195,13 +174,11 @@ gtk_shortcuts_window_get_type
gtk_shortcuts_section_get_type
gtk_shortcuts_group_get_type
gtk_shortcuts_shortcut_get_type
gtk_signal_list_item_factory_get_type
gtk_single_selection_get_type
gtk_size_group_get_type
gtk_slice_list_model_get_type
gtk_snapshot_get_type
gtk_sort_list_model_get_type
gtk_sorter_get_type
gtk_spin_button_get_type
gtk_spinner_get_type
gtk_stack_get_type
@@ -209,10 +186,6 @@ gtk_stack_page_get_type
gtk_stack_sidebar_get_type
gtk_stack_switcher_get_type
gtk_statusbar_get_type
gtk_string_filter_get_type
gtk_string_list_get_type
gtk_string_object_get_type
gtk_string_sorter_get_type
gtk_switch_get_type
gtk_level_bar_get_type
gtk_style_context_get_type
@@ -230,7 +203,6 @@ gtk_tree_drag_dest_get_type
gtk_tree_drag_source_get_type
gtk_tree_list_model_get_type
gtk_tree_list_row_get_type
gtk_tree_list_row_sorter_get_type
gtk_tree_model_filter_get_type
gtk_tree_model_get_type
gtk_tree_model_sort_get_type

View File

@@ -5,7 +5,7 @@ in what happens to translate a key press or mouse motion of the users into a
change of a GTK widget, you should read this chapter. This knowledge will also
be useful if you decide to implement your own widgets.
## Devices and events
Devices and events
The most basic input devices that every computer user has interacted with are
keyboards and mice; beyond these, GTK supports touchpads, touchscreens and
@@ -13,14 +13,14 @@ more exotic input devices such as graphics tablets. Inside GTK, every such
input device is represented by a #GdkDevice object.
To simplify dealing with the variability between these input devices, GTK
has a concept of logical and physical devices. The concrete physical devices that
has a concept of master and slave devices. The concrete physical devices that
have many different characteristics (mice may have 2 or 3 or 8 buttons,
keyboards have different layouts and may or may not have a separate number
block, etc) are represented as physical devices. Each physical device is
associated with a virtual logical device. Logical devices always come in
block, etc) are represented as slave devices. Each slave device is
associated with a virtual master device. Master devices always come in
pointer/keyboard pairs - you can think of such a pair as a 'seat'.
GTK widgets generally deal with the logical devices, and thus can be used
GTK widgets generally deal with the master devices, and thus can be used
with any pointing device or keyboard.
When a user interacts with an input device (e.g. moves a mouse or presses

View File

@@ -0,0 +1,101 @@
# List widgets
GTK provides powerful widgets to display and edit lists of data. This document gives an overview over the concepts and how they work together to allow developers to implement lists.
Lists are intended to be used whenever developers want to display lists of objects in roughly the same way.
Lists are perfectly fine to be used for very short list of only 2 or 3 elements, but generally scale fine to millions of items. Of course, the larger the list grows, the more care needs to be taken to choose the right data structures to keep things running well.
Lists are meant to be used with changing data, both with the items itself changing as well as the list adding and removing items. Of course, they work just as well with static data.
## Terminology
These terms are used throughout the documentation when talking about lists and you should be aware of what they refer to. These are often generic terms that have a specific meaning in this context.
**_Views_** or **_list widgets_** are the widgets that hold and manage the lists. Examples of thse widgets would be #GtkListView or #GtkGridView.
Views display data from a **_model_**. A model is a #GListModel and models can be provided in 3 ways or combinations thereof:
* Many list models implementations already exist. There are models that provide specific data, like #GtkDirectoryList. And there are models like #GListStore that allow building lists manually.
* Wrapping list models exists like #GtkFilterListModel or #GtkSortListModel that modify or adapt or combine other models.
* Last but not least, developers are encouraged to create their own #GListModel implementations. The interface is kept deliberately small to make this easy.
The same model can be used in multiple different views and wrapped with multiple different models at once.
The elements in a model are called **_items_**. All items are #GObjects.
Every item in a model has a **_position_** which is the unsigned integer that describes where in the model the item is located. This position can of course change as items are added or removed from the model.
It is important to be aware of the difference between items and positions because the mapping from position to item is not permanent, so developers should think about whether they want to track items or positions when working with models. Oftentimes some things are really hard to do one way but very easy the other way.
The other important part of a view is a **_factory_**. Each factory is a #GtkListItemFactory implementation that takes care of mapping the items of the model to widgets that can be shown in the view.
The way factories do this is by creating a **_listitem_** for each item that is currently in use. Listitems are always #GtkListItem objects. They are only ever created by GTK and provide information about what item they are meant to display.
Different factory implementations use various different methods to allow developers to add the right widgets to listitems and to link those widgets with the item managed by the listitem. Finding a suitable factory implementation for the data displayed, the programming language and development environment is an important task that can simplify setting up the view tremendously.
Views support selections via a **_selection model_**. A selection model is an implementation of the #GtkSelectionModel interface on top of the #GListModel interface that allows marking each item in a model as either selected or not selected. Just like regular models, this can be implemented either by implementing #GtkSelectionModel directly or by wrapping a model with one of the GTK models provided for this purposes, such as #GtkNoSelection or #GtkSingleSelection. The behavior of selection models - ie which items they allow selecting and what effect this has on other items - is completely up to the selection model. As such, single-selections, multi-selections or sharing selection state between different selection models and/or views is possible. The selection state of an item is exposed in the listitem via the GtkListItem:selected property.
Views and listitems also support activation. Activation means that double clicking or pressing enter while inside a focused row will cause the view to emit and activation signal such as GtkListView::activate. This provides an easy way to set up lists, but can also be turned off on listitems if undesired.
Both selections and activation are supported among other things via widget actions (FIXME: Link docs). This allows developers to add widgets to their lists that cause selections to change or to trigger activation via the #GtkActionable interface. For a list of all supported actions see the relevant documentation. (FIXME: where do we document actions and how to I link that?)
## Behind the scenes
While for short lists it is not a problem to instantiate widgets for every item in the model, once lists grow to thousands or millions of elements, this gets less feasible. Because of this, the views only create a limited amount of listitems and recycle them by binding them to new items. In general, views try to keep listitems available only for the items that can actually be seen on screen.
While this behavior allows views to scale effortlessly to huge lists, it has a few implication on what can be done with views. For example, it is not possible to query a view for a listitem used for a certain position - there might not be one and even if there is, that listitem might soon be recycled for a new position.
It is also important that developers save state they care about in the item and do not rely on the widgets they created as those widgets can be recycled for a new position at any time causing any state to be lost.
Another important requirement for views is that they need to know which items are not visible so they can be recycled. Views achieve that by implementing the #GtkScrollable interface and expecting to be placed directly into a #GtkScrolledWindow.
Of course, if you are only using models with few items, this is not important and you can treat views like any other widget. But if you use large lists and your performance suffers, you should be aware of this. Views also allow tuning the number of listitems they create such as with gtk_grid_view_set_max_columns(), and developers running into performance problems should definitely study the tradeoffs of those and experiment with them.
## Displaying trees
While #GtkTreeView provided builtin support for trees, the list widgets, and in particular #GListModel do not. This was a design choice because the common use case is displaying lists and not trees and it greatly simplifies the API interface provided.
However, GTK provides functionality to make trees look and behave like lists for the people who still want to display lists. This is achieved by using the #GtkTreeListModel model to flatten a tree into a list. The #GtkTreeExpander widget can then be used inside a listitem to allow users to expand and collapse rows and provide a similar experience to #GtkTreeView.
Developers should refer to those objects' API reference for more discussion on the topic.
## comparison to GtkTreeView
Developers familiar with #GtkTreeView may wonder how this way of doing lists compares to the way they know. This section will try to outline the similarities and differences between the two.
This new approach tries to provide roughly the same functionality as the old approach but often uses a very different approach to achieve these goals.
The main difference and one of the primary reasons for this new development is that items can be displayed using regular widgets and #GtkCellRenderer is no longer necessary. This allows all benefits that widgets provide, such as complex layout and animating widgets and not only makes cell renderers obsolete, but also #GtkCellArea.
The other big difference is the massive change to the data model. #GtkTreeModel was a rather complex interface for a tree data structure and #GListModel was deliberately designed to be a simple data structure for lists only. (See above (FIXME: link) for how to still do trees with this new model.) Another big change is that the new model allows for bulk changes via the #GListModel:items-changed signal while #GtkTreeModel only allows a single item to change at once. The goal here is of course to encourage implementation of custom list models.
Another consequence of the new model is that it is now easily possible to refer to the contents of a row in the model directly by keeping the item, while #GtkTreeRowReference was a very slow mechanism to achieve the same. And because the items are real objects, developers can make them emit change signals causing listitems and their children to update, which wasn't possible with #GtkTreeModel.
The selection handling is also different. While selections used to be managed via custom code in each widget, selection state is now meant to be managed by the selection models. In particular this allows for complex use cases with specialized requirements (FIXME: Can I add a shoutout to @mitch here because I vividly remember a huge discussion about GtkTreeView's selection behavior and the Gimp).
Finally here's a quick list of equivalent functionality to look for when transitioning code for easy lookup:
| old | new |
| ------------------- | ----------------------------------- |
| #GtkTreeModel | #GListModel |
| #GtkTreePath | #guint position, #GtkTreeListRow |
| #GtkTreeIter | #guint position |
| GtkTreeRowReference | #GObject item |
| #GtkListStore | #GListStore |
| #GtkTreeStore | #GtkTreeListModel, #GtkTreeExpander |
| #GtkTreeSelection | #GtkSelectionModel |
| #GtkTreeViewColumn | FIXME: ColumnView |
| #GtkTreeView | #GtkListView, FIXME: ColumnView |
| #GtkCellView | ? |
| #GtkComboBox | FIXME |
| #GtkIconView | #GtkGridView |
| #GtkTreeSortable | FIXME: ColumnView? |
| #GtkTreeModelSort | #GtkSortListModel |
| #GtkTreeModelFilter | #GtkFilterListModel |
| #GtkCellLayout | #GtkListItemFactory |
| #GtkCellArea | #GtkWidget |
| #GtkCellRenderer | #GtkWidget |

Some files were not shown because too many files have changed in this diff Show More