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
);
52 void cbox_menu_destroy(struct cbox_menu
*menu
)
56 for (i
= 0; i
< menu
->items
->len
; i
++)
57 cbox_menu_item_destroy(g_ptr_array_index(menu
->items
, i
));
59 g_ptr_array_free(menu
->items
, TRUE
);
60 g_string_chunk_free(menu
->strings
);
65 gchar *cbox_menu_item_value_format(const struct cbox_menu_item *item, void *context)
69 case menu_item_static:
71 return ((struct cbox_menu_item_extras_static *)(item->extras))->format_value(item, context);
73 return g_strdup_printf("");
74 case menu_item_submenu:
75 return g_strdup_printf("...");
76 case menu_item_command:
77 return g_strdup_printf("<cmd>");
80 return g_strdup_printf("(null)");
83 case menu_item_value_int:
84 return g_strdup_printf(((struct cbox_menu_item_extras_int *)(item->extras))->fmt, *(int *)item->value);
85 case menu_item_value_double:
86 return g_strdup_printf(((struct cbox_menu_item_extras_double *)(item->extras))->fmt, *(double *)item->value);
87 case menu_item_value_enum:
88 return g_strdup_printf("<enum>%d", *(int *)item->value);
90 return g_strdup_printf("");
98 void cbox_menu_state_size(struct cbox_menu_state
*menu_state
)
100 struct cbox_menu
*menu
= menu_state
->menu
;
102 menu_state
->size
.label_width
= 0;
103 menu_state
->size
.value_width
= 0;
104 menu_state
->size
.height
= 0;
105 menu_state
->yspace
= getmaxy(menu_state
->window
) - 2;
107 for (i
= 0; i
< menu
->items
->len
; i
++)
109 struct cbox_menu_item
*item
= g_ptr_array_index(menu
->items
, i
);
112 item
->y
= 1 + menu_state
->size
.height
;
113 item
->item_class
->measure(item
, menu_state
);
117 void cbox_menu_state_draw(struct cbox_menu_state
*menu_state
)
119 struct cbox_menu
*menu
= menu_state
->menu
;
122 werase(menu_state
->window
);
123 box(menu_state
->window
, 0, 0);
124 for (i
= 0; i
< menu
->items
->len
; i
++)
126 struct cbox_menu_item
*item
= g_ptr_array_index(menu
->items
, i
);
127 gchar
*str
= item
->item_class
->format_value(item
, menu_state
);
128 item
->item_class
->draw(item
, menu_state
, str
, menu_state
->cursor
== i
);
131 wrefresh(menu_state
->window
);
134 static void cbox_menu_page_draw(struct cbox_ui_page
*p
)
136 struct cbox_menu_page
*mp
= p
->user_data
;
137 struct cbox_menu_state
*st
= mp
->state
;
138 cbox_menu_state_size(st
);
139 cbox_menu_state_draw(st
);
142 static int cbox_menu_is_item_enabled(struct cbox_menu
*menu
, int item
)
144 assert(item
>= 0 && item
< menu
->items
->len
);
146 return ((struct cbox_menu_item
*)g_ptr_array_index(menu
->items
, item
))->item_class
->on_key
!= NULL
;
149 struct cbox_menu_state
*cbox_menu_state_new(struct cbox_menu_page
*page
, struct cbox_menu
*menu
, WINDOW
*window
, void *context
)
151 struct cbox_menu_state
*st
= malloc(sizeof(struct cbox_menu_state
));
157 st
->context
= context
;
159 st
->menu_is_temporary
= 0;
161 while(st
->cursor
< menu
->items
->len
- 1 && !cbox_menu_is_item_enabled(menu
, st
->cursor
))
167 int cbox_menu_page_on_idle(struct cbox_ui_page
*p
)
169 struct cbox_menu_page
*mp
= p
->user_data
;
170 struct cbox_menu_state
*st
= mp
->state
;
171 cbox_menu_state_size(st
);
172 cbox_menu_state_draw(st
);
176 int cbox_menu_page_on_key(struct cbox_ui_page
*p
, int ch
)
178 struct cbox_menu_page
*mp
= p
->user_data
;
179 struct cbox_menu_state
*st
= mp
->state
;
180 struct cbox_menu
*menu
= st
->menu
;
181 struct cbox_menu_item
*item
= NULL
;
182 int pos
= st
->cursor
;
184 if (st
->cursor
>= 0 && st
->cursor
< menu
->items
->len
)
185 item
= g_ptr_array_index(menu
->items
, st
->cursor
);
190 if (item
->item_class
->on_key
)
192 res
= item
->item_class
->on_key(item
, st
, ch
);
196 cbox_menu_state_size(st
);
197 cbox_menu_state_draw(st
);
214 pos
= ch
== KEY_END
? menu
->items
->len
- 1 : st
->cursor
- 1;
215 while(pos
>= 0 && !cbox_menu_is_item_enabled(menu
, pos
))
221 st
->yoffset
= st
->size
.height
- st
->yspace
;
226 if (pos
>= 0 && pos
< menu
->items
->len
)
228 int npos
= st
->cursor
;
230 // show up to 2 disabled items above
231 while(npos
>= 1 && !cbox_menu_is_item_enabled(menu
, npos
- 1) && count
< 2)
236 item
= g_ptr_array_index(menu
->items
, npos
);
237 if (item
->y
< 1 + st
->yoffset
)
238 st
->yoffset
= item
->y
- 1;
240 cbox_menu_state_draw(st
);
244 pos
= ch
== KEY_HOME
? 0 : st
->cursor
+ 1;
245 while(pos
< menu
->items
->len
&& !cbox_menu_is_item_enabled(menu
, pos
))
247 if (pos
< menu
->items
->len
)
251 else if (pos
>= 0 && pos
< menu
->items
->len
)
253 item
= g_ptr_array_index(menu
->items
, st
->cursor
);
254 if (item
->y
- 1 - st
->yoffset
>= st
->yspace
)
255 st
->yoffset
= item
->y
- st
->yspace
;
257 cbox_menu_state_draw(st
);
263 void cbox_menu_state_destroy(struct cbox_menu_state
*st
)
268 struct cbox_menu_page
*cbox_menu_page_new()
270 struct cbox_menu_page
*page
= malloc(sizeof(struct cbox_menu_page
));
272 page
->page
.user_data
= page
;
273 page
->page
.draw
= cbox_menu_page_draw
;
274 page
->page
.on_key
= cbox_menu_page_on_key
;
275 page
->page
.on_idle
= cbox_menu_page_on_idle
;
279 void cbox_menu_page_destroy(struct cbox_menu_page
*p
)