#include #include #include #include #include #include "nk.h" #define MAX_PATH_LEN 512 struct file_browser { /* path */ char file[MAX_PATH_LEN]; char home[MAX_PATH_LEN]; char desktop[MAX_PATH_LEN]; char directory[MAX_PATH_LEN]; /* directory content */ char **files; char **directories; long file_count; long dir_count; long widest; //struct media *media; }; static struct file_browser sbrowser; static struct file_browser *browser = &sbrowser; static void dir_free_list(char **list, ulong size) { ulong i; for (i = 0; i < size; ++i) free(list[i]); free(list); } static int qstrcmp(void *a, void *b) { const char **as = a; const char **bb = b; return strcmp(*as, *bb); } static char** dir_list(const char *dir, int return_subdirs, long *count) { int fd; long i, n, size, len; char *p, **results; Dir *d; if((fd = open(dir, OREAD)) < 0){ nope: *count = 0; return nil; } n = dirreadall(fd, &d); close(fd); if(n <= 0) goto nope; results = calloc(n, sizeof(char**)); if(results == nil) goto nope; size = 0; for(i = 0; i < n; i++){ if(return_subdirs != ((d[i].qid.type & QTDIR) == QTDIR)) continue; p = d[i].name; len = strlen(p); if(len > browser->widest) browser->widest = len; results[size++] = smprint("%s%s", p, d[i].qid.type & QTDIR ? "/" : ""); } qsort(results, size, sizeof(char*), qstrcmp); free(d); *count = size; return results; } static void file_browser_reload_directory_content(struct file_browser *browser, const char *path) { strncpy(browser->directory, path, MAX_PATH_LEN); cleanname(browser->directory); dir_free_list(browser->files, browser->file_count); dir_free_list(browser->directories, browser->dir_count); browser->files = dir_list(path, 0, &browser->file_count); browser->directories = dir_list(path, 1, &browser->dir_count); } static void filebrowser(struct nk_context *ctx) { struct nk_rect total_space; float spacing_x; static float ratio[] = {0.25f, NK_UNDEFINED}; spacing_x = ctx->style.window.spacing.x; if(nk_begin(ctx, "File Browser", nk_rect(10, 10, Dx(screen->r)-20, Dy(screen->r)-20), NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR)){ //nk_layout_row_dynamic(ctx, 0, 1); //nk_label(ctx, "Hello, world!", NK_TEXT_LEFT); /* output path directory selector in the menubar */ ctx->style.window.spacing.x = 0; nk_menubar_begin(ctx); { Rune r; int len; char *d = browser->directory; char *begin; nk_layout_row_dynamic(ctx, 25, 6); if(nk_button_label(ctx, "/")) file_browser_reload_directory_content(browser, "/"); d += chartorune(&r, d); begin = d; while(*d != 0){ len = chartorune(&r, d); if(r == '/'){ *d = '\0'; if(nk_button_label(ctx, begin)){ *d++ = '/'; *d = '\0'; file_browser_reload_directory_content(browser, browser->directory); break; } *d = '/'; begin = d + 1; } d += len; } if(*begin && nk_button_label(ctx, begin)) file_browser_reload_directory_content(browser, browser->directory); } nk_menubar_end(ctx); ctx->style.window.spacing.x = spacing_x; /* window layout */ total_space = nk_window_get_content_region(ctx); nk_layout_row(ctx, NK_DYNAMIC, total_space.h, 2, ratio); nk_group_begin(ctx, "Special", NK_WINDOW_NO_SCROLLBAR); { //struct nk_image home = media->icons.home; //struct nk_image desktop = media->icons.desktop; //struct nk_image computer = media->icons.computer; nk_layout_row_dynamic(ctx, 40, 1); if (nk_button_label(ctx, "home")) file_browser_reload_directory_content(browser, browser->home); if (nk_button_label(ctx,"desktop")) file_browser_reload_directory_content(browser, browser->desktop); if (nk_button_label(ctx,"computer")) file_browser_reload_directory_content(browser, "/"); nk_group_end(ctx); } /* output directory content window */ nk_group_begin(ctx, "Content", 0); { int index = -1; long i = 0, j = 0, k = 0; long rows = 0, cols = 0; long count = browser->dir_count + browser->file_count; cols = 4; rows = count / cols; for (i = 0; i <= rows; i += 1) { // {long n = j + cols; // nk_layout_row_dynamic(ctx, 135, (int)cols); // for (; j < count && j < n; ++j) { // /* draw one row of icons */ // if (j < browser->dir_count) { // /* draw and execute directory buttons */ // if (nk_button_image(ctx,media->icons.directory)) // index = (int)j; // } else { // /* draw and execute files buttons */ // //struct nk_image *icon; // long fileIndex = (j - browser->dir_count); // //icon = media_icon_for_file(media,browser->files[fileIndex]); // if (nk_button_image(ctx, *icon)) { // strncpy(browser->file, browser->directory, MAX_PATH_LEN); // n = strlen(browser->file); // strncpy(browser->file + n, browser->files[fileIndex], MAX_PATH_LEN - n); // ret = 1; // } // } // }} {long n = k + cols; nk_layout_row_dynamic(ctx, 20, (int)cols); for (; k < count && k < n; k++) { /* draw one row of labels */ if (k < browser->dir_count) { if(nk_button_label(ctx, browser->directories[k])) index = k; } else { long t = k-browser->dir_count; if(nk_button_label(ctx, browser->files[t])){ print("%s/%s\n", browser->directory, browser->files[t]); threadexitsall(nil); } } }} } if (index != -1) { strcat(browser->directory, "/"); long n = strlen(browser->directory); strncpy(browser->directory + n, browser->directories[index], MAX_PATH_LEN - n); n = strlen(browser->directory); if (n < MAX_PATH_LEN - 1) { browser->directory[n] = '/'; browser->directory[n+1] = '\0'; } file_browser_reload_directory_content(browser, browser->directory); } nk_group_end(ctx); } } nk_end(ctx); } void usage(void) { fprint(2, "usage: %s\n", argv0); threadexitsall("usage"); } void threadmain(int argc, char *argv[]) { char *home; ARGBEGIN{ default: usage(); }ARGEND memset(browser, 0, sizeof(*browser)); home = getenv("home"); if(home != nil){ strcpy(browser->home, home); free(home); } strcpy(browser->directory, browser->home); file_browser_reload_directory_content(browser, browser->directory); nkinit(filebrowser); }