gtk/demos/gtk-demo/main.c

1231 lines
31 KiB
C
Raw Normal View History

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include <gtk/gtk.h>
#include <glib/gstdio.h>
#include "demos.h"
static GtkWidget *info_view;
static GtkWidget *source_view;
static gchar *current_file = NULL;
static GtkWidget *notebook;
2013-12-03 01:35:57 +00:00
static GtkWidget *treeview;
static GtkWidget *toplevel;
enum {
NAME_COLUMN,
TITLE_COLUMN,
FILENAME_COLUMN,
FUNC_COLUMN,
STYLE_COLUMN,
NUM_COLUMNS
};
typedef struct _CallbackData CallbackData;
struct _CallbackData
{
GtkTreeModel *model;
GtkTreePath *path;
};
static void
activate_about (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkApplication *app = user_data;
const gchar *authors[] = {
"The GTK Team",
NULL
};
char *version;
GString *s;
s = g_string_new ("");
g_string_append (s, "System libraries\n");
g_string_append_printf (s, "\tGLib\t%d.%d.%d\n",
glib_major_version,
glib_minor_version,
glib_micro_version);
g_string_append_printf (s, "\tPango\t%s\n",
pango_version_string ());
g_string_append_printf (s, "\tGTK\t%d.%d.%d\n",
gtk_get_major_version (),
gtk_get_minor_version (),
gtk_get_micro_version ());
g_string_append_printf (s, "\nA link can apppear here: <http://www.gtk.org>");
version = g_strdup_printf ("%s\nRunning against GTK %d.%d.%d",
PACKAGE_VERSION,
gtk_get_major_version (),
gtk_get_minor_version (),
gtk_get_micro_version ());
gtk_show_about_dialog (GTK_WINDOW (gtk_application_get_active_window (app)),
"program-name", "GTK Demo",
"version", version,
2020-04-26 04:44:48 +00:00
"copyright", "©1997—2020 The GTK Team",
"license-type", GTK_LICENSE_LGPL_2_1,
"website", "http://www.gtk.org",
"comments", "Program to demonstrate GTK widgets",
"authors", authors,
2019-04-01 22:49:09 +00:00
"logo-icon-name", "org.gtk.Demo4",
"title", "About GTK Demo",
"system-information", s->str,
NULL);
g_string_free (s, TRUE);
g_free (version);
}
static void
activate_quit (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkApplication *app = user_data;
GtkWidget *win;
GList *list, *next;
list = gtk_application_get_windows (app);
while (list)
{
win = list->data;
next = list->next;
gtk_widget_destroy (GTK_WIDGET (win));
list = next;
}
}
static void
activate_inspector (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
gtk_window_set_interactive_debugging (TRUE);
}
static void
window_closed_cb (GtkWidget *window, gpointer data)
{
CallbackData *cbdata = data;
GtkTreeIter iter;
PangoStyle style;
gtk_tree_model_get_iter (cbdata->model, &iter, cbdata->path);
gtk_tree_model_get (GTK_TREE_MODEL (cbdata->model), &iter,
STYLE_COLUMN, &style,
-1);
if (style == PANGO_STYLE_ITALIC)
gtk_tree_store_set (GTK_TREE_STORE (cbdata->model), &iter,
STYLE_COLUMN, PANGO_STYLE_NORMAL,
-1);
gtk_tree_path_free (cbdata->path);
g_free (cbdata);
}
2013-12-03 01:35:57 +00:00
static void
2013-12-13 15:01:18 +00:00
run_example_for_row (GtkWidget *window,
GtkTreeModel *model,
GtkTreeIter *iter)
2013-12-03 01:35:57 +00:00
{
PangoStyle style;
GDoDemoFunc func;
GtkWidget *demo;
gtk_tree_model_get (GTK_TREE_MODEL (model),
2013-12-13 15:01:18 +00:00
iter,
2013-12-03 01:35:57 +00:00
FUNC_COLUMN, &func,
STYLE_COLUMN, &style,
-1);
if (func)
{
gtk_tree_store_set (GTK_TREE_STORE (model),
2013-12-13 15:01:18 +00:00
iter,
2013-12-03 01:35:57 +00:00
STYLE_COLUMN, (style == PANGO_STYLE_ITALIC ? PANGO_STYLE_NORMAL : PANGO_STYLE_ITALIC),
-1);
demo = (func) (window);
if (demo != NULL)
{
CallbackData *cbdata;
cbdata = g_new (CallbackData, 1);
cbdata->model = model;
2013-12-13 15:01:18 +00:00
cbdata->path = gtk_tree_model_get_path (model, iter);
2013-12-03 01:35:57 +00:00
2019-05-20 03:31:03 +00:00
if (GTK_IS_WINDOW (demo))
{
gtk_window_set_transient_for (GTK_WINDOW (demo), GTK_WINDOW (window));
gtk_window_set_modal (GTK_WINDOW (demo), TRUE);
}
2013-12-03 01:35:57 +00:00
g_signal_connect (demo, "destroy",
G_CALLBACK (window_closed_cb), cbdata);
}
}
}
2013-12-13 15:01:18 +00:00
static void
activate_run (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
GtkWidget *window = user_data;
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
if (gtk_tree_selection_get_selected (selection, &model, &iter))
run_example_for_row (window, model, &iter);
2013-12-13 15:01:18 +00:00
}
/* Stupid syntax highlighting.
*
* No regex was used in the making of this highlighting.
* It should only work for simple cases. This is good, as
* that's all we should have in the demos.
*/
/* This code should not be used elsewhere, except perhaps as an example of how
* to iterate through a text buffer.
*/
enum {
STATE_NORMAL,
STATE_IN_COMMENT
};
static const char *tokens[] =
{
"/*",
"\"",
NULL
};
static const char *types[] =
{
"static",
"const ",
"void",
"gint",
" int ",
" char ",
"gchar ",
"gfloat",
"float",
"double",
"gint8",
"gint16",
"gint32",
"guint",
"guint8",
"guint16",
"guint32",
"guchar",
"glong",
"gboolean" ,
"gshort",
"gushort",
"gulong",
"gdouble",
"gldouble",
"gpointer",
"NULL",
"GList",
"GSList",
"FALSE",
"TRUE",
"FILE ",
"GtkColorSelection ",
"GtkWidget ",
"GtkButton ",
"GdkColor ",
"GdkRectangle ",
"GdkEventExpose ",
"GdkGC ",
"GdkPixbufLoader ",
"GdkPixbuf ",
"GError",
"size_t",
"GtkAboutDialog ",
"GtkAction ",
"GtkActionEntry ",
"GtkRadioActionEntry ",
"GtkIconFactory ",
"GtkTextBuffer ",
"GtkStatusbar ",
"GtkTextIter ",
"GtkTextMark ",
"GdkEventWindowState ",
"GtkActionGroup ",
"GtkUIManager ",
"GtkRadioAction ",
"GtkActionClass ",
"GtkToggleActionEntry ",
"GtkAssistant ",
"GtkBuilder ",
"GtkSizeGroup ",
"GtkTreeModel ",
"GtkTreeSelection ",
"GdkDisplay ",
"GdkScreen ",
GdkWindow -> GdkSurface initial type rename This renames the GdkWindow class and related classes (impl, backend subclasses) to surface. Additionally it renames related types: GdkWindowAttr, GdkWindowPaint, GdkWindowWindowClass, GdkWindowType, GdkWindowTypeHint, GdkWindowHints, GdkWindowState, GdkWindowEdge This is an automatic conversion using the below commands: git sed -f g GdkWindowWindowClass GdkSurfaceSurfaceClass git sed -f g GdkWindow GdkSurface git sed -f g "gdk_window\([ _\(\),;]\|$\)" "gdk_surface\1" # Avoid hitting gdk_windowing git sed -f g "GDK_WINDOW\([ _\(]\|$\)" "GDK_SURFACE\1" # Avoid hitting GDK_WINDOWING git sed "GDK_\([A-Z]*\)IS_WINDOW\([_ (]\|$\)" "GDK_\1IS_SURFACE\2" git sed GDK_TYPE_WINDOW GDK_TYPE_SURFACE git sed -f g GdkPointerWindowInfo GdkPointerSurfaceInfo git sed -f g "BROADWAY_WINDOW" "BROADWAY_SURFACE" git sed -f g "broadway_window" "broadway_surface" git sed -f g "BroadwayWindow" "BroadwaySurface" git sed -f g "WAYLAND_WINDOW" "WAYLAND_SURFACE" git sed -f g "wayland_window" "wayland_surface" git sed -f g "WaylandWindow" "WaylandSurface" git sed -f g "X11_WINDOW" "X11_SURFACE" git sed -f g "x11_window" "x11_surface" git sed -f g "X11Window" "X11Surface" git sed -f g "WIN32_WINDOW" "WIN32_SURFACE" git sed -f g "win32_window" "win32_surface" git sed -f g "Win32Window" "Win32Surface" git sed -f g "QUARTZ_WINDOW" "QUARTZ_SURFACE" git sed -f g "quartz_window" "quartz_surface" git sed -f g "QuartzWindow" "QuartzSurface" git checkout NEWS* po-properties
2018-03-20 10:40:08 +00:00
"GdkSurface ",
"GdkEventButton ",
"GdkCursor ",
"GtkTreeIter ",
"GtkTreeViewColumn ",
"GdkDisplayManager ",
2017-12-02 13:39:37 +00:00
"GdkClipboard ",
"GtkIconSize ",
"GtkImage ",
"GdkDragContext ",
"GtkSelectionData ",
"GtkDialog ",
"GtkMenuItem ",
"GtkListStore ",
"GtkCellLayout ",
"GtkCellRenderer ",
"GtkTreePath ",
"GtkTreeStore ",
"GtkEntry ",
"GtkEditable ",
"GtkEditableInterface ",
"GdkPixmap ",
"GdkEventConfigure ",
"GdkEventMotion ",
"GdkModifierType ",
"GtkEntryCompletion ",
"GtkToolItem ",
"GDir ",
"GtkIconView ",
"GtkCellRendererText ",
"GtkContainer ",
"GtkPaned ",
"GtkPrintOperation ",
"GtkPrintContext ",
"cairo_t ",
"PangoLayout "
"PangoFontDescription ",
"PangoRenderer ",
"PangoMatrix ",
"PangoContext ",
"PangoLayout ",
"GtkToggleButton ",
"GString ",
"GtkIconSize ",
"GtkTreeView ",
"GtkTextTag ",
"GdkEvent ",
"GdkEventKey ",
"GtkTextView ",
"GdkBitmap ",
"GtkTextChildAnchor ",
"GArray ",
"GtkCellEditable ",
"GtkCellRendererToggle ",
NULL
};
static const char *control[] =
{
" if ",
" while ",
" else",
" do ",
" for ",
"?",
":",
"return ",
"goto ",
NULL
};
void
parse_chars (gchar *text,
gchar **end_ptr,
gint *state,
const char **tag,
gboolean start)
{
gint i;
gchar *next_token;
/* Handle comments first */
if (*state == STATE_IN_COMMENT)
{
*end_ptr = strstr (text, "*/");
if (*end_ptr)
{
*end_ptr += 2;
*state = STATE_NORMAL;
*tag = "comment";
}
return;
}
*tag = NULL;
*end_ptr = NULL;
/* check for comment */
if (!strncmp (text, "/*", 2))
{
*end_ptr = strstr (text, "*/");
if (*end_ptr)
*end_ptr += 2;
else
*state = STATE_IN_COMMENT;
*tag = "comment";
return;
}
/* check for preprocessor defines */
if (*text == '#' && start)
{
*end_ptr = NULL;
*tag = "preprocessor";
return;
}
/* functions */
if (start && * text != '\t' && *text != ' ' && *text != '{' && *text != '}')
{
if (strstr (text, "("))
{
*end_ptr = strstr (text, "(");
*tag = "function";
return;
}
}
/* check for types */
for (i = 0; types[i] != NULL; i++)
if (!strncmp (text, types[i], strlen (types[i])) ||
(start && types[i][0] == ' ' && !strncmp (text, types[i] + 1, strlen (types[i]) - 1)))
{
*end_ptr = text + strlen (types[i]);
*tag = "type";
return;
}
/* check for control */
for (i = 0; control[i] != NULL; i++)
if (!strncmp (text, control[i], strlen (control[i])))
{
*end_ptr = text + strlen (control[i]);
*tag = "control";
return;
}
/* check for string */
if (text[0] == '"')
{
gint maybe_escape = FALSE;
*end_ptr = text + 1;
*tag = "string";
while (**end_ptr != '\000')
{
if (**end_ptr == '\"' && !maybe_escape)
{
*end_ptr += 1;
return;
}
if (**end_ptr == '\\')
maybe_escape = TRUE;
else
maybe_escape = FALSE;
*end_ptr += 1;
}
return;
}
/* not at the start of a tag. Find the next one. */
for (i = 0; tokens[i] != NULL; i++)
{
next_token = strstr (text, tokens[i]);
if (next_token)
{
if (*end_ptr)
*end_ptr = (*end_ptr<next_token)?*end_ptr:next_token;
else
*end_ptr = next_token;
}
}
for (i = 0; types[i] != NULL; i++)
{
next_token = strstr (text, types[i]);
if (next_token)
{
if (*end_ptr)
*end_ptr = (*end_ptr<next_token)?*end_ptr:next_token;
else
*end_ptr = next_token;
}
}
for (i = 0; control[i] != NULL; i++)
{
next_token = strstr (text, control[i]);
if (next_token)
{
if (*end_ptr)
*end_ptr = (*end_ptr<next_token)?*end_ptr:next_token;
else
*end_ptr = next_token;
}
}
}
/* While not as cool as c-mode, this will do as a quick attempt at highlighting */
void
fontify (GtkTextBuffer *source_buffer)
{
GtkTextIter start_iter, next_iter, tmp_iter;
gint state;
gchar *text;
gchar *start_ptr, *end_ptr;
const char *tag;
2016-02-14 15:49:22 +00:00
gtk_text_buffer_create_tag (source_buffer, "source",
"font", "monospace",
NULL);
gtk_text_buffer_create_tag (source_buffer, "comment",
"foreground", "DodgerBlue",
NULL);
gtk_text_buffer_create_tag (source_buffer, "type",
"foreground", "ForestGreen",
NULL);
gtk_text_buffer_create_tag (source_buffer, "string",
"foreground", "RosyBrown",
"weight", PANGO_WEIGHT_BOLD,
NULL);
gtk_text_buffer_create_tag (source_buffer, "control",
"foreground", "purple",
NULL);
gtk_text_buffer_create_tag (source_buffer, "preprocessor",
"style", PANGO_STYLE_OBLIQUE,
"foreground", "burlywood4",
NULL);
gtk_text_buffer_create_tag (source_buffer, "function",
"weight", PANGO_WEIGHT_BOLD,
"foreground", "DarkGoldenrod4",
NULL);
gtk_text_buffer_get_bounds (source_buffer, &start_iter, &tmp_iter);
gtk_text_buffer_apply_tag_by_name (source_buffer, "source", &start_iter, &tmp_iter);
state = STATE_NORMAL;
gtk_text_buffer_get_iter_at_offset (source_buffer, &start_iter, 0);
next_iter = start_iter;
while (gtk_text_iter_forward_line (&next_iter))
{
gboolean start = TRUE;
start_ptr = text = gtk_text_iter_get_text (&start_iter, &next_iter);
do
{
parse_chars (start_ptr, &end_ptr, &state, &tag, start);
start = FALSE;
if (end_ptr)
{
tmp_iter = start_iter;
gtk_text_iter_forward_chars (&tmp_iter, end_ptr - start_ptr);
}
else
{
tmp_iter = next_iter;
}
if (tag)
gtk_text_buffer_apply_tag_by_name (source_buffer, tag, &start_iter, &tmp_iter);
start_iter = tmp_iter;
start_ptr = end_ptr;
}
while (end_ptr);
g_free (text);
start_iter = next_iter;
}
}
static GtkWidget *
display_image (const char *resource)
{
GtkWidget *sw, *image;
image = gtk_image_new_from_resource (resource);
gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
gtk_widget_set_valign (image, GTK_ALIGN_CENTER);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), image);
return sw;
}
static GtkWidget *
display_text (const char *resource)
{
GtkTextBuffer *buffer;
GtkWidget *textview, *sw;
GBytes *bytes;
bytes = g_resources_lookup_data (resource, 0, NULL);
g_assert (bytes);
g_assert (g_utf8_validate (g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), NULL));
textview = gtk_text_view_new ();
g_object_set (textview,
"left-margin", 20,
"right-margin", 20,
"top-margin", 20,
"bottom-margin", 20,
NULL);
gtk_text_view_set_editable (GTK_TEXT_VIEW (textview), FALSE);
gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (textview), FALSE);
/* Make it a bit nicer for text. */
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (textview), GTK_WRAP_WORD);
gtk_text_view_set_pixels_above_lines (GTK_TEXT_VIEW (textview), 2);
gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (textview), 2);
buffer = gtk_text_buffer_new (NULL);
gtk_text_buffer_set_text (buffer, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes));
if (g_str_has_suffix (resource, ".c"))
fontify (buffer);
gtk_text_view_set_buffer (GTK_TEXT_VIEW (textview), buffer);
g_bytes_unref (bytes);
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), textview);
return sw;
}
static GtkWidget *
display_video (const char *resource)
{
GtkWidget *video;
video = gtk_video_new_for_resource (resource);
gtk_video_set_loop (GTK_VIDEO (video), TRUE);
return video;
}
static GtkWidget *
display_nothing (const char *resource)
{
GtkWidget *widget;
char *str;
str = g_strdup_printf ("The lazy GTK developers forgot to add a way to display the resource '%s'", resource);
widget = gtk_label_new (str);
gtk_label_set_wrap (GTK_LABEL (widget), TRUE);
g_free (str);
return widget;
}
static struct {
const char *extension;
GtkWidget * (* display_func) (const char *resource);
} display_funcs[] = {
{ ".gif", display_image },
{ ".jpg", display_image },
{ ".png", display_image },
{ ".c", display_text },
{ ".css", display_text },
{ ".glsl", display_text },
{ ".h", display_text },
{ ".txt", display_text },
{ ".ui", display_text },
{ ".webm", display_video }
};
static void
add_data_tab (const gchar *demoname)
{
gchar *resource_dir, *resource_name;
gchar **resources;
GtkWidget *widget, *label;
guint i, j;
resource_dir = g_strconcat ("/", demoname, NULL);
resources = g_resources_enumerate_children (resource_dir, 0, NULL);
if (resources == NULL)
{
g_free (resource_dir);
return;
}
for (i = 0; resources[i]; i++)
{
resource_name = g_strconcat (resource_dir, "/", resources[i], NULL);
for (j = 0; j < G_N_ELEMENTS(display_funcs); j++)
{
if (g_str_has_suffix (resource_name, display_funcs[j].extension))
break;
}
if (j < G_N_ELEMENTS(display_funcs))
widget = display_funcs[j].display_func (resource_name);
else
widget = display_nothing (resource_name);
label = gtk_label_new (resources[i]);
gtk_widget_show (label);
gtk_notebook_append_page (GTK_NOTEBOOK (notebook), widget, label);
g_object_set (gtk_notebook_get_page (GTK_NOTEBOOK (notebook), widget),
"tab-expand", FALSE,
NULL);
g_free (resource_name);
}
g_strfreev (resources);
g_free (resource_dir);
}
static void
remove_data_tabs (void)
{
gint i;
for (i = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)) - 1; i > 1; i--)
gtk_notebook_remove_page (GTK_NOTEBOOK (notebook), i);
}
void
load_file (const gchar *demoname,
const gchar *filename)
{
GtkTextBuffer *info_buffer, *source_buffer;
GtkTextIter start, end;
2013-01-29 13:51:06 +00:00
char *resource_filename;
GError *err = NULL;
int state = 0;
gboolean in_para = 0;
gchar **lines;
2013-01-29 13:51:06 +00:00
GBytes *bytes;
gint i;
if (!g_strcmp0 (current_file, filename))
return;
remove_data_tabs ();
add_data_tab (demoname);
g_free (current_file);
current_file = g_strdup (filename);
info_buffer = gtk_text_buffer_new (NULL);
gtk_text_buffer_create_tag (info_buffer, "title",
"font", "Sans 18",
"pixels-below-lines", 10,
NULL);
source_buffer = gtk_text_buffer_new (NULL);
gtk_text_buffer_begin_irreversible_action (info_buffer);
gtk_text_buffer_begin_irreversible_action (source_buffer);
resource_filename = g_strconcat ("/sources/", filename, NULL);
2013-01-29 13:51:06 +00:00
bytes = g_resources_lookup_data (resource_filename, 0, &err);
g_free (resource_filename);
2013-01-29 13:51:06 +00:00
if (bytes == NULL)
{
g_warning ("Cannot open source for %s: %s", filename, err->message);
g_error_free (err);
return;
}
2013-01-29 13:51:06 +00:00
lines = g_strsplit (g_bytes_get_data (bytes, NULL), "\n", -1);
g_bytes_unref (bytes);
gtk_text_buffer_get_iter_at_offset (info_buffer, &start, 0);
for (i = 0; lines[i] != NULL; i++)
{
gchar *p;
gchar *q;
gchar *r;
/* Make sure \r is stripped at the end for the poor windows people */
lines[i] = g_strchomp (lines[i]);
p = lines[i];
switch (state)
{
case 0:
/* Reading title */
while (*p == '/' || *p == '*' || g_ascii_isspace (*p))
p++;
r = p;
while (*r != '\0')
{
while (*r != '/' && *r != ':' && *r != '\0')
r++;
if (*r == '/')
{
r++;
p = r;
}
if (r[0] == ':' && r[1] == ':')
*r = '\0';
}
q = p + strlen (p);
while (q > p && g_ascii_isspace (*(q - 1)))
q--;
if (q > p)
{
int len_chars = g_utf8_pointer_to_offset (p, q);
end = start;
g_assert (strlen (p) >= q - p);
gtk_text_buffer_insert (info_buffer, &end, p, q - p);
start = end;
gtk_text_iter_backward_chars (&start, len_chars);
gtk_text_buffer_apply_tag_by_name (info_buffer, "title", &start, &end);
start = end;
while (*p && *p != '\n') p++;
state++;
}
break;
case 1:
/* Reading body of info section */
while (g_ascii_isspace (*p))
p++;
if (*p == '*' && *(p + 1) == '/')
{
gtk_text_buffer_get_iter_at_offset (source_buffer, &start, 0);
state++;
}
else
{
int len;
while (*p == '*' || g_ascii_isspace (*p))
p++;
len = strlen (p);
while (g_ascii_isspace (*(p + len - 1)))
len--;
if (len > 0)
{
if (in_para)
gtk_text_buffer_insert (info_buffer, &start, " ", 1);
g_assert (strlen (p) >= len);
gtk_text_buffer_insert (info_buffer, &start, p, len);
in_para = 1;
}
else
{
gtk_text_buffer_insert (info_buffer, &start, "\n", 1);
in_para = 0;
}
}
break;
case 2:
/* Skipping blank lines */
while (g_ascii_isspace (*p))
p++;
if (!*p)
break;
p = lines[i];
state++;
G_GNUC_FALLTHROUGH;
case 3:
/* Reading program body */
gtk_text_buffer_insert (source_buffer, &start, p, -1);
if (lines[i+1] != NULL)
gtk_text_buffer_insert (source_buffer, &start, "\n", 1);
break;
default:
g_assert_not_reached ();
}
}
g_strfreev (lines);
fontify (source_buffer);
fix bug where it always set the foreground, even if we were only using a 2001-02-12 Havoc Pennington <hp@pobox.com> * gdk/gdkpango.c (gdk_pango_get_gc): fix bug where it always set the foreground, even if we were only using a stipple. (gdk_draw_layout_line_with_colors): new function, allow override colors (gdk_draw_layout_with_colors): new function, allow override colors (gdk_pango_layout_line_get_clip_region): function to get the clip region for a logical text range (gdk_pango_layout_get_clip_region): get the clip region for a logical text range * gdk/x11/gdkcolor-x11.c: forward declare gdk_colormap_sync(), (gdk_colormap_new): fix call to gdk_colormap_sync() so it has the right number of arguments. * gtk/gtktextbtree.c (gtk_text_btree_node_check_consistency): enhance the function to check that node data corresponds to a view still belonging to the tree. * gtk/gtktreeview.c (gtk_tree_view_changed): we were leaking the GtkTreePath (gtk_tree_view_inserted): ditto (gtk_tree_view_child_toggled): ditto * gtk/gtktreemodel.c (gtk_tree_path_append_index): use realloc to simplify this code. * gtk/gtkcellrenderertext.c (get_layout): fix leak of a PangoAttrList * demos/gtk-demo/main.c (load_file): Fix leak of a GString * gtk/gtkentry.c (gtk_entry_realize): Fix leak of a GdkCursor * gtk/gtkmenubar.c (gtk_menu_bar_size_request): consider toggle size in the size request (gtk_menu_bar_size_allocate): consider toggle size here * gtk/gtkimagemenuitem.h, gtkimagemenuitem.c: Menu item that displays a widget in the toggle slot * gtk/testgtk.c: test GtkImageMenuItem * gtk/Makefile.am, gtk/gtk.h: Add GtkImageMenuItem * gtk/gtkmenuitem.h: Use "gint" not "guint16" for toggle size request and allocation * gtk/gtkmenu.c (gtk_menu_size_request): use gint not guint16 * gtk/gtkcheckmenuitem.c (gtk_check_menu_item_toggle_size_request): ditto
2001-02-13 05:44:47 +00:00
gtk_text_buffer_end_irreversible_action (source_buffer);
gtk_text_view_set_buffer (GTK_TEXT_VIEW (source_view), source_buffer);
g_object_unref (source_buffer);
gtk_text_buffer_end_irreversible_action (info_buffer);
gtk_text_view_set_buffer (GTK_TEXT_VIEW (info_view), info_buffer);
g_object_unref (info_buffer);
}
static void
selection_cb (GtkTreeSelection *selection,
GtkTreeModel *model)
{
GtkTreeIter iter;
2013-12-03 01:35:57 +00:00
char *name;
char *filename;
char *title;
if (! gtk_tree_selection_get_selected (selection, NULL, &iter))
return;
gtk_tree_model_get (model, &iter,
NAME_COLUMN, &name,
2013-12-03 01:35:57 +00:00
TITLE_COLUMN, &title,
FILENAME_COLUMN, &filename,
-1);
if (filename)
load_file (name, filename);
gtk_window_set_title (GTK_WINDOW (toplevel), title);
2013-12-03 01:35:57 +00:00
g_free (name);
2013-12-03 01:35:57 +00:00
g_free (title);
g_free (filename);
}
static void
populate_model (GtkTreeModel *model)
{
Demo *d = gtk_demos;
/* this code only supports 1 level of children. If we
* want more we probably have to use a recursing function.
*/
while (d->title)
{
Demo *children = d->children;
GtkTreeIter iter;
gtk_tree_store_append (GTK_TREE_STORE (model), &iter, NULL);
gtk_tree_store_set (GTK_TREE_STORE (model),
&iter,
NAME_COLUMN, d->name,
TITLE_COLUMN, d->title,
FILENAME_COLUMN, d->filename,
FUNC_COLUMN, d->func,
STYLE_COLUMN, PANGO_STYLE_NORMAL,
-1);
d++;
if (!children)
continue;
while (children->title)
{
GtkTreeIter child_iter;
gtk_tree_store_append (GTK_TREE_STORE (model), &child_iter, &iter);
gtk_tree_store_set (GTK_TREE_STORE (model),
&child_iter,
NAME_COLUMN, children->name,
TITLE_COLUMN, children->title,
FILENAME_COLUMN, children->filename,
FUNC_COLUMN, children->func,
STYLE_COLUMN, PANGO_STYLE_NORMAL,
-1);
children++;
}
}
}
remove validation idle 2001-02-08 Havoc Pennington <hp@redhat.com> * gtk/gtktextview.c (gtk_text_view_destroy_layout): remove validation idle * demos/gtk-demo/main.c (create_tree): adjust to changes in text cell renderer * demos/pixbuf-demo.c (timeout): remove deprecated gtk_widget_draw * demos/testpixbuf-save.c (main): remove deprecated gtk_drawing_area_size * gtk/gtktreeview.c (gtk_tree_view_size_allocate): allocate buttons even if the model isn't setup. gtk_tree_view_check_dirty() at the start of the allocation. (gtk_tree_view_check_dirty): handle column->button == NULL, handle unsetup or NULL model. * gtk/gtkstyle.c (gtk_default_draw_flat_box): drawing for the even/odd/sorted cells in the tree view. * gtk/gtktreeselection.c (gtk_tree_selection_real_unselect_all): bugfixes * gtk/gtktreeview.c: assorted bugfixy stuff. Draw the row backgrounds with draw_flat_box using different detail for even/odd rows. * gtk/gtkrbtree.c, gtkrbtree.h: Keep track of the parity of each row, so we can draw the alternating colors thing * gtk/gtktexttag.c (gtk_text_tag_set_property): if we change a property from a synonym property, notify for the synonym. Also, nuke the background_gdk_set and foreground_gdk_set synonyms (gtk_text_tag_get_property): Always return the font, even if all its fields aren't set * gtk/gtkcellrenderertext.h (struct _GtkCellRendererText): don't store the attr list; it leaves us with no way to change attributes in _render according to the render flags, and no way to implement get_property. Instead store all the specific text attributes. Separate whether an attribute is enabled from its value. Sync all properties with GtkTextTag, make them all consistent, etc. * gtk/gtkcellrenderer.h: Add a flag GTK_CELL_RENDERER_SORTED so renderers can highlight the sort row/column * gtk/gtktreeviewcolumn.c (gtk_tree_view_column_get_property): use accessor functions to get values; this has the side effect of showing up which accessor functions were missing. Added those. * gtk/gtktreeviewcolumn.h: Replace set_justification with set_alignment, to be consistent with GtkLabel, GtkMisc * gtk/gtktreeviewcolumn.c: Added code to display sort indicator arrow. * gtk/Makefile.am (gtk_public_h_sources): add gtktreesortable.h * gtk/gtktreesortable.h: updates in here
2001-02-08 23:36:53 +00:00
static void
startup (GApplication *app)
{
GtkBuilder *builder;
GMenuModel *appmenu;
const char *ids[] = { "appmenu", NULL };
builder = gtk_builder_new ();
gtk_builder_add_objects_from_resource (builder, "/ui/appmenu.ui", ids, NULL);
appmenu = (GMenuModel *)gtk_builder_get_object (builder, "appmenu");
gtk_application_set_app_menu (GTK_APPLICATION (app), appmenu);
g_object_unref (builder);
}
2013-12-13 15:01:18 +00:00
static void
row_activated_cb (GtkWidget *tree_view,
GtkTreePath *path,
GtkTreeViewColumn *column)
{
GtkTreeIter iter;
GtkWidget *window;
GtkTreeModel *model;
window = GTK_WIDGET (gtk_widget_get_root (tree_view));
2013-12-13 15:01:18 +00:00
model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
gtk_tree_model_get_iter (model, &iter, path);
run_example_for_row (window, model, &iter);
}
static void
activate (GApplication *app)
{
GtkBuilder *builder;
GtkWindow *window;
GtkWidget *widget;
GtkTreeModel *model;
GtkTreeIter iter;
2013-12-03 01:35:57 +00:00
static GActionEntry win_entries[] = {
{ "run", activate_run, NULL, NULL, NULL }
};
builder = gtk_builder_new_from_resource ("/ui/main.ui");
window = (GtkWindow *)gtk_builder_get_object (builder, "window");
gtk_application_add_window (GTK_APPLICATION (app), window);
g_action_map_add_action_entries (G_ACTION_MAP (window),
win_entries, G_N_ELEMENTS (win_entries),
window);
notebook = (GtkWidget *)gtk_builder_get_object (builder, "notebook");
info_view = (GtkWidget *)gtk_builder_get_object (builder, "info-textview");
source_view = (GtkWidget *)gtk_builder_get_object (builder, "source-textview");
treeview = (GtkWidget *)gtk_builder_get_object (builder, "treeview");
model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
toplevel = GTK_WIDGET (window);
load_file (gtk_demos[0].name, gtk_demos[0].filename);
populate_model (model);
2013-12-13 15:01:18 +00:00
g_signal_connect (treeview, "row-activated", G_CALLBACK (row_activated_cb), model);
widget = (GtkWidget *)gtk_builder_get_object (builder, "treeview-selection");
g_signal_connect (widget, "changed", G_CALLBACK (selection_cb), model);
gtk_tree_model_get_iter_first (gtk_tree_view_get_model (GTK_TREE_VIEW (treeview)), &iter);
gtk_tree_selection_select_iter (GTK_TREE_SELECTION (widget), &iter);
gtk_tree_view_collapse_all (GTK_TREE_VIEW (treeview));
2017-01-19 09:02:04 +00:00
gtk_widget_show (GTK_WIDGET (window));
g_object_unref (builder);
}
static gboolean
auto_quit (gpointer data)
{
g_application_quit (G_APPLICATION (data));
return G_SOURCE_REMOVE;
}
static void
list_demos (void)
{
Demo *d, *c;
d = gtk_demos;
while (d->title)
{
c = d->children;
if (d->name)
g_print ("%s\n", d->name);
d++;
while (c && c->title)
{
if (c->name)
g_print ("%s\n", c->name);
c++;
}
}
}
static gint
command_line (GApplication *app,
GApplicationCommandLine *cmdline)
{
GVariantDict *options;
const gchar *name = NULL;
gboolean autoquit = FALSE;
gboolean list = FALSE;
Demo *d, *c;
GDoDemoFunc func = 0;
GtkWidget *window, *demo;
activate (app);
options = g_application_command_line_get_options_dict (cmdline);
g_variant_dict_lookup (options, "run", "&s", &name);
g_variant_dict_lookup (options, "autoquit", "b", &autoquit);
g_variant_dict_lookup (options, "list", "b", &list);
if (list)
{
list_demos ();
g_application_quit (app);
return 0;
}
if (name == NULL)
goto out;
window = gtk_application_get_windows (GTK_APPLICATION (app))->data;
d = gtk_demos;
while (d->title)
{
c = d->children;
if (g_strcmp0 (d->name, name) == 0)
{
func = d->func;
goto out;
}
d++;
while (c && c->title)
{
if (g_strcmp0 (c->name, name) == 0)
{
func = c->func;
goto out;
}
c++;
}
}
out:
if (func)
{
demo = (func) (window);
gtk_window_set_transient_for (GTK_WINDOW (demo), GTK_WINDOW (window));
gtk_window_set_modal (GTK_WINDOW (demo), TRUE);
}
if (autoquit)
g_timeout_add_seconds (1, auto_quit, app);
return 0;
}
static void
print_version (void)
{
g_print ("gtk3-demo %d.%d.%d\n",
gtk_get_major_version (),
gtk_get_minor_version (),
gtk_get_micro_version ());
}
static int
local_options (GApplication *app,
GVariantDict *options,
gpointer data)
{
gboolean version = FALSE;
g_variant_dict_lookup (options, "version", "b", &version);
if (version)
{
print_version ();
return 0;
}
return -1;
}
int
main (int argc, char **argv)
{
GtkApplication *app;
static GActionEntry app_entries[] = {
{ "about", activate_about, NULL, NULL, NULL },
{ "quit", activate_quit, NULL, NULL, NULL },
{ "inspector", activate_inspector, NULL, NULL, NULL },
};
struct {
const gchar *action_and_target;
const gchar *accelerators[2];
} accels[] = {
{ "app.about", { "F1", NULL } },
{ "app.quit", { "<Control>q", NULL } },
};
int i;
fix some shell typos 2001-05-04 Havoc Pennington <hp@redhat.com> * configure.in: fix some shell typos * gtk/gtkcolorsel.c (gtk_color_selection_destroy): warning fix * gtk/gtkimage.c: handle animations * gtk/gtkcheckbutton.c (gtk_check_button_size_request): request border_width * 2, not just border_width * gtk/gtkscale.c: add "format_value" signal to allow people to override the way values are drawn. (gtk_scale_get_value_size): fix width/height mistake, and compute size from actual displayed text, not from made-up text. * gtk/gtktexttag.c (gtk_text_tag_class_init): fix return type in signal registration * tests/testtext.c: Add "Remove all tags" menu item for testing * gtk/gtktextbuffer.c (gtk_text_buffer_remove_all_tags): implement * demos/gtk-demo/main.c (main): add hack so we can find modules without installing gtk * demos/gtk-demo/textview.c (insert_text): demo font scaling * gtk/gtkcellrenderertext.c: Add "scale" property (font scaling factor) (gtk_cell_renderer_text_set_property): remove some bogus g_object_notify * gtk/gtktexttag.c: add "scale" property which is a font scaling factor * gtk/gtktextlayout.c (add_text_attrs): add font scale attribute to layout * gtk/gtktextiter.c (gtk_text_iter_is_start): rename from gtk_text_iter_is_first 2001-05-04 Havoc Pennington <hp@redhat.com> * pixops/pixops.c (pixops_process): merge fix from stable: Patch from hoshem@mel.comcen.com.au to fix nonzero X offsets. Fixes bug #50371. * gdk-pixbuf/pixops/pixops.c (pixops_composite_nearest): merge from stable: Patch from OKADA Mitsuru <m-okada@fjb.co.jp> to fix confusion of using "src" instead of "p". (pixops_composite_color_nearest): Use a more accurate (and correct, to begin with) compositing method. This cures checks showing through on images with no alpha. * gdk-pixbuf.c (gdk_pixbuf_fill): fix bug that left some trailing bytes unfilled. * gdk-pixbuf-io.h: fix UpdatedNotifyFunc to use signed ints * gdk-pixbuf-loader.h (struct _GdkPixbufLoaderClass): Change area_updated signal to use signed ints. Removed animation-related signals. * io-gif.c, io-gif-animation.h, io-gif-animation.c: Massive rewrite action * gdk-pixbuf-animation.c: Add GdkPixbufAnimationIter to abstract all the pesky details. Remove old frame-based API. Make GdkPixbufAnimation an abstract base class, derived by the loaders.
2001-05-07 15:58:47 +00:00
/* Most code in gtk-demo is intended to be exemplary, but not
* these few lines, which are just a hack so gtk-demo will work
* in the GTK tree without installing it.
*/
if (g_file_test ("../../modules/input/immodules.cache", G_FILE_TEST_EXISTS))
fix some shell typos 2001-05-04 Havoc Pennington <hp@redhat.com> * configure.in: fix some shell typos * gtk/gtkcolorsel.c (gtk_color_selection_destroy): warning fix * gtk/gtkimage.c: handle animations * gtk/gtkcheckbutton.c (gtk_check_button_size_request): request border_width * 2, not just border_width * gtk/gtkscale.c: add "format_value" signal to allow people to override the way values are drawn. (gtk_scale_get_value_size): fix width/height mistake, and compute size from actual displayed text, not from made-up text. * gtk/gtktexttag.c (gtk_text_tag_class_init): fix return type in signal registration * tests/testtext.c: Add "Remove all tags" menu item for testing * gtk/gtktextbuffer.c (gtk_text_buffer_remove_all_tags): implement * demos/gtk-demo/main.c (main): add hack so we can find modules without installing gtk * demos/gtk-demo/textview.c (insert_text): demo font scaling * gtk/gtkcellrenderertext.c: Add "scale" property (font scaling factor) (gtk_cell_renderer_text_set_property): remove some bogus g_object_notify * gtk/gtktexttag.c: add "scale" property which is a font scaling factor * gtk/gtktextlayout.c (add_text_attrs): add font scale attribute to layout * gtk/gtktextiter.c (gtk_text_iter_is_start): rename from gtk_text_iter_is_first 2001-05-04 Havoc Pennington <hp@redhat.com> * pixops/pixops.c (pixops_process): merge fix from stable: Patch from hoshem@mel.comcen.com.au to fix nonzero X offsets. Fixes bug #50371. * gdk-pixbuf/pixops/pixops.c (pixops_composite_nearest): merge from stable: Patch from OKADA Mitsuru <m-okada@fjb.co.jp> to fix confusion of using "src" instead of "p". (pixops_composite_color_nearest): Use a more accurate (and correct, to begin with) compositing method. This cures checks showing through on images with no alpha. * gdk-pixbuf.c (gdk_pixbuf_fill): fix bug that left some trailing bytes unfilled. * gdk-pixbuf-io.h: fix UpdatedNotifyFunc to use signed ints * gdk-pixbuf-loader.h (struct _GdkPixbufLoaderClass): Change area_updated signal to use signed ints. Removed animation-related signals. * io-gif.c, io-gif-animation.h, io-gif-animation.c: Massive rewrite action * gdk-pixbuf-animation.c: Add GdkPixbufAnimationIter to abstract all the pesky details. Remove old frame-based API. Make GdkPixbufAnimation an abstract base class, derived by the loaders.
2001-05-07 15:58:47 +00:00
{
g_setenv ("GTK_IM_MODULE_FILE", "../../modules/input/immodules.cache", TRUE);
fix some shell typos 2001-05-04 Havoc Pennington <hp@redhat.com> * configure.in: fix some shell typos * gtk/gtkcolorsel.c (gtk_color_selection_destroy): warning fix * gtk/gtkimage.c: handle animations * gtk/gtkcheckbutton.c (gtk_check_button_size_request): request border_width * 2, not just border_width * gtk/gtkscale.c: add "format_value" signal to allow people to override the way values are drawn. (gtk_scale_get_value_size): fix width/height mistake, and compute size from actual displayed text, not from made-up text. * gtk/gtktexttag.c (gtk_text_tag_class_init): fix return type in signal registration * tests/testtext.c: Add "Remove all tags" menu item for testing * gtk/gtktextbuffer.c (gtk_text_buffer_remove_all_tags): implement * demos/gtk-demo/main.c (main): add hack so we can find modules without installing gtk * demos/gtk-demo/textview.c (insert_text): demo font scaling * gtk/gtkcellrenderertext.c: Add "scale" property (font scaling factor) (gtk_cell_renderer_text_set_property): remove some bogus g_object_notify * gtk/gtktexttag.c: add "scale" property which is a font scaling factor * gtk/gtktextlayout.c (add_text_attrs): add font scale attribute to layout * gtk/gtktextiter.c (gtk_text_iter_is_start): rename from gtk_text_iter_is_first 2001-05-04 Havoc Pennington <hp@redhat.com> * pixops/pixops.c (pixops_process): merge fix from stable: Patch from hoshem@mel.comcen.com.au to fix nonzero X offsets. Fixes bug #50371. * gdk-pixbuf/pixops/pixops.c (pixops_composite_nearest): merge from stable: Patch from OKADA Mitsuru <m-okada@fjb.co.jp> to fix confusion of using "src" instead of "p". (pixops_composite_color_nearest): Use a more accurate (and correct, to begin with) compositing method. This cures checks showing through on images with no alpha. * gdk-pixbuf.c (gdk_pixbuf_fill): fix bug that left some trailing bytes unfilled. * gdk-pixbuf-io.h: fix UpdatedNotifyFunc to use signed ints * gdk-pixbuf-loader.h (struct _GdkPixbufLoaderClass): Change area_updated signal to use signed ints. Removed animation-related signals. * io-gif.c, io-gif-animation.h, io-gif-animation.c: Massive rewrite action * gdk-pixbuf-animation.c: Add GdkPixbufAnimationIter to abstract all the pesky details. Remove old frame-based API. Make GdkPixbufAnimation an abstract base class, derived by the loaders.
2001-05-07 15:58:47 +00:00
}
/* -- End of hack -- */
2019-04-01 22:49:09 +00:00
app = gtk_application_new ("org.gtk.Demo4", G_APPLICATION_NON_UNIQUE|G_APPLICATION_HANDLES_COMMAND_LINE);
g_action_map_add_action_entries (G_ACTION_MAP (app),
app_entries, G_N_ELEMENTS (app_entries),
app);
for (i = 0; i < G_N_ELEMENTS (accels); i++)
gtk_application_set_accels_for_action (app, accels[i].action_and_target, accels[i].accelerators);
g_application_add_main_option (G_APPLICATION (app), "version", 0, 0, G_OPTION_ARG_NONE, "Show program version", NULL);
g_application_add_main_option (G_APPLICATION (app), "run", 0, 0, G_OPTION_ARG_STRING, "Run an example", "EXAMPLE");
g_application_add_main_option (G_APPLICATION (app), "list", 0, 0, G_OPTION_ARG_NONE, "List examples", NULL);
g_application_add_main_option (G_APPLICATION (app), "autoquit", 0, 0, G_OPTION_ARG_NONE, "Quit after a delay", NULL);
g_signal_connect (app, "startup", G_CALLBACK (startup), NULL);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
g_signal_connect (app, "command-line", G_CALLBACK (command_line), NULL);
g_signal_connect (app, "handle-local-options", G_CALLBACK (local_options), NULL);
g_application_run (G_APPLICATION (app), argc, argv);
return 0;
}