menu_st *menu_handle_item(menu_st *menulist, int num) { item_st *item; /* out of bounds */ if(num < 0 || num >= menulist->num_items) { Dprintf("menu_handle_item::Invalid item"); return menulist; } item = &menulist->items[num]; menulist->lastsel = -1; if(SUB_MENU_HEADER & item->op) { /* Destroy timer */ menu_handle_timer(menulist, 1); /* create another sub-menu */ menulist = menu_right_transition(menulist, item); } else if(ACTION_MENU & item->op) { /* execute the function */ void (* fp)(void); fp = item->action; (* fp)(); menulist->lastsel = 0; } else if(BOOLEAN_MENU & item->op) { /* toggle boolean; draw */ item->sel_option = !(item->sel_option); if(item->setting != 0) ipod_set_setting(item->setting, item->sel_option); menu_retext_pixmap(menulist, num - menulist->top_item, item); } else if(OPTION_MENU & item->op) { /* rotate option; draw */ item->sel_option = ((item->sel_option + 1) > (item->item_count - 1) ? 0 : item->sel_option + 1); if(item->setting != 0) ipod_set_setting(item->setting, item->sel_option); menu_retext_pixmap(menulist, num - menulist->top_item, item); } else if(SETTING_ITEM & item->op) { if(item->setting != 0) ipod_set_setting(item->setting, item->item_count); menulist = menu_destroy(menulist); } /* this isnt an else, so you can do (ACTION_MENU|SUB_MENU_PREV) */ if(SUB_MENU_PREV & item->op) { menulist = menu_destroy(menulist); } return menulist; }
/* does the drawing, safe(and recommended) to use {in, as} an exposure event */ void menu_draw(menu_st *menulist) { int i; /* appearance changed, force a redraw */ if(menulist->scheme_no != appearance_get_color_scheme() || get_current_font() != menulist->font) { menu_update_menu(menulist); } /* first draw; init onscreen text items */ if(menulist->init == 0) { for(i = (menulist->num_items > menulist->screen_items) ? menulist->screen_items : menulist->num_items; i; i--) menu_retext_pixmap(menulist, i - 1, &menulist->items[menulist->top_item + (i - 1)]); menulist->init = 1; } #if 0 else if(menulist->lastsel == menulist->sel) { Dprintf("Aborted draw because %d == %d\n", menulist->sel, menulist->lastsel); return; } Dprintf("Continuing, %d != %d\n", menulist->sel, menulist->lastsel); #endif /* draw each pixmap */ for(i = 0; i < menulist->screen_items; i++) menu_draw_item(menulist, i); /* erase the bottom unused part of the allocated screen */ GrSetGCForeground(menulist->menu_gc, appearance_get_color( CS_BG )); GrFillRect(menulist->menu_wid, menulist->menu_gc, menulist->x, menulist->height * menulist->screen_items, menulist->w, menulist->h - (menulist->height * menulist->screen_items)); GrSetGCForeground(menulist->menu_gc, BLACK); /* draw scrollbar if needed */ if(menulist->num_items > menulist->screen_items) { menulist->scrollbar = 1; menu_draw_scrollbar(menulist); } else menulist->scrollbar = 0; /* deal with the timer */ menu_handle_timer(menulist, 0); menulist->lastsel = menulist->sel; }
/* flash selected item. ala apple fw */ void menu_flash_selected(menu_st * menulist) { int item; item = menulist->sel - menulist->top_item; GrSetGCForeground(menulist->menu_gc, WHITE); GrFillRect(menulist->menu_wid, menulist->menu_gc, menulist->x, menulist->y + item * menulist->height, menulist->w - (menulist->scrollbar ? 8 : 0), menulist->height); GrSetGCForeground(menulist->menu_gc, BLACK); menulist->items[menulist->sel].op |= CFLASH; menu_handle_timer(menulist, 0); }
static int browser_do_keystroke(GR_EVENT * event) { int ret = 0; switch(event->type) { case GR_EVENT_TYPE_TIMER: if(((GR_EVENT_TIMER *)event)->tid == browser_key_timer) { GrDestroyTimer(browser_key_timer); browser_key_timer = 0; menu_handle_timer(browser_menu, 1); browser_action(browser_menu->items[browser_menu->sel].orig_pos); browser_do_draw(); } else menu_draw_timer(browser_menu); break; case GR_EVENT_TYPE_KEY_DOWN: switch (event->keystroke.ch) { case '\r': case '\n': if(browser_menu->parent == NULL) browser_key_timer = GrCreateTimer(browser_wid, 500); else { menu_handle_timer(browser_menu, 1); browser_menu = menu_handle_item(browser_menu, browser_menu->sel); if(browser_menu_overlay) { browser_menu = browser_menu_overlay; browser_menu_overlay = 0; } browser_do_draw(); } break; case 'm': case 'q': browser_menu = menu_destroy(browser_menu); ret |= KEY_CLICK; if(browser_menu != NULL) { browser_do_draw(); break; } browser_exit(); GrDestroyGC(browser_gc); pz_close_window(browser_wid); break; case 'r': if (menu_shift_selected(browser_menu, 1)) { menu_draw(browser_menu); ret |= KEY_CLICK; } break; case 'l': if (menu_shift_selected(browser_menu, -1)) { menu_draw(browser_menu); ret |= KEY_CLICK; } break; default: ret |= KEY_UNUSED; } break; case GR_EVENT_TYPE_KEY_UP: switch (event->keystroke.ch) { case '\r': case '\n': if(browser_key_timer) { GrDestroyTimer(browser_key_timer); browser_key_timer = 0; menu_handle_timer(browser_menu, 1); browser_selection_activated(browser_menu->items[browser_menu->sel].orig_pos); browser_do_draw(); } break; } break; default: ret |= EVENT_UNUSED; break; } return ret; }
void menu_draw_timer(menu_st *menulist) { char *c = strdup(">"); int colors[] = {CS_ARROW0, CS_ARROW1, CS_ARROW2, CS_ARROW3, CS_ARROW3, CS_ARROW2, CS_ARROW1, CS_ARROW0}; if(menulist->items[menulist->sel].op & CFLASH) { menulist->items[menulist->sel].op ^= CFLASH; menu_clear_pixmap(menulist, menulist->sel - menulist->top_item); menu_retext_pixmap(menulist, menulist->sel - menulist->top_item, &menulist->items[menulist->sel]); menu_handle_timer(menulist, 0); free(c); return; } if(menulist->items[menulist->sel].text_width > menulist->w - (8 + (menulist->scrollbar ? 8 : 0))) { int item, diff, move; item = menulist->sel - menulist->top_item; diff = (menulist->items[menulist->sel].text_width + 8) - (menulist->w - (8 + (menulist->scrollbar ? 8 : 0))); menulist->timer_step++; move = (!((menulist->timer_step / diff) % 2) ? (menulist->timer_step % diff) : (diff - (menulist->timer_step % diff))); if (menulist->timer == INT_MAX - 1) menulist->timer = 0; /* xor the pixmap */ GrSetGCMode(menulist->menu_gc, GR_MODE_XOR); if (hw_version == 0 || hw_version == 0x6 || hw_version == 0xc || hw_version == 0xb) { /* make sure that the xor works properly for devices with * fbrev turned off (host, photo) */ GrSetGCForeground(menulist->menu_gc, WHITE); } GrFillRect(menulist->pixmaps[menulist->pixmap_pos[item]], menulist->menu_gc, move, 0, menulist->w, menulist->height); GrCopyArea(menulist->menu_wid, menulist->menu_gc, menulist->x, (item * menulist->height) + menulist->y, menulist->w - (menulist->scrollbar ? 8 : 0), menulist->height, menulist->pixmaps[menulist->pixmap_pos[item]], move, 0, 0); /* un umm xor the pixmap */ GrFillRect(menulist->pixmaps[menulist->pixmap_pos[item]], menulist->menu_gc, move, 0, menulist->w, menulist->height); GrSetGCMode(menulist->menu_gc, GR_MODE_SET); if (hw_version == 0 || hw_version == 0x6 || hw_version == 0xc || hw_version == 0xb) { /* reset fix for xor on certain devices (host, photo) */ GrSetGCForeground(menulist->menu_gc, BLACK); } free(c); return; } GrSetGCUseBackground(menulist->menu_gc, GR_FALSE); /* cycle through colors */ if (menulist->timer_step < 0 || menulist->timer_step >= 12) menulist->timer_step = 0; GrSetGCForeground(menulist->menu_gc, appearance_get_color(colors[menulist->timer_step < 8 ? menulist->timer_step : 7])); menulist->timer_step++; /* executable instead */ if(EXECUTE_MENU & menulist->items[menulist->sel].op) *c = 'x'; /* double; with a 1px offset for bold */ GrText(menulist->menu_wid, menulist->menu_gc, menulist->x + (menulist->w - 8) - 6, menulist->height * (menulist->sel - menulist->top_item) + menulist->y + 2, c, -1, GR_TFASCII | GR_TFTOP); GrText(menulist->menu_wid, menulist->menu_gc, menulist->x + (menulist->w - 8) - 7, menulist->height * (menulist->sel - menulist->top_item) + menulist->y + 2, c, -1, GR_TFASCII | GR_TFTOP); GrSetGCForeground(menulist->menu_gc, BLACK); GrSetGCUseBackground(menulist->menu_gc, GR_TRUE); free(c); }