mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-27 14:10:30 +00:00
00cb4c66cf
That way, local scrolling is available and the scrolling isn't random. Recycling should now involve reordering the recycled widgets instead of just keeping their order because all of them got recycled.
324 lines
8.0 KiB
C
324 lines
8.0 KiB
C
/* -*- mode: C; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "frame-stats.h"
|
|
|
|
|
|
static gboolean no_auto_scroll = FALSE;
|
|
static gint n_columns = 20;
|
|
static double scroll_pages = 0;
|
|
|
|
|
|
/* This is our dummy item for the model. */
|
|
#define DATA_TABLE_TYPE_ITEM (data_table_item_get_type ())
|
|
G_DECLARE_FINAL_TYPE (DataTableItem, data_table_item, DATA_TABLE, ITEM, GObject)
|
|
|
|
struct _DataTableItem
|
|
{
|
|
GObject parent_instance;
|
|
int data;
|
|
};
|
|
|
|
struct _DataTableItemClass
|
|
{
|
|
GObjectClass parent_class;
|
|
};
|
|
|
|
G_DEFINE_TYPE (DataTableItem, data_table_item, G_TYPE_OBJECT)
|
|
|
|
static void data_table_item_init (DataTableItem *item) {}
|
|
|
|
static void data_table_item_class_init (DataTableItemClass *class) {}
|
|
|
|
static DataTableItem *
|
|
data_table_item_new (int data)
|
|
{
|
|
DataTableItem *item = g_object_new (DATA_TABLE_TYPE_ITEM, NULL);
|
|
item->data = data;
|
|
return item;
|
|
}
|
|
|
|
|
|
static void
|
|
set_adjustment_to_fraction (GtkAdjustment *adjustment,
|
|
double fraction)
|
|
{
|
|
double upper = gtk_adjustment_get_upper (adjustment);
|
|
double lower = gtk_adjustment_get_lower (adjustment);
|
|
double page_size = gtk_adjustment_get_page_size (adjustment);
|
|
|
|
gtk_adjustment_set_value (adjustment,
|
|
(1 - fraction) * lower +
|
|
fraction * (upper - page_size));
|
|
}
|
|
|
|
static void
|
|
move_adjustment_by_pages (GtkAdjustment *adjustment,
|
|
double n_pages)
|
|
{
|
|
double page_size = gtk_adjustment_get_page_size (adjustment);
|
|
double value = gtk_adjustment_get_value (adjustment);
|
|
|
|
value += page_size * n_pages;
|
|
/* the adjustment will clamp properly */
|
|
gtk_adjustment_set_value (adjustment, value);
|
|
}
|
|
|
|
static gboolean
|
|
scroll_column_view (GtkWidget *column_view,
|
|
GdkFrameClock *frame_clock,
|
|
gpointer user_data)
|
|
{
|
|
GtkAdjustment *vadjustment;
|
|
|
|
vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (column_view));
|
|
|
|
if (scroll_pages == 0.0)
|
|
set_adjustment_to_fraction (vadjustment, g_random_double ());
|
|
else
|
|
move_adjustment_by_pages (vadjustment, (g_random_double () * 2 - 1) * scroll_pages);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
enum WidgetType
|
|
{
|
|
WIDGET_TYPE_NONE,
|
|
WIDGET_TYPE_LABEL,
|
|
WIDGET_TYPE_TEXT,
|
|
WIDGET_TYPE_INSCRIPTION,
|
|
};
|
|
|
|
static enum WidgetType widget_type = WIDGET_TYPE_INSCRIPTION;
|
|
|
|
static void
|
|
setup (GtkSignalListItemFactory *factory,
|
|
GObject *listitem)
|
|
{
|
|
GtkWidget *widget;
|
|
|
|
switch (widget_type)
|
|
{
|
|
case WIDGET_TYPE_NONE:
|
|
/* It's actually a box, just to request size similar to labels. */
|
|
widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
|
gtk_widget_set_size_request (widget, 50, 18);
|
|
break;
|
|
case WIDGET_TYPE_LABEL:
|
|
widget = gtk_label_new ("");
|
|
break;
|
|
case WIDGET_TYPE_TEXT:
|
|
widget = gtk_text_new ();
|
|
break;
|
|
case WIDGET_TYPE_INSCRIPTION:
|
|
widget = gtk_inscription_new ("");
|
|
gtk_inscription_set_min_chars (GTK_INSCRIPTION (widget), 6);
|
|
break;
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
|
|
gtk_list_item_set_child (GTK_LIST_ITEM (listitem), widget);
|
|
}
|
|
|
|
static void
|
|
bind (GtkSignalListItemFactory *factory,
|
|
GObject *listitem,
|
|
gpointer name)
|
|
{
|
|
GtkWidget *widget;
|
|
GObject *item;
|
|
|
|
widget = gtk_list_item_get_child (GTK_LIST_ITEM (listitem));
|
|
item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
|
|
|
|
char buffer[16] = { 0, };
|
|
g_snprintf (buffer,
|
|
sizeof (buffer),
|
|
"%c%d",
|
|
GPOINTER_TO_INT (name),
|
|
DATA_TABLE_ITEM (item)->data);
|
|
|
|
switch (widget_type)
|
|
{
|
|
case WIDGET_TYPE_NONE:
|
|
break;
|
|
case WIDGET_TYPE_LABEL:
|
|
gtk_label_set_label (GTK_LABEL (widget), buffer);
|
|
break;
|
|
case WIDGET_TYPE_TEXT:
|
|
gtk_editable_set_text (GTK_EDITABLE (widget), buffer);
|
|
break;
|
|
case WIDGET_TYPE_INSCRIPTION:
|
|
gtk_inscription_set_text (GTK_INSCRIPTION (widget), buffer);
|
|
break;
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
parse_widget_arg (const gchar* option_name,
|
|
const gchar* value,
|
|
gpointer data,
|
|
GError** error)
|
|
{
|
|
if (!g_strcmp0 (value, "none"))
|
|
{
|
|
widget_type = WIDGET_TYPE_NONE;
|
|
return TRUE;
|
|
}
|
|
else if (!g_strcmp0 (value, "label"))
|
|
{
|
|
widget_type = WIDGET_TYPE_LABEL;
|
|
return TRUE;
|
|
}
|
|
else if (!g_strcmp0 (value, "text"))
|
|
{
|
|
widget_type = WIDGET_TYPE_TEXT;
|
|
return TRUE;
|
|
}
|
|
else if (!g_strcmp0 (value, "inscription"))
|
|
{
|
|
widget_type = WIDGET_TYPE_INSCRIPTION;
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
|
|
"Invalid option value");
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static GOptionEntry options[] = {
|
|
{
|
|
"widget",
|
|
'w',
|
|
G_OPTION_FLAG_NONE,
|
|
G_OPTION_ARG_CALLBACK,
|
|
parse_widget_arg,
|
|
"Cell item widget to use, can be one of: none, label, text, inscription",
|
|
"WIDGET"
|
|
},
|
|
{
|
|
"no-auto-scroll",
|
|
'n',
|
|
G_OPTION_FLAG_NONE,
|
|
G_OPTION_ARG_NONE,
|
|
&no_auto_scroll,
|
|
"Disable automatic scrolling",
|
|
NULL
|
|
},
|
|
{
|
|
"columns",
|
|
'c',
|
|
G_OPTION_FLAG_NONE,
|
|
G_OPTION_ARG_INT,
|
|
&n_columns,
|
|
"Column count",
|
|
"COUNT"
|
|
},
|
|
{
|
|
"pages",
|
|
'p',
|
|
G_OPTION_FLAG_NONE,
|
|
G_OPTION_ARG_DOUBLE,
|
|
&scroll_pages,
|
|
"Maximum number of pages to scroll (or 0 for random)",
|
|
"COUNT"
|
|
},
|
|
{ NULL }
|
|
};
|
|
|
|
static void
|
|
quit_cb (GtkWidget *widget,
|
|
gpointer data)
|
|
{
|
|
gboolean *done = data;
|
|
|
|
*done = TRUE;
|
|
|
|
g_main_context_wakeup (NULL);
|
|
}
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
GtkWidget *window;
|
|
GtkWidget *scrolled_window;
|
|
GListStore *store;
|
|
int i;
|
|
GtkMultiSelection *multi_selection;
|
|
GtkWidget *column_view;
|
|
GError *error = NULL;
|
|
gboolean done = FALSE;
|
|
|
|
GOptionContext *context = g_option_context_new (NULL);
|
|
g_option_context_add_main_entries (context, options, NULL);
|
|
frame_stats_add_options (g_option_context_get_main_group (context));
|
|
|
|
if (!g_option_context_parse (context, &argc, &argv, &error))
|
|
{
|
|
g_printerr ("Option parsing failed: %s\n", error->message);
|
|
return 1;
|
|
}
|
|
|
|
gtk_init ();
|
|
|
|
window = gtk_window_new ();
|
|
frame_stats_ensure (GTK_WINDOW (window));
|
|
gtk_window_set_default_size (GTK_WINDOW (window), 1700, 900);
|
|
|
|
scrolled_window = gtk_scrolled_window_new ();
|
|
gtk_window_set_child (GTK_WINDOW (window), scrolled_window);
|
|
|
|
store = g_list_store_new (DATA_TABLE_TYPE_ITEM);
|
|
for (i = 0; i < 10000; ++i)
|
|
{
|
|
DataTableItem *item = data_table_item_new (i);
|
|
g_list_store_append (store, item);
|
|
g_object_unref (item);
|
|
}
|
|
|
|
multi_selection = gtk_multi_selection_new (G_LIST_MODEL (store));
|
|
column_view = gtk_column_view_new (GTK_SELECTION_MODEL (multi_selection));
|
|
|
|
gtk_column_view_set_show_column_separators (GTK_COLUMN_VIEW (column_view), TRUE);
|
|
gtk_column_view_set_show_row_separators (GTK_COLUMN_VIEW (column_view), TRUE);
|
|
gtk_widget_add_css_class (column_view, "data-table");
|
|
|
|
for (i = 0; i < MIN (n_columns, 127 - 65); ++i)
|
|
{
|
|
const char name[] = { 'A' + i, '\0' };
|
|
|
|
GtkListItemFactory *factory = gtk_signal_list_item_factory_new ();
|
|
g_signal_connect (factory, "setup", G_CALLBACK (setup), NULL);
|
|
g_signal_connect (factory, "bind", G_CALLBACK (bind), GINT_TO_POINTER (name[0]));
|
|
|
|
gtk_column_view_append_column (GTK_COLUMN_VIEW (column_view),
|
|
gtk_column_view_column_new (name, factory));
|
|
}
|
|
|
|
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled_window),
|
|
column_view);
|
|
|
|
if (!no_auto_scroll)
|
|
{
|
|
gtk_widget_add_tick_callback (column_view,
|
|
scroll_column_view,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
|
|
gtk_window_present (GTK_WINDOW (window));
|
|
g_signal_connect (window, "destroy",
|
|
G_CALLBACK (quit_cb), &done);
|
|
|
|
while (!done)
|
|
g_main_context_iteration (NULL, TRUE);
|
|
|
|
return 0;
|
|
}
|