1 
2 
3 #include "config.h"
4 #include <gtk/gtk.h>
5 
6 typedef struct {
7   GtkTextView parent;
8 } MyTextView;
9 
10 typedef struct {
11   GtkTextViewClass parent_class;
12 } MyTextViewClass;
13 
14 static GType my_text_view_get_type (void);
15 G_DEFINE_TYPE (MyTextView, my_text_view, GTK_TYPE_TEXT_VIEW);
16 
17 static void snapshot_background (GtkWidget *widget, GtkSnapshot *snapshot);
18 
19 static void
my_text_view_init(MyTextView * text_view)20 my_text_view_init (MyTextView *text_view)
21 {
22 }
23 
my_text_view_snapshot_layer(GtkTextView * textview,GtkTextViewLayer layer,GtkSnapshot * snapshot)24 static void my_text_view_snapshot_layer (GtkTextView       *textview,
25                                          GtkTextViewLayer   layer,
26                                          GtkSnapshot       *snapshot)
27 {
28   if (layer == GTK_TEXT_VIEW_LAYER_BELOW_TEXT)
29     snapshot_background (GTK_WIDGET (textview), snapshot);
30 }
31 
32 static void
my_text_view_class_init(MyTextViewClass * klass)33 my_text_view_class_init (MyTextViewClass *klass)
34 {
35   GTK_TEXT_VIEW_CLASS (klass)->snapshot_layer = my_text_view_snapshot_layer;
36 }
37 
38 static void
create_tags(GtkTextBuffer * buffer)39 create_tags (GtkTextBuffer *buffer)
40 {
41 
42   gtk_text_buffer_create_tag (buffer, "italic",
43                               "style", PANGO_STYLE_ITALIC, NULL);
44 
45   gtk_text_buffer_create_tag (buffer, "bold",
46                               "weight", PANGO_WEIGHT_BOLD, NULL);
47 
48   gtk_text_buffer_create_tag (buffer, "x-large",
49                               "scale", PANGO_SCALE_X_LARGE, NULL);
50 
51   gtk_text_buffer_create_tag (buffer, "semi_blue_foreground",
52                               "foreground", "rgba(0,0,255,0.7)", NULL);
53 
54   gtk_text_buffer_create_tag (buffer, "semi_red_background",
55                               "background", "rgba(255,0,0,0.5)", NULL);
56 
57   gtk_text_buffer_create_tag (buffer, "semi_orange_paragraph_background",
58                               "paragraph-background", "rgba(255,165,0,0.5)", NULL);
59 
60   gtk_text_buffer_create_tag (buffer, "word_wrap",
61                               "wrap_mode", GTK_WRAP_WORD, NULL);
62 }
63 
64 
65 static GtkTextChildAnchor *
insert_text(GtkTextBuffer * buffer)66 insert_text (GtkTextBuffer *buffer)
67 {
68   GtkTextIter  iter;
69   GtkTextIter  start, end;
70   GtkTextMark *para_start;
71   GtkTextChildAnchor *anchor;
72 
73   /* get start of buffer; each insertion will revalidate the
74    * iterator to point to just after the inserted text.
75    */
76   gtk_text_buffer_get_iter_at_offset (buffer, &iter, 0);
77 
78   gtk_text_buffer_insert (buffer, &iter,
79       "This test shows text view rendering some text with rgba colors.\n\n", -1);
80 
81   gtk_text_buffer_insert (buffer, &iter, "For example, you can have ", -1);
82   gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
83                                             "italic translucent blue text", -1,
84                                             "italic",
85 					    "semi_blue_foreground",
86 					    "x-large",
87 					    NULL);
88 
89   gtk_text_buffer_insert (buffer, &iter, ", or ", -1);
90 
91   gtk_text_buffer_insert (buffer, &iter, ", ", -1);
92   gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
93                                             "bold text with translucent red background", -1,
94                                             "bold",
95 					    "semi_red_background",
96 					    "x-large",
97 					    NULL);
98   gtk_text_buffer_insert (buffer, &iter, ".\n\n", -1);
99 
100   anchor = gtk_text_buffer_create_child_anchor (buffer, &iter);
101 
102   /* Store the beginning of the other paragraph */
103   para_start = gtk_text_buffer_create_mark (buffer, "para_start", &iter, TRUE);
104 
105   gtk_text_buffer_insert (buffer, &iter,
106       "Paragraph background colors can also be set with rgba color values .\n", -1);
107 
108   gtk_text_buffer_insert (buffer, &iter, "For instance, you can have ", -1);
109   gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
110                                             "bold translucent blue text", -1,
111                                             "bold",
112 					    "semi_blue_foreground",
113 					    "x-large",
114 					    NULL);
115 
116   gtk_text_buffer_insert (buffer, &iter, ", or ", -1);
117 
118   gtk_text_buffer_insert (buffer, &iter, ", ", -1);
119   gtk_text_buffer_insert_with_tags_by_name (buffer, &iter,
120                                             "italic text with translucent red background", -1,
121                                             "italic",
122 					    "semi_red_background",
123 					    "x-large",
124 					    NULL);
125 
126   gtk_text_buffer_insert (buffer, &iter, " all rendered onto a translucent orange paragraph background.\n", -1);
127 
128   gtk_text_buffer_get_bounds (buffer, &start, &end);
129 
130   gtk_text_buffer_get_iter_at_mark (buffer, &iter, para_start);
131   gtk_text_buffer_apply_tag_by_name (buffer, "semi_orange_paragraph_background", &iter, &end);
132 
133   /* Apply word_wrap tag to whole buffer */
134   gtk_text_buffer_get_bounds (buffer, &start, &end);
135   gtk_text_buffer_apply_tag_by_name (buffer, "word_wrap", &start, &end);
136 
137   return anchor;
138 }
139 
140 
141 /* Size of checks and gray levels for alpha compositing checkerboard */
142 #define CHECK_SIZE  10
143 #define CHECK_DARK  (1.0 / 3.0)
144 #define CHECK_LIGHT (2.0 / 3.0)
145 
146 static void
snapshot_background(GtkWidget * widget,GtkSnapshot * snapshot)147 snapshot_background (GtkWidget   *widget,
148                      GtkSnapshot *snapshot)
149 {
150   GdkRectangle visible_rect;
151 
152   gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (widget), &visible_rect);
153 
154   gtk_snapshot_append_color (snapshot,
155                              &(GdkRGBA) { CHECK_DARK, CHECK_DARK, CHECK_DARK, 1.0 },
156                              &GRAPHENE_RECT_INIT(visible_rect.x, visible_rect.y, visible_rect.width, visible_rect.height));
157 
158   gtk_snapshot_push_repeat (snapshot,
159                             &GRAPHENE_RECT_INIT(visible_rect.x, visible_rect.y, visible_rect.width, visible_rect.height),
160                             &GRAPHENE_RECT_INIT(visible_rect.x, visible_rect.y, CHECK_SIZE * 2, CHECK_SIZE * 2));
161   gtk_snapshot_append_color (snapshot,
162                              &(GdkRGBA) { CHECK_LIGHT, CHECK_LIGHT, CHECK_LIGHT, 1.0 },
163                              &GRAPHENE_RECT_INIT(visible_rect.x, visible_rect.y, CHECK_SIZE, CHECK_SIZE));
164   gtk_snapshot_append_color (snapshot,
165                              &(GdkRGBA) { CHECK_LIGHT, CHECK_LIGHT, CHECK_LIGHT, 1.0 },
166                              &GRAPHENE_RECT_INIT(visible_rect.x + CHECK_SIZE, visible_rect.y + CHECK_SIZE, CHECK_SIZE, CHECK_SIZE));
167   gtk_snapshot_pop (snapshot);
168 }
169 
170 int
main(int argc,char ** argv)171 main (int argc, char **argv)
172 {
173   GtkWidget *window, *textview, *sw, *button, *button2;
174   GtkTextBuffer *buffer;
175   GtkTextChildAnchor *anchor;
176 
177   gtk_init ();
178 
179   window   = gtk_window_new ();
180   sw       = gtk_scrolled_window_new ();
181   textview = g_object_new (my_text_view_get_type (), NULL);
182   buffer   = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview));
183   button   = gtk_button_new_with_label ("Fixed Child");
184   button2   = gtk_button_new_with_label ("Flowed Child");
185 
186   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
187                                   GTK_POLICY_AUTOMATIC,
188                                   GTK_POLICY_AUTOMATIC);
189 
190   gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
191 
192   create_tags (buffer);
193   anchor = insert_text (buffer);
194 
195   gtk_window_set_child (GTK_WINDOW (window), sw);
196   gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), textview);
197   gtk_text_view_add_overlay (GTK_TEXT_VIEW (textview),
198                              button,
199                              50, 150);
200 
201   gtk_text_view_add_child_at_anchor (GTK_TEXT_VIEW (textview),
202                                      button2, anchor);
203 
204   gtk_widget_show (window);
205 
206   while (TRUE)
207     g_main_context_iteration (NULL, TRUE);
208 
209   return 0;
210 }
211