Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d233b10559 | |||
| b4f9f252d7 | |||
| 373c06b148 | |||
| c84cd97fbc | |||
| 6b7d295cfe | |||
| 481d438380 | |||
| f4e1057431 | |||
| fa0166180e | |||
| 13d84c202b | |||
| 5846794075 | |||
| 201da90e23 | |||
| 8d4fcabf01 | |||
| 3f8735a488 | |||
| a4dc248512 | |||
| ef451b056a | |||
| 59aaabb161 | |||
| 663ca21328 | |||
| 77435d31fa | |||
| 6edb8f096f | |||
| c4dfee8860 | |||
| 8ac1e77c9a | |||
| 65ceb6c15a | |||
| f70d10f6ac | |||
| 0bbd083d79 | |||
| 102d2986c6 | |||
| c74201ca87 | |||
| b09019a5b4 | |||
| 1dd08ad8db | |||
| eb0704855f | |||
| c4c1d4a1b3 | |||
| e6756f605e | |||
| 1f4b8e089e | |||
| c0e08db739 | |||
| 1c337d350d | |||
| 81e675dfbf | |||
| 8556221429 | |||
| 1b4109a7fd | |||
| df0786be7a | |||
| 3f545da08d |
@@ -9,6 +9,7 @@
|
||||
<property name="default-height">768</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="start">
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">document-open-symbolic</property>
|
||||
|
||||
@@ -140,7 +140,6 @@
|
||||
</gresource>
|
||||
<gresource prefix="/listview_colors">
|
||||
<file compressed="true">color.names.txt</file>
|
||||
<file>listview_colors.css</file>
|
||||
</gresource>
|
||||
<gresource prefix="/shortcuts">
|
||||
<file>shortcuts.ui</file>
|
||||
@@ -226,6 +225,7 @@
|
||||
<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>
|
||||
|
||||
@@ -92,7 +92,7 @@ strings_setup_item_full (GtkSignalListItemFactory *factory,
|
||||
gtk_label_set_xalign (GTK_LABEL (title), 0.0);
|
||||
description = gtk_label_new ("");
|
||||
gtk_label_set_xalign (GTK_LABEL (description), 0.0);
|
||||
gtk_widget_add_css_class (description, "dim-label");
|
||||
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);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<style>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<property name="title">Font Explorer</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="reset">
|
||||
<property name="receives-default">1</property>
|
||||
|
||||
@@ -30,6 +30,7 @@ do_headerbar (GtkWidget *do_widget)
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
|
||||
button = gtk_button_new ();
|
||||
icon = g_themed_icon_new ("mail-send-receive-symbolic");
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<property name="default-height">500</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<style>
|
||||
|
||||
@@ -627,23 +627,6 @@ setup_listitem_cb (GtkListItemFactory *factory,
|
||||
gtk_expression_unref (color_expression);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_selection_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, 8, 8);
|
||||
gtk_expression_bind (color_expression, picture, "paintable", NULL);
|
||||
|
||||
gtk_list_item_set_child (list_item, picture);
|
||||
}
|
||||
|
||||
static void
|
||||
set_title (gpointer item,
|
||||
const char *title)
|
||||
@@ -794,47 +777,6 @@ bind_number_item (GtkSignalListItemFactory *factory,
|
||||
g_free (string);
|
||||
}
|
||||
|
||||
static void
|
||||
update_selection_count (GListModel *model,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added,
|
||||
gpointer data)
|
||||
{
|
||||
char *text;
|
||||
text = g_strdup_printf ("%u", g_list_model_get_n_items (model));
|
||||
gtk_label_set_label (GTK_LABEL (data), text);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
static void
|
||||
update_selection_average (GListModel *model,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added,
|
||||
gpointer data)
|
||||
{
|
||||
guint n = g_list_model_get_n_items (model);
|
||||
GdkRGBA c = { 0, 0, 0, 1 };
|
||||
guint i;
|
||||
GtkColor *color;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
color = g_list_model_get_item (model, i);
|
||||
|
||||
c.red += color->color.red;
|
||||
c.green += color->color.green;
|
||||
c.blue += color->color.blue;
|
||||
|
||||
g_object_unref (color);
|
||||
}
|
||||
|
||||
color = gtk_color_new ("", c.red / n, c.green / n, c.blue / n);
|
||||
gtk_picture_set_paintable (GTK_PICTURE (data), GDK_PAINTABLE (color));
|
||||
g_object_unref (color);
|
||||
}
|
||||
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
GtkWidget *
|
||||
@@ -855,26 +797,11 @@ do_listview_colors (GtkWidget *do_widget)
|
||||
PangoAttrList *attrs;
|
||||
char *string;
|
||||
guint len;
|
||||
GtkWidget *selection_view;
|
||||
GListModel *selection_filter;
|
||||
GListModel *no_selection;
|
||||
GtkWidget *grid;
|
||||
GtkWidget *selection_size_label;
|
||||
GtkWidget *selection_average_picture;
|
||||
GtkWidget *selection_info_toggle;
|
||||
GtkWidget *selection_info_revealer;
|
||||
GtkCssProvider *provider;
|
||||
|
||||
provider = gtk_css_provider_new ();
|
||||
gtk_css_provider_load_from_resource (provider, "/listview_colors/listview_colors.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_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);
|
||||
@@ -882,85 +809,14 @@ do_listview_colors (GtkWidget *do_widget)
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer*)&window);
|
||||
|
||||
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
|
||||
gtk_window_set_child (GTK_WINDOW (window), box);
|
||||
|
||||
selection_info_revealer = gtk_revealer_new ();
|
||||
gtk_box_append (GTK_BOX (box), selection_info_revealer);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
gtk_revealer_set_child (GTK_REVEALER (selection_info_revealer), grid);
|
||||
gtk_widget_set_margin_start (grid, 10);
|
||||
gtk_widget_set_margin_end (grid, 10);
|
||||
gtk_widget_set_margin_top (grid, 10);
|
||||
gtk_widget_set_margin_bottom (grid, 10);
|
||||
gtk_grid_set_row_spacing (GTK_GRID (grid), 10);
|
||||
gtk_grid_set_column_spacing (GTK_GRID (grid), 10);
|
||||
|
||||
label = gtk_label_new ("Selection");
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_widget_add_css_class (label, "title-3");
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 5, 1);
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Size:"), 0, 2, 1, 1);
|
||||
|
||||
selection_size_label = gtk_label_new ("0");
|
||||
gtk_grid_attach (GTK_GRID (grid), selection_size_label, 1, 2, 1, 1);
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Average:"), 2, 2, 1, 1);
|
||||
|
||||
selection_average_picture = gtk_picture_new ();
|
||||
gtk_widget_set_size_request (selection_average_picture, 32, 32);
|
||||
gtk_grid_attach (GTK_GRID (grid), selection_average_picture, 3, 2, 1, 1);
|
||||
|
||||
label = gtk_label_new ("");
|
||||
gtk_widget_set_hexpand (label, TRUE);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 4, 2, 1, 1);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_widget_set_hexpand (sw, TRUE);
|
||||
|
||||
gtk_grid_attach (GTK_GRID (grid), sw, 0, 1, 5, 1);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
|
||||
GTK_POLICY_NEVER,
|
||||
GTK_POLICY_AUTOMATIC);
|
||||
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_selection_listitem_cb), NULL);
|
||||
selection_view = gtk_grid_view_new_with_factory (factory);
|
||||
gtk_widget_add_css_class (selection_view, "compact");
|
||||
gtk_grid_view_set_max_columns (GTK_GRID_VIEW (selection_view), 200);
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), selection_view);
|
||||
|
||||
sw = gtk_scrolled_window_new ();
|
||||
gtk_box_append (GTK_BOX (box), sw);
|
||||
gtk_window_set_child (GTK_WINDOW (window), sw);
|
||||
|
||||
gridview = create_color_grid ();
|
||||
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), gridview);
|
||||
gtk_widget_set_hexpand (sw, TRUE);
|
||||
gtk_widget_set_vexpand (sw, TRUE);
|
||||
model = gtk_grid_view_get_model (GTK_GRID_VIEW (gridview));
|
||||
|
||||
selection_filter = G_LIST_MODEL (gtk_selection_filter_model_new (GTK_SELECTION_MODEL (model)));
|
||||
g_signal_connect (selection_filter, "items-changed", G_CALLBACK (update_selection_count), selection_size_label);
|
||||
g_signal_connect (selection_filter, "items-changed", G_CALLBACK (update_selection_average), selection_average_picture);
|
||||
|
||||
no_selection = G_LIST_MODEL (gtk_no_selection_new (selection_filter));
|
||||
gtk_grid_view_set_model (GTK_GRID_VIEW (selection_view), no_selection);
|
||||
g_object_unref (selection_filter);
|
||||
g_object_unref (no_selection);
|
||||
|
||||
g_object_get (model, "model", &model, NULL);
|
||||
|
||||
selection_info_toggle = gtk_toggle_button_new ();
|
||||
gtk_button_set_icon_name (GTK_BUTTON (selection_info_toggle), "emblem-important-symbolic");
|
||||
gtk_widget_set_tooltip_text (selection_info_toggle, "Show selection info");
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), selection_info_toggle);
|
||||
|
||||
g_object_bind_property (selection_info_toggle, "active",
|
||||
selection_info_revealer, "reveal-child",
|
||||
G_BINDING_DEFAULT);
|
||||
|
||||
button = gtk_button_new_with_mnemonic ("_Refill");
|
||||
g_signal_connect (button, "clicked",
|
||||
G_CALLBACK (refill),
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
.view.compact > child {
|
||||
padding: 1px;
|
||||
}
|
||||
@@ -174,6 +174,7 @@
|
||||
<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>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<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>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<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>
|
||||
|
||||
@@ -194,8 +194,8 @@ create_weather_model (void)
|
||||
}
|
||||
|
||||
static void
|
||||
setup_widget (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
setup_widget (GtkListItem *list_item,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkWidget *box, *child;
|
||||
|
||||
@@ -218,8 +218,8 @@ setup_widget (GtkSignalListItemFactory *factory,
|
||||
}
|
||||
|
||||
static void
|
||||
bind_widget (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *list_item)
|
||||
bind_widget (GtkListItem *list_item,
|
||||
gpointer unused)
|
||||
{
|
||||
GtkWidget *box, *child;
|
||||
GtkWeatherInfo *info;
|
||||
@@ -282,12 +282,11 @@ create_weather_view (void)
|
||||
{
|
||||
GtkWidget *listview;
|
||||
GListModel *model, *selection;
|
||||
GtkListItemFactory *factory;
|
||||
|
||||
factory = gtk_signal_list_item_factory_new ();
|
||||
g_signal_connect (factory, "setup", G_CALLBACK (setup_widget), NULL);
|
||||
g_signal_connect (factory, "bind", G_CALLBACK (bind_widget), NULL);
|
||||
listview = gtk_list_view_new_with_factory (factory);
|
||||
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 ();
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
<property name="default-height">600</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="headerbar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="valign">center</property>
|
||||
|
||||
@@ -69,6 +69,7 @@ do_markup (GtkWidget *do_widget)
|
||||
g_signal_connect (show_source, "toggled", G_CALLBACK (source_toggled), stack);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), show_source);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ demos = files([
|
||||
'listview_minesweeper.c',
|
||||
'listview_settings.c',
|
||||
'listview_weather.c',
|
||||
'listview_words.c',
|
||||
'markup.c',
|
||||
'modelbutton.c',
|
||||
'overlay.c',
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
<property name="title" translatable="yes">Model Button</property>
|
||||
<property name="resizable">0</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar"/>
|
||||
<object class="GtkHeaderBar">
|
||||
<property name="show-title-buttons">1</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
|
||||
@@ -392,6 +392,7 @@ do_paint (GtkWidget *toplevel)
|
||||
gtk_window_set_child (GTK_WINDOW (window), draw_area);
|
||||
|
||||
headerbar = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (headerbar), TRUE);
|
||||
|
||||
colorbutton = gtk_color_button_new ();
|
||||
g_signal_connect (colorbutton, "color-set",
|
||||
|
||||
@@ -276,6 +276,7 @@ do_peg_solitaire (GtkWidget *do_widget)
|
||||
g_signal_connect (restart, "clicked", G_CALLBACK (restart), NULL);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), restart);
|
||||
window = gtk_window_new ();
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
|
||||
@@ -40,6 +40,7 @@ do_sidebar (GtkWidget *do_widget)
|
||||
gtk_widget_set_size_request (window, 500, 350);
|
||||
|
||||
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_title (GTK_WINDOW(window), "Stack Sidebar");
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
|
||||
@@ -470,6 +470,7 @@ do_sliding_puzzle (GtkWidget *do_widget)
|
||||
g_signal_connect (restart, "clicked", G_CALLBACK (reshuffle), NULL);
|
||||
|
||||
header = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (header), TRUE);
|
||||
gtk_header_bar_pack_start (GTK_HEADER_BAR (header), restart);
|
||||
gtk_header_bar_pack_end (GTK_HEADER_BAR (header), tweak);
|
||||
window = gtk_window_new ();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<property name="resizable">0</property>
|
||||
<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>
|
||||
|
||||
@@ -73,6 +73,7 @@ do_video_player (GtkWidget *do_widget)
|
||||
gtk_window_set_child (GTK_WINDOW (window), video);
|
||||
|
||||
title = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (title), TRUE);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (window), title);
|
||||
|
||||
open_button = gtk_button_new_with_mnemonic ("_Open");
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<property name="default-height">768</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkBox">
|
||||
<style>
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
<property name="focus-widget">text_view</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="start">
|
||||
<object class="GtkButton">
|
||||
<property name="icon-name">document-open-symbolic</property>
|
||||
|
||||
@@ -436,6 +436,7 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<property name="title">GTK Widget Factory</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="headerbar1">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="stack_switcher">
|
||||
<property name="stack">toplevel_stack</property>
|
||||
|
||||
@@ -1423,6 +1423,7 @@ the search bar below the header bar.
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
@@ -1536,6 +1537,7 @@ GtkMenuButton, GtkRevealer and GtkListBox.
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -74,7 +74,6 @@
|
||||
<xi:include href="xml/gtksingleselection.xml" />
|
||||
<xi:include href="xml/gtkmultiselection.xml" />
|
||||
</section>
|
||||
<xi:include href="xml/gtkselectionfiltermodel.xml" />
|
||||
<xi:include href="xml/gtkbookmarklist.xml" />
|
||||
<xi:include href="xml/gtkdirectorylist.xml" />
|
||||
<xi:include href="xml/gtkstringlist.xml" />
|
||||
|
||||
@@ -348,6 +348,7 @@ GtkBitset
|
||||
gtk_bitset_ref
|
||||
gtk_bitset_unref
|
||||
gtk_bitset_new_empty
|
||||
gtk_bitset_new_range
|
||||
gtk_bitset_copy
|
||||
<SUBSECTION>
|
||||
gtk_bitset_contains
|
||||
@@ -449,7 +450,6 @@ gtk_single_selection_get_type
|
||||
<TITLE>GtkMultiSeledction</TITLE>
|
||||
GtkMultiSelection
|
||||
gtk_multi_selection_new
|
||||
gtk_multi_selection_get_model
|
||||
<SUBSECTION Private>
|
||||
gtk_multi_selection_get_type
|
||||
</SECTION>
|
||||
@@ -1544,6 +1544,9 @@ 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
|
||||
<SUBSECTION Standard>
|
||||
GTK_FILTER_LIST_MODEL
|
||||
GTK_IS_FILTER_LIST_MODEL
|
||||
@@ -7613,13 +7616,3 @@ gtk_string_list_get_string
|
||||
GtkStringObject
|
||||
gtk_string_object_get_string
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>gtkselectionfiltermodel</FILE>
|
||||
<TITLE>GtkSelectionFilterModel</TITLE>
|
||||
GtkSelectionFilterModel
|
||||
gtk_selection_filter_model_new
|
||||
gtk_selection_filter_model_new_for_type
|
||||
gtk_selection_filter_model_set_model
|
||||
gtk_selection_filter_model_get_model
|
||||
</SECTION>
|
||||
|
||||
@@ -184,7 +184,6 @@ gtk_scrollbar_get_type
|
||||
gtk_scrolled_window_get_type
|
||||
gtk_search_bar_get_type
|
||||
gtk_search_entry_get_type
|
||||
gtk_selection_filter_model_get_type
|
||||
gtk_selection_model_get_type
|
||||
gtk_separator_get_type
|
||||
gtk_settings_get_type
|
||||
|
||||
@@ -411,7 +411,6 @@ and gtk_box_append(). You can also reorder box children as necessary.
|
||||
The gtk_header_bar_set_show_close_button() function has been renamed to
|
||||
the more accurate name gtk_header_bar_set_show_title_buttons(). The
|
||||
corresponding getter and the property itself have also been renamed.
|
||||
The default value of the property is now %TRUE instead of %FALSE.
|
||||
|
||||
The gtk_header_bar_set_custom_title() function has been renamed to
|
||||
the more accurate name gtk_header_bar_set_title_widget(). The
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child type="title">
|
||||
<object class="GtkStackSwitcher" id="tabs">
|
||||
<property name="stack">stack</property>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<property name="default-height">400</property>
|
||||
<child type="titlebar">
|
||||
<object class="GtkHeaderBar" id="header">
|
||||
<property name="show-title-buttons">1</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="lines_label">
|
||||
<property name="visible">0</property>
|
||||
|
||||
@@ -15,6 +15,7 @@ new_window (GApplication *app,
|
||||
gtk_window_set_icon_name (GTK_WINDOW (window), "sunny");
|
||||
|
||||
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);
|
||||
|
||||
overlay = gtk_overlay_new ();
|
||||
|
||||
@@ -1184,7 +1184,7 @@ _gdk_wm_protocols_filter (const XEvent *xevent,
|
||||
if (timings)
|
||||
timings->drawn_time = frame_drawn_time;
|
||||
|
||||
if (!surface_impl->toplevel->frame_still_painting && surface_impl->toplevel->frame_pending)
|
||||
if (surface_impl->toplevel->frame_pending)
|
||||
{
|
||||
surface_impl->toplevel->frame_pending = FALSE;
|
||||
gdk_surface_thaw_updates (win);
|
||||
|
||||
+10
-49
@@ -582,23 +582,6 @@ create_legacy_context (GdkDisplay *display,
|
||||
}
|
||||
|
||||
#ifdef HAVE_XDAMAGE
|
||||
static void
|
||||
finish_frame (GdkGLContext *context)
|
||||
{
|
||||
GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context);
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
|
||||
if (context_x11->xdamage == 0)
|
||||
return;
|
||||
|
||||
if (context_x11->frame_fence == 0)
|
||||
return;
|
||||
|
||||
glDeleteSync (context_x11->frame_fence);
|
||||
context_x11->frame_fence = 0;
|
||||
_gdk_x11_surface_set_frame_still_painting (surface, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_context_for_frame_fence (GdkGLContext *context)
|
||||
{
|
||||
@@ -645,6 +628,7 @@ on_gl_surface_xevent (GdkGLContext *context,
|
||||
GdkX11Display *display_x11)
|
||||
{
|
||||
GdkX11GLContext *context_x11 = GDK_X11_GL_CONTEXT (context);
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
XDamageNotifyEvent *damage_xevent;
|
||||
|
||||
if (!context_x11->is_attached)
|
||||
@@ -691,7 +675,9 @@ on_gl_surface_xevent (GdkGLContext *context,
|
||||
case GL_WAIT_FAILED:
|
||||
if (wait_result == GL_WAIT_FAILED)
|
||||
g_warning ("failed to wait on GL fence associated with last swap buffers call");
|
||||
finish_frame (context);
|
||||
glDeleteSync (context_x11->frame_fence);
|
||||
context_x11->frame_fence = 0;
|
||||
_gdk_x11_surface_set_frame_still_painting (surface, FALSE);
|
||||
break;
|
||||
|
||||
/* We assume that if the fence hasn't been signaled, that this
|
||||
@@ -710,21 +696,6 @@ on_gl_surface_xevent (GdkGLContext *context,
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_surface_state_changed (GdkGLContext *context)
|
||||
{
|
||||
GdkSurface *surface = gdk_gl_context_get_surface (context);
|
||||
|
||||
if ((surface->state & GDK_SURFACE_STATE_WITHDRAWN) == 0)
|
||||
return;
|
||||
|
||||
/* If we're about to withdraw the surface, then we don't care if the frame is
|
||||
* still getting rendered by the GPU. The compositor is going to remove the surface
|
||||
* from the scene anyway, so wrap up the frame.
|
||||
*/
|
||||
finish_frame (context);
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
@@ -907,23 +878,13 @@ gdk_x11_gl_context_realize (GdkGLContext *context,
|
||||
gdk_x11_surface_get_xid (surface),
|
||||
XDamageReportRawRectangles);
|
||||
if (gdk_x11_display_error_trap_pop (display))
|
||||
{
|
||||
context_x11->xdamage = 0;
|
||||
}
|
||||
context_x11->xdamage = 0;
|
||||
else
|
||||
{
|
||||
g_signal_connect_object (G_OBJECT (display),
|
||||
"xevent",
|
||||
G_CALLBACK (on_gl_surface_xevent),
|
||||
context,
|
||||
G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (G_OBJECT (surface),
|
||||
"notify::state",
|
||||
G_CALLBACK (on_surface_state_changed),
|
||||
context,
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
}
|
||||
g_signal_connect_object (G_OBJECT (display),
|
||||
"xevent",
|
||||
G_CALLBACK (on_gl_surface_xevent),
|
||||
context,
|
||||
G_CONNECT_SWAPPED);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+6
-16
@@ -2241,23 +2241,12 @@ render_cross_fade_node (GskGLRenderer *self,
|
||||
{
|
||||
GskRenderNode *start_node = gsk_cross_fade_node_get_start_child (node);
|
||||
GskRenderNode *end_node = gsk_cross_fade_node_get_end_child (node);
|
||||
const float progress = gsk_cross_fade_node_get_progress (node);
|
||||
float progress = gsk_cross_fade_node_get_progress (node);
|
||||
TextureRegion start_region;
|
||||
TextureRegion end_region;
|
||||
gboolean is_offscreen1, is_offscreen2;
|
||||
OpCrossFade *op;
|
||||
|
||||
if (progress <= 0)
|
||||
{
|
||||
gsk_gl_renderer_add_render_ops (self, start_node, builder);
|
||||
return;
|
||||
}
|
||||
else if (progress >= 1)
|
||||
{
|
||||
gsk_gl_renderer_add_render_ops (self, end_node, builder);
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO: We create 2 textures here as big as the cross-fade node, but both the
|
||||
* start and the end node might be a lot smaller than that. */
|
||||
|
||||
@@ -2277,10 +2266,11 @@ render_cross_fade_node (GskGLRenderer *self,
|
||||
&end_region, &is_offscreen2,
|
||||
FORCE_OFFSCREEN | RESET_CLIP | RESET_OPACITY))
|
||||
{
|
||||
const float prev_opacity = ops_set_opacity (builder, builder->current_opacity * progress);
|
||||
gsk_gl_renderer_add_render_ops (self, start_node, builder);
|
||||
ops_set_opacity (builder, prev_opacity);
|
||||
|
||||
load_vertex_data_with_region (ops_draw (builder, NULL),
|
||||
node,
|
||||
builder,
|
||||
&start_region,
|
||||
TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+19
-19
@@ -104,7 +104,7 @@ gsk_color_node_peek_color (GskRenderNode *node)
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_color_node_new:
|
||||
* gsk_color_node_new:
|
||||
* @rgba: a #GdkRGBA specifying a color
|
||||
* @bounds: the rectangle to render the color into
|
||||
*
|
||||
@@ -216,7 +216,7 @@ gsk_linear_gradient_node_diff (GskRenderNode *node1,
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
gsk_render_node_diff_impossible (node1, node2, region);
|
||||
}
|
||||
|
||||
@@ -1163,7 +1163,7 @@ gsk_inset_shadow_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_inset_shadow_node_new:
|
||||
* gsk_inset_shadow_node_new:
|
||||
* @outline: outline of the region containing the shadow
|
||||
* @color: color of the shadow
|
||||
* @dx: horizontal offset of shadow
|
||||
@@ -1465,7 +1465,7 @@ gsk_outset_shadow_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_outset_shadow_node_new:
|
||||
* gsk_outset_shadow_node_new:
|
||||
* @outline: outline of the region surrounded by shadow
|
||||
* @color: color of the shadow
|
||||
* @dx: horizontal offset of shadow
|
||||
@@ -1672,7 +1672,7 @@ gsk_cairo_node_peek_surface (GskRenderNode *node)
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_cairo_node_new:
|
||||
* gsk_cairo_node_new:
|
||||
* @bounds: the rectangle to render to
|
||||
*
|
||||
* Creates a #GskRenderNode that will render a cairo surface
|
||||
@@ -1982,7 +1982,7 @@ gsk_transform_node_draw (GskRenderNode *node,
|
||||
ctm.xy, ctm.yy,
|
||||
ctm.x0, ctm.y0));
|
||||
cairo_transform (cr, &ctm);
|
||||
|
||||
|
||||
gsk_render_node_draw (self->child, cr);
|
||||
}
|
||||
|
||||
@@ -2062,7 +2062,7 @@ gsk_transform_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_transform_node_new:
|
||||
* gsk_transform_node_new:
|
||||
* @child: The node to transform
|
||||
* @transform: (transfer none): The transform to apply
|
||||
*
|
||||
@@ -2188,7 +2188,7 @@ gsk_opacity_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_opacity_node_new:
|
||||
* gsk_opacity_node_new:
|
||||
* @child: The node to draw
|
||||
* @opacity: The opacity to apply
|
||||
*
|
||||
@@ -2380,7 +2380,7 @@ nope:
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_color_matrix_node_new:
|
||||
* gsk_color_matrix_node_new:
|
||||
* @child: The node to draw
|
||||
* @color_matrix: The matrix to apply
|
||||
* @color_offset: Values to add to the color
|
||||
@@ -2533,7 +2533,7 @@ gsk_repeat_node_draw (GskRenderNode *node,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_repeat_node_new:
|
||||
* gsk_repeat_node_new:
|
||||
* @bounds: The bounds of the area to be painted
|
||||
* @child: The child to repeat
|
||||
* @child_bounds: (allow-none): The area of the child to repeat or %NULL to
|
||||
@@ -2670,7 +2670,7 @@ gsk_clip_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_clip_node_new:
|
||||
* gsk_clip_node_new:
|
||||
* @child: The node to draw
|
||||
* @clip: The clip to apply
|
||||
*
|
||||
@@ -2800,7 +2800,7 @@ gsk_rounded_clip_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_rounded_clip_node_new:
|
||||
* gsk_rounded_clip_node_new:
|
||||
* @child: The node to draw
|
||||
* @clip: The clip to apply
|
||||
*
|
||||
@@ -3013,7 +3013,7 @@ gsk_shadow_node_get_bounds (GskShadowNode *self,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_shadow_node_new:
|
||||
* gsk_shadow_node_new:
|
||||
* @child: The node to draw
|
||||
* @shadows: (array length=n_shadows): The shadows to apply
|
||||
* @n_shadows: number of entries in the @shadows array
|
||||
@@ -3210,7 +3210,7 @@ gsk_blend_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_blend_node_new:
|
||||
* gsk_blend_node_new:
|
||||
* @bottom: The bottom node to be drawn
|
||||
* @top: The node to be blended onto the @bottom node
|
||||
* @blend_mode: The blend mode to use
|
||||
@@ -3359,7 +3359,7 @@ gsk_cross_fade_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_cross_fade_node_new:
|
||||
* gsk_cross_fade_node_new:
|
||||
* @start: The start node to be drawn
|
||||
* @end: The node to be cross_fadeed onto the @start node
|
||||
* @progress: How far the fade has progressed from start to end. The value will
|
||||
@@ -3549,7 +3549,7 @@ font_has_color_glyphs (const PangoFont *font)
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_text_node_new:
|
||||
* gsk_text_node_new:
|
||||
* @font: the #PangoFont containing the glyphs
|
||||
* @glyphs: the #PangoGlyphString to render
|
||||
* @color: the foreground color to render with
|
||||
@@ -3953,7 +3953,7 @@ gsk_blur_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_blur_node_new:
|
||||
* gsk_blur_node_new:
|
||||
* @child: the child node to blur
|
||||
* @radius: the blur radius
|
||||
*
|
||||
@@ -4076,9 +4076,9 @@ gsk_debug_node_diff (GskRenderNode *node1,
|
||||
}
|
||||
|
||||
/**
|
||||
* gsk_debug_node_new:
|
||||
* gsk_debug_node_new:
|
||||
* @child: The child to add debug info for
|
||||
* @message: (transfer full): The debug message
|
||||
* @message: (transfer full): The debug message
|
||||
*
|
||||
* Creates a #GskRenderNode that will add debug information about
|
||||
* the given @child.
|
||||
|
||||
@@ -295,7 +295,6 @@ gtk_cell_accessible_action_do_action (AtkAction *action,
|
||||
GtkCellAccessible *cell = GTK_CELL_ACCESSIBLE (action);
|
||||
GtkCellAccessibleParent *parent;
|
||||
|
||||
cell = GTK_CELL_ACCESSIBLE (action);
|
||||
if (gtk_accessible_get_widget (GTK_ACCESSIBLE (cell)) == NULL)
|
||||
return FALSE;
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ static gunichar
|
||||
gtk_password_entry_accessible_get_character_at_offset (AtkText *atk_text,
|
||||
gint offset)
|
||||
{
|
||||
GtkText *text = get_text_widget (GTK_ACCESSIBLE (atk_text));
|
||||
GtkText *text;
|
||||
char *contents, *index;
|
||||
gunichar result;
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <gtk/gtkappchooserbutton.h>
|
||||
#include <gtk/gtkapplication.h>
|
||||
#include <gtk/gtkapplicationwindow.h>
|
||||
#include <gtk/gtkarraystore.h>
|
||||
#include <gtk/gtkaspectframe.h>
|
||||
#include <gtk/gtkassistant.h>
|
||||
#include <gtk/gtkbinlayout.h>
|
||||
@@ -133,6 +134,7 @@
|
||||
#include <gtk/gtkfontchooserdialog.h>
|
||||
#include <gtk/gtkfontchooserwidget.h>
|
||||
#include <gtk/gtkframe.h>
|
||||
#include <gtk/gtkfunctionslistitemfactory.h>
|
||||
#include <gtk/gtkgesture.h>
|
||||
#include <gtk/gtkgestureclick.h>
|
||||
#include <gtk/gtkgesturedrag.h>
|
||||
@@ -213,7 +215,6 @@
|
||||
#include <gtk/gtkscrolledwindow.h>
|
||||
#include <gtk/gtksearchbar.h>
|
||||
#include <gtk/gtksearchentry.h>
|
||||
#include <gtk/gtkselectionfiltermodel.h>
|
||||
#include <gtk/gtkselectionmodel.h>
|
||||
#include <gtk/gtkseparator.h>
|
||||
#include <gtk/gtksettings.h>
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
#ifndef __GTK_ARRAY_IMPL_PRIVATE_H__
|
||||
#define __GTK_ARRAY_IMPL_PRIVATE_H__
|
||||
|
||||
|
||||
/* This is a dumbed-down GPtrArray, which takes some stack
|
||||
* space to use. When using this, the general case should always
|
||||
* be that the number of elements is lower than reserved_size.
|
||||
* The GPtrArray should only be used in extreme cases.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint reserved_size;
|
||||
guint len;
|
||||
void **stack_space;
|
||||
GPtrArray *ptr_array;
|
||||
|
||||
} GtkArray;
|
||||
|
||||
|
||||
static inline void
|
||||
gtk_array_init (GtkArray *self,
|
||||
void **stack_space,
|
||||
guint reserved_size)
|
||||
{
|
||||
self->reserved_size = reserved_size;
|
||||
self->len = 0;
|
||||
self->stack_space = stack_space;
|
||||
self->ptr_array = NULL;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
gtk_array_index (const GtkArray *self,
|
||||
guint index)
|
||||
{
|
||||
g_assert (index < self->len);
|
||||
|
||||
if (G_LIKELY (!self->ptr_array))
|
||||
return self->stack_space[index];
|
||||
|
||||
return g_ptr_array_index (self->ptr_array, index);
|
||||
}
|
||||
|
||||
static inline void
|
||||
gtk_array_add (GtkArray *self,
|
||||
void *element)
|
||||
{
|
||||
if (G_LIKELY (self->len < self->reserved_size))
|
||||
{
|
||||
self->stack_space[self->len] = element;
|
||||
self->len++;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Need to fall back to the GPtrArray */
|
||||
if (G_UNLIKELY (!self->ptr_array))
|
||||
{
|
||||
self->ptr_array = g_ptr_array_new_full (self->len + 1, NULL);
|
||||
memcpy (self->ptr_array->pdata, self->stack_space, sizeof (void *) * self->len);
|
||||
self->ptr_array->len = self->len;
|
||||
}
|
||||
|
||||
g_ptr_array_add (self->ptr_array, element);
|
||||
self->len++; /* We still count self->len */
|
||||
}
|
||||
|
||||
static inline void
|
||||
gtk_array_insert (GtkArray *self,
|
||||
guint index,
|
||||
void *element)
|
||||
{
|
||||
if (index >= self->len)
|
||||
{
|
||||
gtk_array_add (self, element);
|
||||
return;
|
||||
}
|
||||
|
||||
if (G_LIKELY (self->len < self->reserved_size))
|
||||
{
|
||||
memmove (self->stack_space + index + 1, self->stack_space + index,
|
||||
sizeof (void *) * (self->len - index));
|
||||
self->stack_space[index] = element;
|
||||
self->len++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (!self->ptr_array))
|
||||
{
|
||||
self->ptr_array = g_ptr_array_new_full (self->len + 1, NULL);
|
||||
memcpy (self->ptr_array->pdata, self->stack_space, sizeof (void *) * self->len);
|
||||
self->ptr_array->len = self->len;
|
||||
}
|
||||
|
||||
g_assert (self->ptr_array);
|
||||
g_ptr_array_insert (self->ptr_array, index, element);
|
||||
self->len++;
|
||||
}
|
||||
|
||||
static inline void
|
||||
gtk_array_free (GtkArray *self,
|
||||
GDestroyNotify element_free_func)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (G_LIKELY (!self->ptr_array))
|
||||
{
|
||||
if (element_free_func)
|
||||
{
|
||||
for (i = 0; i < self->len; i++)
|
||||
element_free_func (self->stack_space[i]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert (self->ptr_array);
|
||||
|
||||
if (element_free_func)
|
||||
{
|
||||
for (i = 0; i < self->ptr_array->len; i++)
|
||||
element_free_func (g_ptr_array_index (self->ptr_array, i));
|
||||
}
|
||||
|
||||
g_ptr_array_free (self->ptr_array, TRUE);
|
||||
}
|
||||
|
||||
static inline void **
|
||||
gtk_array_get_data (GtkArray *self)
|
||||
{
|
||||
if (G_LIKELY (!self->ptr_array))
|
||||
return self->stack_space;
|
||||
|
||||
return self->ptr_array->pdata;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkarraystore.h"
|
||||
|
||||
#define GTK_VECTOR_ELEMENT_TYPE GObject *
|
||||
#define GTK_VECTOR_FREE_FUNC g_object_unref
|
||||
#include "gtkvectorimpl.c"
|
||||
|
||||
/**
|
||||
* SECTION:gtkarraystore
|
||||
* @title: GtkArrayStore
|
||||
* @short_description: A simple array implementation of #GListModel
|
||||
*
|
||||
* #GtkArrayStore is a simple implementation of #GListModel that stores all
|
||||
* items in memory.
|
||||
*
|
||||
* It provides appending, deletions, and lookups in O(1) time and insertions
|
||||
* in O(N) time. it is implemented using an array.
|
||||
*/
|
||||
|
||||
/**
|
||||
* GtkArrayStore:
|
||||
*
|
||||
* #GtkArrayStore is an opaque data structure and can only be accessed
|
||||
* using the following functions.
|
||||
**/
|
||||
|
||||
struct _GtkArrayStore
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GType item_type;
|
||||
GtkVector items;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_ITEM_TYPE,
|
||||
N_PROPERTIES
|
||||
};
|
||||
|
||||
static void gtk_array_store_iface_init (GListModelInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkArrayStore, gtk_array_store, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_array_store_iface_init));
|
||||
|
||||
static void
|
||||
gtk_array_store_dispose (GObject *object)
|
||||
{
|
||||
GtkArrayStore *self = GTK_ARRAY_STORE (object);
|
||||
|
||||
gtk_vector_clear (&self->items);
|
||||
|
||||
G_OBJECT_CLASS (gtk_array_store_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_array_store_get_property (GObject *object,
|
||||
guint property_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkArrayStore *self = GTK_ARRAY_STORE (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_ITEM_TYPE:
|
||||
g_value_set_gtype (value, self->item_type);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_array_store_set_property (GObject *object,
|
||||
guint property_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkArrayStore *self = GTK_ARRAY_STORE (object);
|
||||
|
||||
switch (property_id)
|
||||
{
|
||||
case PROP_ITEM_TYPE: /* construct-only */
|
||||
g_assert (g_type_is_a (g_value_get_gtype (value), G_TYPE_OBJECT));
|
||||
self->item_type = g_value_get_gtype (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_array_store_class_init (GtkArrayStoreClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = gtk_array_store_dispose;
|
||||
object_class->get_property = gtk_array_store_get_property;
|
||||
object_class->set_property = gtk_array_store_set_property;
|
||||
|
||||
/**
|
||||
* GtkArrayStore:item-type:
|
||||
*
|
||||
* The type of items contained in this list self. Items must be
|
||||
* subclasses of #GObject.
|
||||
**/
|
||||
g_object_class_install_property (object_class, PROP_ITEM_TYPE,
|
||||
g_param_spec_gtype ("item-type", "", "", G_TYPE_OBJECT,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
static GType
|
||||
gtk_array_store_get_item_type (GListModel *list)
|
||||
{
|
||||
GtkArrayStore *self = GTK_ARRAY_STORE (list);
|
||||
|
||||
return self->item_type;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_array_store_get_n_items (GListModel *list)
|
||||
{
|
||||
GtkArrayStore *self = GTK_ARRAY_STORE (list);
|
||||
|
||||
return gtk_vector_get_size (&self->items);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
gtk_array_store_get_item (GListModel *list,
|
||||
guint position)
|
||||
{
|
||||
GtkArrayStore *self = GTK_ARRAY_STORE (list);
|
||||
|
||||
if (position >= gtk_vector_get_size (&self->items))
|
||||
return NULL;
|
||||
|
||||
return g_object_ref (gtk_vector_get (&self->items, position));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_array_store_iface_init (GListModelInterface *iface)
|
||||
{
|
||||
iface->get_item_type = gtk_array_store_get_item_type;
|
||||
iface->get_n_items = gtk_array_store_get_n_items;
|
||||
iface->get_item = gtk_array_store_get_item;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_array_store_init (GtkArrayStore *self)
|
||||
{
|
||||
gtk_vector_init (&self->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_array_store_new:
|
||||
* @item_type: the #GType of items in the list
|
||||
*
|
||||
* Creates a new #GtkArrayStore with items of type @item_type. @item_type
|
||||
* must be a subclass of #GObject.
|
||||
*
|
||||
* Returns: a new #GtkArrayStore
|
||||
*/
|
||||
GtkArrayStore *
|
||||
gtk_array_store_new (GType item_type)
|
||||
{
|
||||
g_return_val_if_fail (g_type_is_a (item_type, G_TYPE_OBJECT), NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_ARRAY_STORE,
|
||||
"item-type", item_type,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_array_store_append:
|
||||
* @self: a #GtkArrayStore
|
||||
* @item: (type GObject): the new item
|
||||
*
|
||||
* Appends @item to @self. @item must be of type #GtkArrayStore:item-type.
|
||||
*
|
||||
* This function takes a ref on @item.
|
||||
*
|
||||
* Use gtk_array_store_splice() to append multiple items at the same time
|
||||
* efficiently.
|
||||
*/
|
||||
void
|
||||
gtk_array_store_append (GtkArrayStore *self,
|
||||
gpointer item)
|
||||
{
|
||||
guint position;
|
||||
|
||||
g_return_if_fail (GTK_IS_ARRAY_STORE (self));
|
||||
g_return_if_fail (g_type_is_a (G_OBJECT_TYPE (item), self->item_type));
|
||||
|
||||
position = gtk_vector_get_size (&self->items);
|
||||
gtk_vector_append (&self->items, g_object_ref (item));
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), position, 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_array_store_remove_all:
|
||||
* @self: a #GtkArrayStore
|
||||
*
|
||||
* Removes all items from @self.
|
||||
*
|
||||
* Since: 2.44
|
||||
*/
|
||||
void
|
||||
gtk_array_store_remove_all (GtkArrayStore *self)
|
||||
{
|
||||
guint n_items;
|
||||
|
||||
g_return_if_fail (GTK_IS_ARRAY_STORE (self));
|
||||
|
||||
n_items = gtk_vector_get_size (&self->items);
|
||||
gtk_vector_clear (&self->items);
|
||||
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), 0, n_items, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_array_store_splice:
|
||||
* @self: a #GtkArrayStore
|
||||
* @position: the position at which to make the change
|
||||
* @n_removals: the number of items to remove
|
||||
* @additions: (array length=n_additions) (element-type GObject): the items to add
|
||||
* @n_additions: the number of items to add
|
||||
*
|
||||
* Changes @self by removing @n_removals items and adding @n_additions
|
||||
* items to it. @additions must contain @n_additions items of type
|
||||
* #GtkArrayStore:item-type. %NULL is not permitted.
|
||||
*
|
||||
* This function is more efficient than gtk_array_store_insert() and
|
||||
* gtk_array_store_remove(), because it only emits
|
||||
* #GListModel::items-changed once for the change.
|
||||
*
|
||||
* This function takes a ref on each item in @additions.
|
||||
*
|
||||
* The parameters @position and @n_removals must be correct (ie:
|
||||
* @position + @n_removals must be less than or equal to the length of
|
||||
* the list at the time this function is called).
|
||||
*
|
||||
* Since: 2.44
|
||||
*/
|
||||
void
|
||||
gtk_array_store_splice (GtkArrayStore *self,
|
||||
guint position,
|
||||
guint n_removals,
|
||||
gpointer *additions,
|
||||
guint n_additions)
|
||||
{
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (GTK_IS_ARRAY_STORE (self));
|
||||
g_return_if_fail (position + n_removals >= position); /* overflow */
|
||||
g_return_if_fail (position + n_removals <= gtk_vector_get_size (&self->items));
|
||||
|
||||
for (i = 0; i < n_additions; i++)
|
||||
g_object_ref (additions[i]);
|
||||
|
||||
gtk_vector_splice (&self->items, position, n_removals, (GObject **) additions, n_additions);
|
||||
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), position, n_removals, n_additions);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_ARRAY_STORE_H__
|
||||
#define __GTK_ARRAY_STORE_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_ARRAY_STORE (gtk_array_store_get_type ())
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE(GtkArrayStore, gtk_array_store, GTK, ARRAY_STORE, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkArrayStore * gtk_array_store_new (GType item_type);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_array_store_append (GtkArrayStore *store,
|
||||
gpointer item);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_array_store_remove_all (GtkArrayStore *store);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_array_store_splice (GtkArrayStore *store,
|
||||
guint position,
|
||||
guint n_removals,
|
||||
gpointer *additions,
|
||||
guint n_additions);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_ARRAY_STORE_H__ */
|
||||
+23
-1
@@ -268,7 +268,7 @@ gtk_bitset_get_nth (const GtkBitset *self,
|
||||
*
|
||||
* Creates a new empty bitset.
|
||||
*
|
||||
* Returns: A new empty bitset.
|
||||
* Returns: A new empty bitset
|
||||
**/
|
||||
GtkBitset *
|
||||
gtk_bitset_new_empty (void)
|
||||
@@ -284,6 +284,28 @@ gtk_bitset_new_empty (void)
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_bitset_new_range:
|
||||
* @start: first value to add
|
||||
* @n_items: number of consecutive values to add
|
||||
*
|
||||
* Creates a bitset with the given range set.
|
||||
*
|
||||
* Returns: A new bitset
|
||||
**/
|
||||
GtkBitset *
|
||||
gtk_bitset_new_range (guint start,
|
||||
guint n_items)
|
||||
{
|
||||
GtkBitset *self;
|
||||
|
||||
self = gtk_bitset_new_empty ();
|
||||
|
||||
gtk_bitset_add_range (self, start, n_items);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_bitset_copy:
|
||||
* @self: a #GtkBitset
|
||||
|
||||
@@ -65,6 +65,9 @@ GDK_AVAILABLE_IN_ALL
|
||||
GtkBitset * gtk_bitset_new_empty (void);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkBitset * gtk_bitset_copy (const GtkBitset *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkBitset * gtk_bitset_new_range (guint start,
|
||||
guint n_items);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_bitset_remove_all (GtkBitset *self);
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
/**
|
||||
* SECTION:gtkbuilderlistitemfactory
|
||||
* @Title: GtkBuilderListItemFactory
|
||||
* @Tiitle: GtkBuilderListItemFactory
|
||||
* @Short_description: A listitem factory using ui files
|
||||
*
|
||||
* #GtkBuilderListItemFactory is a #GtkListItemFactory that creates
|
||||
|
||||
+2
-2
@@ -940,7 +940,7 @@ header_drag_end (GtkGestureDrag *gesture,
|
||||
|
||||
column = g_list_model_get_item (G_LIST_MODEL (self->columns), self->drag_pos);
|
||||
header = gtk_column_view_column_get_header (column);
|
||||
gtk_widget_remove_css_class (header, "dnd");
|
||||
gtk_style_context_remove_class (gtk_widget_get_style_context (header), "dnd");
|
||||
|
||||
sequence = gtk_gesture_single_get_current_sequence (GTK_GESTURE_SINGLE (gesture));
|
||||
if (!gtk_gesture_handles_sequence (GTK_GESTURE (gesture), sequence))
|
||||
@@ -1027,7 +1027,7 @@ header_drag_update (GtkGestureDrag *gesture,
|
||||
header = gtk_column_view_column_get_header (column);
|
||||
|
||||
gtk_widget_insert_after (header, self->header, gtk_widget_get_last_child (self->header));
|
||||
gtk_widget_add_css_class (header, "dnd");
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (header), "dnd");
|
||||
|
||||
gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED);
|
||||
if (!gtk_widget_has_focus (GTK_WIDGET (self)))
|
||||
|
||||
+13
-15
@@ -391,9 +391,9 @@ gtk_css_provider_init (GtkCssProvider *css_provider)
|
||||
}
|
||||
|
||||
static void
|
||||
verify_tree_match_results (GtkCssProvider *provider,
|
||||
GtkCssNode *node,
|
||||
GtkArray *tree_rules)
|
||||
verify_tree_match_results (GtkCssProvider *provider,
|
||||
GtkCssNode *node,
|
||||
GtkCssSelectorMatches *tree_rules)
|
||||
{
|
||||
#ifdef VERIFY_TREE
|
||||
GtkCssProviderPrivate *priv = gtk_css_provider_get_instance_private (provider);
|
||||
@@ -407,9 +407,9 @@ verify_tree_match_results (GtkCssProvider *provider,
|
||||
|
||||
ruleset = &g_array_index (priv->rulesets, GtkCssRuleset, i);
|
||||
|
||||
for (j = 0; j < tree_rules->len; j++)
|
||||
for (j = 0; j < gtk_css_selector_matches_get_size (tree_rules); j++)
|
||||
{
|
||||
if (ruleset == gtk_array_index (tree_rules, j))
|
||||
if (ruleset == gtk_css_selector_matches_get (tree_rules, j))
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
@@ -459,22 +459,21 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider,
|
||||
GtkCssRuleset *ruleset;
|
||||
guint j;
|
||||
int i;
|
||||
GtkArray tree_rules_array;
|
||||
GtkCssRuleset *rules_stack[32];
|
||||
GtkCssSelectorMatches tree_rules;
|
||||
|
||||
if (_gtk_css_selector_tree_is_empty (priv->tree))
|
||||
return;
|
||||
|
||||
gtk_array_init (&tree_rules_array, (void**)rules_stack, 32);
|
||||
_gtk_css_selector_tree_match_all (priv->tree, filter, node, &tree_rules_array);
|
||||
gtk_css_selector_matches_init (&tree_rules);
|
||||
_gtk_css_selector_tree_match_all (priv->tree, filter, node, &tree_rules);
|
||||
|
||||
if (tree_rules_array.len > 0)
|
||||
if (!gtk_css_selector_matches_is_empty (&tree_rules))
|
||||
{
|
||||
verify_tree_match_results (css_provider, node, &tree_rules_array);
|
||||
verify_tree_match_results (css_provider, node, &tree_rules);
|
||||
|
||||
for (i = tree_rules_array.len - 1; i >= 0; i--)
|
||||
for (i = gtk_css_selector_matches_get_size (&tree_rules) - 1; i >= 0; i--)
|
||||
{
|
||||
ruleset = gtk_array_index (&tree_rules_array, i);
|
||||
ruleset = gtk_css_selector_matches_get (&tree_rules, i);
|
||||
|
||||
if (ruleset->styles == NULL)
|
||||
continue;
|
||||
@@ -493,9 +492,8 @@ gtk_css_style_provider_lookup (GtkStyleProvider *provider,
|
||||
ruleset->styles[j].value);
|
||||
}
|
||||
}
|
||||
|
||||
gtk_array_free (&tree_rules_array, NULL);
|
||||
}
|
||||
gtk_css_selector_matches_clear (&tree_rules);
|
||||
|
||||
if (change)
|
||||
*change = gtk_css_selector_tree_get_change_all (priv->tree, filter, node);
|
||||
|
||||
+17
-20
@@ -24,7 +24,6 @@
|
||||
|
||||
#include "gtkcssprovider.h"
|
||||
#include "gtkstylecontextprivate.h"
|
||||
#include "gtkarrayimplprivate.h"
|
||||
|
||||
#include <errno.h>
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1500
|
||||
@@ -152,14 +151,14 @@ gtk_css_selector_tree_get_matches (const GtkCssSelectorTree *tree)
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_array_insert_sorted (GtkArray *array,
|
||||
gpointer data)
|
||||
gtk_css_selector_matches_insert_sorted (GtkCssSelectorMatches *matches,
|
||||
gpointer data)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < array->len; i++)
|
||||
for (i = 0; i < gtk_css_selector_matches_get_size (matches); i++)
|
||||
{
|
||||
gpointer elem = gtk_array_index (array, i);
|
||||
gpointer elem = gtk_css_selector_matches_get (matches, i);
|
||||
|
||||
if (data == elem)
|
||||
return;
|
||||
@@ -168,7 +167,7 @@ gtk_array_insert_sorted (GtkArray *array,
|
||||
break;
|
||||
}
|
||||
|
||||
gtk_array_insert (array, i, data);
|
||||
gtk_css_selector_matches_splice (matches, i, 0, (gpointer[1]) { data }, 1);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
@@ -1877,7 +1876,7 @@ gtk_css_selector_tree_get_change (const GtkCssSelectorTree *tree,
|
||||
|
||||
static void
|
||||
gtk_css_selector_tree_found_match (const GtkCssSelectorTree *tree,
|
||||
GtkArray *results)
|
||||
GtkCssSelectorMatches *results)
|
||||
{
|
||||
int i;
|
||||
gpointer *matches;
|
||||
@@ -1887,7 +1886,7 @@ gtk_css_selector_tree_found_match (const GtkCssSelectorTree *tree,
|
||||
return;
|
||||
|
||||
for (i = 0; matches[i] != NULL; i++)
|
||||
gtk_array_insert_sorted (results, matches[i]);
|
||||
gtk_css_selector_matches_insert_sorted (results, matches[i]);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1895,7 +1894,7 @@ gtk_css_selector_tree_match (const GtkCssSelectorTree *tree,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
gboolean match_filter,
|
||||
GtkCssNode *node,
|
||||
GtkArray *results)
|
||||
GtkCssSelectorMatches *results)
|
||||
{
|
||||
const GtkCssSelectorTree *prev;
|
||||
GtkCssNode *child;
|
||||
@@ -1932,7 +1931,7 @@ void
|
||||
_gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node,
|
||||
GtkArray *out_tree_rules)
|
||||
GtkCssSelectorMatches *out_tree_rules)
|
||||
{
|
||||
const GtkCssSelectorTree *iter;
|
||||
|
||||
@@ -2117,8 +2116,7 @@ subdivide_infos (GByteArray *array,
|
||||
GHashTableIter iter;
|
||||
guint max_count;
|
||||
gpointer key, value;
|
||||
void *exact_matches_stack[8];
|
||||
GtkArray exact_matches_array;
|
||||
GtkCssSelectorMatches exact_matches;
|
||||
gint32 res;
|
||||
guint i;
|
||||
|
||||
@@ -2160,7 +2158,7 @@ subdivide_infos (GByteArray *array,
|
||||
matched_infos = g_alloca (sizeof (GtkCssSelectorRuleSetInfo *) * n_infos);
|
||||
remaining_infos = g_alloca (sizeof (GtkCssSelectorRuleSetInfo *) * n_infos);
|
||||
|
||||
gtk_array_init (&exact_matches_array, (void**)exact_matches_stack, 8);
|
||||
gtk_css_selector_matches_init (&exact_matches);
|
||||
for (i = 0; i < n_infos; i++)
|
||||
{
|
||||
GtkCssSelectorRuleSetInfo *info = infos[i];
|
||||
@@ -2171,7 +2169,7 @@ subdivide_infos (GByteArray *array,
|
||||
if (info->current_selector == NULL)
|
||||
{
|
||||
/* Matches current node */
|
||||
gtk_array_add (&exact_matches_array, info->match);
|
||||
gtk_css_selector_matches_append (&exact_matches, info->match);
|
||||
if (info->selector_match != NULL)
|
||||
*info->selector_match = GUINT_TO_POINTER (tree_offset);
|
||||
}
|
||||
@@ -2188,17 +2186,16 @@ subdivide_infos (GByteArray *array,
|
||||
}
|
||||
}
|
||||
|
||||
if (exact_matches_array.len > 0)
|
||||
if (!gtk_css_selector_matches_is_empty (&exact_matches))
|
||||
{
|
||||
gtk_array_add (&exact_matches_array, NULL); /* Null terminate */
|
||||
gtk_css_selector_matches_append (&exact_matches, NULL); /* Null terminate */
|
||||
res = array->len;
|
||||
g_byte_array_append (array, (guint8 *)gtk_array_get_data (&exact_matches_array),
|
||||
exact_matches_array.len * sizeof (gpointer));
|
||||
|
||||
gtk_array_free (&exact_matches_array, NULL);
|
||||
g_byte_array_append (array, (guint8 *) gtk_css_selector_matches_get_data (&exact_matches),
|
||||
gtk_css_selector_matches_get_size (&exact_matches) * sizeof (gpointer));
|
||||
}
|
||||
else
|
||||
res = GTK_CSS_SELECTOR_TREE_EMPTY_OFFSET;
|
||||
gtk_css_selector_matches_clear (&exact_matches);
|
||||
get_tree (array, tree_offset)->matches_offset = res;
|
||||
|
||||
res = subdivide_infos (array, matched_infos, n_matched, tree_offset);
|
||||
|
||||
@@ -21,7 +21,12 @@
|
||||
#include "gtk/gtkcountingbloomfilterprivate.h"
|
||||
#include "gtk/gtkcsstypesprivate.h"
|
||||
#include "gtk/gtkcssparserprivate.h"
|
||||
#include "gtk/gtkarrayimplprivate.h"
|
||||
|
||||
#define GTK_VECTOR_ELEMENT_TYPE gpointer
|
||||
#define GTK_VECTOR_TYPE_NAME GtkCssSelectorMatches
|
||||
#define GTK_VECTOR_NAME gtk_css_selector_matches
|
||||
#define GTK_VECTOR_PREALLOC 32
|
||||
#include "gtk/gtkvectorimpl.c"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -45,8 +50,8 @@ int _gtk_css_selector_compare (const GtkCssSelector *a,
|
||||
void _gtk_css_selector_tree_free (GtkCssSelectorTree *tree);
|
||||
void _gtk_css_selector_tree_match_all (const GtkCssSelectorTree *tree,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node,
|
||||
GtkArray *out_tree_rules);
|
||||
GtkCssNode *node,
|
||||
GtkCssSelectorMatches *out_tree_rules);
|
||||
GtkCssChange gtk_css_selector_tree_get_change_all (const GtkCssSelectorTree *tree,
|
||||
const GtkCountingBloomFilter *filter,
|
||||
GtkCssNode *node);
|
||||
|
||||
+1
-1
@@ -943,7 +943,7 @@ gtk_drop_down_set_from_strings (GtkDropDown *self,
|
||||
|
||||
set_default_factory (self);
|
||||
|
||||
model = G_LIST_MODEL (gtk_string_list_new ((const char **)texts));
|
||||
model = G_LIST_MODEL (gtk_string_list_new (texts));
|
||||
gtk_drop_down_set_model (self, model);
|
||||
g_object_unref (model);
|
||||
}
|
||||
|
||||
+11
-44
@@ -1,4 +1,3 @@
|
||||
|
||||
/*
|
||||
* Copyright © 2019 Benjamin Otte
|
||||
*
|
||||
@@ -29,50 +28,18 @@
|
||||
* @Short_description: Expressions to values
|
||||
* @Title: GtkExpression
|
||||
*
|
||||
* GtkExpression provides a way to describe references to values.
|
||||
* GtkExpression provides a way to describe references to #GValues.
|
||||
*
|
||||
* An important aspect of expressions is that the value can be obtained
|
||||
* from a source that is several steps away. For example, an expression
|
||||
* may describe ‘the value of property A of @object1, which is itself the
|
||||
* value of a property of @object2’. And @object1 may not even exist yet
|
||||
* at the time that the expression is created. This is contrast to GObject
|
||||
* property bindings, which can only create direct connections between
|
||||
* the properties of two objects that must both exist for the duration
|
||||
* of the binding.
|
||||
*
|
||||
* An expression needs to be "evaluated" to obtain the value that it currently
|
||||
* refers to. An evaluation always happens in the context of a current object
|
||||
* called `this` (it mirrors the behavior of object-oriented languages),
|
||||
* which may or may not influence the result of the evaluation. Use
|
||||
* gtk_expression_evaluate() for evaluating an expression.
|
||||
* An expression needs to be "evaluated" to obtain the value that it currently refers
|
||||
* to. An evaluation always happens in the context of a current object called `this`
|
||||
* (it mirrors the behavior of object-oriented languages), which may or may not
|
||||
* influence the result of the evaluation. Use gtk_expression_evaluate() for
|
||||
* evaluating an expression.
|
||||
*
|
||||
* Various methods for defining expressions exist, from simple constants via
|
||||
* gtk_constant_expression_new() to looking up properties in a #GObject (even
|
||||
* recursively) via gtk_property_expression_new() or providing custom functions
|
||||
* to transform and combine expressions via gtk_closure_expression_new().
|
||||
*
|
||||
* Here is an example of a complex expression:
|
||||
* |[
|
||||
* color_expr = gtk_property_expression_new (GTK_TYPE_LIST_ITEM,
|
||||
* NULL, "item");
|
||||
* expression = gtk_property_expression_new (GTK_TYPE_COLOR,
|
||||
* color_expr,
|
||||
* "name");
|
||||
* ]|
|
||||
* when evaluated with `this` being a GtkListItem, it will obtain the
|
||||
* "item" property from the GtkListItem, and then obtain the "name" property
|
||||
* from the resulting object (which is assumed to be of type GTK_TYPE_COLOR).
|
||||
*
|
||||
* A more concise way to describe this would be
|
||||
* |[
|
||||
* this->item->name
|
||||
* ]|
|
||||
*
|
||||
* The most likely place where you will encounter expressions is in the context
|
||||
* of list models and list widgets using them. For example, #GtkDropDown is
|
||||
* evaluating a GtkExpression to obtain strings from the items in its model
|
||||
* that it can then use to match against the contents of its search entry.
|
||||
* #GtkStringFilter is using a GtkExpression for a similar reason.
|
||||
* recursively) via gtk_property_expression_new() or providing custom functions to
|
||||
* transform and combine expressions via gtk_closure_expression_new().
|
||||
*
|
||||
* By default, expressions are not paying attention to changes and evaluation is
|
||||
* just a snapshot of the current state at a given time. To get informed about
|
||||
@@ -1570,12 +1537,12 @@ GTK_DEFINE_EXPRESSION_TYPE (GtkCClosureExpression,
|
||||
/**
|
||||
* gtk_cclosure_expression_new:
|
||||
* @value_type: the type of the value that this expression evaluates to
|
||||
* @marshal: (scope call) (nullable): marshaller used for creating a closure
|
||||
* @marshal: (scope call): marshaller used for creating a closure
|
||||
* @n_params: the number of params needed for evaluating @closure
|
||||
* @params: (array length=n_params) (transfer full): expressions for each parameter
|
||||
* @callback_func: (scope notified) (closure user_data) (destroy user_destroy): callback used for creating a closure
|
||||
* @user_data: (nullable): user data used for creating a closure
|
||||
* @user_destroy: (nullable): destroy notify for @user_data
|
||||
* @user_data: user data used for creating a closure
|
||||
* @user_destroy: destroy notify for @user_data
|
||||
*
|
||||
* This function is a variant of gtk_closure_expression_new() that
|
||||
* creates a #GClosure by calling gtk_cclosure_new() with the given
|
||||
|
||||
+4
-92
@@ -73,7 +73,6 @@
|
||||
#include "gtkbuilderprivate.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkfilter.h"
|
||||
|
||||
typedef struct _GtkFileFilterClass GtkFileFilterClass;
|
||||
typedef struct _FilterRule FilterRule;
|
||||
@@ -91,12 +90,12 @@ typedef enum {
|
||||
|
||||
struct _GtkFileFilterClass
|
||||
{
|
||||
GtkFilterClass parent_class;
|
||||
GInitiallyUnownedClass parent_class;
|
||||
};
|
||||
|
||||
struct _GtkFileFilter
|
||||
{
|
||||
GtkFilter parent_instance;
|
||||
GInitiallyUnowned parent_instance;
|
||||
|
||||
gchar *name;
|
||||
GSList *rules;
|
||||
@@ -108,7 +107,7 @@ struct _FilterRule
|
||||
{
|
||||
FilterRuleType type;
|
||||
GtkFileFilterFlags needed;
|
||||
|
||||
|
||||
union {
|
||||
gchar *pattern;
|
||||
gchar *mime_type;
|
||||
@@ -157,12 +156,7 @@ static void gtk_file_filter_buildable_custom_tag_end (GtkBuildable
|
||||
const gchar *tagname,
|
||||
gpointer data);
|
||||
|
||||
static gboolean gtk_file_filter_match (GtkFilter *filter,
|
||||
gpointer item);
|
||||
static GtkFilterMatch gtk_file_filter_get_strictness (GtkFilter *filter);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkFileFilter, gtk_file_filter, G_TYPE_OBJECT,
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkFileFilter, gtk_file_filter, G_TYPE_INITIALLY_UNOWNED,
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
|
||||
gtk_file_filter_buildable_init))
|
||||
|
||||
@@ -175,15 +169,11 @@ static void
|
||||
gtk_file_filter_class_init (GtkFileFilterClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
GtkFilterClass *filter_class = GTK_FILTER_CLASS (class);
|
||||
|
||||
gobject_class->set_property = gtk_file_filter_set_property;
|
||||
gobject_class->get_property = gtk_file_filter_get_property;
|
||||
gobject_class->finalize = gtk_file_filter_finalize;
|
||||
|
||||
filter_class->match = gtk_file_filter_match;
|
||||
filter_class->get_strictness = gtk_file_filter_get_strictness;
|
||||
|
||||
/**
|
||||
* GtkFileFilter:name:
|
||||
*
|
||||
@@ -446,84 +436,6 @@ gtk_file_filter_buildable_custom_tag_end (GtkBuildable *buildable,
|
||||
}
|
||||
}
|
||||
|
||||
/* GtkFilter implementation */
|
||||
|
||||
static gboolean
|
||||
gtk_file_filter_match (GtkFilter *filter,
|
||||
gpointer item)
|
||||
{
|
||||
GtkFileFilter *file_filter = GTK_FILE_FILTER (filter);
|
||||
GFileInfo *info;
|
||||
GFile *file;
|
||||
GtkFileFilterInfo filter_info = { 0, };
|
||||
GtkFileFilterFlags required;
|
||||
gboolean result;
|
||||
char *mime_type = NULL;
|
||||
char *filename = NULL;
|
||||
char *uri = NULL;
|
||||
|
||||
if (!G_IS_FILE_INFO (item))
|
||||
return TRUE;
|
||||
|
||||
info = G_FILE_INFO (item);
|
||||
file = G_FILE (g_file_info_get_attribute_object (info, "standard::file"));
|
||||
|
||||
required = file_filter->needed;
|
||||
|
||||
filter_info.contains = GTK_FILE_FILTER_DISPLAY_NAME;
|
||||
filter_info.display_name = g_file_info_get_display_name (info);
|
||||
|
||||
if (required & GTK_FILE_FILTER_MIME_TYPE)
|
||||
{
|
||||
const char *s = g_file_info_get_content_type (info);
|
||||
if (!s)
|
||||
s = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
|
||||
|
||||
if (s)
|
||||
{
|
||||
mime_type = g_content_type_get_mime_type (s);
|
||||
if (mime_type)
|
||||
{
|
||||
filter_info.mime_type = mime_type;
|
||||
filter_info.contains |= GTK_FILE_FILTER_MIME_TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (required & GTK_FILE_FILTER_FILENAME)
|
||||
{
|
||||
filename = g_file_get_path (file);
|
||||
if (filename)
|
||||
{
|
||||
filter_info.filename = filename;
|
||||
filter_info.contains |= GTK_FILE_FILTER_FILENAME;
|
||||
}
|
||||
}
|
||||
|
||||
if (required & GTK_FILE_FILTER_URI)
|
||||
{
|
||||
uri = g_file_get_uri (file);
|
||||
if (uri)
|
||||
{
|
||||
filter_info.uri = uri;
|
||||
filter_info.contains |= GTK_FILE_FILTER_URI;
|
||||
}
|
||||
}
|
||||
|
||||
result = gtk_file_filter_filter (file_filter, &filter_info);
|
||||
|
||||
g_free (mime_type);
|
||||
g_free (filename);
|
||||
g_free (uri);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static GtkFilterMatch
|
||||
gtk_file_filter_get_strictness (GtkFilter *filter)
|
||||
{
|
||||
return GTK_FILTER_MATCH_SOME;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_file_filter_new:
|
||||
|
||||
+331
-355
@@ -21,7 +21,7 @@
|
||||
|
||||
#include "gtkfilterlistmodel.h"
|
||||
|
||||
#include "gtkrbtreeprivate.h"
|
||||
#include "gtkbitset.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
@@ -35,30 +35,22 @@
|
||||
* listmodel.
|
||||
* It hides some elements from the other model according to
|
||||
* criteria given by a #GtkFilter.
|
||||
*
|
||||
* The model can be set up to do incremental searching, so that
|
||||
* filtering long lists doesn't block the UI. See
|
||||
* gtk_filter_list_model_set_incremental() for details.
|
||||
*/
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_FILTER,
|
||||
PROP_INCREMENTAL,
|
||||
PROP_ITEM_TYPE,
|
||||
PROP_MODEL,
|
||||
PROP_PENDING,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
typedef struct _FilterNode FilterNode;
|
||||
typedef struct _FilterAugment FilterAugment;
|
||||
|
||||
struct _FilterNode
|
||||
{
|
||||
guint visible : 1;
|
||||
};
|
||||
|
||||
struct _FilterAugment
|
||||
{
|
||||
guint n_items;
|
||||
guint n_visible;
|
||||
};
|
||||
|
||||
struct _GtkFilterListModel
|
||||
{
|
||||
GObject parent_instance;
|
||||
@@ -67,8 +59,11 @@ struct _GtkFilterListModel
|
||||
GListModel *model;
|
||||
GtkFilter *filter;
|
||||
GtkFilterMatch strictness;
|
||||
gboolean incremental;
|
||||
|
||||
GtkRbTree *items; /* NULL if strictness != GTK_FILTER_MATCH_SOME */
|
||||
GtkBitset *matches; /* NULL if strictness != GTK_FILTER_MATCH_SOME */
|
||||
GtkBitset *pending; /* not yet filtered items or NULL if all filtered */
|
||||
guint pending_cb; /* idle callback handle */
|
||||
};
|
||||
|
||||
struct _GtkFilterListModelClass
|
||||
@@ -78,119 +73,6 @@ struct _GtkFilterListModelClass
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
|
||||
|
||||
static void
|
||||
gtk_filter_list_model_augment (GtkRbTree *filter,
|
||||
gpointer _aug,
|
||||
gpointer _node,
|
||||
gpointer left,
|
||||
gpointer right)
|
||||
{
|
||||
FilterNode *node = _node;
|
||||
FilterAugment *aug = _aug;
|
||||
|
||||
aug->n_items = 1;
|
||||
aug->n_visible = node->visible ? 1 : 0;
|
||||
|
||||
if (left)
|
||||
{
|
||||
FilterAugment *left_aug = gtk_rb_tree_get_augment (filter, left);
|
||||
aug->n_items += left_aug->n_items;
|
||||
aug->n_visible += left_aug->n_visible;
|
||||
}
|
||||
if (right)
|
||||
{
|
||||
FilterAugment *right_aug = gtk_rb_tree_get_augment (filter, right);
|
||||
aug->n_items += right_aug->n_items;
|
||||
aug->n_visible += right_aug->n_visible;
|
||||
}
|
||||
}
|
||||
|
||||
static FilterNode *
|
||||
gtk_filter_list_model_get_nth_filtered (GtkRbTree *tree,
|
||||
guint position,
|
||||
guint *out_unfiltered)
|
||||
{
|
||||
FilterNode *node, *tmp;
|
||||
guint unfiltered;
|
||||
|
||||
node = gtk_rb_tree_get_root (tree);
|
||||
unfiltered = 0;
|
||||
|
||||
while (node)
|
||||
{
|
||||
tmp = gtk_rb_tree_node_get_left (node);
|
||||
if (tmp)
|
||||
{
|
||||
FilterAugment *aug = gtk_rb_tree_get_augment (tree, tmp);
|
||||
if (position < aug->n_visible)
|
||||
{
|
||||
node = tmp;
|
||||
continue;
|
||||
}
|
||||
position -= aug->n_visible;
|
||||
unfiltered += aug->n_items;
|
||||
}
|
||||
|
||||
if (node->visible)
|
||||
{
|
||||
if (position == 0)
|
||||
break;
|
||||
position--;
|
||||
}
|
||||
|
||||
unfiltered++;
|
||||
|
||||
node = gtk_rb_tree_node_get_right (node);
|
||||
}
|
||||
|
||||
if (out_unfiltered)
|
||||
*out_unfiltered = unfiltered;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static FilterNode *
|
||||
gtk_filter_list_model_get_nth (GtkRbTree *tree,
|
||||
guint position,
|
||||
guint *out_filtered)
|
||||
{
|
||||
FilterNode *node, *tmp;
|
||||
guint filtered;
|
||||
|
||||
node = gtk_rb_tree_get_root (tree);
|
||||
filtered = 0;
|
||||
|
||||
while (node)
|
||||
{
|
||||
tmp = gtk_rb_tree_node_get_left (node);
|
||||
if (tmp)
|
||||
{
|
||||
FilterAugment *aug = gtk_rb_tree_get_augment (tree, tmp);
|
||||
if (position < aug->n_items)
|
||||
{
|
||||
node = tmp;
|
||||
continue;
|
||||
}
|
||||
position -= aug->n_items;
|
||||
filtered += aug->n_visible;
|
||||
}
|
||||
|
||||
if (position == 0)
|
||||
break;
|
||||
|
||||
position--;
|
||||
if (node->visible)
|
||||
filtered++;
|
||||
|
||||
node = gtk_rb_tree_node_get_right (node);
|
||||
}
|
||||
|
||||
if (out_filtered)
|
||||
*out_filtered = filtered;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static GType
|
||||
gtk_filter_list_model_get_item_type (GListModel *list)
|
||||
{
|
||||
@@ -203,8 +85,6 @@ static guint
|
||||
gtk_filter_list_model_get_n_items (GListModel *list)
|
||||
{
|
||||
GtkFilterListModel *self = GTK_FILTER_LIST_MODEL (list);
|
||||
FilterAugment *aug;
|
||||
FilterNode *node;
|
||||
|
||||
switch (self->strictness)
|
||||
{
|
||||
@@ -215,18 +95,12 @@ gtk_filter_list_model_get_n_items (GListModel *list)
|
||||
return g_list_model_get_n_items (self->model);
|
||||
|
||||
case GTK_FILTER_MATCH_SOME:
|
||||
break;
|
||||
return gtk_bitset_get_size (self->matches);
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = gtk_rb_tree_get_root (self->items);
|
||||
if (node == NULL)
|
||||
return 0;
|
||||
|
||||
aug = gtk_rb_tree_get_augment (self->items, node);
|
||||
return aug->n_visible;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
@@ -246,7 +120,9 @@ gtk_filter_list_model_get_item (GListModel *list,
|
||||
break;
|
||||
|
||||
case GTK_FILTER_MATCH_SOME:
|
||||
gtk_filter_list_model_get_nth_filtered (self->items, position, &unfiltered);
|
||||
unfiltered = gtk_bitset_get_nth (self->matches, position);
|
||||
if (unfiltered == 0 && position >= gtk_bitset_get_size (self->matches))
|
||||
return NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -268,8 +144,8 @@ G_DEFINE_TYPE_WITH_CODE (GtkFilterListModel, gtk_filter_list_model, G_TYPE_OBJEC
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_filter_list_model_model_init))
|
||||
|
||||
static gboolean
|
||||
gtk_filter_list_model_run_filter (GtkFilterListModel *self,
|
||||
guint position)
|
||||
gtk_filter_list_model_run_filter_on_item (GtkFilterListModel *self,
|
||||
guint position)
|
||||
{
|
||||
gpointer item;
|
||||
gboolean visible;
|
||||
@@ -284,26 +160,120 @@ gtk_filter_list_model_run_filter (GtkFilterListModel *self,
|
||||
return visible;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_filter_list_model_add_items (GtkFilterListModel *self,
|
||||
FilterNode *after,
|
||||
guint position,
|
||||
guint n_items)
|
||||
static void
|
||||
gtk_filter_list_model_run_filter (GtkFilterListModel *self,
|
||||
guint n_steps)
|
||||
{
|
||||
FilterNode *node;
|
||||
guint i, n_visible;
|
||||
GtkBitsetIter iter;
|
||||
guint i, pos;
|
||||
gboolean more;
|
||||
|
||||
n_visible = 0;
|
||||
g_return_if_fail (GTK_IS_FILTER_LIST_MODEL (self));
|
||||
|
||||
for (i = 0; i < n_items; i++)
|
||||
if (self->pending == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0, more = gtk_bitset_iter_init_first (&iter, self->pending, &pos);
|
||||
i < n_steps && more;
|
||||
i++, more = gtk_bitset_iter_next (&iter, &pos))
|
||||
{
|
||||
node = gtk_rb_tree_insert_before (self->items, after);
|
||||
node->visible = gtk_filter_list_model_run_filter (self, position + i);
|
||||
if (node->visible)
|
||||
n_visible++;
|
||||
if (gtk_filter_list_model_run_filter_on_item (self, pos))
|
||||
gtk_bitset_add (self->matches, pos);
|
||||
}
|
||||
|
||||
return n_visible;
|
||||
if (more)
|
||||
gtk_bitset_remove_range_closed (self->pending, 0, pos);
|
||||
else
|
||||
g_clear_pointer (&self->pending, gtk_bitset_unref);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PENDING]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_filter_list_model_stop_filtering (GtkFilterListModel *self)
|
||||
{
|
||||
gboolean notify_pending = self->pending != NULL;
|
||||
|
||||
g_clear_pointer (&self->pending, gtk_bitset_unref);
|
||||
g_clear_handle_id (&self->pending_cb, g_source_remove);
|
||||
|
||||
if (notify_pending)
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PENDING]);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_filter_list_model_emit_items_changed_for_changes (GtkFilterListModel *self,
|
||||
GtkBitset *old)
|
||||
{
|
||||
GtkBitset *changes;
|
||||
|
||||
changes = gtk_bitset_copy (self->matches);
|
||||
gtk_bitset_difference (changes, old);
|
||||
if (!gtk_bitset_is_empty (changes))
|
||||
{
|
||||
guint min, max;
|
||||
|
||||
min = gtk_bitset_get_minimum (changes);
|
||||
max = gtk_bitset_get_maximum (changes);
|
||||
g_list_model_items_changed (G_LIST_MODEL (self),
|
||||
min > 0 ? gtk_bitset_get_size_in_range (self->matches, 0, min - 1) : 0,
|
||||
gtk_bitset_get_size_in_range (old, min, max),
|
||||
gtk_bitset_get_size_in_range (self->matches, min, max));
|
||||
}
|
||||
gtk_bitset_unref (changes);
|
||||
gtk_bitset_unref (old);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_filter_list_model_run_filter_cb (gpointer data)
|
||||
{
|
||||
GtkFilterListModel *self = data;
|
||||
GtkBitset *old;
|
||||
|
||||
old = gtk_bitset_copy (self->matches);
|
||||
gtk_filter_list_model_run_filter (self, 512);
|
||||
|
||||
if (self->pending == NULL)
|
||||
gtk_filter_list_model_stop_filtering (self);
|
||||
|
||||
gtk_filter_list_model_emit_items_changed_for_changes (self, old);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
/* NB: bitset is (transfer full) */
|
||||
static void
|
||||
gtk_filter_list_model_start_filtering (GtkFilterListModel *self,
|
||||
GtkBitset *items)
|
||||
{
|
||||
if (self->pending)
|
||||
{
|
||||
gtk_bitset_union (self->pending, items);
|
||||
gtk_bitset_unref (items);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PENDING]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gtk_bitset_is_empty (items))
|
||||
{
|
||||
gtk_bitset_unref (items);
|
||||
return;
|
||||
}
|
||||
|
||||
self->pending = items;
|
||||
|
||||
if (!self->incremental)
|
||||
{
|
||||
gtk_filter_list_model_run_filter (self, G_MAXUINT);
|
||||
g_assert (self->pending == NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PENDING]);
|
||||
g_assert (self->pending_cb == 0);
|
||||
self->pending_cb = g_idle_add (gtk_filter_list_model_run_filter_cb, self);
|
||||
g_source_set_name_by_id (self->pending_cb, "[gtk] gtk_filter_list_model_run_filter_cb");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -313,8 +283,7 @@ gtk_filter_list_model_items_changed_cb (GListModel *model,
|
||||
guint added,
|
||||
GtkFilterListModel *self)
|
||||
{
|
||||
FilterNode *node;
|
||||
guint i, filter_position, filter_removed, filter_added;
|
||||
guint filter_removed, filter_added;
|
||||
|
||||
switch (self->strictness)
|
||||
{
|
||||
@@ -332,22 +301,22 @@ gtk_filter_list_model_items_changed_cb (GListModel *model,
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
node = gtk_filter_list_model_get_nth (self->items, position, &filter_position);
|
||||
if (removed > 0)
|
||||
filter_removed = gtk_bitset_get_size_in_range (self->matches, position, position + removed - 1);
|
||||
else
|
||||
filter_removed = 0;
|
||||
|
||||
filter_removed = 0;
|
||||
for (i = 0; i < removed; i++)
|
||||
{
|
||||
FilterNode *next = gtk_rb_tree_node_get_next (node);
|
||||
if (node->visible)
|
||||
filter_removed++;
|
||||
gtk_rb_tree_remove (self->items, node);
|
||||
node = next;
|
||||
}
|
||||
gtk_bitset_slice (self->matches, position, removed, added);
|
||||
if (self->pending)
|
||||
gtk_bitset_slice (self->pending, position, removed, added);
|
||||
|
||||
filter_added = gtk_filter_list_model_add_items (self, node, position, added);
|
||||
gtk_filter_list_model_start_filtering (self, gtk_bitset_new_range (position, added));
|
||||
filter_added = gtk_bitset_get_size_in_range (self->matches, position, position + added - 1);
|
||||
|
||||
if (filter_removed > 0 || filter_added > 0)
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), filter_position, filter_removed, filter_added);
|
||||
g_list_model_items_changed (G_LIST_MODEL (self),
|
||||
gtk_bitset_get_size_in_range (self->matches, 0, position),
|
||||
filter_removed, filter_added);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -364,6 +333,10 @@ gtk_filter_list_model_set_property (GObject *object,
|
||||
gtk_filter_list_model_set_filter (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_INCREMENTAL:
|
||||
gtk_filter_list_model_set_incremental (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_ITEM_TYPE:
|
||||
self->item_type = g_value_get_gtype (value);
|
||||
break;
|
||||
@@ -392,6 +365,10 @@ gtk_filter_list_model_get_property (GObject *object,
|
||||
g_value_set_object (value, self->filter);
|
||||
break;
|
||||
|
||||
case PROP_INCREMENTAL:
|
||||
g_value_set_boolean (value, self->incremental);
|
||||
break;
|
||||
|
||||
case PROP_ITEM_TYPE:
|
||||
g_value_set_gtype (value, self->item_type);
|
||||
break;
|
||||
@@ -400,6 +377,10 @@ gtk_filter_list_model_get_property (GObject *object,
|
||||
g_value_set_object (value, self->model);
|
||||
break;
|
||||
|
||||
case PROP_PENDING:
|
||||
g_value_set_uint (value, gtk_filter_list_model_get_pending (self));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@@ -412,109 +393,16 @@ gtk_filter_list_model_clear_model (GtkFilterListModel *self)
|
||||
if (self->model == NULL)
|
||||
return;
|
||||
|
||||
gtk_filter_list_model_stop_filtering (self);
|
||||
g_signal_handlers_disconnect_by_func (self->model, gtk_filter_list_model_items_changed_cb, self);
|
||||
g_clear_object (&self->model);
|
||||
if (self->items)
|
||||
gtk_rb_tree_remove_all (self->items);
|
||||
}
|
||||
|
||||
/*<private>
|
||||
* gtk_filter_list_model_find_filtered:
|
||||
* @self: a #GtkFilterListModel
|
||||
* @start: (out) (caller-allocates): number of unfiltered items
|
||||
* at start of list
|
||||
* @end: (out) (caller-allocates): number of unfiltered items
|
||||
* at end of list
|
||||
* @n_items: (out) (caller-allocates): number of unfiltered items in
|
||||
* list
|
||||
*
|
||||
* Checks if elements in self->items are filtered out and returns
|
||||
* the range that they occupy.
|
||||
* This function is intended to be used for GListModel::items-changed
|
||||
* emissions, so it is called in an intermediate state for @self.
|
||||
*
|
||||
* Returns: %TRUE if elements are filtered out, %FALSE if none are
|
||||
**/
|
||||
static gboolean
|
||||
gtk_filter_list_model_find_filtered (GtkFilterListModel *self,
|
||||
guint *start,
|
||||
guint *end,
|
||||
guint *n_items)
|
||||
{
|
||||
FilterNode *root, *node, *tmp;
|
||||
FilterAugment *aug;
|
||||
|
||||
if (self->items == NULL || self->model == NULL)
|
||||
return FALSE;
|
||||
|
||||
root = gtk_rb_tree_get_root (self->items);
|
||||
if (root == NULL)
|
||||
return FALSE; /* empty parent model */
|
||||
|
||||
aug = gtk_rb_tree_get_augment (self->items, root);
|
||||
if (aug->n_items == aug->n_visible)
|
||||
return FALSE; /* all items visible */
|
||||
|
||||
/* find first filtered */
|
||||
*start = 0;
|
||||
*end = 0;
|
||||
*n_items = aug->n_visible;
|
||||
|
||||
node = root;
|
||||
while (node)
|
||||
{
|
||||
tmp = gtk_rb_tree_node_get_left (node);
|
||||
if (tmp)
|
||||
{
|
||||
aug = gtk_rb_tree_get_augment (self->items, tmp);
|
||||
if (aug->n_visible < aug->n_items)
|
||||
{
|
||||
node = tmp;
|
||||
continue;
|
||||
}
|
||||
*start += aug->n_items;
|
||||
}
|
||||
|
||||
if (!node->visible)
|
||||
break;
|
||||
|
||||
(*start)++;
|
||||
|
||||
node = gtk_rb_tree_node_get_right (node);
|
||||
}
|
||||
|
||||
/* find last filtered by doing everything the opposite way */
|
||||
node = root;
|
||||
while (node)
|
||||
{
|
||||
tmp = gtk_rb_tree_node_get_right (node);
|
||||
if (tmp)
|
||||
{
|
||||
aug = gtk_rb_tree_get_augment (self->items, tmp);
|
||||
if (aug->n_visible < aug->n_items)
|
||||
{
|
||||
node = tmp;
|
||||
continue;
|
||||
}
|
||||
*end += aug->n_items;
|
||||
}
|
||||
|
||||
if (!node->visible)
|
||||
break;
|
||||
|
||||
(*end)++;
|
||||
|
||||
node = gtk_rb_tree_node_get_left (node);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
if (self->matches)
|
||||
gtk_bitset_remove_all (self->matches);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_filter_list_model_refilter (GtkFilterListModel *self);
|
||||
|
||||
static void
|
||||
gtk_filter_list_model_update_strictness_and_refilter (GtkFilterListModel *self)
|
||||
gtk_filter_list_model_refilter (GtkFilterListModel *self,
|
||||
GtkFilterChange change)
|
||||
{
|
||||
GtkFilterMatch new_strictness;
|
||||
|
||||
@@ -532,8 +420,9 @@ gtk_filter_list_model_update_strictness_and_refilter (GtkFilterListModel *self)
|
||||
case GTK_FILTER_MATCH_NONE:
|
||||
{
|
||||
guint n_before = g_list_model_get_n_items (G_LIST_MODEL (self));
|
||||
g_clear_pointer (&self->items, gtk_rb_tree_unref);
|
||||
g_clear_pointer (&self->matches, gtk_bitset_unref);
|
||||
self->strictness = new_strictness;
|
||||
gtk_filter_list_model_stop_filtering (self);
|
||||
if (n_before > 0)
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), 0, n_before, 0);
|
||||
}
|
||||
@@ -553,16 +442,35 @@ gtk_filter_list_model_update_strictness_and_refilter (GtkFilterListModel *self)
|
||||
case GTK_FILTER_MATCH_SOME:
|
||||
{
|
||||
guint start, end, n_before, n_after;
|
||||
|
||||
gtk_filter_list_model_stop_filtering (self);
|
||||
self->strictness = new_strictness;
|
||||
if (gtk_filter_list_model_find_filtered (self, &start, &end, &n_before))
|
||||
n_after = g_list_model_get_n_items (G_LIST_MODEL (self));
|
||||
start = gtk_bitset_get_minimum (self->matches);
|
||||
end = gtk_bitset_get_maximum (self->matches);
|
||||
|
||||
n_before = gtk_bitset_get_size (self->matches);
|
||||
if (n_before == n_after)
|
||||
{
|
||||
n_after = g_list_model_get_n_items (G_LIST_MODEL (self));
|
||||
g_clear_pointer (&self->items, gtk_rb_tree_unref);
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), start, n_before - end - start, n_after - end - start);
|
||||
g_clear_pointer (&self->matches, gtk_bitset_unref);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_clear_pointer (&self->items, gtk_rb_tree_unref);
|
||||
GtkBitset *inverse;
|
||||
|
||||
inverse = gtk_bitset_new_range (0, n_after);
|
||||
gtk_bitset_subtract (inverse, self->matches);
|
||||
/* otherwise all items would be visible */
|
||||
g_assert (!gtk_bitset_is_empty (inverse));
|
||||
|
||||
/* find first filtered */
|
||||
start = gtk_bitset_get_minimum (inverse);
|
||||
end = n_after - gtk_bitset_get_maximum (inverse) - 1;
|
||||
|
||||
gtk_bitset_unref (inverse);
|
||||
|
||||
g_clear_pointer (&self->matches, gtk_bitset_unref);
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), start, n_before - end - start, n_after - end - start);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -574,40 +482,44 @@ gtk_filter_list_model_update_strictness_and_refilter (GtkFilterListModel *self)
|
||||
break;
|
||||
|
||||
case GTK_FILTER_MATCH_SOME:
|
||||
switch (self->strictness)
|
||||
{
|
||||
case GTK_FILTER_MATCH_NONE:
|
||||
{
|
||||
GtkBitset *old, *pending;
|
||||
|
||||
if (self->matches == NULL)
|
||||
{
|
||||
guint n_after;
|
||||
self->strictness = new_strictness;
|
||||
self->items = gtk_rb_tree_new (FilterNode,
|
||||
FilterAugment,
|
||||
gtk_filter_list_model_augment,
|
||||
NULL, NULL);
|
||||
n_after = gtk_filter_list_model_add_items (self, NULL, 0, g_list_model_get_n_items (self->model));
|
||||
if (n_after > 0)
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), 0, 0, n_after);
|
||||
if (self->strictness == GTK_FILTER_MATCH_ALL)
|
||||
old = gtk_bitset_new_range (0, g_list_model_get_n_items (self->model));
|
||||
else
|
||||
old = gtk_bitset_new_empty ();
|
||||
}
|
||||
break;
|
||||
case GTK_FILTER_MATCH_ALL:
|
||||
else
|
||||
{
|
||||
guint start, end, n_before, n_after;
|
||||
self->strictness = new_strictness;
|
||||
self->items = gtk_rb_tree_new (FilterNode,
|
||||
FilterAugment,
|
||||
gtk_filter_list_model_augment,
|
||||
NULL, NULL);
|
||||
n_before = g_list_model_get_n_items (self->model);
|
||||
gtk_filter_list_model_add_items (self, NULL, 0, n_before);
|
||||
if (gtk_filter_list_model_find_filtered (self, &start, &end, &n_after))
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), start, n_before - end - start, n_after - end - start);
|
||||
old = self->matches;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
case GTK_FILTER_MATCH_SOME:
|
||||
gtk_filter_list_model_refilter (self);
|
||||
break;
|
||||
}
|
||||
self->strictness = new_strictness;
|
||||
switch (change)
|
||||
{
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
G_GNUC_FALLTHROUGH;
|
||||
case GTK_FILTER_CHANGE_DIFFERENT:
|
||||
self->matches = gtk_bitset_new_empty ();
|
||||
pending = gtk_bitset_new_range (0, g_list_model_get_n_items (self->model));
|
||||
break;
|
||||
case GTK_FILTER_CHANGE_LESS_STRICT:
|
||||
self->matches = gtk_bitset_copy (old);
|
||||
pending = gtk_bitset_new_range (0, g_list_model_get_n_items (self->model));
|
||||
gtk_bitset_subtract (pending, self->matches);
|
||||
break;
|
||||
case GTK_FILTER_CHANGE_MORE_STRICT:
|
||||
self->matches = gtk_bitset_new_empty ();
|
||||
pending = gtk_bitset_copy (old);
|
||||
break;
|
||||
}
|
||||
gtk_filter_list_model_start_filtering (self, pending);
|
||||
|
||||
gtk_filter_list_model_emit_items_changed_for_changes (self, old);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -616,7 +528,7 @@ gtk_filter_list_model_filter_changed_cb (GtkFilter *filter,
|
||||
GtkFilterChange change,
|
||||
GtkFilterListModel *self)
|
||||
{
|
||||
gtk_filter_list_model_update_strictness_and_refilter (self);
|
||||
gtk_filter_list_model_refilter (self, change);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -636,7 +548,7 @@ gtk_filter_list_model_dispose (GObject *object)
|
||||
|
||||
gtk_filter_list_model_clear_model (self);
|
||||
gtk_filter_list_model_clear_filter (self);
|
||||
g_clear_pointer (&self->items, gtk_rb_tree_unref);
|
||||
g_clear_pointer (&self->matches, gtk_bitset_unref);
|
||||
|
||||
G_OBJECT_CLASS (gtk_filter_list_model_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -662,6 +574,18 @@ gtk_filter_list_model_class_init (GtkFilterListModelClass *class)
|
||||
GTK_TYPE_FILTER,
|
||||
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFilterListModel:incremental:
|
||||
*
|
||||
* If the model should filter items incrementally
|
||||
*/
|
||||
properties[PROP_INCREMENTAL] =
|
||||
g_param_spec_boolean ("incremental",
|
||||
P_("Incremental"),
|
||||
P_("Filer items incrementally"),
|
||||
FALSE,
|
||||
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFilterListModel:item-type:
|
||||
*
|
||||
@@ -684,7 +608,19 @@ gtk_filter_list_model_class_init (GtkFilterListModelClass *class)
|
||||
P_("Model"),
|
||||
P_("The model being filtered"),
|
||||
G_TYPE_LIST_MODEL,
|
||||
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkFilterListModel:pending:
|
||||
*
|
||||
* Number of items not yet filtered
|
||||
*/
|
||||
properties[PROP_PENDING] =
|
||||
g_param_spec_uint ("pending",
|
||||
P_("Pending"),
|
||||
P_("Number of items not yet filtered"),
|
||||
0, G_MAXUINT, 0,
|
||||
GTK_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
|
||||
}
|
||||
@@ -728,7 +664,7 @@ gtk_filter_list_model_new (GListModel *model,
|
||||
*
|
||||
* Creates a new empty filter list model set up to return items of type @item_type.
|
||||
* It is up to the application to set a proper filter and model to ensure
|
||||
* the item type is matched.
|
||||
* the item type is matches.
|
||||
*
|
||||
* Returns: a new #GtkFilterListModel
|
||||
**/
|
||||
@@ -769,7 +705,7 @@ gtk_filter_list_model_set_filter (GtkFilterListModel *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_filter_list_model_update_strictness_and_refilter (self);
|
||||
gtk_filter_list_model_refilter (self, GTK_FILTER_CHANGE_LESS_STRICT);
|
||||
}
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FILTER]);
|
||||
@@ -828,13 +764,18 @@ gtk_filter_list_model_set_model (GtkFilterListModel *self,
|
||||
if (removed == 0)
|
||||
{
|
||||
self->strictness = GTK_FILTER_MATCH_NONE;
|
||||
gtk_filter_list_model_update_strictness_and_refilter (self);
|
||||
gtk_filter_list_model_refilter (self, GTK_FILTER_CHANGE_LESS_STRICT);
|
||||
added = 0;
|
||||
}
|
||||
else if (self->items)
|
||||
added = gtk_filter_list_model_add_items (self, NULL, 0, g_list_model_get_n_items (model));
|
||||
else if (self->matches)
|
||||
{
|
||||
gtk_filter_list_model_start_filtering (self, gtk_bitset_new_range (0, g_list_model_get_n_items (model)));
|
||||
added = gtk_bitset_get_size (self->matches);
|
||||
}
|
||||
else
|
||||
added = g_list_model_get_n_items (model);
|
||||
{
|
||||
added = g_list_model_get_n_items (model);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -864,54 +805,89 @@ gtk_filter_list_model_get_model (GtkFilterListModel *self)
|
||||
return self->model;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_filter_list_model_refilter (GtkFilterListModel *self)
|
||||
/**
|
||||
* gtk_filter_list_model_set_incremental:
|
||||
* @self: a #GtkFilterListModel
|
||||
* @incremental: %TRUE to enable incremental filtering
|
||||
*
|
||||
* When incremental filtering is enabled, the filterlistmodel will not run
|
||||
* filters immediately, but will instead queue an idle handler that
|
||||
* incrementally filters the items and adds them to the list. This of course
|
||||
* means that items are not instantly added to the list, but only appear
|
||||
* incrementally.
|
||||
*
|
||||
* When your filter blocks the UI while filtering, you might consider
|
||||
* turning this on. Depending on your model and filters, this may become
|
||||
* interesting around 10,000 to 100,000 items.
|
||||
*
|
||||
* By default, incremental filtering is disabled.
|
||||
**/
|
||||
void
|
||||
gtk_filter_list_model_set_incremental (GtkFilterListModel *self,
|
||||
gboolean incremental)
|
||||
{
|
||||
FilterNode *node;
|
||||
guint i, first_change, last_change;
|
||||
guint n_is_visible, n_was_visible;
|
||||
gboolean visible;
|
||||
|
||||
g_return_if_fail (GTK_IS_FILTER_LIST_MODEL (self));
|
||||
|
||||
if (self->items == NULL || self->model == NULL)
|
||||
|
||||
if (self->incremental == incremental)
|
||||
return;
|
||||
|
||||
first_change = G_MAXUINT;
|
||||
last_change = 0;
|
||||
n_is_visible = 0;
|
||||
n_was_visible = 0;
|
||||
for (i = 0, node = gtk_rb_tree_get_first (self->items);
|
||||
node != NULL;
|
||||
i++, node = gtk_rb_tree_node_get_next (node))
|
||||
{
|
||||
visible = gtk_filter_list_model_run_filter (self, i);
|
||||
if (visible == node->visible)
|
||||
{
|
||||
if (visible)
|
||||
{
|
||||
n_is_visible++;
|
||||
n_was_visible++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
self->incremental = incremental;
|
||||
|
||||
node->visible = visible;
|
||||
gtk_rb_tree_node_mark_dirty (node);
|
||||
first_change = MIN (n_is_visible, first_change);
|
||||
if (visible)
|
||||
n_is_visible++;
|
||||
else
|
||||
n_was_visible++;
|
||||
last_change = MAX (n_is_visible, last_change);
|
||||
if (!incremental)
|
||||
{
|
||||
GtkBitset *old;
|
||||
gtk_filter_list_model_run_filter (self, G_MAXUINT);
|
||||
|
||||
old = gtk_bitset_copy (self->matches);
|
||||
gtk_filter_list_model_run_filter (self, 512);
|
||||
|
||||
gtk_filter_list_model_stop_filtering (self);
|
||||
|
||||
gtk_filter_list_model_emit_items_changed_for_changes (self, old);
|
||||
}
|
||||
|
||||
if (first_change <= last_change)
|
||||
{
|
||||
g_list_model_items_changed (G_LIST_MODEL (self),
|
||||
first_change,
|
||||
last_change - first_change + n_was_visible - n_is_visible,
|
||||
last_change - first_change);
|
||||
}
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_INCREMENTAL]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_filter_list_model_get_incremental:
|
||||
* @self: a #GtkFilterListModel
|
||||
*
|
||||
* Returns whether incremental filtering was enabled via
|
||||
* gtk_filter_list_model_set_incremental().
|
||||
*
|
||||
* Returns: %TRUE if incremental filtering is enabled
|
||||
**/
|
||||
gboolean
|
||||
gtk_filter_list_model_get_incremental (GtkFilterListModel *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILTER_LIST_MODEL (self), FALSE);
|
||||
|
||||
return self->incremental;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_filter_list_model_get_pending:
|
||||
* @self: a #GtkFilterListModel
|
||||
*
|
||||
* Returns the number of items that have not been filtered yet.
|
||||
*
|
||||
* When incremental filtering is not enabled, this always returns 0.
|
||||
*
|
||||
* You can use this value to check if @self is busy filtering by
|
||||
* comparing the return value to 0 or you can compute the percentage
|
||||
* of the filter remaining by dividing the return value by
|
||||
* g_list_model_get_n_items(gtk_filter_list_model_get_model (self)).
|
||||
*
|
||||
* Returns: The number of items not yet filtered
|
||||
**/
|
||||
guint
|
||||
gtk_filter_list_model_get_pending (GtkFilterListModel *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FILTER_LIST_MODEL (self), FALSE);
|
||||
|
||||
if (self->pending == NULL)
|
||||
return 0;
|
||||
|
||||
return gtk_bitset_get_size (self->pending);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,14 @@ void gtk_filter_list_model_set_model (GtkFilterListMo
|
||||
GListModel *model);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GListModel * gtk_filter_list_model_get_model (GtkFilterListModel *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_filter_list_model_set_incremental (GtkFilterListModel *self,
|
||||
gboolean incremental);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gtk_filter_list_model_get_incremental (GtkFilterListModel *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
guint gtk_filter_list_model_get_pending (GtkFilterListModel *self);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright © 2019 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkfunctionslistitemfactory.h"
|
||||
|
||||
#include "gtklistitemfactoryprivate.h"
|
||||
#include "gtklistitemprivate.h"
|
||||
|
||||
struct _GtkFunctionsListItemFactory
|
||||
{
|
||||
GtkListItemFactory parent_instance;
|
||||
|
||||
GtkListItemSetupFunc setup_func;
|
||||
GtkListItemBindFunc bind_func;
|
||||
gpointer user_data;
|
||||
GDestroyNotify user_destroy;
|
||||
};
|
||||
|
||||
struct _GtkFunctionsListItemFactoryClass
|
||||
{
|
||||
GtkListItemFactoryClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkFunctionsListItemFactory, gtk_functions_list_item_factory, GTK_TYPE_LIST_ITEM_FACTORY)
|
||||
|
||||
static void
|
||||
gtk_functions_list_item_factory_setup (GtkListItemFactory *factory,
|
||||
GtkListItemWidget *widget,
|
||||
GtkListItem *list_item)
|
||||
{
|
||||
GtkFunctionsListItemFactory *self = GTK_FUNCTIONS_LIST_ITEM_FACTORY (factory);
|
||||
|
||||
if (self->setup_func)
|
||||
self->setup_func (list_item, self->user_data);
|
||||
|
||||
GTK_LIST_ITEM_FACTORY_CLASS (gtk_functions_list_item_factory_parent_class)->setup (factory, widget, list_item);
|
||||
|
||||
if (gtk_list_item_get_item (list_item) != NULL && self->bind_func)
|
||||
self->bind_func (list_item, self->user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_functions_list_item_factory_update (GtkListItemFactory *factory,
|
||||
GtkListItemWidget *widget,
|
||||
GtkListItem *list_item,
|
||||
guint position,
|
||||
gpointer item,
|
||||
gboolean selected)
|
||||
{
|
||||
GtkFunctionsListItemFactory *self = GTK_FUNCTIONS_LIST_ITEM_FACTORY (factory);
|
||||
|
||||
GTK_LIST_ITEM_FACTORY_CLASS (gtk_functions_list_item_factory_parent_class)->update (factory, widget, list_item, position, item, selected);
|
||||
|
||||
if (item != NULL && self->bind_func)
|
||||
self->bind_func (list_item, self->user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_functions_list_item_factory_finalize (GObject *object)
|
||||
{
|
||||
GtkFunctionsListItemFactory *self = GTK_FUNCTIONS_LIST_ITEM_FACTORY (object);
|
||||
|
||||
if (self->user_destroy)
|
||||
self->user_destroy (self->user_data);
|
||||
|
||||
G_OBJECT_CLASS (gtk_functions_list_item_factory_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_functions_list_item_factory_class_init (GtkFunctionsListItemFactoryClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkListItemFactoryClass *factory_class = GTK_LIST_ITEM_FACTORY_CLASS (klass);
|
||||
|
||||
object_class->finalize = gtk_functions_list_item_factory_finalize;
|
||||
|
||||
factory_class->setup = gtk_functions_list_item_factory_setup;
|
||||
factory_class->update = gtk_functions_list_item_factory_update;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_functions_list_item_factory_init (GtkFunctionsListItemFactory *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_functions_list_item_factory_new: (skip)
|
||||
* @setup_func: (scope call) (destroy user_destroy): the setup function for the list item factory
|
||||
* @bind_func: (scope call) (destroy user_destroy): the bind function for the list item factory
|
||||
* @user_data: user data for the @setup_func and @bind_func functions
|
||||
* @user_destroy: a function called to destroy @user_data
|
||||
*
|
||||
* Creates a new #GtkListItemFactory with the given functions.
|
||||
*
|
||||
* Returns: (transfer full): the newly created list item factory object
|
||||
*/
|
||||
GtkListItemFactory *
|
||||
gtk_functions_list_item_factory_new (GtkListItemSetupFunc setup_func,
|
||||
GtkListItemBindFunc bind_func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_destroy)
|
||||
{
|
||||
GtkFunctionsListItemFactory *self;
|
||||
|
||||
g_return_val_if_fail (setup_func || bind_func, NULL);
|
||||
g_return_val_if_fail (user_data != NULL || user_destroy == NULL, NULL);
|
||||
|
||||
self = g_object_new (GTK_TYPE_FUNCTIONS_LIST_ITEM_FACTORY, NULL);
|
||||
|
||||
self->setup_func = setup_func;
|
||||
self->bind_func = bind_func;
|
||||
self->user_data = user_data;
|
||||
self->user_destroy = user_destroy;
|
||||
|
||||
return GTK_LIST_ITEM_FACTORY (self);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright © 2019 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __GTK_FUNCTIONS_LIST_ITEM_FACTORY_H__
|
||||
#define __GTK_FUNCTIONS_LIST_ITEM_FACTORY_H__
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gtk/gtklistitemfactory.h>
|
||||
#include <gtk/gtklistitem.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_FUNCTIONS_LIST_ITEM_FACTORY (gtk_functions_list_item_factory_get_type ())
|
||||
#define GTK_FUNCTIONS_LIST_ITEM_FACTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTK_TYPE_FUNCTIONS_LIST_ITEM_FACTORY, GtkFunctionsListItemFactory))
|
||||
#define GTK_FUNCTIONS_LIST_ITEM_FACTORY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTK_TYPE_FUNCTIONS_LIST_ITEM_FACTORY, GtkFunctionsListItemFactoryClass))
|
||||
#define GTK_IS_FUNCTIONS_LIST_ITEM_FACTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTK_TYPE_FUNCTIONS_LIST_ITEM_FACTORY))
|
||||
#define GTK_IS_FUNCTIONS_LIST_ITEM_FACTORY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTK_TYPE_FUNCTIONS_LIST_ITEM_FACTORY))
|
||||
#define GTK_FUNCTIONS_LIST_ITEM_FACTORY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GTK_TYPE_FUNCTIONS_LIST_ITEM_FACTORY, GtkFunctionsListItemFactoryClass))
|
||||
|
||||
typedef struct _GtkFunctionsListItemFactory GtkFunctionsListItemFactory;
|
||||
typedef struct _GtkFunctionsListItemFactoryClass GtkFunctionsListItemFactoryClass;
|
||||
|
||||
/**
|
||||
* GtkListItemSetupFunc:
|
||||
* @item: the #GtkListItem to set up
|
||||
* @user_data: (closure): user data
|
||||
*
|
||||
* Called whenever a new list item needs to be setup for managing a row in
|
||||
* the list.
|
||||
*
|
||||
* At this point, the list item is not bound yet, so gtk_list_item_get_item()
|
||||
* will return %NULL.
|
||||
* The list item will later be bound to an item via the #GtkListItemBindFunc.
|
||||
*/
|
||||
typedef void (* GtkListItemSetupFunc) (GtkListItem *item, gpointer user_data);
|
||||
|
||||
/**
|
||||
* GtkListItemBindFunc:
|
||||
* @item: the #GtkListItem to bind
|
||||
* @user_data: (closure): user data
|
||||
*
|
||||
* Binds a#GtkListItem previously set up via a #GtkListItemSetupFunc to
|
||||
* an @item.
|
||||
*
|
||||
* Rebinding a @item to different @items is supported as well as
|
||||
* unbinding it by setting @item to %NULL.
|
||||
*/
|
||||
typedef void (* GtkListItemBindFunc) (GtkListItem *item,
|
||||
gpointer user_data);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gtk_functions_list_item_factory_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkListItemFactory * gtk_functions_list_item_factory_new (GtkListItemSetupFunc setup_func,
|
||||
GtkListItemBindFunc bind_func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_destroy);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_FUNCTIONS_LIST_ITEM_FACTORY_H__ */
|
||||
@@ -1171,8 +1171,6 @@ gtk_grid_view_init (GtkGridView *self)
|
||||
gtk_list_base_set_anchor_max_widgets (GTK_LIST_BASE (self),
|
||||
self->max_columns * GTK_GRID_VIEW_MAX_VISIBLE_ROWS,
|
||||
self->max_columns);
|
||||
|
||||
gtk_widget_add_css_class (GTK_WIDGET (self), "view");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-3
@@ -595,7 +595,7 @@ gtk_header_bar_class_init (GtkHeaderBarClass *class)
|
||||
g_param_spec_boolean ("show-title-buttons",
|
||||
P_("Show title buttons"),
|
||||
P_("Whether to show title buttons"),
|
||||
TRUE,
|
||||
FALSE,
|
||||
GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
@@ -629,7 +629,6 @@ gtk_header_bar_init (GtkHeaderBar *bar)
|
||||
|
||||
priv->title_widget = NULL;
|
||||
priv->decoration_layout = NULL;
|
||||
priv->show_title_buttons = TRUE;
|
||||
priv->state = GDK_SURFACE_STATE_WITHDRAWN;
|
||||
|
||||
priv->handle = gtk_window_handle_new ();
|
||||
@@ -647,7 +646,6 @@ gtk_header_bar_init (GtkHeaderBar *bar)
|
||||
gtk_center_box_set_end_widget (GTK_CENTER_BOX (priv->center_box), priv->end_box);
|
||||
|
||||
construct_title_label (bar);
|
||||
create_window_controls (bar);
|
||||
}
|
||||
|
||||
static GtkBuildableIface *parent_buildable_iface;
|
||||
|
||||
+29
-25
@@ -55,6 +55,13 @@
|
||||
#include "gdk/gdktextureprivate.h"
|
||||
#include "gdk/gdkprofilerprivate.h"
|
||||
|
||||
#define GTK_VECTOR_ELEMENT_TYPE char *
|
||||
#define GTK_VECTOR_NULL_TERMINATED 1
|
||||
#define GTK_VECTOR_FREE_FUNC g_free
|
||||
#define GTK_VECTOR_TYPE_NAME GtkStrvBuilder
|
||||
#define GTK_VECTOR_NAME gtk_strv_builder
|
||||
#include "gtkvectorimpl.c"
|
||||
|
||||
/**
|
||||
* SECTION:gtkicontheme
|
||||
* @Short_description: Looking up icons by name
|
||||
@@ -2276,13 +2283,13 @@ real_choose_icon (GtkIconTheme *self,
|
||||
}
|
||||
|
||||
static void
|
||||
icon_name_list_add_icon (GPtrArray *icons,
|
||||
const gchar *dir_suffix,
|
||||
gchar *icon_name)
|
||||
icon_name_list_add_icon (GtkStrvBuilder *icons,
|
||||
const gchar *dir_suffix,
|
||||
gchar *icon_name)
|
||||
{
|
||||
if (dir_suffix)
|
||||
g_ptr_array_add (icons, g_strconcat (icon_name, dir_suffix, NULL));
|
||||
g_ptr_array_add (icons, icon_name);
|
||||
gtk_strv_builder_append (icons, g_strconcat (icon_name, dir_suffix, NULL));
|
||||
gtk_strv_builder_append (icons, icon_name);
|
||||
}
|
||||
|
||||
static GtkIconPaintable *
|
||||
@@ -2296,7 +2303,7 @@ choose_icon (GtkIconTheme *self,
|
||||
{
|
||||
gboolean has_regular = FALSE, has_symbolic = FALSE;
|
||||
GtkIconPaintable *icon;
|
||||
GPtrArray *new_names;
|
||||
GtkStrvBuilder new_names;
|
||||
const gchar *dir_suffix;
|
||||
guint i;
|
||||
|
||||
@@ -2327,73 +2334,70 @@ choose_icon (GtkIconTheme *self,
|
||||
|
||||
if ((flags & GTK_ICON_LOOKUP_FORCE_REGULAR) && has_symbolic)
|
||||
{
|
||||
new_names = g_ptr_array_new_with_free_func (g_free);
|
||||
gtk_strv_builder_init (&new_names);
|
||||
for (i = 0; icon_names[i]; i++)
|
||||
{
|
||||
if (icon_name_is_symbolic (icon_names[i], -1))
|
||||
icon_name_list_add_icon (new_names, dir_suffix, g_strndup (icon_names[i], strlen (icon_names[i]) - strlen ("-symbolic")));
|
||||
icon_name_list_add_icon (&new_names, dir_suffix, g_strndup (icon_names[i], strlen (icon_names[i]) - strlen ("-symbolic")));
|
||||
else
|
||||
icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i]));
|
||||
icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
|
||||
}
|
||||
for (i = 0; icon_names[i]; i++)
|
||||
{
|
||||
if (icon_name_is_symbolic (icon_names[i], -1))
|
||||
icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i]));
|
||||
icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
|
||||
}
|
||||
g_ptr_array_add (new_names, NULL);
|
||||
|
||||
icon = real_choose_icon (self,
|
||||
(const gchar **) new_names->pdata,
|
||||
(const char **) gtk_strv_builder_get_data (&new_names),
|
||||
size,
|
||||
scale,
|
||||
flags & ~(GTK_ICON_LOOKUP_FORCE_REGULAR | GTK_ICON_LOOKUP_FORCE_SYMBOLIC),
|
||||
non_blocking);
|
||||
|
||||
g_ptr_array_free (new_names, TRUE);
|
||||
gtk_strv_builder_clear (&new_names);
|
||||
}
|
||||
else if ((flags & GTK_ICON_LOOKUP_FORCE_SYMBOLIC) && has_regular)
|
||||
{
|
||||
new_names = g_ptr_array_new_with_free_func (g_free);
|
||||
gtk_strv_builder_init (&new_names);
|
||||
for (i = 0; icon_names[i]; i++)
|
||||
{
|
||||
if (!icon_name_is_symbolic (icon_names[i], -1))
|
||||
icon_name_list_add_icon (new_names, dir_suffix, g_strconcat (icon_names[i], "-symbolic", NULL));
|
||||
icon_name_list_add_icon (&new_names, dir_suffix, g_strconcat (icon_names[i], "-symbolic", NULL));
|
||||
else
|
||||
icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i]));
|
||||
icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
|
||||
}
|
||||
for (i = 0; icon_names[i]; i++)
|
||||
{
|
||||
if (!icon_name_is_symbolic (icon_names[i], -1))
|
||||
icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i]));
|
||||
icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
|
||||
}
|
||||
g_ptr_array_add (new_names, NULL);
|
||||
|
||||
icon = real_choose_icon (self,
|
||||
(const gchar **) new_names->pdata,
|
||||
(const char **) gtk_strv_builder_get_data (&new_names),
|
||||
size,
|
||||
scale,
|
||||
flags & ~(GTK_ICON_LOOKUP_FORCE_REGULAR | GTK_ICON_LOOKUP_FORCE_SYMBOLIC),
|
||||
non_blocking);
|
||||
|
||||
g_ptr_array_free (new_names, TRUE);
|
||||
gtk_strv_builder_clear (&new_names);
|
||||
}
|
||||
else if (dir_suffix)
|
||||
{
|
||||
new_names = g_ptr_array_new_with_free_func (g_free);
|
||||
gtk_strv_builder_init (&new_names);
|
||||
for (i = 0; icon_names[i]; i++)
|
||||
{
|
||||
icon_name_list_add_icon (new_names, dir_suffix, g_strdup (icon_names[i]));
|
||||
icon_name_list_add_icon (&new_names, dir_suffix, g_strdup (icon_names[i]));
|
||||
}
|
||||
g_ptr_array_add (new_names, NULL);
|
||||
|
||||
icon = real_choose_icon (self,
|
||||
(const gchar **) new_names->pdata,
|
||||
(const char **) gtk_strv_builder_get_data (&new_names),
|
||||
size,
|
||||
scale,
|
||||
flags & ~(GTK_ICON_LOOKUP_FORCE_REGULAR | GTK_ICON_LOOKUP_FORCE_SYMBOLIC),
|
||||
non_blocking);
|
||||
|
||||
g_ptr_array_free (new_names, TRUE);
|
||||
gtk_strv_builder_clear (&new_names);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+4
-7
@@ -3573,15 +3573,12 @@ static void
|
||||
gtk_label_unrealize (GtkWidget *widget)
|
||||
{
|
||||
GtkLabel *self = GTK_LABEL (widget);
|
||||
GdkClipboard *clipboard;
|
||||
|
||||
clipboard = gtk_widget_get_primary_clipboard (widget);
|
||||
if (self->select_info &&
|
||||
self->select_info->provider)
|
||||
{
|
||||
GdkClipboard *clipboard = gtk_widget_get_primary_clipboard (widget);
|
||||
|
||||
if (gdk_clipboard_get_content (clipboard) == self->select_info->provider)
|
||||
gdk_clipboard_set_content (clipboard, NULL);
|
||||
}
|
||||
gdk_clipboard_get_content (clipboard) == self->select_info->provider)
|
||||
gdk_clipboard_set_content (clipboard, NULL);
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_label_parent_class)->unrealize (widget);
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
* Because views do not display the whole list at once but only a few
|
||||
* items, they only need to maintain a few widgets at a time. They will
|
||||
* instruct the #GtkListItemFactory to create these widgets and bind them
|
||||
* to the items that are currently displayed.
|
||||
* to the items that are currently displayed.
|
||||
* As the list model changes or the user scrolls to the list, the items will
|
||||
* change and the view will instruct the factory to bind the widgets to those
|
||||
* new items.
|
||||
@@ -56,13 +56,13 @@
|
||||
* Various implementations of #GtkListItemFactory exist to allow you different
|
||||
* ways to provide those widgets. The most common implementations are
|
||||
* #GtkBuilderListItemFactory which takes a #GtkBuilder .ui file and then creates
|
||||
* widgets and manages everything automatically from the information in that file
|
||||
* and manages widgets everything automatically from the information in that file
|
||||
* and #GtkSignalListItemFactory which allows you to connect to signals with your
|
||||
* own code and retain full control over how the widgets are setup and managed.
|
||||
*
|
||||
* A #GtkListItemFactory is supposed to be final - that means its behavior should
|
||||
* not change and the first widget created from it should behave the same way as
|
||||
* the last widget created from it.
|
||||
* the last widget created from it.
|
||||
* If you intend to do changes to the behavior, it is recommended that you create
|
||||
* a new #GtkListItemFactory which will allow the views to recreate its widgets.
|
||||
*
|
||||
|
||||
@@ -925,8 +925,6 @@ gtk_list_view_init (GtkListView *self)
|
||||
gtk_list_base_set_anchor_max_widgets (GTK_LIST_BASE (self),
|
||||
GTK_LIST_VIEW_MAX_LIST_ITEMS,
|
||||
GTK_LIST_VIEW_EXTRA_ITEMS);
|
||||
|
||||
gtk_widget_add_css_class (GTK_WIDGET (self), "view");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+24
-20
@@ -95,7 +95,6 @@
|
||||
#include "gdk/gdk-private.h"
|
||||
#include "gsk/gskprivate.h"
|
||||
#include "gsk/gskrendernodeprivate.h"
|
||||
#include "gtkarrayimplprivate.h"
|
||||
#include "gtknative.h"
|
||||
|
||||
#include <locale.h>
|
||||
@@ -138,6 +137,13 @@
|
||||
#include "a11y/gtkaccessibility.h"
|
||||
#include "inspector/window.h"
|
||||
|
||||
#define GTK_VECTOR_ELEMENT_TYPE GtkWidget *
|
||||
#define GTK_VECTOR_TYPE_NAME GtkWidgetStack
|
||||
#define GTK_VECTOR_NAME gtk_widget_stack
|
||||
#define GTK_VECTOR_FREE_FUNC g_object_unref
|
||||
#define GTK_VECTOR_PREALLOC 16
|
||||
#include "gtkvectorimpl.c"
|
||||
|
||||
static GtkWindowGroup *gtk_main_get_window_group (GtkWidget *widget);
|
||||
|
||||
static gint pre_initialized = FALSE;
|
||||
@@ -1321,8 +1327,7 @@ gtk_synthesize_crossing_events (GtkRoot *toplevel,
|
||||
double x, y;
|
||||
GtkWidget *prev;
|
||||
gboolean seen_ancestor;
|
||||
GtkArray target_array;
|
||||
GtkWidget *stack_targets[16];
|
||||
GtkWidgetStack target_array;
|
||||
int i;
|
||||
|
||||
if (old_target == new_target)
|
||||
@@ -1376,19 +1381,19 @@ gtk_synthesize_crossing_events (GtkRoot *toplevel,
|
||||
widget = _gtk_widget_get_parent (widget);
|
||||
}
|
||||
|
||||
gtk_array_init (&target_array, (void**)stack_targets, 16);
|
||||
gtk_widget_stack_init (&target_array);
|
||||
for (widget = new_target; widget; widget = _gtk_widget_get_parent (widget))
|
||||
gtk_array_add (&target_array, widget);
|
||||
gtk_widget_stack_append (&target_array, g_object_ref (widget));
|
||||
|
||||
crossing.direction = GTK_CROSSING_IN;
|
||||
|
||||
seen_ancestor = FALSE;
|
||||
for (i = (int)target_array.len - 1; i >= 0; i--)
|
||||
for (i = gtk_widget_stack_get_size (&target_array) - 1; i >= 0; i--)
|
||||
{
|
||||
widget = gtk_array_index (&target_array, i);
|
||||
widget = gtk_widget_stack_get (&target_array, i);
|
||||
|
||||
if (i < (int)target_array.len - 1)
|
||||
crossing.new_descendent = gtk_array_index (&target_array, i + 1);
|
||||
if (i < gtk_widget_stack_get_size (&target_array) - 1)
|
||||
crossing.new_descendent = gtk_widget_stack_get (&target_array, i + 1);
|
||||
else
|
||||
crossing.new_descendent = NULL;
|
||||
|
||||
@@ -1417,7 +1422,7 @@ gtk_synthesize_crossing_events (GtkRoot *toplevel,
|
||||
gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE);
|
||||
}
|
||||
|
||||
gtk_array_free (&target_array, NULL);
|
||||
gtk_widget_stack_clear (&target_array);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
@@ -1994,13 +1999,12 @@ gtk_propagate_event_internal (GtkWidget *widget,
|
||||
{
|
||||
gint handled_event = FALSE;
|
||||
GtkWidget *target = widget;
|
||||
GtkArray widget_array;
|
||||
GtkWidget *stack_widgets[16];
|
||||
GtkWidgetStack widget_array;
|
||||
int i;
|
||||
|
||||
/* First, propagate event down */
|
||||
gtk_array_init (&widget_array, (void**)stack_widgets, 16);
|
||||
gtk_array_add (&widget_array, g_object_ref (widget));
|
||||
gtk_widget_stack_init (&widget_array);
|
||||
gtk_widget_stack_append (&widget_array, g_object_ref (widget));
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@@ -2008,16 +2012,16 @@ gtk_propagate_event_internal (GtkWidget *widget,
|
||||
if (!widget)
|
||||
break;
|
||||
|
||||
gtk_array_add (&widget_array, g_object_ref (widget));
|
||||
gtk_widget_stack_append (&widget_array, g_object_ref (widget));
|
||||
|
||||
if (widget == topmost)
|
||||
break;
|
||||
}
|
||||
|
||||
i = widget_array.len - 1;
|
||||
i = gtk_widget_stack_get_size (&widget_array) - 1;
|
||||
for (;;)
|
||||
{
|
||||
widget = gtk_array_index (&widget_array, i);
|
||||
widget = gtk_widget_stack_get (&widget_array, i);
|
||||
|
||||
if (!_gtk_widget_is_sensitive (widget))
|
||||
{
|
||||
@@ -2050,9 +2054,9 @@ gtk_propagate_event_internal (GtkWidget *widget,
|
||||
* parents can see the button and motion
|
||||
* events of the children.
|
||||
*/
|
||||
for (i = 0; i < widget_array.len; i++)
|
||||
for (i = 0; i < gtk_widget_stack_get_size (&widget_array); i++)
|
||||
{
|
||||
widget = gtk_array_index (&widget_array, i);
|
||||
widget = gtk_widget_stack_get (&widget_array, i);
|
||||
|
||||
/* Scroll events are special cased here because it
|
||||
* feels wrong when scrolling a GtkViewport, say,
|
||||
@@ -2071,7 +2075,7 @@ gtk_propagate_event_internal (GtkWidget *widget,
|
||||
}
|
||||
}
|
||||
|
||||
gtk_array_free (&widget_array, g_object_unref);
|
||||
gtk_widget_stack_clear (&widget_array);
|
||||
return handled_event;
|
||||
}
|
||||
|
||||
|
||||
@@ -386,19 +386,3 @@ gtk_multi_selection_new (GListModel *model)
|
||||
"model", model,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_multi_selection_get_model:
|
||||
* @self: a #GtkMultiSelection
|
||||
*
|
||||
* Returns the underlying model of @self.
|
||||
*
|
||||
* Returns: (transfer none): the underlying model
|
||||
*/
|
||||
GListModel *
|
||||
gtk_multi_selection_get_model (GtkMultiSelection *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_MULTI_SELECTION (self), NULL);
|
||||
|
||||
return self->model;
|
||||
}
|
||||
|
||||
@@ -33,8 +33,6 @@ G_DECLARE_FINAL_TYPE (GtkMultiSelection, gtk_multi_selection, GTK, MULTI_SELECTI
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GListModel * gtk_multi_selection_new (GListModel *model);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GListModel * gtk_multi_selection_get_model (GtkMultiSelection *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
@@ -250,6 +250,16 @@ G_DEFINE_TYPE_WITH_CODE (GtkRange, gtk_range, GTK_TYPE_WIDGET,
|
||||
static guint signals[LAST_SIGNAL];
|
||||
static GParamSpec *properties[LAST_PROP];
|
||||
|
||||
static void
|
||||
gtk_range_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
GtkRange *range = GTK_RANGE (widget);
|
||||
GtkRangePrivate *priv = gtk_range_get_instance_private (range);
|
||||
|
||||
gtk_widget_snapshot_child (widget, priv->trough_widget, snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_range_class_init (GtkRangeClass *class)
|
||||
{
|
||||
@@ -265,6 +275,7 @@ gtk_range_class_init (GtkRangeClass *class)
|
||||
gobject_class->dispose = gtk_range_dispose;
|
||||
|
||||
widget_class->measure = gtk_range_measure;
|
||||
widget_class->snapshot = gtk_range_snapshot;
|
||||
widget_class->size_allocate = gtk_range_size_allocate;
|
||||
widget_class->unmap = gtk_range_unmap;
|
||||
widget_class->direction_changed = gtk_range_direction_changed;
|
||||
|
||||
+12
-14
@@ -47,12 +47,14 @@ static void
|
||||
gtk_theming_background_snapshot_color (GtkCssBoxes *boxes,
|
||||
GtkSnapshot *snapshot,
|
||||
const GdkRGBA *bg_color,
|
||||
guint n_bg_values)
|
||||
const GtkCssValue *background_image)
|
||||
{
|
||||
const GskRoundedRect *box;
|
||||
gint n_values;
|
||||
GtkCssArea clip;
|
||||
|
||||
clip = _gtk_css_area_value_get (_gtk_css_array_value_get_nth (boxes->style->background->background_clip, n_bg_values - 1));
|
||||
|
||||
n_values = _gtk_css_array_value_get_n_values (background_image);
|
||||
clip = _gtk_css_area_value_get (_gtk_css_array_value_get_nth (boxes->style->background->background_clip, n_values - 1));
|
||||
box = gtk_css_boxes_get_box (boxes, clip);
|
||||
|
||||
if (gsk_rounded_rect_is_rectilinear (box))
|
||||
@@ -92,6 +94,9 @@ gtk_theming_background_snapshot_layer (GtkCssBoxes *bg,
|
||||
|
||||
pos = _gtk_css_array_value_get_nth (background->background_position, idx);
|
||||
repeat = _gtk_css_array_value_get_nth (background->background_repeat, idx);
|
||||
hrepeat = _gtk_css_background_repeat_value_get_x (repeat);
|
||||
vrepeat = _gtk_css_background_repeat_value_get_y (repeat);
|
||||
|
||||
|
||||
origin = gtk_css_boxes_get_box (bg,
|
||||
_gtk_css_area_value_get (
|
||||
@@ -120,13 +125,8 @@ gtk_theming_background_snapshot_layer (GtkCssBoxes *bg,
|
||||
/* optimization */
|
||||
if (image_width == width)
|
||||
hrepeat = GTK_CSS_REPEAT_STYLE_NO_REPEAT;
|
||||
else
|
||||
hrepeat = _gtk_css_background_repeat_value_get_x (repeat);
|
||||
|
||||
if (image_height == height)
|
||||
vrepeat = GTK_CSS_REPEAT_STYLE_NO_REPEAT;
|
||||
else
|
||||
vrepeat = _gtk_css_background_repeat_value_get_y (repeat);
|
||||
|
||||
gtk_snapshot_push_debug (snapshot, "Layer %u", idx);
|
||||
gtk_snapshot_push_rounded_clip (snapshot, clip);
|
||||
@@ -262,8 +262,7 @@ gtk_css_style_snapshot_background (GtkCssBoxes *boxes,
|
||||
gboolean has_bg_color;
|
||||
gboolean has_bg_image;
|
||||
gboolean has_shadow;
|
||||
int idx;
|
||||
guint number_of_layers;
|
||||
gint idx;
|
||||
|
||||
if (background->base.type == GTK_CSS_BACKGROUND_INITIAL_VALUES)
|
||||
return;
|
||||
@@ -287,11 +286,10 @@ gtk_css_style_snapshot_background (GtkCssBoxes *boxes,
|
||||
snapshot,
|
||||
gtk_css_boxes_get_border_box (boxes));
|
||||
|
||||
number_of_layers = _gtk_css_array_value_get_n_values (background_image);
|
||||
|
||||
if (has_bg_image)
|
||||
{
|
||||
GtkCssValue *blend_modes = background->background_blend_mode;
|
||||
const int number_of_layers = _gtk_css_array_value_get_n_values (background_image);
|
||||
GskBlendMode *blend_mode_values = g_alloca (sizeof (GskBlendMode) * number_of_layers);
|
||||
|
||||
for (idx = number_of_layers - 1; idx >= 0; idx--)
|
||||
@@ -303,7 +301,7 @@ gtk_css_style_snapshot_background (GtkCssBoxes *boxes,
|
||||
}
|
||||
|
||||
if (has_bg_color)
|
||||
gtk_theming_background_snapshot_color (boxes, snapshot, bg_color, number_of_layers);
|
||||
gtk_theming_background_snapshot_color (boxes, snapshot, bg_color, background_image);
|
||||
|
||||
for (idx = number_of_layers - 1; idx >= 0; idx--)
|
||||
{
|
||||
@@ -321,7 +319,7 @@ gtk_css_style_snapshot_background (GtkCssBoxes *boxes,
|
||||
}
|
||||
else if (has_bg_color)
|
||||
{
|
||||
gtk_theming_background_snapshot_color (boxes, snapshot, bg_color, number_of_layers);
|
||||
gtk_theming_background_snapshot_color (boxes, snapshot, bg_color, background_image);
|
||||
}
|
||||
|
||||
if (has_shadow)
|
||||
|
||||
+44
-14
@@ -79,23 +79,22 @@
|
||||
*
|
||||
* |[<!-- language="plain" -->
|
||||
* scale[.fine-tune][.marks-before][.marks-after]
|
||||
* ├── [value][.top][.right][.bottom][.left]
|
||||
* ├── marks.top
|
||||
* │ ├── mark
|
||||
* │ ┊ ├── [label]
|
||||
* │ ┊ ╰── indicator
|
||||
* ┊ ┊
|
||||
* │ ╰── mark
|
||||
* ├── marks.bottom
|
||||
* │ ├── mark
|
||||
* │ ┊ ├── indicator
|
||||
* │ ┊ ╰── [label]
|
||||
* ┊ ┊
|
||||
* │ ╰── mark
|
||||
* ╰── trough
|
||||
* ├── [fill]
|
||||
* ├── [highlight]
|
||||
* ╰── slider
|
||||
* ├── [value][.top][.right][.bottom][.left]
|
||||
* ├── trough
|
||||
* │ ├── [fill]
|
||||
* │ ├── [highlight]
|
||||
* │ ╰── slider
|
||||
* ╰── marks.bottom
|
||||
* ├── mark
|
||||
* ┊ ├── indicator
|
||||
* ┊ ╰── [label]
|
||||
* ╰── mark
|
||||
* ]|
|
||||
*
|
||||
* GtkScale has a main CSS node with name scale and a subnode for its contents,
|
||||
@@ -198,6 +197,8 @@ static void gtk_scale_measure (GtkWidget *widget,
|
||||
static void gtk_scale_get_range_border (GtkRange *range,
|
||||
GtkBorder *border);
|
||||
static void gtk_scale_finalize (GObject *object);
|
||||
static void gtk_scale_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot);
|
||||
static void gtk_scale_real_get_layout_offsets (GtkScale *scale,
|
||||
gint *x,
|
||||
gint *y);
|
||||
@@ -660,6 +661,7 @@ gtk_scale_class_init (GtkScaleClass *class)
|
||||
gobject_class->notify = gtk_scale_notify;
|
||||
gobject_class->finalize = gtk_scale_finalize;
|
||||
|
||||
widget_class->snapshot = gtk_scale_snapshot;
|
||||
widget_class->size_allocate = gtk_scale_size_allocate;
|
||||
widget_class->measure = gtk_scale_measure;
|
||||
widget_class->grab_focus = gtk_widget_grab_focus_self;
|
||||
@@ -1091,9 +1093,14 @@ gtk_scale_set_draw_value (GtkScale *scale,
|
||||
"css-name", "value",
|
||||
"label", txt,
|
||||
NULL);
|
||||
|
||||
g_free (txt);
|
||||
|
||||
gtk_widget_insert_after (priv->value_widget, GTK_WIDGET (scale), NULL);
|
||||
if (priv->value_pos == GTK_POS_TOP || priv->value_pos == GTK_POS_LEFT)
|
||||
gtk_widget_insert_after (priv->value_widget, GTK_WIDGET (scale), NULL);
|
||||
else
|
||||
gtk_widget_insert_before (priv->value_widget, GTK_WIDGET (scale), NULL);
|
||||
|
||||
gtk_range_set_round_digits (GTK_RANGE (scale), priv->digits);
|
||||
update_value_position (scale);
|
||||
update_label_request (scale);
|
||||
@@ -1462,6 +1469,25 @@ gtk_scale_measure (GtkWidget *widget,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scale_snapshot (GtkWidget *widget,
|
||||
GtkSnapshot *snapshot)
|
||||
{
|
||||
GtkScale *scale = GTK_SCALE (widget);
|
||||
GtkScalePrivate *priv = gtk_scale_get_instance_private (scale);
|
||||
|
||||
if (priv->top_marks_widget)
|
||||
gtk_widget_snapshot_child (widget, priv->top_marks_widget, snapshot);
|
||||
|
||||
if (priv->bottom_marks_widget)
|
||||
gtk_widget_snapshot_child (widget, priv->bottom_marks_widget, snapshot);
|
||||
|
||||
if (priv->value_widget)
|
||||
gtk_widget_snapshot_child (widget, priv->value_widget, snapshot);
|
||||
|
||||
GTK_WIDGET_CLASS (gtk_scale_parent_class)->snapshot (widget, snapshot);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_scale_real_get_layout_offsets (GtkScale *scale,
|
||||
gint *x,
|
||||
@@ -1696,7 +1722,9 @@ gtk_scale_add_mark (GtkScale *scale,
|
||||
|
||||
gtk_widget_insert_after (priv->top_marks_widget,
|
||||
GTK_WIDGET (scale),
|
||||
priv->value_widget);
|
||||
(priv->value_widget &&
|
||||
(priv->value_pos == GTK_POS_TOP || priv->value_pos == GTK_POS_LEFT)) ?
|
||||
priv->value_widget : NULL);
|
||||
gtk_widget_add_css_class (priv->top_marks_widget, GTK_STYLE_CLASS_TOP);
|
||||
}
|
||||
marks_widget = priv->top_marks_widget;
|
||||
@@ -1714,7 +1742,9 @@ gtk_scale_add_mark (GtkScale *scale,
|
||||
|
||||
gtk_widget_insert_before (priv->bottom_marks_widget,
|
||||
GTK_WIDGET (scale),
|
||||
gtk_range_get_trough_widget (GTK_RANGE (scale)));
|
||||
(priv->value_widget &&
|
||||
(priv->value_pos == GTK_POS_BOTTOM || priv->value_pos == GTK_POS_RIGHT)) ?
|
||||
priv->value_widget: NULL);
|
||||
gtk_widget_add_css_class (priv->bottom_marks_widget, GTK_STYLE_CLASS_BOTTOM);
|
||||
}
|
||||
marks_widget = priv->bottom_marks_widget;
|
||||
|
||||
+2
-13
@@ -546,19 +546,8 @@ gtk_scrolled_window_compute_expand (GtkWidget *widget,
|
||||
gboolean *hexpand,
|
||||
gboolean *vexpand)
|
||||
{
|
||||
GtkScrolledWindow *scrolled_window = GTK_SCROLLED_WINDOW (widget);
|
||||
GtkScrolledWindowPrivate *priv = gtk_scrolled_window_get_instance_private (scrolled_window);
|
||||
|
||||
if (priv->child)
|
||||
{
|
||||
*hexpand = gtk_widget_compute_expand (priv->child, GTK_ORIENTATION_HORIZONTAL);
|
||||
*vexpand = gtk_widget_compute_expand (priv->child, GTK_ORIENTATION_VERTICAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
*hexpand = FALSE;
|
||||
*vexpand = FALSE;
|
||||
}
|
||||
*hexpand = TRUE;
|
||||
*vexpand = TRUE;
|
||||
}
|
||||
|
||||
static GtkSizeRequestMode
|
||||
|
||||
@@ -1,373 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkselectionfiltermodel.h"
|
||||
#include "gtkbitset.h"
|
||||
|
||||
#include "gtkintl.h"
|
||||
#include "gtkprivate.h"
|
||||
|
||||
/**
|
||||
* SECTION:gtkselectionfiltermodel
|
||||
* @title: GtkSelectionFilterModel
|
||||
* @short_description: A list model that turns a selection in a model
|
||||
* @see_also: #GtkSelectionModel
|
||||
*
|
||||
* #GtkSelectionFilterModel is a list model that presents the
|
||||
* selected items in a #GtkSelectionModel as its own list model.
|
||||
*/
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ITEM_TYPE,
|
||||
PROP_MODEL,
|
||||
NUM_PROPERTIES
|
||||
};
|
||||
|
||||
struct _GtkSelectionFilterModel
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GType item_type;
|
||||
GtkSelectionModel *model;
|
||||
GtkBitset *selection;
|
||||
};
|
||||
|
||||
struct _GtkSelectionFilterModelClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
|
||||
|
||||
static GType
|
||||
gtk_selection_filter_model_get_item_type (GListModel *list)
|
||||
{
|
||||
GtkSelectionFilterModel *self = GTK_SELECTION_FILTER_MODEL (list);
|
||||
|
||||
return self->item_type;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_selection_filter_model_get_n_items (GListModel *list)
|
||||
{
|
||||
GtkSelectionFilterModel *self = GTK_SELECTION_FILTER_MODEL (list);
|
||||
|
||||
if (self->selection)
|
||||
return gtk_bitset_get_size (self->selection);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
gtk_selection_filter_model_get_item (GListModel *list,
|
||||
guint position)
|
||||
{
|
||||
GtkSelectionFilterModel *self = GTK_SELECTION_FILTER_MODEL (list);
|
||||
|
||||
position = gtk_bitset_get_nth (self->selection, position);
|
||||
|
||||
return g_list_model_get_item (G_LIST_MODEL (self->model), position);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_selection_filter_model_list_model_init (GListModelInterface *iface)
|
||||
{
|
||||
iface->get_item_type = gtk_selection_filter_model_get_item_type;
|
||||
iface->get_n_items = gtk_selection_filter_model_get_n_items;
|
||||
iface->get_item = gtk_selection_filter_model_get_item;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkSelectionFilterModel, gtk_selection_filter_model, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, gtk_selection_filter_model_list_model_init))
|
||||
|
||||
static void
|
||||
selection_filter_model_items_changed (GtkSelectionFilterModel *self,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added)
|
||||
{
|
||||
GtkBitset *selection;
|
||||
guint sel_position = 0;
|
||||
guint sel_removed = 0;
|
||||
guint sel_added = 0;
|
||||
|
||||
selection = gtk_selection_model_get_selection (self->model);
|
||||
|
||||
if (position > 0)
|
||||
sel_position = gtk_bitset_get_size_in_range (self->selection, 0, position - 1);
|
||||
|
||||
if (removed > 0)
|
||||
sel_removed = gtk_bitset_get_size_in_range (self->selection, position, position + removed - 1);
|
||||
|
||||
if (added > 0)
|
||||
sel_added = gtk_bitset_get_size_in_range (selection, position, position + added - 1);
|
||||
|
||||
gtk_bitset_unref (self->selection);
|
||||
self->selection = gtk_bitset_copy (selection);
|
||||
|
||||
gtk_bitset_unref (selection);
|
||||
|
||||
if (sel_removed > 0 || sel_added > 0)
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), sel_position, sel_removed, sel_added);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_selection_filter_model_items_changed_cb (GListModel *model,
|
||||
guint position,
|
||||
guint removed,
|
||||
guint added,
|
||||
GtkSelectionFilterModel *self)
|
||||
{
|
||||
selection_filter_model_items_changed (self, position, removed, added);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_selection_filter_model_selection_changed_cb (GListModel *model,
|
||||
guint position,
|
||||
guint n_items,
|
||||
GtkSelectionFilterModel *self)
|
||||
{
|
||||
selection_filter_model_items_changed (self, position, n_items, n_items);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_selection_filter_model_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkSelectionFilterModel *self = GTK_SELECTION_FILTER_MODEL (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ITEM_TYPE:
|
||||
self->item_type = g_value_get_gtype (value);
|
||||
break;
|
||||
|
||||
case PROP_MODEL:
|
||||
gtk_selection_filter_model_set_model (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_selection_filter_model_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkSelectionFilterModel *self = GTK_SELECTION_FILTER_MODEL (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_ITEM_TYPE:
|
||||
g_value_set_gtype (value, self->item_type);
|
||||
break;
|
||||
|
||||
case PROP_MODEL:
|
||||
g_value_set_object (value, self->model);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_selection_filter_model_clear_model (GtkSelectionFilterModel *self)
|
||||
{
|
||||
if (self->model == NULL)
|
||||
return;
|
||||
|
||||
g_signal_handlers_disconnect_by_func (self->model, gtk_selection_filter_model_items_changed_cb, self);
|
||||
g_signal_handlers_disconnect_by_func (self->model, gtk_selection_filter_model_selection_changed_cb, self);
|
||||
|
||||
g_clear_object (&self->model);
|
||||
g_clear_pointer (&self->selection, gtk_bitset_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_selection_filter_model_dispose (GObject *object)
|
||||
{
|
||||
GtkSelectionFilterModel *self = GTK_SELECTION_FILTER_MODEL (object);
|
||||
|
||||
gtk_selection_filter_model_clear_model (self);
|
||||
|
||||
G_OBJECT_CLASS (gtk_selection_filter_model_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_selection_filter_model_class_init (GtkSelectionFilterModelClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
|
||||
gobject_class->set_property = gtk_selection_filter_model_set_property;
|
||||
gobject_class->get_property = gtk_selection_filter_model_get_property;
|
||||
gobject_class->dispose = gtk_selection_filter_model_dispose;
|
||||
|
||||
/**
|
||||
* GtkSelectionFilterModel:item-type:
|
||||
*
|
||||
* The #GType for elements of this object
|
||||
*/
|
||||
properties[PROP_ITEM_TYPE] =
|
||||
g_param_spec_gtype ("item-type",
|
||||
P_("Item type"),
|
||||
P_("The type of elements of this object"),
|
||||
G_TYPE_OBJECT,
|
||||
GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GtkSelectionFilterModel:model:
|
||||
*
|
||||
* The model being filtered
|
||||
*/
|
||||
properties[PROP_MODEL] =
|
||||
g_param_spec_object ("model",
|
||||
P_("Model"),
|
||||
P_("The model being filtered"),
|
||||
GTK_TYPE_SELECTION_MODEL,
|
||||
GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, NUM_PROPERTIES, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_selection_filter_model_init (GtkSelectionFilterModel *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_selection_filter_model_new:
|
||||
* @model: the selection model to filter
|
||||
*
|
||||
* Creates a new #GtkSelectionFilterModel that will include the
|
||||
* selected items from the underlying selection model.
|
||||
*
|
||||
* Returns: a new #GtkSelectionFilterModel
|
||||
**/
|
||||
GtkSelectionFilterModel *
|
||||
gtk_selection_filter_model_new (GtkSelectionModel *model)
|
||||
{
|
||||
GtkSelectionFilterModel *result;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_SELECTION_MODEL (model), NULL);
|
||||
|
||||
result = g_object_new (GTK_TYPE_SELECTION_FILTER_MODEL,
|
||||
"item-type", g_list_model_get_item_type (G_LIST_MODEL (model)),
|
||||
"model", model,
|
||||
NULL);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_selection_filter_model_new_for_type:
|
||||
* @item_type: the type of the items that will be returned
|
||||
*
|
||||
* Creates a new empty selection filter model set up to return items
|
||||
* of type @item_type. It is up to the application to set a proper
|
||||
* selection model to ensure the item type is matched.
|
||||
*
|
||||
* Returns: a new #GtkSelectionFilterModel
|
||||
**/
|
||||
GtkSelectionFilterModel *
|
||||
gtk_selection_filter_model_new_for_type (GType item_type)
|
||||
{
|
||||
g_return_val_if_fail (g_type_is_a (item_type, G_TYPE_OBJECT), NULL);
|
||||
|
||||
return g_object_new (GTK_TYPE_SELECTION_FILTER_MODEL,
|
||||
"item-type", item_type,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_selection_filter_model_set_model:
|
||||
* @self: a #GtkSelectionFilterModel
|
||||
* @model: (allow-none): The model to be filtered
|
||||
*
|
||||
* Sets the model to be filtered.
|
||||
*
|
||||
* Note that GTK makes no effort to ensure that @model conforms to
|
||||
* the item type of @self. It assumes that the caller knows what they
|
||||
* are doing and have set up an appropriate filter to ensure that item
|
||||
* types match.
|
||||
**/
|
||||
void
|
||||
gtk_selection_filter_model_set_model (GtkSelectionFilterModel *self,
|
||||
GtkSelectionModel *model)
|
||||
{
|
||||
guint removed, added;
|
||||
|
||||
g_return_if_fail (GTK_IS_SELECTION_FILTER_MODEL (self));
|
||||
g_return_if_fail (model == NULL || GTK_IS_SELECTION_MODEL (model));
|
||||
g_return_if_fail (model == NULL || g_type_is_a (g_list_model_get_item_type (G_LIST_MODEL (model)),
|
||||
self->item_type));
|
||||
|
||||
if (self->model == model)
|
||||
return;
|
||||
|
||||
removed = g_list_model_get_n_items (G_LIST_MODEL (self));
|
||||
gtk_selection_filter_model_clear_model (self);
|
||||
|
||||
if (model)
|
||||
{
|
||||
GtkBitset *selection;
|
||||
|
||||
self->model = g_object_ref (model);
|
||||
|
||||
selection = gtk_selection_model_get_selection (self->model);
|
||||
self->selection = gtk_bitset_copy (selection);
|
||||
gtk_bitset_unref (selection);
|
||||
|
||||
g_signal_connect (model, "items-changed", G_CALLBACK (gtk_selection_filter_model_items_changed_cb), self);
|
||||
g_signal_connect (model, "selection-changed", G_CALLBACK (gtk_selection_filter_model_selection_changed_cb), self);
|
||||
}
|
||||
|
||||
added = g_list_model_get_n_items (G_LIST_MODEL (self));
|
||||
|
||||
if (removed > 0 || added > 0)
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), 0, removed, added);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_MODEL]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_selection_filter_model_get_model:
|
||||
* @self: a #GtkSelectionFilterModel
|
||||
*
|
||||
* Gets the model currently filtered or %NULL if none.
|
||||
*
|
||||
* Returns: (nullable) (transfer none): The model that gets filtered
|
||||
**/
|
||||
GtkSelectionModel *
|
||||
gtk_selection_filter_model_get_model (GtkSelectionFilterModel *self)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_SELECTION_FILTER_MODEL (self), NULL);
|
||||
|
||||
return self->model;
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Matthias Clasen
|
||||
*/
|
||||
|
||||
#ifndef __GTK_SELECTION_FILTER_MODEL_H__
|
||||
#define __GTK_SELECTION_FILTER_MODEL_H__
|
||||
|
||||
|
||||
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gtk/gtk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gtk/gtkselectionmodel.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GTK_TYPE_SELECTION_FILTER_MODEL (gtk_selection_filter_model_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkSelectionFilterModel, gtk_selection_filter_model, GTK, SELECTION_FILTER_MODEL, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkSelectionFilterModel * gtk_selection_filter_model_new (GtkSelectionModel *model);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkSelectionFilterModel * gtk_selection_filter_model_new_for_type (GType item_type);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_selection_filter_model_set_model (GtkSelectionFilterModel *self,
|
||||
GtkSelectionModel *model);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkSelectionModel * gtk_selection_filter_model_get_model (GtkSelectionFilterModel *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SELECTION_FILTER_MODEL_H__ */
|
||||
@@ -860,7 +860,9 @@ gtk_shortcuts_window_init (GtkShortcutsWindow *self)
|
||||
priv->search_text_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
||||
priv->search_image_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
||||
|
||||
priv->header_bar = GTK_HEADER_BAR (gtk_header_bar_new ());
|
||||
priv->header_bar = g_object_new (GTK_TYPE_HEADER_BAR,
|
||||
"show-title-buttons", TRUE,
|
||||
NULL);
|
||||
gtk_window_set_titlebar (GTK_WINDOW (self), GTK_WIDGET (priv->header_bar));
|
||||
|
||||
search_button = g_object_new (GTK_TYPE_TOGGLE_BUTTON,
|
||||
|
||||
+115
-32
@@ -34,6 +34,11 @@
|
||||
|
||||
#include "gtk/gskpango.h"
|
||||
|
||||
#define GTK_VECTOR_NAME gtk_snapshot_nodes
|
||||
#define GTK_VECTOR_TYPE_NAME GtkSnapshotNodes
|
||||
#define GTK_VECTOR_ELEMENT_TYPE GskRenderNode *
|
||||
#define GTK_VECTOR_FREE_FUNC gsk_render_node_unref
|
||||
#include "gtkvectorimpl.c"
|
||||
|
||||
/**
|
||||
* SECTION:gtksnapshot
|
||||
@@ -54,6 +59,85 @@
|
||||
* use gtk_snapshot_new().
|
||||
*/
|
||||
|
||||
typedef struct _GtkSnapshotState GtkSnapshotState;
|
||||
|
||||
typedef GskRenderNode * (* GtkSnapshotCollectFunc) (GtkSnapshot *snapshot,
|
||||
GtkSnapshotState *state,
|
||||
GskRenderNode **nodes,
|
||||
guint n_nodes);
|
||||
|
||||
struct _GtkSnapshotState {
|
||||
guint start_node_index;
|
||||
guint n_nodes;
|
||||
|
||||
GskTransform * transform;
|
||||
|
||||
GtkSnapshotCollectFunc collect_func;
|
||||
union {
|
||||
struct {
|
||||
double opacity;
|
||||
} opacity;
|
||||
struct {
|
||||
double radius;
|
||||
} blur;
|
||||
struct {
|
||||
graphene_matrix_t matrix;
|
||||
graphene_vec4_t offset;
|
||||
} color_matrix;
|
||||
struct {
|
||||
graphene_rect_t bounds;
|
||||
graphene_rect_t child_bounds;
|
||||
} repeat;
|
||||
struct {
|
||||
graphene_rect_t bounds;
|
||||
} clip;
|
||||
struct {
|
||||
GskRoundedRect bounds;
|
||||
} rounded_clip;
|
||||
struct {
|
||||
gsize n_shadows;
|
||||
GskShadow *shadows;
|
||||
GskShadow a_shadow; /* Used if n_shadows == 1 */
|
||||
} shadow;
|
||||
struct {
|
||||
GskBlendMode blend_mode;
|
||||
GskRenderNode *bottom_node;
|
||||
} blend;
|
||||
struct {
|
||||
double progress;
|
||||
GskRenderNode *start_node;
|
||||
} cross_fade;
|
||||
struct {
|
||||
char *message;
|
||||
} debug;
|
||||
} data;
|
||||
};
|
||||
|
||||
static void gtk_snapshot_state_clear (GtkSnapshotState *state);
|
||||
|
||||
#define GTK_VECTOR_NAME gtk_snapshot_states
|
||||
#define GTK_VECTOR_TYPE_NAME GtkSnapshotStates
|
||||
#define GTK_VECTOR_ELEMENT_TYPE GtkSnapshotState
|
||||
#define GTK_VECTOR_FREE_FUNC gtk_snapshot_state_clear
|
||||
#define GTK_VECTOR_BY_VALUE 1
|
||||
#include "gtkvectorimpl.c"
|
||||
|
||||
/* This is a nasty little hack. We typedef GtkSnapshot to the fake object GdkSnapshot
|
||||
* so that we don't need to typecast between them.
|
||||
* After all, the GdkSnapshot only exist so poor language bindings don't trip. Hardcore
|
||||
* C code can just blatantly ignore such layering violations with a typedef.
|
||||
*/
|
||||
struct _GdkSnapshot {
|
||||
GObject parent_instance; /* it's really GdkSnapshot, but don't tell anyone! */
|
||||
|
||||
GtkSnapshotStates state_stack;
|
||||
GtkSnapshotNodes nodes;
|
||||
};
|
||||
|
||||
struct _GtkSnapshotClass {
|
||||
GObjectClass parent_class; /* it's really GdkSnapshotClass, but don't tell anyone! */
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkSnapshot, gtk_snapshot, GDK_TYPE_SNAPSHOT)
|
||||
|
||||
static void
|
||||
@@ -61,11 +145,11 @@ gtk_snapshot_dispose (GObject *object)
|
||||
{
|
||||
GtkSnapshot *snapshot = GTK_SNAPSHOT (object);
|
||||
|
||||
if (snapshot->state_stack)
|
||||
if (!gtk_snapshot_states_is_empty (&snapshot->state_stack))
|
||||
gsk_render_node_unref (gtk_snapshot_to_node (snapshot));
|
||||
|
||||
g_assert (snapshot->state_stack == NULL);
|
||||
g_assert (snapshot->nodes == NULL);
|
||||
g_assert (gtk_snapshot_states_is_empty (&snapshot->state_stack));
|
||||
g_assert (gtk_snapshot_nodes_is_empty (&snapshot->nodes));
|
||||
|
||||
G_OBJECT_CLASS (gtk_snapshot_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -112,15 +196,15 @@ gtk_snapshot_push_state (GtkSnapshot *snapshot,
|
||||
GskTransform *transform,
|
||||
GtkSnapshotCollectFunc collect_func)
|
||||
{
|
||||
const gsize n_states = snapshot->state_stack->len;
|
||||
const gsize n_states = gtk_snapshot_states_get_size (&snapshot->state_stack);
|
||||
GtkSnapshotState *state;
|
||||
|
||||
g_array_set_size (snapshot->state_stack, n_states + 1);
|
||||
state = &g_array_index (snapshot->state_stack, GtkSnapshotState, n_states);
|
||||
gtk_snapshot_states_set_size (&snapshot->state_stack, n_states + 1);
|
||||
state = gtk_snapshot_states_get (&snapshot->state_stack, n_states);
|
||||
|
||||
state->transform = gsk_transform_ref (transform);
|
||||
state->collect_func = collect_func;
|
||||
state->start_node_index = snapshot->nodes->len;
|
||||
state->start_node_index = gtk_snapshot_nodes_get_size (&snapshot->nodes);
|
||||
state->n_nodes = 0;
|
||||
|
||||
return state;
|
||||
@@ -129,17 +213,21 @@ gtk_snapshot_push_state (GtkSnapshot *snapshot,
|
||||
static GtkSnapshotState *
|
||||
gtk_snapshot_get_current_state (const GtkSnapshot *snapshot)
|
||||
{
|
||||
g_assert (snapshot->state_stack->len > 0);
|
||||
gsize size = gtk_snapshot_states_get_size (&snapshot->state_stack);
|
||||
|
||||
return &g_array_index (snapshot->state_stack, GtkSnapshotState, snapshot->state_stack->len - 1);
|
||||
g_assert (size > 0);
|
||||
|
||||
return gtk_snapshot_states_get (&snapshot->state_stack, size - 1);
|
||||
}
|
||||
|
||||
static GtkSnapshotState *
|
||||
gtk_snapshot_get_previous_state (const GtkSnapshot *snapshot)
|
||||
{
|
||||
g_assert (snapshot->state_stack->len > 1);
|
||||
gsize size = gtk_snapshot_states_get_size (&snapshot->state_stack);
|
||||
|
||||
return &g_array_index (snapshot->state_stack, GtkSnapshotState, snapshot->state_stack->len - 2);
|
||||
g_assert (size > 1);
|
||||
|
||||
return gtk_snapshot_states_get (&snapshot->state_stack, size - 2);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -162,9 +250,8 @@ gtk_snapshot_new (void)
|
||||
|
||||
snapshot = g_object_new (GTK_TYPE_SNAPSHOT, NULL);
|
||||
|
||||
snapshot->state_stack = g_array_new (FALSE, TRUE, sizeof (GtkSnapshotState));
|
||||
g_array_set_clear_func (snapshot->state_stack, (GDestroyNotify)gtk_snapshot_state_clear);
|
||||
snapshot->nodes = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_render_node_unref);
|
||||
gtk_snapshot_states_init (&snapshot->state_stack);
|
||||
gtk_snapshot_nodes_init (&snapshot->nodes);
|
||||
|
||||
gtk_snapshot_push_state (snapshot,
|
||||
NULL,
|
||||
@@ -1029,30 +1116,28 @@ gtk_snapshot_pop_one (GtkSnapshot *snapshot)
|
||||
guint state_index;
|
||||
GskRenderNode *node;
|
||||
|
||||
if (snapshot->state_stack->len == 0)
|
||||
if (gtk_snapshot_states_is_empty (&snapshot->state_stack))
|
||||
{
|
||||
g_warning ("Too many gtk_snapshot_pop() calls.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state = gtk_snapshot_get_current_state (snapshot);
|
||||
state_index = snapshot->state_stack->len - 1;
|
||||
state_index = gtk_snapshot_states_get_size (&snapshot->state_stack) - 1;
|
||||
|
||||
if (state->collect_func)
|
||||
{
|
||||
node = state->collect_func (snapshot,
|
||||
state,
|
||||
(GskRenderNode **) snapshot->nodes->pdata + state->start_node_index,
|
||||
(GskRenderNode **) gtk_snapshot_nodes_index (&snapshot->nodes, state->start_node_index),
|
||||
state->n_nodes);
|
||||
|
||||
/* The collect func may not modify the state stack... */
|
||||
g_assert (state_index == snapshot->state_stack->len - 1);
|
||||
g_assert (state_index == gtk_snapshot_states_get_size (&snapshot->state_stack) - 1);
|
||||
|
||||
/* Remove all the state's nodes from the list of nodes */
|
||||
g_assert (state->start_node_index + state->n_nodes == snapshot->nodes->len);
|
||||
g_ptr_array_remove_range (snapshot->nodes,
|
||||
snapshot->nodes->len - state->n_nodes,
|
||||
state->n_nodes);
|
||||
g_assert (state->start_node_index + state->n_nodes == gtk_snapshot_nodes_get_size (&snapshot->nodes));
|
||||
gtk_snapshot_nodes_splice (&snapshot->nodes, state->start_node_index, state->n_nodes, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1063,10 +1148,10 @@ gtk_snapshot_pop_one (GtkSnapshot *snapshot)
|
||||
/* move the nodes to the parent */
|
||||
previous_state = gtk_snapshot_get_previous_state (snapshot);
|
||||
previous_state->n_nodes += state->n_nodes;
|
||||
g_assert (previous_state->start_node_index + previous_state->n_nodes == snapshot->nodes->len);
|
||||
g_assert (previous_state->start_node_index + previous_state->n_nodes == gtk_snapshot_nodes_get_size (&snapshot->nodes));
|
||||
}
|
||||
|
||||
g_array_remove_index (snapshot->state_stack, state_index);
|
||||
gtk_snapshot_states_splice (&snapshot->state_stack, state_index, 1, NULL, 0);
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -1081,7 +1166,7 @@ gtk_snapshot_append_node_internal (GtkSnapshot *snapshot,
|
||||
|
||||
if (current_state)
|
||||
{
|
||||
g_ptr_array_add (snapshot->nodes, node);
|
||||
gtk_snapshot_nodes_append (&snapshot->nodes, node);
|
||||
current_state->n_nodes ++;
|
||||
}
|
||||
else
|
||||
@@ -1162,16 +1247,14 @@ gtk_snapshot_to_node (GtkSnapshot *snapshot)
|
||||
result = gtk_snapshot_pop_internal (snapshot);
|
||||
|
||||
/* We should have exactly our initial state */
|
||||
if (snapshot->state_stack->len > 0)
|
||||
if (!gtk_snapshot_states_is_empty (&snapshot->state_stack))
|
||||
{
|
||||
g_warning ("Too many gtk_snapshot_push() calls. %u states remaining.", snapshot->state_stack->len);
|
||||
g_warning ("Too many gtk_snapshot_push() calls. %zu states remaining.",
|
||||
gtk_snapshot_states_get_size (&snapshot->state_stack));
|
||||
}
|
||||
|
||||
g_array_free (snapshot->state_stack, TRUE);
|
||||
g_ptr_array_free (snapshot->nodes, TRUE);
|
||||
|
||||
snapshot->state_stack = NULL;
|
||||
snapshot->nodes = NULL;
|
||||
gtk_snapshot_states_clear (&snapshot->state_stack);
|
||||
gtk_snapshot_nodes_clear (&snapshot->nodes);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -24,76 +24,6 @@
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkSnapshotState GtkSnapshotState;
|
||||
|
||||
typedef GskRenderNode * (* GtkSnapshotCollectFunc) (GtkSnapshot *snapshot,
|
||||
GtkSnapshotState *state,
|
||||
GskRenderNode **nodes,
|
||||
guint n_nodes);
|
||||
|
||||
struct _GtkSnapshotState {
|
||||
guint start_node_index;
|
||||
guint n_nodes;
|
||||
|
||||
GskTransform * transform;
|
||||
|
||||
GtkSnapshotCollectFunc collect_func;
|
||||
union {
|
||||
struct {
|
||||
double opacity;
|
||||
} opacity;
|
||||
struct {
|
||||
double radius;
|
||||
} blur;
|
||||
struct {
|
||||
graphene_matrix_t matrix;
|
||||
graphene_vec4_t offset;
|
||||
} color_matrix;
|
||||
struct {
|
||||
graphene_rect_t bounds;
|
||||
graphene_rect_t child_bounds;
|
||||
} repeat;
|
||||
struct {
|
||||
graphene_rect_t bounds;
|
||||
} clip;
|
||||
struct {
|
||||
GskRoundedRect bounds;
|
||||
} rounded_clip;
|
||||
struct {
|
||||
gsize n_shadows;
|
||||
GskShadow *shadows;
|
||||
GskShadow a_shadow; /* Used if n_shadows == 1 */
|
||||
} shadow;
|
||||
struct {
|
||||
GskBlendMode blend_mode;
|
||||
GskRenderNode *bottom_node;
|
||||
} blend;
|
||||
struct {
|
||||
double progress;
|
||||
GskRenderNode *start_node;
|
||||
} cross_fade;
|
||||
struct {
|
||||
char *message;
|
||||
} debug;
|
||||
} data;
|
||||
};
|
||||
|
||||
/* This is a nasty little hack. We typedef GtkSnapshot to the fake object GdkSnapshot
|
||||
* so that we don't need to typecast between them.
|
||||
* After all, the GdkSnapshot only exist so poor language bindings don't trip. Hardcore
|
||||
* C code can just blatantly ignore such layering violations with a typedef.
|
||||
*/
|
||||
struct _GdkSnapshot {
|
||||
GObject parent_instance; /* it's really GdkSnapshot, but don't tell anyone! */
|
||||
|
||||
GArray *state_stack;
|
||||
GPtrArray *nodes;
|
||||
};
|
||||
|
||||
struct _GtkSnapshotClass {
|
||||
GObjectClass parent_class; /* it's really GdkSnapshotClass, but don't tell anyone! */
|
||||
};
|
||||
|
||||
void gtk_snapshot_append_text (GtkSnapshot *snapshot,
|
||||
PangoFont *font,
|
||||
PangoGlyphString *glyphs,
|
||||
|
||||
@@ -110,9 +110,9 @@ gtk_string_filter_match (GtkFilter *filter,
|
||||
!gtk_expression_evaluate (self->expression, item, &value))
|
||||
return FALSE;
|
||||
s = g_value_get_string (&value);
|
||||
if (s == NULL)
|
||||
return FALSE;
|
||||
prepared = gtk_string_filter_prepare (self, s);
|
||||
if (prepared == NULL)
|
||||
return FALSE;
|
||||
|
||||
switch (self->match_mode)
|
||||
{
|
||||
|
||||
+26
-30
@@ -138,20 +138,13 @@ gtk_string_object_class_init (GtkStringObjectClass *class)
|
||||
|
||||
pspec = g_param_spec_string ("string", "String", "String",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_property (object_class, PROP_STRING, pspec);
|
||||
|
||||
}
|
||||
|
||||
static GtkStringObject *
|
||||
gtk_string_object_new (const char *string)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_STRING_OBJECT, "string", string, NULL);
|
||||
}
|
||||
|
||||
static GtkStringObject *
|
||||
gtk_string_object_new_take (char *string)
|
||||
{
|
||||
@@ -163,6 +156,12 @@ gtk_string_object_new_take (char *string)
|
||||
return obj;
|
||||
}
|
||||
|
||||
static GtkStringObject *
|
||||
gtk_string_object_new (const char *string)
|
||||
{
|
||||
return gtk_string_object_new_take (g_strdup (string));
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_string_object_get_string:
|
||||
* @self: a #GtkStringObject
|
||||
@@ -432,15 +431,13 @@ gtk_string_list_init (GtkStringList *self)
|
||||
* Returns: a new #GtkStringList
|
||||
*/
|
||||
GtkStringList *
|
||||
gtk_string_list_new (const char **strings)
|
||||
gtk_string_list_new (const char * const *strings)
|
||||
{
|
||||
GtkStringList *self;
|
||||
guint i;
|
||||
|
||||
self = g_object_new (GTK_TYPE_STRING_LIST, NULL);
|
||||
|
||||
for (i = 0; strings[i]; i++)
|
||||
g_sequence_append (self->items, gtk_string_object_new (strings[i]));
|
||||
gtk_string_list_splice (self, 0, 0, strings);
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -450,11 +447,10 @@ gtk_string_list_new (const char **strings)
|
||||
* @self: a #GtkStringList
|
||||
* @position: the position at which to make the change
|
||||
* @n_removals: the number of strings to remove
|
||||
* @additions: (array length=n_additions): the strings to add
|
||||
* @n_additions: the number of items to add
|
||||
* @additions: (array zero-terminated=1) (nullable): The strings to add
|
||||
*
|
||||
* Changes @self by removing @n_removals strings and adding @n_additions
|
||||
* strings to it.
|
||||
* Changes @self by removing @n_removals strings and adding @additions
|
||||
* to it.
|
||||
*
|
||||
* This function is more efficient than gtk_string_list_insert() and
|
||||
* gtk_string_list_remove(), because it only emits
|
||||
@@ -467,14 +463,13 @@ gtk_string_list_new (const char **strings)
|
||||
* of the list at the time this function is called).
|
||||
*/
|
||||
void
|
||||
gtk_string_list_splice (GtkStringList *self,
|
||||
guint position,
|
||||
guint n_removals,
|
||||
const char **additions,
|
||||
guint n_additions)
|
||||
gtk_string_list_splice (GtkStringList *self,
|
||||
guint position,
|
||||
guint n_removals,
|
||||
const char * const *additions)
|
||||
{
|
||||
GSequenceIter *it;
|
||||
guint n_items;
|
||||
guint add, n_items;
|
||||
|
||||
g_return_if_fail (GTK_IS_STRING_LIST (self));
|
||||
g_return_if_fail (position + n_removals >= position); /* overflow */
|
||||
@@ -494,17 +489,18 @@ gtk_string_list_splice (GtkStringList *self,
|
||||
it = end;
|
||||
}
|
||||
|
||||
if (n_additions)
|
||||
if (additions)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < n_additions; i++)
|
||||
for (add = 0; additions[add]; add++)
|
||||
{
|
||||
g_sequence_insert_before (it, gtk_string_object_new (additions[i]));
|
||||
g_sequence_insert_before (it, gtk_string_object_new (additions[add]));
|
||||
}
|
||||
}
|
||||
else
|
||||
add = 0;
|
||||
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), position, n_removals, n_additions);
|
||||
if (n_removals || add)
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), position, n_removals, add);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -589,8 +585,8 @@ gtk_string_list_remove (GtkStringList *self,
|
||||
* @self: a #GtkStringList
|
||||
* @position: the position to get the string for
|
||||
*
|
||||
* Gets the string that is at @position in @self. @position
|
||||
* must be smaller than the current length of the list.
|
||||
* Gets the string that is at @position in @self. If @self
|
||||
* does not contain @position items, %NULL is returned.
|
||||
*
|
||||
* This function returns the const char *. To get the
|
||||
* object wrapping it, use g_list_model_get_item().
|
||||
|
||||
+13
-14
@@ -45,30 +45,29 @@ GDK_AVAILABLE_IN_ALL
|
||||
G_DECLARE_FINAL_TYPE (GtkStringList, gtk_string_list, GTK, STRING_LIST, GObject)
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkStringList * gtk_string_list_new (const char **strings);
|
||||
GtkStringList * gtk_string_list_new (const char * const *strings);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_string_list_append (GtkStringList *self,
|
||||
const char *string);
|
||||
void gtk_string_list_append (GtkStringList *self,
|
||||
const char *string);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_string_list_take (GtkStringList *self,
|
||||
char *string);
|
||||
void gtk_string_list_take (GtkStringList *self,
|
||||
char *string);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_string_list_remove (GtkStringList *self,
|
||||
guint position);
|
||||
void gtk_string_list_remove (GtkStringList *self,
|
||||
guint position);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_string_list_splice (GtkStringList *self,
|
||||
guint position,
|
||||
guint n_removals,
|
||||
const char **additions,
|
||||
guint n_additions);
|
||||
void gtk_string_list_splice (GtkStringList *self,
|
||||
guint position,
|
||||
guint n_removals,
|
||||
const char * const *additions);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
const char * gtk_string_list_get_string (GtkStringList *self,
|
||||
guint position);
|
||||
const char * gtk_string_list_get_string (GtkStringList *self,
|
||||
guint position);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
+72
-20
@@ -111,13 +111,27 @@ struct _GtkTextLayoutPrivate
|
||||
GtkTextLineDisplayCache *cache;
|
||||
};
|
||||
|
||||
static GtkTextLineData *gtk_text_layout_real_wrap (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
/* may be NULL */
|
||||
GtkTextLineData *line_data);
|
||||
|
||||
static void gtk_text_layout_invalidated (GtkTextLayout *layout);
|
||||
|
||||
static void gtk_text_layout_real_invalidate (GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end);
|
||||
static void gtk_text_layout_real_invalidate_cursors(GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end);
|
||||
static void gtk_text_layout_invalidate_cache (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
gboolean cursors_only);
|
||||
static void gtk_text_layout_invalidate_cursor_line (GtkTextLayout *layout,
|
||||
gboolean cursors_only);
|
||||
static void gtk_text_layout_real_free_line_data (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
GtkTextLineData *line_data);
|
||||
static void gtk_text_layout_emit_changed (GtkTextLayout *layout,
|
||||
gint y,
|
||||
gint old_height,
|
||||
@@ -235,11 +249,16 @@ gtk_text_layout_class_init (GtkTextLayoutClass *klass)
|
||||
object_class->dispose = gtk_text_layout_dispose;
|
||||
object_class->finalize = gtk_text_layout_finalize;
|
||||
|
||||
klass->wrap = gtk_text_layout_real_wrap;
|
||||
klass->invalidate = gtk_text_layout_real_invalidate;
|
||||
klass->invalidate_cursors = gtk_text_layout_real_invalidate_cursors;
|
||||
klass->free_line_data = gtk_text_layout_real_free_line_data;
|
||||
|
||||
signals[INVALIDATED] =
|
||||
g_signal_new (I_("invalidated"),
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
G_STRUCT_OFFSET (GtkTextLayoutClass, invalidated),
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE,
|
||||
@@ -249,7 +268,7 @@ gtk_text_layout_class_init (GtkTextLayoutClass *klass)
|
||||
g_signal_new (I_("changed"),
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
G_STRUCT_OFFSET (GtkTextLayoutClass, changed),
|
||||
NULL, NULL,
|
||||
_gtk_marshal_VOID__INT_INT_INT,
|
||||
G_TYPE_NONE,
|
||||
@@ -264,7 +283,7 @@ gtk_text_layout_class_init (GtkTextLayoutClass *klass)
|
||||
g_signal_new (I_("allocate-child"),
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
G_STRUCT_OFFSET (GtkTextLayoutClass, allocate_child),
|
||||
NULL, NULL,
|
||||
_gtk_marshal_VOID__OBJECT_INT_INT,
|
||||
G_TYPE_NONE,
|
||||
@@ -671,6 +690,39 @@ gtk_text_layout_cursors_changed (GtkTextLayout *layout,
|
||||
gtk_text_layout_emit_changed (layout, y, old_height, new_height);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_text_layout_free_line_data (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
GtkTextLineData *line_data)
|
||||
{
|
||||
GTK_TEXT_LAYOUT_GET_CLASS (layout)->free_line_data (layout, line, line_data);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_text_layout_invalidate (GtkTextLayout *layout,
|
||||
const GtkTextIter *start_index,
|
||||
const GtkTextIter *end_index)
|
||||
{
|
||||
GTK_TEXT_LAYOUT_GET_CLASS (layout)->invalidate (layout, start_index, end_index);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_text_layout_invalidate_cursors (GtkTextLayout *layout,
|
||||
const GtkTextIter *start_index,
|
||||
const GtkTextIter *end_index)
|
||||
{
|
||||
GTK_TEXT_LAYOUT_GET_CLASS (layout)->invalidate_cursors (layout, start_index, end_index);
|
||||
}
|
||||
|
||||
GtkTextLineData*
|
||||
gtk_text_layout_wrap (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
/* may be NULL */
|
||||
GtkTextLineData *line_data)
|
||||
{
|
||||
return GTK_TEXT_LAYOUT_GET_CLASS (layout)->wrap (layout, line, line_data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* gtk_text_layout_get_lines:
|
||||
@@ -840,10 +892,10 @@ gtk_text_layout_update_cursor_line (GtkTextLayout *layout)
|
||||
gtk_text_line_display_cache_set_cursor_line (priv->cache, priv->cursor_line);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_text_layout_invalidate (GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end)
|
||||
static void
|
||||
gtk_text_layout_real_invalidate (GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end)
|
||||
{
|
||||
GtkTextLine *line;
|
||||
GtkTextLine *last_line;
|
||||
@@ -884,20 +936,20 @@ gtk_text_layout_invalidate (GtkTextLayout *layout,
|
||||
gtk_text_layout_invalidated (layout);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_text_layout_invalidate_cursors (GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end)
|
||||
static void
|
||||
gtk_text_layout_real_invalidate_cursors (GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end)
|
||||
{
|
||||
GtkTextLayoutPrivate *priv = GTK_TEXT_LAYOUT_GET_PRIVATE (layout);
|
||||
gtk_text_line_display_cache_invalidate_range (priv->cache, layout, start, end, TRUE);
|
||||
gtk_text_layout_invalidated (layout);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_text_layout_free_line_data (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
GtkTextLineData *line_data)
|
||||
static void
|
||||
gtk_text_layout_real_free_line_data (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
GtkTextLineData *line_data)
|
||||
{
|
||||
gtk_text_layout_invalidate_cache (layout, line, FALSE);
|
||||
|
||||
@@ -1096,11 +1148,11 @@ gtk_text_layout_validate (GtkTextLayout *layout,
|
||||
}
|
||||
}
|
||||
|
||||
GtkTextLineData *
|
||||
gtk_text_layout_wrap (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
/* may be NULL */
|
||||
GtkTextLineData *line_data)
|
||||
static GtkTextLineData*
|
||||
gtk_text_layout_real_wrap (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
/* may be NULL */
|
||||
GtkTextLineData *line_data)
|
||||
{
|
||||
GtkTextLineDisplay *display;
|
||||
PangoRectangle ink_rect, logical_rect;
|
||||
|
||||
@@ -167,6 +167,44 @@ struct _GtkTextLayout
|
||||
struct _GtkTextLayoutClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* Some portion of the layout was invalidated
|
||||
*/
|
||||
void (*invalidated) (GtkTextLayout *layout);
|
||||
|
||||
/* A range of the layout changed appearance and possibly height
|
||||
*/
|
||||
void (*changed) (GtkTextLayout *layout,
|
||||
gint y,
|
||||
gint old_height,
|
||||
gint new_height);
|
||||
GtkTextLineData* (*wrap) (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
GtkTextLineData *line_data); /* may be NULL */
|
||||
void (*get_log_attrs) (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
PangoLogAttr **attrs,
|
||||
gint *n_attrs);
|
||||
void (*invalidate) (GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end);
|
||||
void (*free_line_data) (GtkTextLayout *layout,
|
||||
GtkTextLine *line,
|
||||
GtkTextLineData *line_data);
|
||||
|
||||
void (*allocate_child) (GtkTextLayout *layout,
|
||||
GtkWidget *child,
|
||||
gint x,
|
||||
gint y);
|
||||
|
||||
void (*invalidate_cursors) (GtkTextLayout *layout,
|
||||
const GtkTextIter *start,
|
||||
const GtkTextIter *end);
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_gtk_reserved1) (void);
|
||||
void (*_gtk_reserved2) (void);
|
||||
void (*_gtk_reserved3) (void);
|
||||
};
|
||||
|
||||
struct _GtkTextAttrAppearance
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
#define SCREEN_HEIGHT(widget) text_window_get_height (GTK_TEXT_VIEW (widget)->priv->text_window)
|
||||
|
||||
#define SPACE_FOR_CURSOR 1
|
||||
#define CURSOR_ASPECT_RATIO (0.04)
|
||||
|
||||
typedef struct _GtkTextWindow GtkTextWindow;
|
||||
typedef struct _GtkTextPendingScroll GtkTextPendingScroll;
|
||||
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright © 2020 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors: Benjamin Otte <otte@gnome.org>
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifndef GTK_VECTOR_TYPE_NAME
|
||||
#define GTK_VECTOR_TYPE_NAME GtkVector
|
||||
#endif
|
||||
|
||||
#ifndef GTK_VECTOR_NAME
|
||||
#define GTK_VECTOR_NAME gtk_vector
|
||||
#endif
|
||||
|
||||
#ifndef GTK_VECTOR_ELEMENT_TYPE
|
||||
#define GTK_VECTOR_ELEMENT_TYPE gpointer
|
||||
#endif
|
||||
|
||||
#ifdef GTK_VECTOR_PREALLOC
|
||||
#if GTK_VECTOR_PREALLOC == 0
|
||||
#undef GTK_VECTOR_PREALLOC
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef GTK_VECTOR_NULL_TERMINATED
|
||||
#define GTK_VECTOR_REAL_SIZE(_size) ((_size) + 1)
|
||||
#else
|
||||
#define GTK_VECTOR_REAL_SIZE(_size) (_size)
|
||||
#endif
|
||||
|
||||
/* make this readable */
|
||||
#define _T_ GTK_VECTOR_ELEMENT_TYPE
|
||||
#define GtkVector GTK_VECTOR_TYPE_NAME
|
||||
#define gtk_vector_paste_more(GTK_VECTOR_NAME, func_name) GTK_VECTOR_NAME ## _ ## func_name
|
||||
#define gtk_vector_paste(GTK_VECTOR_NAME, func_name) gtk_vector_paste_more (GTK_VECTOR_NAME, func_name)
|
||||
#define gtk_vector(func_name) gtk_vector_paste (GTK_VECTOR_NAME, func_name)
|
||||
|
||||
typedef struct GtkVector GtkVector;
|
||||
|
||||
struct GtkVector
|
||||
{
|
||||
_T_ *start;
|
||||
_T_ *end;
|
||||
_T_ *end_allocation;
|
||||
#ifdef GTK_VECTOR_PREALLOC
|
||||
_T_ preallocated[GTK_VECTOR_REAL_SIZE(GTK_VECTOR_PREALLOC)];
|
||||
#endif
|
||||
};
|
||||
|
||||
/* no G_GNUC_UNUSED here, if you don't use an array type, remove it. */
|
||||
static inline void
|
||||
gtk_vector(init) (GtkVector *self)
|
||||
{
|
||||
#ifdef GTK_VECTOR_PREALLOC
|
||||
self->start = self->preallocated;
|
||||
self->end = self->start;
|
||||
self->end_allocation = self->start + GTK_VECTOR_PREALLOC;
|
||||
#ifdef GTK_VECTOR_NULL_TERMINATED
|
||||
*self->start = *(_T_[1]) {};
|
||||
#endif
|
||||
#else
|
||||
self->start = NULL;
|
||||
self->end = NULL;
|
||||
self->end_allocation = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
gtk_vector(free_elements) (_T_ *start,
|
||||
_T_ *end)
|
||||
{
|
||||
#ifdef GTK_VECTOR_FREE_FUNC
|
||||
_T_ *e;
|
||||
for (e = start; e < end; e++)
|
||||
#ifdef GTK_VECTOR_BY_VALUE
|
||||
GTK_VECTOR_FREE_FUNC (e);
|
||||
#else
|
||||
GTK_VECTOR_FREE_FUNC (*e);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* no G_GNUC_UNUSED here */
|
||||
static inline void
|
||||
gtk_vector(clear) (GtkVector *self)
|
||||
{
|
||||
gtk_vector(free_elements) (self->start, self->end);
|
||||
|
||||
#ifdef GTK_VECTOR_PREALLOC
|
||||
if (self->start != self->preallocated)
|
||||
g_free (self->start);
|
||||
#endif
|
||||
gtk_vector(init) (self);
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline _T_ *
|
||||
gtk_vector(get_data) (const GtkVector *self)
|
||||
{
|
||||
return self->start;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline _T_ *
|
||||
gtk_vector(index) (const GtkVector *self,
|
||||
gsize pos)
|
||||
{
|
||||
return self->start + pos;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline gsize
|
||||
gtk_vector(get_capacity) (const GtkVector *self)
|
||||
{
|
||||
return self->end_allocation - self->start;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline gsize
|
||||
gtk_vector(get_size) (const GtkVector *self)
|
||||
{
|
||||
return self->end - self->start;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static inline gboolean
|
||||
gtk_vector(is_empty) (const GtkVector *self)
|
||||
{
|
||||
return self->end == self->start;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
gtk_vector(reserve) (GtkVector *self,
|
||||
gsize n)
|
||||
{
|
||||
gsize new_size, size;
|
||||
|
||||
if (n <= gtk_vector(get_capacity) (self))
|
||||
return;
|
||||
|
||||
size = gtk_vector(get_size) (self);
|
||||
new_size = 1 << g_bit_storage (MAX (n, 16) - 1);
|
||||
|
||||
#ifdef GTK_VECTOR_PREALLOC
|
||||
if (self->start == self->preallocated)
|
||||
{
|
||||
self->start = g_new (_T_, new_size);
|
||||
memcpy (self->start, self->preallocated, sizeof (_T_) * GTK_VECTOR_REAL_SIZE (size));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef GTK_VECTOR_NULL_TERMINATED
|
||||
if (self->start == NULL)
|
||||
{
|
||||
self->start = g_new (_T_, new_size);
|
||||
*self->start = *(_T_[1]) {};
|
||||
}
|
||||
else
|
||||
#endif
|
||||
self->start = g_renew (_T_, self->start, new_size);
|
||||
|
||||
self->end = self->start + size;
|
||||
self->end_allocation = self->start + new_size;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
gtk_vector(splice) (GtkVector *self,
|
||||
gsize pos,
|
||||
gsize removed,
|
||||
_T_ *additions,
|
||||
gsize added)
|
||||
{
|
||||
gsize size;
|
||||
gsize remaining;
|
||||
|
||||
size = gtk_vector(get_size) (self);
|
||||
g_assert (pos + removed <= size);
|
||||
remaining = size - pos - removed;
|
||||
|
||||
gtk_vector(free_elements) (gtk_vector(index) (self, pos),
|
||||
gtk_vector(index) (self, pos + removed));
|
||||
|
||||
gtk_vector(reserve) (self, size - removed + added);
|
||||
|
||||
if (GTK_VECTOR_REAL_SIZE (remaining) && removed != added)
|
||||
memmove (gtk_vector(index) (self, pos + added),
|
||||
gtk_vector(index) (self, pos + removed),
|
||||
GTK_VECTOR_REAL_SIZE (remaining) * sizeof (_T_));
|
||||
|
||||
if (added)
|
||||
{
|
||||
if (additions)
|
||||
memcpy (gtk_vector(index) (self, pos),
|
||||
additions,
|
||||
added * sizeof (_T_));
|
||||
else
|
||||
memset (gtk_vector(index) (self, pos), 0, added * sizeof (_T_));
|
||||
}
|
||||
|
||||
/* might overflow, but does the right thing */
|
||||
self->end += added - removed;
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
gtk_vector(set_size) (GtkVector *self,
|
||||
gsize new_size)
|
||||
{
|
||||
gsize old_size = gtk_vector(get_size) (self);
|
||||
if (new_size > old_size)
|
||||
gtk_vector(splice) (self, old_size, 0, NULL, new_size - old_size);
|
||||
else
|
||||
gtk_vector(splice) (self, old_size, old_size - new_size, NULL, 0);
|
||||
}
|
||||
|
||||
G_GNUC_UNUSED static void
|
||||
gtk_vector(append) (GtkVector *self,
|
||||
#ifdef GTK_VECTOR_BY_VALUE
|
||||
_T_ *value)
|
||||
#else
|
||||
_T_ value)
|
||||
#endif
|
||||
{
|
||||
gtk_vector(splice) (self,
|
||||
gtk_vector(get_size) (self),
|
||||
0,
|
||||
#ifdef GTK_VECTOR_BY_VALUE
|
||||
value,
|
||||
#else
|
||||
&value,
|
||||
#endif
|
||||
1);
|
||||
}
|
||||
|
||||
#ifdef GTK_VECTOR_BY_VALUE
|
||||
G_GNUC_UNUSED static _T_ *
|
||||
gtk_vector(get) (const GtkVector *self,
|
||||
gsize pos)
|
||||
{
|
||||
return gtk_vector(index) (self, pos);
|
||||
}
|
||||
#else
|
||||
G_GNUC_UNUSED static _T_
|
||||
gtk_vector(get) (const GtkVector *self,
|
||||
gsize pos)
|
||||
{
|
||||
return *gtk_vector(index) (self, pos);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef GTK_VECTOR_NO_UNDEF
|
||||
|
||||
#undef _T_
|
||||
#undef GtkVector
|
||||
#undef gtk_vector_paste_more
|
||||
#undef gtk_vector_paste
|
||||
#undef gtk_vector
|
||||
#undef GTK_VECTOR_REAL_SIZE
|
||||
|
||||
#undef GTK_VECTOR_BY_VALUE
|
||||
#undef GTK_VECTOR_ELEMENT_TYPE
|
||||
#undef GTK_VECTOR_FREE_FUNC
|
||||
#undef GTK_VECTOR_NAME
|
||||
#undef GTK_VECTOR_NULL_TERMINATED
|
||||
#undef GTK_VECTOR_PREALLOC
|
||||
#undef GTK_VECTOR_TYPE_NAME
|
||||
|
||||
#endif
|
||||
+2
-2
@@ -7377,14 +7377,14 @@ static void
|
||||
gtk_widget_real_realize (GtkWidget *widget)
|
||||
{
|
||||
GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
|
||||
GdkFrameClock *frame_clock;
|
||||
|
||||
priv->realized = TRUE;
|
||||
|
||||
/* Connect frame clock */
|
||||
frame_clock = gtk_widget_get_frame_clock (widget);
|
||||
if (priv->tick_callbacks != NULL && !priv->clock_tick_id)
|
||||
{
|
||||
GdkFrameClock *frame_clock = gtk_widget_get_frame_clock (widget);
|
||||
|
||||
priv->clock_tick_id = g_signal_connect (frame_clock, "update",
|
||||
G_CALLBACK (gtk_widget_on_frame_clock_update),
|
||||
widget);
|
||||
|
||||
@@ -4308,6 +4308,7 @@ gtk_window_realize (GtkWidget *widget)
|
||||
if (priv->title_box == NULL)
|
||||
{
|
||||
priv->titlebar = gtk_header_bar_new ();
|
||||
gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (priv->titlebar), TRUE);
|
||||
gtk_widget_add_css_class (priv->titlebar, GTK_STYLE_CLASS_TITLEBAR);
|
||||
gtk_widget_add_css_class (priv->titlebar, "default-decoration");
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ setup_parameter_cb (GtkSignalListItemFactory *factory,
|
||||
label = gtk_label_new (NULL);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.5);
|
||||
gtk_list_item_set_child (list_item, label);
|
||||
gtk_widget_add_css_class (label, "cell");
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -168,7 +168,7 @@ setup_state_cb (GtkSignalListItemFactory *factory,
|
||||
gtk_widget_set_margin_end (label, 5);
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
gtk_list_item_set_child (list_item, label);
|
||||
gtk_widget_add_css_class (label, "cell");
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (label), "cell");
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -215,7 +215,7 @@ bind_changes_cb (GtkSignalListItemFactory *factory,
|
||||
name = action_holder_get_name (ACTION_HOLDER (item));
|
||||
|
||||
editor = gtk_inspector_action_editor_new (group, name, NULL);
|
||||
gtk_widget_add_css_class (editor, "cell");
|
||||
gtk_style_context_add_class (gtk_widget_get_style_context (editor), "cell");
|
||||
gtk_list_item_set_child (list_item, editor);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2020 Red Hat, Inc.
|
||||
* Copyright (c) 2014 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "config.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
#include "tree-data.h"
|
||||
#include "data-list.h"
|
||||
|
||||
#include "object-tree.h"
|
||||
|
||||
@@ -27,14 +27,10 @@
|
||||
#include "gtktogglebutton.h"
|
||||
#include "gtklabel.h"
|
||||
#include "gtkstack.h"
|
||||
#include "gtkboxlayout.h"
|
||||
#include "gtkorientable.h"
|
||||
|
||||
|
||||
struct _GtkInspectorTreeData
|
||||
struct _GtkInspectorDataListPrivate
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkTreeModel *object;
|
||||
GtkTreeModel *types;
|
||||
GtkTreeView *view;
|
||||
@@ -42,22 +38,13 @@ struct _GtkInspectorTreeData
|
||||
gboolean show_data;
|
||||
};
|
||||
|
||||
typedef struct _GtkInspectorTreeDataClass GtkInspectorTreeDataClass;
|
||||
struct _GtkInspectorTreeDataClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GtkInspectorTreeData, gtk_inspector_tree_data, GTK_TYPE_WIDGET)
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkInspectorDataList, gtk_inspector_data_list, GTK_TYPE_BOX)
|
||||
|
||||
static void
|
||||
gtk_inspector_tree_data_init (GtkInspectorTreeData *sl)
|
||||
gtk_inspector_data_list_init (GtkInspectorDataList *sl)
|
||||
{
|
||||
sl->priv = gtk_inspector_data_list_get_instance_private (sl);
|
||||
gtk_widget_init_template (GTK_WIDGET (sl));
|
||||
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (gtk_widget_get_layout_manager (GTK_WIDGET (sl))),
|
||||
GTK_ORIENTATION_VERTICAL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -80,7 +67,7 @@ cell_data_func (GtkTreeViewColumn *col,
|
||||
}
|
||||
|
||||
static void
|
||||
add_columns (GtkInspectorTreeData *sl)
|
||||
add_columns (GtkInspectorDataList *sl)
|
||||
{
|
||||
gint n_columns;
|
||||
GtkCellRenderer *cell;
|
||||
@@ -89,45 +76,45 @@ add_columns (GtkInspectorTreeData *sl)
|
||||
GtkTreeViewColumn *col;
|
||||
gint i;
|
||||
|
||||
n_columns = gtk_tree_model_get_n_columns (sl->object);
|
||||
n_columns = gtk_tree_model_get_n_columns (sl->priv->object);
|
||||
for (i = 0; i < n_columns; i++)
|
||||
{
|
||||
cell = gtk_cell_renderer_text_new ();
|
||||
type = gtk_tree_model_get_column_type (sl->object, i);
|
||||
type = gtk_tree_model_get_column_type (sl->priv->object, i);
|
||||
title = g_strdup_printf ("%d: %s", i, g_type_name (type));
|
||||
col = gtk_tree_view_column_new_with_attributes (title, cell, NULL);
|
||||
g_object_set_data (G_OBJECT (col), "num", GINT_TO_POINTER (i));
|
||||
gtk_tree_view_column_set_cell_data_func (col, cell, cell_data_func, sl, NULL);
|
||||
gtk_tree_view_append_column (sl->view, col);
|
||||
gtk_tree_view_append_column (sl->priv->view, col);
|
||||
g_free (title);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
show_types (GtkInspectorTreeData *sl)
|
||||
show_types (GtkInspectorDataList *sl)
|
||||
{
|
||||
gtk_tree_view_set_model (sl->view, NULL);
|
||||
sl->show_data = FALSE;
|
||||
gtk_tree_view_set_model (sl->priv->view, NULL);
|
||||
sl->priv->show_data = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
show_data (GtkInspectorTreeData *sl)
|
||||
show_data (GtkInspectorDataList *sl)
|
||||
{
|
||||
gtk_tree_view_set_model (sl->view, sl->object);
|
||||
sl->show_data = TRUE;
|
||||
gtk_tree_view_set_model (sl->priv->view, sl->priv->object);
|
||||
sl->priv->show_data = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_view (GtkInspectorTreeData *sl)
|
||||
clear_view (GtkInspectorDataList *sl)
|
||||
{
|
||||
gtk_tree_view_set_model (sl->view, NULL);
|
||||
while (gtk_tree_view_get_n_columns (sl->view) > 0)
|
||||
gtk_tree_view_remove_column (sl->view,
|
||||
gtk_tree_view_get_column (sl->view, 0));
|
||||
gtk_tree_view_set_model (sl->priv->view, NULL);
|
||||
while (gtk_tree_view_get_n_columns (sl->priv->view) > 0)
|
||||
gtk_tree_view_remove_column (sl->priv->view,
|
||||
gtk_tree_view_get_column (sl->priv->view, 0));
|
||||
}
|
||||
|
||||
void
|
||||
gtk_inspector_tree_data_set_object (GtkInspectorTreeData *sl,
|
||||
gtk_inspector_data_list_set_object (GtkInspectorDataList *sl,
|
||||
GObject *object)
|
||||
{
|
||||
GtkWidget *stack;
|
||||
@@ -138,8 +125,8 @@ gtk_inspector_tree_data_set_object (GtkInspectorTreeData *sl,
|
||||
page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (sl));
|
||||
|
||||
clear_view (sl);
|
||||
sl->object = NULL;
|
||||
sl->show_data = FALSE;
|
||||
sl->priv->object = NULL;
|
||||
sl->priv->show_data = FALSE;
|
||||
|
||||
if (!GTK_IS_TREE_MODEL (object))
|
||||
{
|
||||
@@ -148,21 +135,21 @@ gtk_inspector_tree_data_set_object (GtkInspectorTreeData *sl,
|
||||
}
|
||||
|
||||
title = gtk_inspector_get_object_title (object);
|
||||
gtk_label_set_label (GTK_LABEL (sl->object_title), title);
|
||||
gtk_label_set_label (GTK_LABEL (sl->priv->object_title), title);
|
||||
g_free (title);
|
||||
|
||||
g_object_set (page, "visible", TRUE, NULL);
|
||||
|
||||
sl->object = GTK_TREE_MODEL (object);
|
||||
sl->priv->object = GTK_TREE_MODEL (object);
|
||||
add_columns (sl);
|
||||
show_types (sl);
|
||||
}
|
||||
|
||||
static void
|
||||
toggle_show (GtkToggleButton *button,
|
||||
GtkInspectorTreeData *sl)
|
||||
GtkInspectorDataList *sl)
|
||||
{
|
||||
if (gtk_toggle_button_get_active (button) == sl->show_data)
|
||||
if (gtk_toggle_button_get_active (button) == sl->priv->show_data)
|
||||
return;
|
||||
|
||||
if (gtk_toggle_button_get_active (button))
|
||||
@@ -172,16 +159,14 @@ toggle_show (GtkToggleButton *button,
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_inspector_tree_data_class_init (GtkInspectorTreeDataClass *klass)
|
||||
gtk_inspector_data_list_class_init (GtkInspectorDataListClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/tree-data.ui");
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorTreeData, view);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorTreeData, object_title);
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/data-list.ui");
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorDataList, view);
|
||||
gtk_widget_class_bind_template_child_private (widget_class, GtkInspectorDataList, object_title);
|
||||
gtk_widget_class_bind_template_callback (widget_class, toggle_show);
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
|
||||
}
|
||||
|
||||
// vim: set et sw=2 ts=2:
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GTK_INSPECTOR_DATA_LIST_H_
|
||||
#define _GTK_INSPECTOR_DATA_LIST_H_
|
||||
|
||||
#include <gtk/gtkbox.h>
|
||||
|
||||
#define GTK_TYPE_INSPECTOR_DATA_LIST (gtk_inspector_data_list_get_type())
|
||||
#define GTK_INSPECTOR_DATA_LIST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_INSPECTOR_DATA_LIST, GtkInspectorDataList))
|
||||
#define GTK_INSPECTOR_DATA_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_INSPECTOR_DATA_LIST, GtkInspectorDataListClass))
|
||||
#define GTK_INSPECTOR_IS_DATA_LIST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_INSPECTOR_DATA_LIST))
|
||||
#define GTK_INSPECTOR_IS_DATA_LIST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_INSPECTOR_DATA_LIST))
|
||||
#define GTK_INSPECTOR_DATA_LIST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_INSPECTOR_DATA_LIST, GtkInspectorDataListClass))
|
||||
|
||||
|
||||
typedef struct _GtkInspectorDataListPrivate GtkInspectorDataListPrivate;
|
||||
|
||||
typedef struct _GtkInspectorDataList
|
||||
{
|
||||
GtkBox parent;
|
||||
GtkInspectorDataListPrivate *priv;
|
||||
} GtkInspectorDataList;
|
||||
|
||||
typedef struct _GtkInspectorDataListClass
|
||||
{
|
||||
GtkBoxClass parent;
|
||||
} GtkInspectorDataListClass;
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GType gtk_inspector_data_list_get_type (void);
|
||||
void gtk_inspector_data_list_set_object (GtkInspectorDataList *sl,
|
||||
GObject *object);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif // _GTK_INSPECTOR_DATA_LIST_H_
|
||||
|
||||
// vim: set et sw=2 ts=2:
|
||||
@@ -1,5 +1,6 @@
|
||||
<interface domain="gtk40">
|
||||
<template class="GtkInspectorTreeData" parent="GtkWidget">
|
||||
<template class="GtkInspectorDataList" parent="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">6</property>
|
||||
@@ -728,7 +728,6 @@
|
||||
<widgets>
|
||||
<widget name="version_frame"/>
|
||||
<widget name="gl_frame"/>
|
||||
<widget name="monitor_frame"/>
|
||||
<widget name="vulkan_frame"/>
|
||||
<widget name="env_frame"/>
|
||||
<widget name="display_frame"/>
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
#include "controllers.h"
|
||||
#include "css-editor.h"
|
||||
#include "css-node-tree.h"
|
||||
#include "data-list.h"
|
||||
#include "general.h"
|
||||
#include "graphdata.h"
|
||||
#include "list-data.h"
|
||||
#include "logs.h"
|
||||
#include "magnifier.h"
|
||||
#include "menu.h"
|
||||
@@ -43,7 +43,6 @@
|
||||
#include "shortcuts.h"
|
||||
#include "size-groups.h"
|
||||
#include "statistics.h"
|
||||
#include "tree-data.h"
|
||||
#include "visual.h"
|
||||
#include "window.h"
|
||||
|
||||
@@ -65,8 +64,8 @@ gtk_inspector_init (void)
|
||||
g_type_ensure (GTK_TYPE_INSPECTOR_CONTROLLERS);
|
||||
g_type_ensure (GTK_TYPE_INSPECTOR_CSS_EDITOR);
|
||||
g_type_ensure (GTK_TYPE_INSPECTOR_CSS_NODE_TREE);
|
||||
g_type_ensure (GTK_TYPE_INSPECTOR_DATA_LIST);
|
||||
g_type_ensure (GTK_TYPE_INSPECTOR_GENERAL);
|
||||
g_type_ensure (GTK_TYPE_INSPECTOR_LIST_DATA);
|
||||
g_type_ensure (GTK_TYPE_INSPECTOR_LOGS);
|
||||
g_type_ensure (GTK_TYPE_MAGNIFIER);
|
||||
g_type_ensure (GTK_TYPE_INSPECTOR_MAGNIFIER);
|
||||
@@ -79,7 +78,6 @@ gtk_inspector_init (void)
|
||||
g_type_ensure (GTK_TYPE_INSPECTOR_SHORTCUTS);
|
||||
g_type_ensure (GTK_TYPE_INSPECTOR_SIZE_GROUPS);
|
||||
g_type_ensure (GTK_TYPE_INSPECTOR_STATISTICS);
|
||||
g_type_ensure (GTK_TYPE_INSPECTOR_TREE_DATA);
|
||||
g_type_ensure (GTK_TYPE_INSPECTOR_VISUAL);
|
||||
g_type_ensure (GTK_TYPE_INSPECTOR_WINDOW);
|
||||
|
||||
|
||||
@@ -1,274 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
|
||||
#include "list-data.h"
|
||||
|
||||
#include "object-tree.h"
|
||||
|
||||
#include "gtkcolumnview.h"
|
||||
#include "gtktogglebutton.h"
|
||||
#include "gtklabel.h"
|
||||
#include "gtkstack.h"
|
||||
#include "gtkboxlayout.h"
|
||||
#include "gtkorientable.h"
|
||||
#include "gtknoselection.h"
|
||||
#include "gtksignallistitemfactory.h"
|
||||
#include "gtklistitem.h"
|
||||
|
||||
|
||||
struct _GtkInspectorListData
|
||||
{
|
||||
GtkWidget parent_instance;
|
||||
|
||||
GtkInspectorObjectTree *object_tree;
|
||||
GListModel *object;
|
||||
GtkColumnView *view;
|
||||
GtkWidget *items_label;
|
||||
};
|
||||
|
||||
struct _GtkInspectorListDataClass
|
||||
{
|
||||
GtkWidgetClass parent_class;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_OBJECT_TREE,
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GtkInspectorListData, gtk_inspector_list_data, GTK_TYPE_WIDGET)
|
||||
|
||||
static void
|
||||
gtk_inspector_list_data_init (GtkInspectorListData *sl)
|
||||
{
|
||||
gtk_widget_init_template (GTK_WIDGET (sl));
|
||||
|
||||
gtk_orientable_set_orientation (GTK_ORIENTABLE (gtk_widget_get_layout_manager (GTK_WIDGET (sl))),
|
||||
GTK_ORIENTATION_VERTICAL);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_inspector_list_data_set_object (GtkInspectorListData *sl,
|
||||
GObject *object)
|
||||
{
|
||||
GtkWidget *stack;
|
||||
GtkStackPage *page;
|
||||
char *text;
|
||||
GtkNoSelection *selection;
|
||||
|
||||
stack = gtk_widget_get_parent (GTK_WIDGET (sl));
|
||||
page = gtk_stack_get_page (GTK_STACK (stack), GTK_WIDGET (sl));
|
||||
|
||||
gtk_column_view_set_model (sl->view, NULL);
|
||||
sl->object = NULL;
|
||||
|
||||
if (!G_IS_LIST_MODEL (object))
|
||||
{
|
||||
g_object_set (page, "visible", FALSE, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
text = g_strdup_printf ("%u items", g_list_model_get_n_items (G_LIST_MODEL (object)));
|
||||
gtk_label_set_label (GTK_LABEL (sl->items_label), text);
|
||||
g_free (text);
|
||||
|
||||
g_object_set (page, "visible", TRUE, NULL);
|
||||
|
||||
sl->object = G_LIST_MODEL (object);
|
||||
selection = gtk_no_selection_new (sl->object);
|
||||
gtk_column_view_set_model (sl->view, G_LIST_MODEL (selection));
|
||||
g_object_unref (selection);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_object (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkWidget *label;
|
||||
|
||||
label = gtk_label_new ("");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_widget_add_css_class (label, "cell");
|
||||
gtk_list_item_set_child (item, label);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_object (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkWidget *label;
|
||||
gpointer obj;
|
||||
char *text;
|
||||
|
||||
label = gtk_list_item_get_child (item);
|
||||
obj = gtk_list_item_get_item (item);
|
||||
|
||||
text = g_strdup_printf ("%p", obj);
|
||||
gtk_label_set_label (GTK_LABEL (label), text);
|
||||
g_free (text);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_type (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkWidget *label;
|
||||
|
||||
label = gtk_label_new ("");
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0);
|
||||
gtk_widget_add_css_class (label, "cell");
|
||||
gtk_list_item_set_child (item, label);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_type (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkWidget *label;
|
||||
gpointer obj;
|
||||
|
||||
label = gtk_list_item_get_child (item);
|
||||
obj = gtk_list_item_get_item (item);
|
||||
|
||||
gtk_label_set_label (GTK_LABEL (label), G_OBJECT_TYPE_NAME (obj));
|
||||
}
|
||||
|
||||
static void
|
||||
setup_props (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkWidget *button;
|
||||
|
||||
button = gtk_button_new_with_label ("Properties");
|
||||
gtk_widget_add_css_class (button, "cell");
|
||||
gtk_widget_set_halign (button, GTK_ALIGN_START);
|
||||
gtk_list_item_set_child (item, button);
|
||||
}
|
||||
|
||||
static void
|
||||
object_properties (GtkWidget *button,
|
||||
GtkListItem *item)
|
||||
{
|
||||
GtkInspectorListData *sl;
|
||||
gpointer obj;
|
||||
|
||||
sl = GTK_INSPECTOR_LIST_DATA (gtk_widget_get_ancestor (button, GTK_TYPE_INSPECTOR_LIST_DATA));
|
||||
obj = gtk_list_item_get_item (item);
|
||||
g_object_set_data (G_OBJECT (sl->object_tree), "next-tab", (gpointer)"properties");
|
||||
gtk_inspector_object_tree_activate_object (sl->object_tree, obj);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_props (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item,
|
||||
GtkInspectorListData *sl)
|
||||
{
|
||||
g_signal_connect (gtk_list_item_get_child (item), "clicked",
|
||||
G_CALLBACK (object_properties), item);
|
||||
}
|
||||
|
||||
static void
|
||||
unbind_props (GtkSignalListItemFactory *factory,
|
||||
GtkListItem *item)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (gtk_list_item_get_child (item), object_properties, item);
|
||||
}
|
||||
|
||||
static void
|
||||
get_property (GObject *object,
|
||||
guint param_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkInspectorListData *sl = GTK_INSPECTOR_LIST_DATA (object);
|
||||
|
||||
switch (param_id)
|
||||
{
|
||||
case PROP_OBJECT_TREE:
|
||||
g_value_take_object (value, sl->object_tree);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_property (GObject *object,
|
||||
guint param_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkInspectorListData *sl = GTK_INSPECTOR_LIST_DATA (object);
|
||||
|
||||
switch (param_id)
|
||||
{
|
||||
case PROP_OBJECT_TREE:
|
||||
sl->object_tree = g_value_get_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
finalize (GObject *object)
|
||||
{
|
||||
GtkInspectorListData *sl = GTK_INSPECTOR_LIST_DATA (object);
|
||||
|
||||
gtk_inspector_list_data_set_object (sl, NULL);
|
||||
|
||||
G_OBJECT_CLASS (gtk_inspector_list_data_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_inspector_list_data_class_init (GtkInspectorListDataClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
object_class->finalize = finalize;
|
||||
object_class->get_property = get_property;
|
||||
object_class->set_property = set_property;
|
||||
|
||||
g_object_class_install_property (object_class, PROP_OBJECT_TREE,
|
||||
g_param_spec_object ("object-tree", "Object Tree", "Object tree",
|
||||
GTK_TYPE_WIDGET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
gtk_widget_class_set_template_from_resource (widget_class, "/org/gtk/libgtk/inspector/list-data.ui");
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorListData, view);
|
||||
gtk_widget_class_bind_template_child (widget_class, GtkInspectorListData, items_label);
|
||||
|
||||
gtk_widget_class_bind_template_callback (widget_class, setup_object);
|
||||
gtk_widget_class_bind_template_callback (widget_class, bind_object);
|
||||
gtk_widget_class_bind_template_callback (widget_class, setup_type);
|
||||
gtk_widget_class_bind_template_callback (widget_class, bind_type);
|
||||
gtk_widget_class_bind_template_callback (widget_class, setup_props);
|
||||
gtk_widget_class_bind_template_callback (widget_class, bind_props);
|
||||
gtk_widget_class_bind_template_callback (widget_class, unbind_props);
|
||||
|
||||
gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BOX_LAYOUT);
|
||||
}
|
||||
|
||||
// vim: set et sw=2 ts=2:
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _GTK_INSPECTOR_LIST_DATA_H_
|
||||
#define _GTK_INSPECTOR_LIST_DATA_H_
|
||||
|
||||
#include <gtk/gtkbox.h>
|
||||
|
||||
#define GTK_TYPE_INSPECTOR_LIST_DATA (gtk_inspector_list_data_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GtkInspectorListData, gtk_inspector_list_data, GTK, INSPECTOR_LIST_DATA, GtkWidget)
|
||||
|
||||
typedef struct _GtkInspectorListData GtkInspectorListData;
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gtk_inspector_list_data_set_object (GtkInspectorListData *sl,
|
||||
GObject *object);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif // _GTK_INSPECTOR_LIST_DATA_H_
|
||||
|
||||
// vim: set et sw=2 ts=2:
|
||||
@@ -1,68 +0,0 @@
|
||||
<interface domain="gtk40">
|
||||
<template class="GtkInspectorListData" parent="GtkWidget">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">6</property>
|
||||
<property name="margin-start">6</property>
|
||||
<property name="margin-end">6</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="items_label">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="halign">end</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<property name="vscrollbar-policy">always</property>
|
||||
<child>
|
||||
<object class="GtkColumnView" id="view">
|
||||
<style>
|
||||
<class name="list"/>
|
||||
</style>
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn">
|
||||
<property name="title">Object</property>
|
||||
<property name="factory">
|
||||
<object class="GtkSignalListItemFactory">
|
||||
<signal name="setup" handler="setup_object"/>
|
||||
<signal name="bind" handler="bind_object"/>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn">
|
||||
<property name="title">Type</property>
|
||||
<property name="factory">
|
||||
<object class="GtkSignalListItemFactory">
|
||||
<signal name="setup" handler="setup_type"/>
|
||||
<signal name="bind" handler="bind_type"/>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkColumnViewColumn">
|
||||
<property name="title"></property>
|
||||
<property name="expand">1</property>
|
||||
<property name="factory">
|
||||
<object class="GtkSignalListItemFactory">
|
||||
<signal name="setup" handler="setup_props"/>
|
||||
<signal name="bind" handler="bind_props"/>
|
||||
<signal name="unbind" handler="unbind_props"/>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
</interface>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user