Compare commits

..

39 Commits

Author SHA1 Message Date
Matthias Clasen d233b10559 perf test: Add GtkArrayStore 2020-07-03 19:55:00 -04:00
Matthias Clasen b4f9f252d7 wip: more perf test work 2020-07-03 19:54:51 -04:00
Matthias Clasen 373c06b148 wip: Add the old stringlist for comparsion 2020-07-03 19:54:44 -04:00
Matthias Clasen c84cd97fbc wip: benchmarks 2020-07-03 19:54:36 -04:00
Benjamin Otte 6b7d295cfe snapshot: Use GtkVector for the state stack 2020-07-03 04:53:50 +02:00
Benjamin Otte 481d438380 vector: Add a bunch of new features
* GTK_VECTOR_BY_VALUE
   #define this to get GArrray-like behavior
 * gtk_vector_splice (v, 0, 0, NULL, 25)
   Adding items but passing NULL as the items will zero() them.
 * gtk_vector_set_size()
   A nicer way to call gtk_vector_splice()
2020-07-03 04:53:43 +02:00
Benjamin Otte f4e1057431 icontheme: Use GtkVector 2020-07-03 04:21:07 +02:00
Benjamin Otte fa0166180e vector: Add null-termination 2020-07-03 03:05:40 +02:00
Benjamin Otte 13d84c202b xxx vector 2020-07-02 23:32:17 +02:00
Benjamin Otte 5846794075 snapshot: Port node list to vector 2020-07-02 23:32:04 +02:00
Benjamin Otte 201da90e23 snapshot: Move structs into .c file
They aren't used anywhere else.
2020-07-02 22:59:40 +02:00
Matthias Clasen 8d4fcabf01 Bring liststore tests over from GLib
Adapt the GListStore tests from GLib to GtkArrayStore.
2020-07-02 22:56:21 +02:00
Benjamin Otte 3f8735a488 Use preallocated array code
Now with GtkVector, we can use that one instead.
2020-07-02 20:52:28 +02:00
Benjamin Otte a4dc248512 main: Use a GtkVector 2020-07-02 20:52:28 +02:00
Benjamin Otte ef451b056a cssselector: Use GtkVector 2020-07-02 20:52:28 +02:00
Benjamin Otte 59aaabb161 Add GtkArrayStore
This has roughly the same API as GListStore, it's just an array.
2020-07-02 20:52:28 +02:00
Benjamin Otte 663ca21328 Add GtkVector
This is a scary idea where you #define a bunch of preprocessor values
and then #include "gtkvectorimpl.c" and end up with a dynamic array for
that data type.
2020-07-02 20:34:47 +02:00
Matthias Clasen 77435d31fa gtk-demo: Use a progressbar in the words demo
This looks better and a bit more polished.
2020-07-01 02:47:50 +02:00
Matthias Clasen 6edb8f096f gtk-demo: No selection in the words demo
This demo is about filtering, not about selection,
so use a GtkNoSelection.
2020-07-01 02:46:05 +02:00
Matthias Clasen c4dfee8860 gtk-demo: Cosmetic fixes for the words demo
Set a window size, and don't put newlines in titles, left align and
ellipsize the label.
2020-07-01 02:46:05 +02:00
Benjamin Otte 8ac1e77c9a demo: Make words listview load async
And add an "Open" button (why are filechooser buttons such a catastrophe
that I can't make them smaller?).
2020-07-01 02:46:05 +02:00
Benjamin Otte 65ceb6c15a stringlist: Call splice() for adding items after construction
This has the benefit of actually allowing NULL to be passed.
2020-07-01 02:46:05 +02:00
Benjamin Otte f70d10f6ac stringlist: Remove n_additions argument from gtk_string_list_splice()
char ** arrays are null-terminated everywhere, so make sure they are in
splice(), too.

Also fix the argument to be a const char * const * like in the
constructor.
2020-07-01 02:46:05 +02:00
Benjamin Otte 0bbd083d79 stringlist: Clarify docs for gtk_string_list_get_string()
Make sure it's obvious that it behaves like g_list_model_get_item() and
returns NULL for pos >= n_items.
2020-07-01 02:46:05 +02:00
Benjamin Otte 102d2986c6 stringlist: Make one constructor call the other
Simplifies code.
2020-07-01 02:46:05 +02:00
Benjamin Otte c74201ca87 filterlistmodel: Look at type of change
This way we can avoid refiltering most of an already filtered list when
the change becomes more strict.
2020-07-01 02:46:05 +02:00
Benjamin Otte b09019a5b4 gtk-demo: Add incremental filtering to words demo 2020-07-01 02:46:05 +02:00
Benjamin Otte 1dd08ad8db filterlistmodel: Add gtk_filter_list_model_get_pending()
This allows tracking if the model is busy filtering.
2020-07-01 02:46:05 +02:00
Benjamin Otte eb0704855f filterlistmodel: Add incremental filtering 2020-07-01 02:46:05 +02:00
Benjamin Otte c4c1d4a1b3 bitset: Add gtk_bitset_new_range()
It's a common use.
2020-07-01 02:46:05 +02:00
Benjamin Otte e6756f605e stringlist: Make property not construct-only
Massively speeds up creation of long stringlists.
2020-07-01 02:46:05 +02:00
Benjamin Otte 1f4b8e089e filterlistmodel: Rewrite with bitset data structure
Bitsets are more powerful, less memory intensive and faster than the old
GtkRbTree version.
2020-07-01 02:46:05 +02:00
Benjamin Otte c0e08db739 bitset: Add APIs needed for a filterlistmodel 2020-06-30 00:46:56 +02:00
Benjamin Otte 1c337d350d tests: Make testlistview be a list again
The grid conversion was for testing and should never have been
committed.
2020-06-30 00:46:56 +02:00
Benjamin Otte 81e675dfbf gtk-demo: Add a listview demo for filtering strings 2020-06-30 00:36:14 +02:00
Benjamin Otte 8556221429 stringlist: Take a const char const * argument
Sucks that we need to cast a char**, but otherwise we need to cast
{"foo", "bar", "baz" } arrays.
2020-06-30 00:36:14 +02:00
Benjamin Otte 1b4109a7fd scrolledwindow: Expand by default
Use gtk_scrolled_window_set_hexpand/vexpand(FALSE) to make the scrolled
window not expand.
2020-06-30 00:36:13 +02:00
Benjamin Otte df0786be7a stringfilter: Don't crash if the expression returns "" 2020-06-30 00:36:13 +02:00
Benjamin Otte 3f545da08d a11y: Remove double initialization of variables 2020-06-30 00:36:13 +02:00
140 changed files with 7244 additions and 7141 deletions
@@ -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>
+1 -1
View File
@@ -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>
+1 -1
View 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);
+1
View File
@@ -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>
+1
View File
@@ -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>
+1
View File
@@ -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");
+1
View File
@@ -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>
+2 -146
View File
@@ -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),
-3
View File
@@ -1,3 +0,0 @@
.view.compact > child {
padding: 1px;
}
+1
View File
@@ -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>
+1
View File
@@ -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>
+1
View File
@@ -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>
+8 -9
View File
@@ -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 ();
+241
View File
@@ -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;
}
+1
View File
@@ -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>
+1
View File
@@ -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);
+1
View File
@@ -49,6 +49,7 @@ demos = files([
'listview_minesweeper.c',
'listview_settings.c',
'listview_weather.c',
'listview_words.c',
'markup.c',
'modelbutton.c',
'overlay.c',
+3 -1
View File
@@ -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">
+1
View File
@@ -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",
+1
View File
@@ -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),
+1
View File
@@ -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);
+1
View File
@@ -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 ();
+1
View File
@@ -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>
+1
View File
@@ -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");
+1
View File
@@ -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>
+1
View File
@@ -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>
+1
View File
@@ -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>
+2
View File
@@ -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>
-1
View File
@@ -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" />
+4 -11
View File
@@ -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>
-1
View File
@@ -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
-1
View File
@@ -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
+1
View File
@@ -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>
+1
View File
@@ -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>
+1
View File
@@ -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>
+1
View File
@@ -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>
+1
View File
@@ -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>
+1
View File
@@ -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>
+1
View File
@@ -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>
+1
View File
@@ -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 ();
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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.
-1
View File
@@ -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;
+1 -1
View File
@@ -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;
+2 -1
View File
@@ -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>
-137
View File
@@ -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
+287
View File
@@ -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);
}
+54
View File
@@ -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
View File
@@ -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
+3
View File
@@ -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);
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+8 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+8
View File
@@ -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
+135
View File
@@ -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);
}
+82
View File
@@ -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__ */
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+3 -3
View File
@@ -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.
*
-2
View File
@@ -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
View File
@@ -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;
}
-16
View File
@@ -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;
}
-2
View File
@@ -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
+11
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
-373
View File
@@ -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;
}
-52
View File
@@ -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__ */
+3 -1
View File
@@ -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
View File
@@ -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;
}
-70
View File
@@ -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,
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+38
View File
@@ -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
+1
View File
@@ -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;
+280
View File
@@ -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
View File
@@ -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);
+1
View File
@@ -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");
+3 -3
View File
@@ -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:
+54
View File
@@ -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>
-1
View File
@@ -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"/>
+2 -4
View File
@@ -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);
-274
View File
@@ -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:
-38
View File
@@ -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:
-68
View File
@@ -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