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 |
20 | my_text_view_init (MyTextView *text_view) |
21 | { |
22 | } |
23 | |
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 |
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 |
39 | create_tags (GtkTextBuffer *buffer) |
40 | { |
41 | |
42 | gtk_text_buffer_create_tag (buffer, tag_name: "italic" , |
43 | first_property_name: "style" , PANGO_STYLE_ITALIC, NULL); |
44 | |
45 | gtk_text_buffer_create_tag (buffer, tag_name: "bold" , |
46 | first_property_name: "weight" , PANGO_WEIGHT_BOLD, NULL); |
47 | |
48 | gtk_text_buffer_create_tag (buffer, tag_name: "x-large" , |
49 | first_property_name: "scale" , PANGO_SCALE_X_LARGE, NULL); |
50 | |
51 | gtk_text_buffer_create_tag (buffer, tag_name: "semi_blue_foreground" , |
52 | first_property_name: "foreground" , "rgba(0,0,255,0.7)" , NULL); |
53 | |
54 | gtk_text_buffer_create_tag (buffer, tag_name: "semi_red_background" , |
55 | first_property_name: "background" , "rgba(255,0,0,0.5)" , NULL); |
56 | |
57 | gtk_text_buffer_create_tag (buffer, tag_name: "semi_orange_paragraph_background" , |
58 | first_property_name: "paragraph-background" , "rgba(255,165,0,0.5)" , NULL); |
59 | |
60 | gtk_text_buffer_create_tag (buffer, tag_name: "word_wrap" , |
61 | first_property_name: "wrap_mode" , GTK_WRAP_WORD, NULL); |
62 | } |
63 | |
64 | |
65 | static GtkTextChildAnchor * |
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: &iter, char_offset: 0); |
77 | |
78 | gtk_text_buffer_insert (buffer, iter: &iter, |
79 | text: "This test shows text view rendering some text with rgba colors.\n\n" , len: -1); |
80 | |
81 | gtk_text_buffer_insert (buffer, iter: &iter, text: "For example, you can have " , len: -1); |
82 | gtk_text_buffer_insert_with_tags_by_name (buffer, iter: &iter, |
83 | text: "italic translucent blue text" , len: -1, |
84 | first_tag_name: "italic" , |
85 | "semi_blue_foreground" , |
86 | "x-large" , |
87 | NULL); |
88 | |
89 | gtk_text_buffer_insert (buffer, iter: &iter, text: ", or " , len: -1); |
90 | |
91 | gtk_text_buffer_insert (buffer, iter: &iter, text: ", " , len: -1); |
92 | gtk_text_buffer_insert_with_tags_by_name (buffer, iter: &iter, |
93 | text: "bold text with translucent red background" , len: -1, |
94 | first_tag_name: "bold" , |
95 | "semi_red_background" , |
96 | "x-large" , |
97 | NULL); |
98 | gtk_text_buffer_insert (buffer, iter: &iter, text: ".\n\n" , len: -1); |
99 | |
100 | anchor = gtk_text_buffer_create_child_anchor (buffer, iter: &iter); |
101 | |
102 | /* Store the beginning of the other paragraph */ |
103 | para_start = gtk_text_buffer_create_mark (buffer, mark_name: "para_start" , where: &iter, TRUE); |
104 | |
105 | gtk_text_buffer_insert (buffer, iter: &iter, |
106 | text: "Paragraph background colors can also be set with rgba color values .\n" , len: -1); |
107 | |
108 | gtk_text_buffer_insert (buffer, iter: &iter, text: "For instance, you can have " , len: -1); |
109 | gtk_text_buffer_insert_with_tags_by_name (buffer, iter: &iter, |
110 | text: "bold translucent blue text" , len: -1, |
111 | first_tag_name: "bold" , |
112 | "semi_blue_foreground" , |
113 | "x-large" , |
114 | NULL); |
115 | |
116 | gtk_text_buffer_insert (buffer, iter: &iter, text: ", or " , len: -1); |
117 | |
118 | gtk_text_buffer_insert (buffer, iter: &iter, text: ", " , len: -1); |
119 | gtk_text_buffer_insert_with_tags_by_name (buffer, iter: &iter, |
120 | text: "italic text with translucent red background" , len: -1, |
121 | first_tag_name: "italic" , |
122 | "semi_red_background" , |
123 | "x-large" , |
124 | NULL); |
125 | |
126 | gtk_text_buffer_insert (buffer, iter: &iter, text: " all rendered onto a translucent orange paragraph background.\n" , len: -1); |
127 | |
128 | gtk_text_buffer_get_bounds (buffer, start: &start, end: &end); |
129 | |
130 | gtk_text_buffer_get_iter_at_mark (buffer, iter: &iter, mark: para_start); |
131 | gtk_text_buffer_apply_tag_by_name (buffer, name: "semi_orange_paragraph_background" , start: &iter, end: &end); |
132 | |
133 | /* Apply word_wrap tag to whole buffer */ |
134 | gtk_text_buffer_get_bounds (buffer, start: &start, end: &end); |
135 | gtk_text_buffer_apply_tag_by_name (buffer, name: "word_wrap" , start: &start, end: &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 |
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: &visible_rect); |
153 | |
154 | gtk_snapshot_append_color (snapshot, |
155 | color: &(GdkRGBA) { CHECK_DARK, CHECK_DARK, CHECK_DARK, 1.0 }, |
156 | bounds: &GRAPHENE_RECT_INIT(visible_rect.x, visible_rect.y, visible_rect.width, visible_rect.height)); |
157 | |
158 | gtk_snapshot_push_repeat (snapshot, |
159 | bounds: &GRAPHENE_RECT_INIT(visible_rect.x, visible_rect.y, visible_rect.width, visible_rect.height), |
160 | child_bounds: &GRAPHENE_RECT_INIT(visible_rect.x, visible_rect.y, CHECK_SIZE * 2, CHECK_SIZE * 2)); |
161 | gtk_snapshot_append_color (snapshot, |
162 | color: &(GdkRGBA) { CHECK_LIGHT, CHECK_LIGHT, CHECK_LIGHT, 1.0 }, |
163 | bounds: &GRAPHENE_RECT_INIT(visible_rect.x, visible_rect.y, CHECK_SIZE, CHECK_SIZE)); |
164 | gtk_snapshot_append_color (snapshot, |
165 | color: &(GdkRGBA) { CHECK_LIGHT, CHECK_LIGHT, CHECK_LIGHT, 1.0 }, |
166 | bounds: &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 |
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 (object_type: my_text_view_get_type (), NULL); |
182 | buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textview)); |
183 | button = gtk_button_new_with_label (label: "Fixed Child" ); |
184 | button2 = gtk_button_new_with_label (label: "Flowed Child" ); |
185 | |
186 | gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), |
187 | hscrollbar_policy: GTK_POLICY_AUTOMATIC, |
188 | vscrollbar_policy: GTK_POLICY_AUTOMATIC); |
189 | |
190 | gtk_window_set_default_size (GTK_WINDOW (window), width: 400, height: 400); |
191 | |
192 | create_tags (buffer); |
193 | anchor = insert_text (buffer); |
194 | |
195 | gtk_window_set_child (GTK_WINDOW (window), child: sw); |
196 | gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), child: textview); |
197 | gtk_text_view_add_overlay (GTK_TEXT_VIEW (textview), |
198 | child: button, |
199 | xpos: 50, ypos: 150); |
200 | |
201 | gtk_text_view_add_child_at_anchor (GTK_TEXT_VIEW (textview), |
202 | child: button2, anchor); |
203 | |
204 | gtk_widget_show (widget: window); |
205 | |
206 | while (TRUE) |
207 | g_main_context_iteration (NULL, TRUE); |
208 | |
209 | return 0; |
210 | } |
211 | |