2 * Copyright Geoff Levand <geoff@infradead.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #if defined(HAVE_CONFIG_H)
25 #include <linux/input.h>
28 #include "talloc/talloc.h"
29 #include "ui/common/ui-system.h"
33 static void pbt_item_draw_cb(twin_window_t *window)
35 struct pbt_item *item = pbt_item_from_window(window);
38 assert(window == item->window);
42 //pbt_dump_pixmap(window->pixmap);
44 if (pbt_item_is_selected(item) && item->menu->has_focus)
45 image = item->pixmap_active;
46 else if (pbt_item_is_selected(item) && !item->menu->has_focus)
47 image = item->pixmap_selected;
49 image = item->pixmap_idle;
51 pbt_image_draw(window->pixmap, image);
54 static twin_bool_t pbt_item_event_cb(twin_window_t *window,
57 struct pbt_item *item = pbt_item_from_window(window);
59 pbt_dump_event(pbt_item_name(item), window, event);
62 case TwinEventButtonDown:
64 item->on_execute(item);
66 case TwinEventButtonUp:
69 /* prevent window drag */
72 pbt_item_set_as_selected(item);
76 case TwinEventKeyDown:
77 switch(event->u.key.key) {
78 case (twin_keysym_t)XK_Return:
79 case (twin_keysym_t)KEY_ENTER:
81 item->on_execute(item);
83 case (twin_keysym_t)'e':
97 int pbt_item_editor(struct pbt_item *item)
103 struct pbt_item *pbt_item_create(struct pbt_menu *menu, const char *name,
104 unsigned int position, const char *icon_filename, const char *title,
108 struct pbt_item *item;
111 const struct pbt_menu_layout *layout = &menu->layout;
113 static const twin_argb32_t focus_color = 0x10404040;
121 DBGS("%d:%s (%s)\n", position, name, icon_filename);
123 item = talloc_zero(menu, struct pbt_item);
129 item->on_edit = pbt_item_editor;
131 pbt_menu_get_item_quad(menu, position, &q);
133 item->window = twin_window_create(menu->scr->tscreen,
134 TWIN_ARGB32, TwinWindowPlain,
135 q.x, q.y, q.width, q.height);
138 goto fail_window_create;
140 twin_window_set_name(item->window, name);
141 item->window->client_data = item;
142 item->window->draw = pbt_item_draw_cb;
143 item->window->event = pbt_item_event_cb;
145 item->pixmap_idle = twin_pixmap_create(TWIN_ARGB32, q.width, q.height);
146 assert(item->pixmap_idle);
148 item->pixmap_selected = twin_pixmap_create(TWIN_ARGB32, q.width,
150 assert(item->pixmap_selected);
152 item->pixmap_active = twin_pixmap_create(TWIN_ARGB32, q.width,
154 assert(item->pixmap_active);
156 if (!item->pixmap_idle || !item->pixmap_selected || !item->pixmap_active)
157 goto fail_pixmap_create;
159 twin_fill(item->pixmap_idle, 0x01000000, TWIN_SOURCE, 0, 0, q.width,
164 icon = pbt_icon_load(icon_filename);
169 src.source_kind = TWIN_PIXMAP;
172 twin_composite(item->pixmap_idle,
173 //0, (item->pixmap_idle->height - icon->height) / 2,
178 icon->width, icon->height);
182 path = twin_path_create();
186 twin_path_set_font_size(path,
187 twin_int_to_fixed(layout->title.font_size));
188 twin_path_set_font_style(path, TWIN_TEXT_UNHINTED);
191 twin_int_to_fixed(icon->width + layout->text_space),
192 twin_int_to_fixed(layout->title.font_size
193 + layout->text_space));
194 twin_path_utf8(path, title);
195 twin_paint_path(item->pixmap_idle, layout->title.color, path);
196 twin_path_empty(path);
200 twin_path_set_font_size(path,
201 twin_int_to_fixed(layout->text.font_size));
203 twin_int_to_fixed(icon->width + layout->text_space),
204 twin_int_to_fixed(layout->title.font_size
205 + layout->text.font_size
206 + layout->text_space));
207 twin_path_utf8(path, text);
208 twin_paint_path(item->pixmap_idle, layout->text.color, path);
209 twin_path_empty(path);
212 pbt_image_draw(item->pixmap_selected, item->pixmap_idle);
213 pbt_image_draw(item->pixmap_active, item->pixmap_idle);
216 static const struct pbt_border grey_border = {
221 .fill_color = 0xffe0e0e0,
224 //pbt_border_draw(item->pixmap_idle, &pbt_blue_debug_border);
225 pbt_border_draw(item->pixmap_selected, &grey_border);
226 pbt_border_draw(item->pixmap_active, &pbt_green_debug_border);
228 assert(!(stroke_width % 2));
230 /* pixmap_selected */
232 twin_path_rounded_rectangle(path,
233 twin_int_to_fixed(stroke_width / 2),
234 twin_int_to_fixed(stroke_width / 2),
235 twin_int_to_fixed(item->pixmap_selected->width - stroke_width),
236 twin_int_to_fixed(item->pixmap_selected->height - stroke_width),
237 twin_int_to_fixed(corner_rounding),
238 twin_int_to_fixed(corner_rounding));
240 twin_paint_stroke(item->pixmap_selected, focus_color, path,
241 twin_int_to_fixed(stroke_width));
243 twin_path_empty(path);
247 twin_path_rounded_rectangle(path, 0, 0,
248 twin_int_to_fixed(item->pixmap_active->width),
249 twin_int_to_fixed(item->pixmap_active->height),
250 twin_int_to_fixed(corner_rounding),
251 twin_int_to_fixed(corner_rounding));
253 twin_paint_path(item->pixmap_active, focus_color, path);
255 twin_path_empty(path); // FIXME: need it???
257 twin_path_destroy(path);
259 list_add_tail(menu->item_list, &item->list);
261 pbt_item_redraw(item);
271 void _pbt_dump_item(const struct pbt_item* item, const char *func, int line)
273 DBG("%s:%d: %p: %sselected, %sfocus\n", func, line, item,
274 (pbt_item_is_selected(item) ? "+" : "-"),
275 (item->menu->has_focus ? "+" : "-"));
279 * pbt_menu_get_item_quad - Return item coords relative to screen origin.
282 struct pbt_quad *pbt_menu_get_item_quad(const struct pbt_menu *menu,
283 unsigned int pos, struct pbt_quad *q)
285 const struct pbt_menu_layout *layout = &menu->layout;
287 q->x = menu->window->pixmap->x + layout->item_space;
289 q->width = menu->window->pixmap->width - 2 * layout->item_space;
291 q->y = menu->window->pixmap->y + layout->item_space
292 + pos * (layout->item_height + layout->item_space);
294 q->height = layout->item_height;
299 static void pbt_menu_draw_cb(twin_window_t *window)
301 struct pbt_menu *menu = pbt_menu_from_window(window);
302 twin_path_t *path = twin_path_create();
306 pbt_dump_pixmap(window->pixmap);
308 twin_fill(window->pixmap, menu->background_color, TWIN_SOURCE,
309 0, 0, window->pixmap->width, window->pixmap->height);
311 pbt_border_draw(window->pixmap, &menu->border);
313 twin_path_destroy(path);
316 static twin_bool_t pbt_menu_event_cb(twin_window_t *window,
319 struct pbt_menu *menu = pbt_menu_from_window(window);
322 pbt_dump_event(pbt_menu_name(menu), window, event);
324 switch(event->kind) {
325 case TwinEventButtonDown:
326 case TwinEventButtonUp:
327 case TwinEventMotion:
328 /* prevent window drag */
331 pbt_menu_set_focus(menu, 1);
334 if (!pbt_window_contains(window, event))
335 pbt_menu_set_focus(menu, 0);
337 case TwinEventKeyDown:
338 switch(event->u.key.key) {
339 case (twin_keysym_t)XK_Up:
340 case (twin_keysym_t)KEY_UP:
341 i = list_prev_entry(menu->item_list, menu->selected,
344 pbt_item_set_as_selected(i);
346 case (twin_keysym_t)XK_Down:
347 case (twin_keysym_t)KEY_DOWN:
348 i = list_next_entry(menu->item_list, menu->selected,
351 pbt_item_set_as_selected(i);
353 case (twin_keysym_t)XK_Left:
354 case (twin_keysym_t)KEY_LEFT:
356 pbt_menu_set_focus(menu, 0);
357 pbt_menu_set_focus(menu->parent, 1);
361 case (twin_keysym_t)XK_Right:
362 case (twin_keysym_t)KEY_RIGHT:
363 if (menu->selected->sub_menu) {
364 pbt_menu_set_focus(menu, 0);
365 pbt_menu_set_focus(menu->selected->sub_menu, 1);
367 DBGS("no sub_menu\n");
370 return pbt_item_event_cb(menu->selected->window, event);
379 struct pbt_menu *pbt_menu_create(void *talloc_ctx, const char *name,
380 struct pbt_scr *scr, struct pbt_menu *parent, const struct pbt_quad *q,
381 const struct pbt_menu_layout *layout)
383 struct pbt_menu *menu;
389 menu = talloc_zero(talloc_ctx, struct pbt_menu);
395 menu->parent = parent;
396 menu->layout = *layout;
398 menu->item_list = talloc(menu, struct list);
399 list_init(menu->item_list);
401 menu->window = twin_window_create(scr->tscreen, TWIN_ARGB32,
402 TwinWindowPlain, q->x, q->y,
403 q->width, q->height);
408 DBGS("window = %p\n", menu->window);
410 twin_window_set_name(menu->window, name);
412 menu->background_color = 0x01000000; //FIXME: what value???
414 menu->window->draw = pbt_menu_draw_cb;
415 menu->window->event = pbt_menu_event_cb;
416 menu->window->client_data = menu;
418 pbt_dump_pixmap(menu->window->pixmap);
420 pbt_menu_redraw(menu);
430 void pbt_menu_set_focus(struct pbt_menu *menu, int focus)
432 DBGS("%s(%p): %d -> %d\n", pbt_menu_name(menu), menu, menu->has_focus,
435 assert(menu->selected);
437 if (!menu->has_focus == !focus)
440 menu->has_focus = !!focus;
442 /* Route key events to menu with focus. */
445 menu->scr->tscreen->active = menu->window->pixmap;
447 pbt_item_redraw(menu->selected);
450 void pbt_menu_hide(struct pbt_menu *menu)
452 struct pbt_item *item;
457 list_for_each_entry(menu->item_list, item, list) {
459 pbt_menu_hide(item->sub_menu);
461 twin_window_hide(item->window);
462 //twin_window_queue_paint(item->window);
465 twin_window_hide(menu->window);
466 //twin_window_queue_paint(menu->window);
469 void pbt_menu_show(struct pbt_menu *menu, int hide)
471 struct pbt_item *item;
476 twin_window_show(menu->window);
477 pbt_menu_redraw(menu);
479 list_for_each_entry(menu->item_list, item, list) {
480 twin_window_show(item->window);
481 pbt_item_redraw(item);
483 if (item->sub_menu) {
484 if (pbt_item_is_selected(item))
485 pbt_menu_show(item->sub_menu, hide);
487 pbt_menu_hide(item->sub_menu);
492 void pbt_menu_set_selected(struct pbt_menu *menu, struct pbt_item *item)
494 struct pbt_item *last_selected;
498 DBGS("%s(%p): %s(%p) -> %s(%p)\n", pbt_menu_name(menu), menu,
499 (menu->selected ? pbt_menu_name(menu) : "none"),
500 menu->selected, pbt_item_name(item), item);
502 if (menu->selected == item)
505 last_selected = menu->selected;
506 menu->selected = item;
509 pbt_menu_hide(last_selected->sub_menu);
510 pbt_item_redraw(last_selected);
513 pbt_item_redraw(item);
514 pbt_menu_show(item->sub_menu, 0);