diff options
Diffstat (limited to 'apps/menu.c')
-rw-r--r-- | apps/menu.c | 336 |
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 | ||
369 | static int current_subitems[MAX_MENU_SUBITEMS]; | ||
370 | static int current_subitems_count = 0; | ||
371 | |||
372 | void 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 | |||
380 | static 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 | |||
388 | static 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 | |||
414 | static 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 | |||
451 | static 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 | ||
472 | int 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 | |||
691 | int main_menu(void) | ||
692 | { | ||
693 | return do_menu(NULL); | ||
694 | } | ||