summaryrefslogtreecommitdiff
path: root/apps/menu.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/menu.c')
-rw-r--r--apps/menu.c336
1 files changed, 336 insertions, 0 deletions
diff --git a/apps/menu.c b/apps/menu.c
index 261286b8fa..9c5afbe94a 100644
--- a/apps/menu.c
+++ b/apps/menu.c
@@ -35,12 +35,14 @@
35#include "usb.h" 35#include "usb.h"
36#include "panic.h" 36#include "panic.h"
37#include "settings.h" 37#include "settings.h"
38#include "settings_list.h"
38#include "status.h" 39#include "status.h"
39#include "screens.h" 40#include "screens.h"
40#include "talk.h" 41#include "talk.h"
41#include "lang.h" 42#include "lang.h"
42#include "misc.h" 43#include "misc.h"
43#include "action.h" 44#include "action.h"
45#include "menus/exported_menus.h"
44 46
45#ifdef HAVE_LCD_BITMAP 47#ifdef HAVE_LCD_BITMAP
46#include "icons.h" 48#include "icons.h"
@@ -356,3 +358,337 @@ void put_cursorxy(int x, int y, bool on)
356#endif 358#endif
357 } 359 }
358} 360}
361
362/******************************************************************/
363/* New menu stuff here!!
364 ******************************************************************/
365
366
367/* used to allow for dynamic menus */
368#define MAX_MENU_SUBITEMS 64
369static int current_subitems[MAX_MENU_SUBITEMS];
370static int current_subitems_count = 0;
371
372void get_menu_callback(const struct menu_item_ex *m,
373 menu_callback_type menu_callback)
374{
375 if (m->flags&MENU_HAS_DESC)
376 menu_callback= m->callback_and_desc->menu_callback;
377 else menu_callback = m->menu_callback;
378}
379
380static int get_menu_selection(int selected_item, const struct menu_item_ex *menu)
381{
382 int type = (menu->flags&MENU_TYPE_MASK);
383 if (type == MT_MENU && (selected_item<current_subitems_count))
384 return current_subitems[selected_item];
385 return selected_item;
386}
387
388static char * get_menu_item_name(int selected_item,void * data, char *buffer)
389{
390 const struct menu_item_ex *menu = (const struct menu_item_ex *)data;
391 int type = (menu->flags&MENU_TYPE_MASK);
392 selected_item = get_menu_selection(selected_item, menu);
393
394 (void)buffer;
395 /* only MT_MENU or MT_RETURN_ID is allowed in here */
396 if (type == MT_RETURN_ID)
397 {
398 return (char*)menu->strings[selected_item];
399 }
400
401 menu = menu->submenus[selected_item];
402 type = (menu->flags&MENU_TYPE_MASK);
403 if (type == MT_SETTING)
404 {
405 const struct settings_list *v
406 = find_setting(menu->variable);
407 if (v)
408 return str(v->lang_id);
409 else return "Not Done yet!";
410 }
411 return P2STR(menu->callback_and_desc->desc);
412}
413
414static void init_menu_lists(const struct menu_item_ex *menu,
415 struct gui_synclist *lists, int selected, bool callback)
416{
417 int i, count = (menu->flags&MENU_COUNT_MASK)>>MENU_COUNT_SHIFT;
418 menu_callback_type menu_callback = NULL;
419 current_subitems_count = 0;
420 for (i=0; i<count; i++)
421 {
422 get_menu_callback(menu->submenus[i],menu_callback);
423 if (menu_callback)
424 {
425 if (menu_callback(ACTION_REQUEST_MENUITEM,menu->submenus[i])
426 != ACTION_EXIT_MENUITEM)
427 {
428 current_subitems[current_subitems_count] = i;
429 current_subitems_count++;
430 }
431 }
432 else
433 {
434 current_subitems[current_subitems_count] = i;
435 current_subitems_count++;
436 }
437 }
438
439 gui_synclist_init(lists,get_menu_item_name,(void*)menu,false,1);
440 gui_synclist_set_title(lists, P2STR(menu->callback_and_desc->desc), NOICON);
441 gui_synclist_set_icon_callback(lists,NULL);
442 gui_synclist_set_nb_items(lists,current_subitems_count);
443 gui_synclist_limit_scroll(lists,true);
444 gui_synclist_select_item(lists, selected);
445
446 get_menu_callback(menu,menu_callback);
447 if (callback && menu_callback)
448 menu_callback(ACTION_ENTER_MENUITEM,menu);
449}
450
451static void talk_menu_item(const struct menu_item_ex *menu,
452 struct gui_synclist *lists)
453{
454 int id = -1;
455 if (global_settings.talk_menu)
456 {
457 int sel = get_menu_selection(gui_synclist_get_sel_pos(lists),menu);
458 if ((menu->flags&MENU_TYPE_MASK) == MT_MENU)
459 {
460 if ((menu->submenus[sel]->flags&MENU_TYPE_MASK) == MT_SETTING)
461 talk_setting(menu->submenus[sel]->variable);
462 else
463 {
464 id = P2ID(menu->submenus[sel]->callback_and_desc->desc);
465 if (id != -1)
466 talk_id(id,false);
467 }
468 }
469 }
470}
471#define MAX_OPTIONS 32
472int do_menu(const struct menu_item_ex *start_menu)
473{
474 int action;
475 int selected = 0;
476 struct gui_synclist lists;
477 const struct menu_item_ex *temp, *menu;
478 int ret = 0;
479
480 const struct menu_item_ex *menu_stack[MAX_MENUS];
481 int menu_stack_selected_item[MAX_MENUS];
482 int stack_top = 0;
483 bool in_stringlist;
484 menu_callback_type menu_callback = NULL;
485 if (start_menu == NULL)
486 menu = &main_menu_;
487 else menu = start_menu;
488
489 init_menu_lists(menu,&lists,selected,true);
490 in_stringlist = ((menu->flags&MENU_TYPE_MASK) == MT_RETURN_ID);
491
492 talk_menu_item(menu, &lists);
493
494 gui_synclist_draw(&lists);
495 gui_syncstatusbar_draw(&statusbars, true);
496 action_signalscreenchange();
497
498 while (ret == 0)
499 {
500 action = get_action(CONTEXT_MAINMENU,HZ);
501 /* HZ so the status bar redraws corectly */
502 if (action == ACTION_NONE)
503 {
504 gui_syncstatusbar_draw(&statusbars, true);
505 continue;
506 }
507
508 get_menu_callback(menu,menu_callback);
509 if (menu_callback)
510 {
511 action = menu_callback(action,menu);
512 }
513
514 if (gui_synclist_do_button(&lists,action,LIST_WRAP_UNLESS_HELD))
515 {
516 talk_menu_item(menu, &lists);
517 }
518 else if (action == ACTION_MENU_WPS)
519 {
520 ret = MENU_RETURN_TO_WPS;
521 }
522 else if ((action == ACTION_STD_CANCEL) ||
523 (action == ACTION_STD_MENU))
524 {
525 if (in_stringlist)
526 in_stringlist = false;
527 if (stack_top > 0)
528 {
529 get_menu_callback(menu,menu_callback);
530 if (menu_callback)
531 {
532 if (menu_callback(action,menu) ==
533 ACTION_EXIT_MENUITEM)
534 break;
535 }
536 stack_top--;
537 menu = menu_stack[stack_top];
538 init_menu_lists(menu, &lists,
539 menu_stack_selected_item[stack_top], false);
540 talk_menu_item(menu, &lists);
541 }
542 else
543 {
544 break;
545 }
546 }
547 else if (action == ACTION_STD_OK)
548 {
549 int type;
550 selected = get_menu_selection(gui_synclist_get_sel_pos(&lists), menu);
551 temp = menu->submenus[selected];
552 if (in_stringlist)
553 type = (menu->flags&MENU_TYPE_MASK);
554 else type = (temp->flags&MENU_TYPE_MASK);
555 get_menu_callback(temp,menu_callback);
556 if (menu_callback)
557 {
558 action = menu_callback(ACTION_ENTER_MENUITEM,temp);
559 if (action == ACTION_EXIT_MENUITEM)
560 break;
561 }
562 switch (type)
563 {
564 case MT_MENU:
565 if (stack_top < MAX_MENUS)
566 {
567 menu_stack[stack_top] = menu;
568 menu_stack_selected_item[stack_top]
569 = gui_synclist_get_sel_pos(&lists);
570 stack_top++;
571 init_menu_lists(temp, &lists, 0, true);
572 menu = temp;
573 talk_menu_item(menu, &lists);
574 }
575 break;
576 case MT_FUNCTION_CALL:
577 action_signalscreenchange();
578 temp->function();
579 break;
580 case MT_FUNCTION_WITH_PARAM:
581 action_signalscreenchange();
582 temp->func_with_param->function(
583 temp->func_with_param->param);
584 break;
585 case MT_SETTING:
586 {
587 const struct settings_list *setting = find_setting(
588 temp->variable);
589 if (setting)
590 {
591 if ((setting->flags&F_BOOL_SETTING) == F_BOOL_SETTING)
592 {
593 bool temp_var, *var;
594 if (setting->flags&F_TEMPVAR)
595 {
596 temp_var = *(bool*)setting->setting;
597 var = &temp_var;
598 }
599 else
600 {
601 var = (bool*)setting->setting;
602 }
603 set_bool_options(str(setting->lang_id),var,
604 STR(setting->bool_setting->lang_yes),
605 STR(setting->bool_setting->lang_no),
606 setting->bool_setting->option_callback);
607 if (setting->flags&F_TEMPVAR)
608 *(bool*)setting->setting = temp_var;
609 }
610 else if (setting->flags&F_T_SOUND)
611 {
612 set_sound(str(setting->lang_id), setting->setting,
613 setting->sound_setting->setting);
614 }
615 else /* other setting, must be an INT type */
616 {
617 int temp_var, *var;
618 if (setting->flags&F_TEMPVAR)
619 {
620 temp_var = *(int*)setting->setting;
621 var = &temp_var;
622 }
623 else
624 {
625 var = (int*)setting->setting;
626 }
627 DEBUGF("%x\n",setting->flags);
628 if (setting->flags&F_INT_SETTING)
629 {DEBUGF("boo");
630 set_int(str(setting->lang_id),
631 str(setting->int_setting->unit),
632 setting->int_setting->unit,var,
633 setting->int_setting->option_callback,
634 setting->int_setting->step,
635 setting->int_setting->min,
636 setting->int_setting->max,
637 setting->int_setting->formatter);
638 }
639 else if (setting->flags&F_CHOICE_SETTING)
640 {
641 static struct opt_items options[MAX_OPTIONS];
642 int i,j, count = setting->choice_setting->count;
643 for (i=0, j=0; i<count && i<MAX_OPTIONS; i++)
644 {
645 options[j].string =
646 P2STR(setting->choice_setting->desc[i]);
647 options[j].voice_id =
648 P2ID(setting->choice_setting->desc[i]);
649 j++;
650 }
651 set_option(str(setting->lang_id), var, INT,
652 options,count,
653 setting->choice_setting->option_callback);
654 }
655 if (setting->flags&F_TEMPVAR)
656 *(int*)setting->setting = temp_var;
657 }
658 }
659 break;
660 }
661 case MT_RETURN_ID:
662 if (in_stringlist)
663 {
664 action_signalscreenchange();
665 return selected;
666 }
667 else if (stack_top < MAX_MENUS)
668 {
669 menu_stack[stack_top] = menu;
670 menu_stack_selected_item[stack_top] = selected;
671 stack_top++;
672 menu = temp;
673 init_menu_lists(menu,&lists,0,false);
674 in_stringlist = true;
675 }
676 break;
677 }
678 get_menu_callback(temp,menu_callback);
679 if (type != MT_MENU && menu_callback)
680 menu_callback(ACTION_EXIT_MENUITEM,temp);
681 }
682 else if(default_event_handler(action) == SYS_USB_CONNECTED)
683 ret = MENU_ATTACHED_USB;
684 gui_syncstatusbar_draw(&statusbars, true);
685 gui_synclist_draw(&lists);
686 }
687 action_signalscreenchange();
688 return ret;
689}
690
691int main_menu(void)
692{
693 return do_menu(NULL);
694}