2 Calf Box, an open source musical instrument.
3 Copyright (C) 2010 Krzysztof Foltman
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
32 GStringChunk
*strings
;
35 static int cbox_menu_page_on_key(struct cbox_ui_page
*p
, int ch
);
36 static int cbox_menu_page_on_idle(struct cbox_ui_page
*p
);
38 struct cbox_menu
*cbox_menu_new()
40 struct cbox_menu
*menu
= malloc(sizeof(struct cbox_menu
));
42 menu
->items
= g_ptr_array_new();
43 menu
->strings
= g_string_chunk_new(100);
47 struct cbox_menu_item
*cbox_menu_add_item(struct cbox_menu
*menu
, struct cbox_menu_item
*item
)
49 g_ptr_array_add(menu
->items
, item
);
53 void cbox_menu_destroy(struct cbox_menu
*menu
)
57 for (i
= 0; i
< menu
->items
->len
; i
++)
58 cbox_menu_item_destroy(g_ptr_array_index(menu
->items
, i
));
60 g_ptr_array_free(menu
->items
, TRUE
);
61 g_string_chunk_free(menu
->strings
);
67 gchar *cbox_menu_item_value_format(const struct cbox_menu_item *item, void *context)
71 case menu_item_static:
73 return ((struct cbox_menu_item_extras_static *)(item->extras))->format_value(item, context);
75 return g_strdup_printf("");
76 case menu_item_submenu:
77 return g_strdup_printf("...");
78 case menu_item_command:
79 return g_strdup_printf("<cmd>");
82 return g_strdup_printf("(null)");
85 case menu_item_value_int:
86 return g_strdup_printf(((struct cbox_menu_item_extras_int *)(item->extras))->fmt, *(int *)item->value);
87 case menu_item_value_double:
88 return g_strdup_printf(((struct cbox_menu_item_extras_double *)(item->extras))->fmt, *(double *)item->value);
89 case menu_item_value_enum:
90 return g_strdup_printf("<enum>%d", *(int *)item->value);
92 return g_strdup_printf("");
100 void cbox_menu_state_size(struct cbox_menu_state
*menu_state
)
102 struct cbox_menu
*menu
= menu_state
->menu
;
104 menu_state
->size
.label_width
= 0;
105 menu_state
->size
.value_width
= 0;
106 menu_state
->size
.height
= 0;
107 menu_state
->yspace
= getmaxy(menu_state
->window
) - 2;
109 for (i
= 0; i
< menu
->items
->len
; i
++)
111 struct cbox_menu_item
*item
= g_ptr_array_index(menu
->items
, i
);
114 item
->y
= 1 + menu_state
->size
.height
;
115 item
->item_class
->measure(item
, menu_state
);
119 void cbox_menu_state_draw(struct cbox_menu_state
*menu_state
)
121 struct cbox_menu
*menu
= menu_state
->menu
;
124 werase(menu_state
->window
);
125 box(menu_state
->window
, 0, 0);
126 for (i
= 0; i
< menu
->items
->len
; i
++)
128 struct cbox_menu_item
*item
= g_ptr_array_index(menu
->items
, i
);
129 gchar
*str
= item
->item_class
->format_value(item
, menu_state
);
130 item
->item_class
->draw(item
, menu_state
, str
, menu_state
->cursor
== i
);
133 wrefresh(menu_state
->window
);
136 static void cbox_menu_page_draw(struct cbox_ui_page
*p
)
138 struct cbox_menu_page
*mp
= p
->user_data
;
139 struct cbox_menu_state
*st
= mp
->state
;
140 cbox_menu_state_size(st
);
141 cbox_menu_state_draw(st
);
144 static int cbox_menu_is_item_enabled(struct cbox_menu
*menu
, int item
)
146 assert(item
>= 0 && item
< menu
->items
->len
);
148 return ((struct cbox_menu_item
*)g_ptr_array_index(menu
->items
, item
))->item_class
->on_key
!= NULL
;
151 struct cbox_menu_state
*cbox_menu_state_new(struct cbox_menu_page
*page
, struct cbox_menu
*menu
, WINDOW
*window
, void *context
)
153 struct cbox_menu_state
*st
= malloc(sizeof(struct cbox_menu_state
));
159 st
->context
= context
;
161 st
->menu_is_temporary
= 0;
163 while(st
->cursor
< menu
->items
->len
- 1 && !cbox_menu_is_item_enabled(menu
, st
->cursor
))
169 int cbox_menu_page_on_idle(struct cbox_ui_page
*p
)
171 struct cbox_menu_page
*mp
= p
->user_data
;
172 struct cbox_menu_state
*st
= mp
->state
;
173 cbox_menu_state_size(st
);
174 cbox_menu_state_draw(st
);
178 int cbox_menu_page_on_key(struct cbox_ui_page
*p
, int ch
)
180 struct cbox_menu_page
*mp
= p
->user_data
;
181 struct cbox_menu_state
*st
= mp
->state
;
182 struct cbox_menu
*menu
= st
->menu
;
183 struct cbox_menu_item
*item
= NULL
;
184 int pos
= st
->cursor
;
186 if (st
->cursor
>= 0 && st
->cursor
< menu
->items
->len
)
187 item
= g_ptr_array_index(menu
->items
, st
->cursor
);
192 if (item
->item_class
->on_key
)
194 res
= item
->item_class
->on_key(item
, st
, ch
);
198 cbox_menu_state_size(st
);
199 cbox_menu_state_draw(st
);
216 pos
= ch
== KEY_END
? menu
->items
->len
- 1 : st
->cursor
- 1;
217 while(pos
>= 0 && !cbox_menu_is_item_enabled(menu
, pos
))
223 st
->yoffset
= st
->size
.height
- st
->yspace
;
228 if (pos
>= 0 && pos
< menu
->items
->len
)
230 int npos
= st
->cursor
;
232 // show up to 2 disabled items above
233 while(npos
>= 1 && !cbox_menu_is_item_enabled(menu
, npos
- 1) && count
< 2)
238 item
= g_ptr_array_index(menu
->items
, npos
);
239 if (item
->y
< 1 + st
->yoffset
)
240 st
->yoffset
= item
->y
- 1;
242 cbox_menu_state_draw(st
);
246 pos
= ch
== KEY_HOME
? 0 : st
->cursor
+ 1;
247 while(pos
< menu
->items
->len
&& !cbox_menu_is_item_enabled(menu
, pos
))
249 if (pos
< menu
->items
->len
)
253 else if (pos
>= 0 && pos
< menu
->items
->len
)
255 item
= g_ptr_array_index(menu
->items
, st
->cursor
);
256 if (item
->y
- 1 - st
->yoffset
>= st
->yspace
)
257 st
->yoffset
= item
->y
- st
->yspace
;
259 cbox_menu_state_draw(st
);
265 void cbox_menu_state_destroy(struct cbox_menu_state
*st
)
270 struct cbox_menu_page
*cbox_menu_page_new()
272 struct cbox_menu_page
*page
= malloc(sizeof(struct cbox_menu_page
));
274 page
->page
.user_data
= page
;
275 page
->page
.draw
= cbox_menu_page_draw
;
276 page
->page
.on_key
= cbox_menu_page_on_key
;
277 page
->page
.on_idle
= cbox_menu_page_on_idle
;
281 void cbox_menu_page_destroy(struct cbox_menu_page
*p
)