editor: Make text_entry a widget
[profile/ivi/weston.git] / clients / editor.c
1 /*
2  * Copyright © 2012 Openismus GmbH
3  * Copyright © 2012 Intel Corporation
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and
6  * its documentation for any purpose is hereby granted without fee, provided
7  * that the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation, and that the name of the copyright holders not be used in
10  * advertising or publicity pertaining to distribution of the software
11  * without specific, written prior permission.  The copyright holders make
12  * no representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  */
23
24 #include <assert.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include <linux/input.h>
30 #include <cairo.h>
31
32 #include "window.h"
33 #include "text-client-protocol.h"
34
35 struct text_entry {
36         struct widget *widget;
37         struct window *window;
38         char *text;
39         int active;
40         struct text_model *model;
41 };
42
43 struct editor {
44         struct text_model_factory *text_model_factory;
45         struct display *display;
46         struct window *window;
47         struct widget *widget;
48         struct text_entry *entry;
49         struct text_entry *editor;
50 };
51
52 static void text_entry_redraw_handler(struct widget *widget, void *data);
53 static void text_entry_button_handler(struct widget *widget,
54                                       struct input *input, uint32_t time,
55                                       uint32_t button,
56                                       enum wl_pointer_button_state state, void *data);
57
58 static void
59 text_entry_append(struct text_entry *entry, const char *text)
60 {
61         entry->text = realloc(entry->text, strlen(entry->text) + strlen(text) + 1);
62         strcat(entry->text, text);
63 }
64
65
66 static void
67 text_model_commit_string(void *data,
68                          struct text_model *text_model,
69                          const char *text,
70                          uint32_t index)
71 {
72         struct text_entry *entry = data;
73
74         text_entry_append(entry, text); 
75
76         widget_schedule_redraw(entry->widget);
77 }
78
79 static void
80 text_model_preedit_string(void *data,
81                           struct text_model *text_model,
82                           const char *text,
83                           uint32_t index)
84 {
85 }
86
87 static void
88 text_model_preedit_styling(void *data,
89                            struct text_model *text_model)
90 {
91 }
92
93 static void
94 text_model_key(void *data,
95                struct text_model *text_model)
96 {
97 }
98
99 static void
100 text_model_selection_replacement(void *data,
101                                  struct text_model *text_model)
102 {
103 }
104
105 static void
106 text_model_direction(void *data,
107                      struct text_model *text_model)
108 {
109 }
110
111 static void
112 text_model_locale(void *data,
113                   struct text_model *text_model)
114 {
115 }
116
117 static void
118 text_model_activated(void *data,
119                      struct text_model *text_model)
120 {
121         struct text_entry *entry = data;
122
123         entry->active = 1;
124
125         widget_schedule_redraw(entry->widget);
126 }
127
128 static void
129 text_model_deactivated(void *data,
130                        struct text_model *text_model)
131 {
132         struct text_entry *entry = data;
133
134         entry->active = 0;
135
136         widget_schedule_redraw(entry->widget);
137 }
138
139 static const struct text_model_listener text_model_listener = {
140         text_model_commit_string,
141         text_model_preedit_string,
142         text_model_preedit_styling,
143         text_model_key,
144         text_model_selection_replacement,
145         text_model_direction,
146         text_model_locale,
147         text_model_activated,
148         text_model_deactivated
149 };
150
151 static struct text_entry*
152 text_entry_create(struct editor *editor, const char *text)
153 {
154         struct text_entry *entry;
155
156         entry = malloc(sizeof *entry);
157
158         entry->widget = widget_add_widget(editor->widget, entry);
159         entry->window = editor->window;
160         entry->text = strdup(text);
161         entry->active = 0;
162         entry->model = text_model_factory_create_text_model(editor->text_model_factory);
163         text_model_add_listener(entry->model, &text_model_listener, entry);
164
165         widget_set_redraw_handler(entry->widget, text_entry_redraw_handler);
166         widget_set_button_handler(entry->widget, text_entry_button_handler);
167
168         return entry;
169 }
170
171 static void
172 text_entry_destroy(struct text_entry *entry)
173 {
174         widget_destroy(entry->widget);
175         text_model_destroy(entry->model);
176         free(entry->text);
177         free(entry);
178 }
179
180 static void
181 redraw_handler(struct widget *widget, void *data)
182 {
183         struct editor *editor = data;
184         cairo_surface_t *surface;
185         struct rectangle allocation;
186         cairo_t *cr;
187
188         surface = window_get_surface(editor->window);
189         widget_get_allocation(editor->widget, &allocation);
190
191         cr = cairo_create(surface);
192         cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
193         cairo_clip(cr);
194
195         cairo_translate(cr, allocation.x, allocation.y);
196
197         /* Draw background */
198         cairo_push_group(cr);
199         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
200         cairo_set_source_rgba(cr, 1, 1, 1, 1);
201         cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
202         cairo_fill(cr);
203
204         cairo_pop_group_to_source(cr);
205         cairo_paint(cr);
206
207         cairo_destroy(cr);
208         cairo_surface_destroy(surface);
209 }
210
211 static void
212 text_entry_allocate(struct text_entry *entry, int32_t x, int32_t y,
213                     int32_t width, int32_t height)
214 {
215         widget_set_allocation(entry->widget, x, y, width, height);
216 }
217
218 static void
219 resize_handler(struct widget *widget,
220                int32_t width, int32_t height, void *data)
221 {
222         struct editor *editor = data;
223         struct rectangle allocation;
224
225         widget_get_allocation(editor->widget, &allocation);
226
227         text_entry_allocate(editor->entry,
228                             allocation.x + 20, allocation.y + 20,
229                             width - 40, height / 2 - 40);
230         text_entry_allocate(editor->editor,
231                             allocation.x + 20, allocation.y + height / 2 + 20,
232                             width - 40, height / 2 - 40);
233 }
234
235 static void
236 text_entry_activate(struct text_entry *entry,
237                     struct wl_seat *seat)
238 {
239         struct wl_surface *surface = window_get_wl_surface(entry->window);
240
241         text_model_activate(entry->model,
242                             seat,
243                             surface);
244 }
245
246 static void
247 text_entry_deactivate(struct text_entry *entry,
248                       struct wl_seat *seat)
249 {
250         text_model_deactivate(entry->model,
251                               seat);
252 }
253
254 static void
255 text_entry_redraw_handler(struct widget *widget, void *data)
256 {
257         struct text_entry *entry = data;
258         cairo_surface_t *surface;
259         struct rectangle allocation;
260         cairo_t *cr;
261
262         surface = window_get_surface(entry->window);
263         widget_get_allocation(entry->widget, &allocation);
264
265         cr = cairo_create(surface);
266         cairo_rectangle(cr, allocation.x, allocation.y, allocation.width, allocation.height);
267         cairo_clip(cr);
268
269         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
270
271         cairo_push_group(cr);
272         cairo_translate(cr, allocation.x, allocation.y);
273
274         cairo_set_source_rgba(cr, 1, 1, 1, 1);
275         cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
276         cairo_fill(cr);
277
278         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
279
280         if (entry->active) {
281                 cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
282                 cairo_set_line_width (cr, 3);
283                 cairo_set_source_rgba(cr, 0, 0, 1, 1.0);
284                 cairo_stroke(cr);
285         }
286
287         cairo_set_source_rgba(cr, 0, 0, 0, 1);
288         cairo_select_font_face(cr, "sans",
289                                CAIRO_FONT_SLANT_NORMAL,
290                                CAIRO_FONT_WEIGHT_BOLD);
291         cairo_set_font_size(cr, 14);
292
293         cairo_translate(cr, 10, allocation.height / 2);
294         cairo_show_text(cr, entry->text);
295         cairo_pop_group_to_source(cr);
296         cairo_paint(cr);
297
298         cairo_destroy(cr);
299         cairo_surface_destroy(surface);
300 }
301
302 static void
303 text_entry_button_handler(struct widget *widget,
304                           struct input *input, uint32_t time,
305                           uint32_t button,
306                           enum wl_pointer_button_state state, void *data)
307 {
308         struct text_entry *entry = data;
309
310         if (button != BTN_LEFT) {
311                 return;
312         }
313
314         if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
315                 struct wl_seat *seat = input_get_seat(input);
316
317                 text_entry_activate(entry, seat);
318         }
319 }
320
321 static void
322 editor_button_handler(struct widget *widget,
323                       struct input *input, uint32_t time,
324                       uint32_t button,
325                       enum wl_pointer_button_state state, void *data)
326 {
327         struct editor *editor = data;
328
329         if (button != BTN_LEFT) {
330                 return;
331         }
332
333         if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
334                 struct wl_seat *seat = input_get_seat(input);
335
336                 text_entry_deactivate(editor->entry, seat);
337                 text_entry_deactivate(editor->editor, seat);
338         }
339 }
340
341 static void
342 global_handler(struct wl_display *display, uint32_t id,
343                const char *interface, uint32_t version, void *data)
344 {
345         struct editor *editor = data;
346
347         if (!strcmp(interface, "text_model_factory")) {
348                 editor->text_model_factory = wl_display_bind(display, id,
349                                                              &text_model_factory_interface);
350         }
351 }
352
353 int
354 main(int argc, char *argv[])
355 {
356         struct editor editor;
357
358         editor.display = display_create(argc, argv);
359         if (editor.display == NULL) {
360                 fprintf(stderr, "failed to create display: %m\n");
361                 return -1;
362         }
363         wl_display_add_global_listener(display_get_display(editor.display),
364                                        global_handler, &editor);
365
366
367         editor.window = window_create(editor.display);
368         editor.widget = frame_create(editor.window, &editor);
369
370         editor.entry = text_entry_create(&editor, "Entry");
371         editor.editor = text_entry_create(&editor, "Editor");
372
373         window_set_title(editor.window, "Text Editor");
374
375         widget_set_redraw_handler(editor.widget, redraw_handler);
376         widget_set_resize_handler(editor.widget, resize_handler);
377         widget_set_button_handler(editor.widget, editor_button_handler);
378
379         window_schedule_resize(editor.window, 500, 400);
380
381         display_run(editor.display);
382
383         text_entry_destroy(editor.entry);
384         text_entry_destroy(editor.editor);
385
386         return 0;
387 }