diff --git a/docs/reference/gtk/images/drawingarea.png b/docs/reference/gtk/images/drawingarea.png new file mode 100644 index 0000000000..7ab304522b Binary files /dev/null and b/docs/reference/gtk/images/drawingarea.png differ diff --git a/docs/reference/gtk/images/glarea.png b/docs/reference/gtk/images/glarea.png index 1325afcab0..50bf77c062 100644 Binary files a/docs/reference/gtk/images/glarea.png and b/docs/reference/gtk/images/glarea.png differ diff --git a/docs/reference/gtk/meson.build b/docs/reference/gtk/meson.build index 4e72c167da..30d7737339 100644 --- a/docs/reference/gtk/meson.build +++ b/docs/reference/gtk/meson.build @@ -259,6 +259,7 @@ images = [ 'images/down-start.png', 'images/drop-down.png', 'images/drawing.png', + 'images/drawingarea.png', 'images/ease-in-out.png', 'images/ease-in.png', 'images/ease-out.png', diff --git a/docs/reference/gtk/visual_index.xml b/docs/reference/gtk/visual_index.xml index 82fc571465..664d3922fe 100644 --- a/docs/reference/gtk/visual_index.xml +++ b/docs/reference/gtk/visual_index.xml @@ -20,6 +20,7 @@ + diff --git a/docs/tools/widgets.c b/docs/tools/widgets.c index c99cef1d06..3cb08a3410 100644 --- a/docs/tools/widgets.c +++ b/docs/tools/widgets.c @@ -1497,6 +1497,7 @@ create_flow_box (void) static WidgetInfo * create_gl_area (void) { + GtkWidget *vbox; WidgetInfo *info; GtkWidget *widget; GtkWidget *gears; @@ -1513,12 +1514,15 @@ create_gl_area (void) gtk_style_context_add_provider (gtk_widget_get_style_context (gears), GTK_STYLE_PROVIDER (provider), 800); g_object_unref (provider); + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3); gtk_widget_set_halign (widget, GTK_ALIGN_FILL); gtk_widget_set_valign (widget, GTK_ALIGN_FILL); + gtk_box_append (GTK_BOX (vbox), widget); + gtk_box_append (GTK_BOX (vbox), gtk_label_new ("GL Area")); - add_margin (widget); + add_margin (vbox); - info = new_widget_info ("glarea", widget, MEDIUM); + info = new_widget_info ("glarea", vbox, MEDIUM); return info; } @@ -1741,6 +1745,185 @@ create_shortcuts_window (void) return new_widget_info ("shortcuts-window", overlay, ASIS); } +static void +oval_path (cairo_t *cr, + double xc, double yc, + double xr, double yr) +{ + cairo_save (cr); + + cairo_translate (cr, xc, yc); + cairo_scale (cr, 1.0, yr / xr); + cairo_move_to (cr, xr, 0.0); + cairo_arc (cr, + 0, 0, + xr, + 0, 2 * G_PI); + cairo_close_path (cr); + + cairo_restore (cr); +} + +static void +fill_checks (cairo_t *cr, + int x, int y, + int width, int height) +{ + int i, j; + +#define CHECK_SIZE 16 + + cairo_rectangle (cr, x, y, width, height); + cairo_set_source_rgb (cr, 0.4, 0.4, 0.4); + cairo_fill (cr); + + /* Only works for CHECK_SIZE a power of 2 */ + j = x & (-CHECK_SIZE); + + for (; j < height; j += CHECK_SIZE) + { + i = y & (-CHECK_SIZE); + for (; i < width; i += CHECK_SIZE) + if ((i / CHECK_SIZE + j / CHECK_SIZE) % 2 == 0) + cairo_rectangle (cr, i, j, CHECK_SIZE, CHECK_SIZE); + } + + cairo_set_source_rgb (cr, 0.7, 0.7, 0.7); + cairo_fill (cr); + +#undef CHECK_SIZE +} + +static void +draw_3circles (cairo_t *cr, + double xc, double yc, + double radius, + double alpha) +{ + double subradius = radius * (2 / 3. - 0.1); + + cairo_set_source_rgba (cr, 1., 0., 0., alpha); + oval_path (cr, + xc + radius / 3. * cos (G_PI * (0.5)), + yc - radius / 3. * sin (G_PI * (0.5)), + subradius, subradius); + cairo_fill (cr); + + cairo_set_source_rgba (cr, 0., 1., 0., alpha); + oval_path (cr, + xc + radius / 3. * cos (G_PI * (0.5 + 2/.3)), + yc - radius / 3. * sin (G_PI * (0.5 + 2/.3)), + subradius, subradius); + cairo_fill (cr); + + cairo_set_source_rgba (cr, 0., 0., 1., alpha); + oval_path (cr, + xc + radius / 3. * cos (G_PI * (0.5 + 4/.3)), + yc - radius / 3. * sin (G_PI * (0.5 + 4/.3)), + subradius, subradius); + cairo_fill (cr); +} + +static void +groups_draw (GtkDrawingArea *darea, + cairo_t *cr, + int width, + int height, + gpointer data) +{ + cairo_surface_t *overlay, *punch, *circles; + cairo_t *overlay_cr, *punch_cr, *circles_cr; + + /* Fill the background */ + double radius = 0.5 * (width < height ? width : height) - 10; + double xc = width / 2.; + double yc = height / 2.; + + overlay = cairo_surface_create_similar (cairo_get_target (cr), + CAIRO_CONTENT_COLOR_ALPHA, + width, height); + + punch = cairo_surface_create_similar (cairo_get_target (cr), + CAIRO_CONTENT_ALPHA, + width, height); + + circles = cairo_surface_create_similar (cairo_get_target (cr), + CAIRO_CONTENT_COLOR_ALPHA, + width, height); + + fill_checks (cr, 0, 0, width, height); + + /* Draw a black circle on the overlay + */ + overlay_cr = cairo_create (overlay); + cairo_set_source_rgb (overlay_cr, 0., 0., 0.); + oval_path (overlay_cr, xc, yc, radius, radius); + cairo_fill (overlay_cr); + + /* Draw 3 circles to the punch surface, then cut + * that out of the main circle in the overlay + */ + punch_cr = cairo_create (punch); + draw_3circles (punch_cr, xc, yc, radius, 1.0); + cairo_destroy (punch_cr); + + cairo_set_operator (overlay_cr, CAIRO_OPERATOR_DEST_OUT); + cairo_set_source_surface (overlay_cr, punch, 0, 0); + cairo_paint (overlay_cr); + + /* Now draw the 3 circles in a subgroup again + * at half intensity, and use OperatorAdd to join up + * without seams. + */ + circles_cr = cairo_create (circles); + + cairo_set_operator (circles_cr, CAIRO_OPERATOR_OVER); + draw_3circles (circles_cr, xc, yc, radius, 0.5); + cairo_destroy (circles_cr); + + cairo_set_operator (overlay_cr, CAIRO_OPERATOR_ADD); + cairo_set_source_surface (overlay_cr, circles, 0, 0); + cairo_paint (overlay_cr); + + cairo_destroy (overlay_cr); + + cairo_set_source_surface (cr, overlay, 0, 0); + cairo_paint (cr); + + cairo_surface_destroy (overlay); + cairo_surface_destroy (punch); + cairo_surface_destroy (circles); +} + + +static WidgetInfo * +create_drawing_area (void) +{ + GtkWidget *vbox; + WidgetInfo *info; + GtkWidget *widget; + GtkWidget *da; + + widget = gtk_frame_new (NULL); + da = gtk_drawing_area_new (); + gtk_widget_set_size_request (da, 96, 96); + gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), groups_draw, NULL, NULL); + gtk_frame_set_child (GTK_FRAME (widget), da); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_widget_set_halign (widget, GTK_ALIGN_FILL); + gtk_widget_set_valign (widget, GTK_ALIGN_FILL); + + gtk_box_append (GTK_BOX (vbox), widget); + gtk_box_append (GTK_BOX (vbox), gtk_label_new ("Drawing Area")); + + add_margin (vbox); + + info = new_widget_info ("drawingarea", vbox, MEDIUM); + + return info; +} + GList * get_all_widgets (void) { @@ -1814,6 +1997,7 @@ get_all_widgets (void) retval = g_list_prepend (retval, create_popover ()); retval = g_list_prepend (retval, create_menu ()); retval = g_list_prepend (retval, create_shortcuts_window ()); + retval = g_list_prepend (retval, create_drawing_area()); return retval; }