int drawMenuEntry(menuEntry_s* me, gfxScreen_t screen, u16 x, u16 y, bool selected) { if(!me)return 0; int i; //TODO : proper template sort of thing ? //this is all hardcoded and horrible const int totalWidth=selected?ENTRY_WIDTH_SELECTED:ENTRY_WIDTH; const int actualWidth=(selected?ENTRY_FWIDTH_SELECTED:ENTRY_FWIDTH); const int widthOffset=actualWidth-ENTRY_FWIDTH; const int actualHeight=selected?ENTRY_HEIGHT_SELECTED:ENTRY_HEIGHT; if(selected)y-=ENTRY_HEIGHT_SELECTED-ENTRY_HEIGHT; x-=ENTRY_WIDTH+widthOffset; //drop shadow if(selected) { const int sw=4; const int sx=x-sw; for(i=0; i<9; i++)gfxDrawRectangle(screen, GFX_LEFT, ENTRY_BGCOLOR_SHADOW, sx+roundLut[i], y+i, sw, 1); gfxDrawRectangle(screen, GFX_LEFT, ENTRY_BGCOLOR_SHADOW, sx, y+9, sw, actualHeight-9*2); for(i=0; i<9; i++)gfxDrawRectangle(screen, GFX_LEFT, ENTRY_BGCOLOR_SHADOW, sx+roundLut[i], y+actualHeight-1-i, sw, 1); } //main frame for(i=0; i<9; i++)gfxDrawRectangle(screen, GFX_LEFT, ENTRY_BGCOLOR, x-widthOffset+roundLut[i], y+i, actualWidth-roundLut[i]*2, 1); gfxDrawRectangle(screen, GFX_LEFT, ENTRY_BGCOLOR, x-widthOffset, y+9, actualWidth, actualHeight-9*2); for(i=0; i<9; i++)gfxDrawRectangle(screen, GFX_LEFT, ENTRY_BGCOLOR, x-widthOffset+roundLut[i], y+actualHeight-1-i, actualWidth-roundLut[i]*2, 1); //icon frame u8 colorIcon[]={225, 225, 225}; for(i=0; i<5; i++)gfxDrawRectangle(screen, GFX_LEFT, colorIcon, x+3+roundLut2[i], y+4+i, 56-roundLut2[i]*2, 1); gfxDrawRectangle(screen, GFX_LEFT, colorIcon, x+3, y+9, 56, 46); for(i=0; i<5; i++)gfxDrawRectangle(screen, GFX_LEFT, colorIcon, x+3+roundLut2[i], y+4+56-1-i, 56-roundLut2[i]*2, 1); //app specific stuff gfxDrawSprite(screen, GFX_LEFT, me->iconData, ENTRY_ICON_WIDTH, ENTRY_ICON_HEIGHT, x+7, y+8); gfxDrawTextN(screen, GFX_LEFT, &fontTitle, me->name, ENTRY_NAMELENGTH, x+38, y+66); gfxDrawTextN(screen, GFX_LEFT, &fontDescription, me->description, 56, x+26, y+70); if(strlen(me->description) > 56 * 1) { gfxDrawTextN(screen, GFX_LEFT, &fontDescription, me->description + 56, 56, x+18, y+70); } else if(strlen(me->description) > 56 * 2) { gfxDrawTextN(screen, GFX_LEFT, &fontDescription, me->description + 56 * 1, 56, x+18, y+70); gfxDrawTextN(screen, GFX_LEFT, &fontDescription, me->description + 56 * 2, 56, x+10, y+70); } gfxDrawTextN(screen, GFX_LEFT, &fontDescription, me->author, ENTRY_AUTHORLENGTH, x+4, y+ENTRY_HEIGHT-getStringLength(&fontDescription, me->author)-10); return totalWidth; }
void pick_file(file_s *picked, const char *path) { picker = malloc(sizeof(picker_s)); get_dir(path); // key repeat timer static time_t t_start = 0, t_end = 0, t_elapsed = 0; while (aptMainLoop()) { hidScanInput(); u32 kHeld = hidKeysHeld(); u32 kDown = hidKeysDown(); if (hidKeysUp()) { time(&t_start); // reset held timer } if (kDown & KEY_DOWN) { picker->file_index++; if (picker->file_index >= picker->file_count) picker->file_index = 0; time(&t_start); } else if (kHeld & KEY_DOWN) { time(&t_end); t_elapsed = t_end - t_start; if (t_elapsed > 0) { picker->file_index++; if (picker->file_index >= picker->file_count) picker->file_index = 0; svcSleep(100); } } if (kDown & KEY_UP) { picker->file_index--; if (picker->file_index < 0) picker->file_index = picker->file_count - 1; time(&t_start); } else if (kHeld & KEY_UP) { time(&t_end); t_elapsed = t_end - t_start; if (t_elapsed > 0) { picker->file_index--; if (picker->file_index < 0) picker->file_index = picker->file_count - 1; svcSleep(100); } } if (kDown & KEY_A) { int index = picker->file_index; if (!picker->files[index].isDir) { if (confirm(0, "Launch \"%s\" ?", picker->files[index].name)) { strncpy(picked->name, picker->files[index].name, 512); strncpy(picked->path, picker->files[index].path, 512); picked->isDir = picker->files[index].isDir; picked->size = picker->files[index].size; break; } } else { get_dir(picker->files[index].path); } } else if (kDown & KEY_X) { int index = picker->file_index; if (!picker->files[index].isDir) { const char *ext = get_filename_ext(picker->files[index].name); if (strcasecmp(ext, "3dsx") == 0) { if (confirm(3, "Add entry to boot menu: \"%s\" ?", picker->files[index].name)) { if (config->count > CONFIG_MAX_ENTRIES - 1) { debug("Maximum entries reached (%i)\n", CONFIG_MAX_ENTRIES); } else if (configAddEntry(picker->files[index].name, picker->files[index].path, 0) == 0) { debug("Added entry: %s\n", picker->files[index].name); } else { debug("Error adding entry: %s\n", picker->files[index].name); } } } } } else if (kDown & KEY_B) { // exit if we can't go back if (strlen(picker->now_path) <= 1) break; // remove slash if needed if (end_with(picker->now_path, '/')) picker->now_path[strlen(picker->now_path) - 1] = '\0'; // build path char *slash = strrchr(picker->now_path, '/'); if (slash == NULL) break; int len = (int) (slash - picker->now_path); picker->now_path[len] = '\0'; // enter new dir get_dir(picker->now_path); } gfxClear(); gfxDrawText(GFX_TOP, GFX_LEFT, &fontTitle, "*** Select a file ***", 130, 20); int minX = 16; int maxX = 400 - 16; int minY = 32; int maxY = 240 - 16; drawRect(GFX_TOP, GFX_LEFT, minX, minY, maxX, maxY, (u8) 0xFF, (u8) 0xFF, (u8) 0xFF); minY += 20; int i, y = 0; int page = picker->file_index / MAX_LINE; for (i = page * MAX_LINE; i < page * MAX_LINE + MAX_LINE; i++) { if (i >= picker->file_count) break; if (i == picker->file_index) { gfxDrawRectangle(GFX_TOP, GFX_LEFT, (u8[]) {0xDC, 0xDC, 0xDC}, minX + 4, minY + 16 * y, maxX - 23, 15); gfxDrawTextN(GFX_TOP, GFX_LEFT, &fontSelected, picker->files[i].name, 47, minX + 6, minY + 16 * y); if (!picker->files[i].isDir) { gfxDrawText(GFX_BOTTOM, GFX_LEFT, &fontTitle, "Informations", minX + 6, 20); gfxDrawText(GFX_BOTTOM, GFX_LEFT, &fontDefault, "Press (A) to launch\nPress (X) to add to boot menu", minX + 12, 40); } } else { gfxDrawTextN(GFX_TOP, GFX_LEFT, &fontDefault, picker->files[i].name, 47, minX + 6, minY + 16 * y); } y++; }