void buttons_context_draw(const bContext *C, uiLayout *layout) { SpaceButs *sbuts = CTX_wm_space_buts(C); ButsContextPath *path = sbuts->path; uiLayout *row; uiBlock *block; uiBut *but; PointerRNA *ptr; char namebuf[128], *name; int a, icon; if (!path) return; row = uiLayoutRow(layout, true); uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT); block = uiLayoutGetBlock(row); UI_block_emboss_set(block, UI_EMBOSS_NONE); but = uiDefIconButBitC(block, UI_BTYPE_ICON_TOGGLE, SB_PIN_CONTEXT, 0, ICON_UNPINNED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &sbuts->flag, 0, 0, 0, 0, TIP_("Follow context or keep fixed datablock displayed")); UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */ UI_but_func_set(but, pin_cb, NULL, NULL); for (a = 0; a < path->len; a++) { ptr = &path->ptr[a]; if (a != 0) uiItemL(row, "", VICO_SMALL_TRI_RIGHT_VEC); if (ptr->data) { icon = RNA_struct_ui_icon(ptr->type); name = RNA_struct_name_get_alloc(ptr, namebuf, sizeof(namebuf), NULL); if (name) { if (!ELEM(sbuts->mainb, BCONTEXT_RENDER, BCONTEXT_SCENE, BCONTEXT_RENDER_LAYER) && ptr->type == &RNA_Scene) uiItemLDrag(row, ptr, "", icon); /* save some space */ else uiItemLDrag(row, ptr, name, icon); if (name != namebuf) MEM_freeN(name); } else uiItemL(row, "", icon); } } }
/* Note: This function uses pixelspace (0, 0, winx, winy), not view2d. * The controls are laid out as follows: * * ------------------------------------------- * | Directory input | execute | * ------------------------------------------- * | Filename input | + | - | cancel | * ------------------------------------------- * * The input widgets will stretch to fill any excess space. * When there isn't enough space for all controls to be shown, they are * hidden in this order: x/-, execute/cancel, input widgets. */ void file_draw_buttons(const bContext *C, ARegion *ar) { /* Button layout. */ const int max_x = ar->winx - 10; const int line1_y = ar->winy - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN); const int line2_y = line1_y - (IMASEL_BUTTONS_HEIGHT / 2 + IMASEL_BUTTONS_MARGIN); const int input_minw = 20; const int btn_h = UI_UNIT_Y; const int btn_fn_w = UI_UNIT_X; const int btn_minw = 80; const int btn_margin = 20; const int separator = 4; /* Additional locals. */ char uiblockstr[32]; int loadbutton; int fnumbuttons; int min_x = 10; int chan_offs = 0; int available_w = max_x - min_x; int line1_w = available_w; int line2_w = available_w; uiBut *but; uiBlock *block; SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_get_params(sfile); ARegion *artmp; const bool is_browse_only = (sfile->op == NULL); /* Initialize UI block. */ BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar); block = UI_block_begin(C, ar, uiblockstr, UI_EMBOSS); /* exception to make space for collapsed region icon */ for (artmp = CTX_wm_area(C)->regionbase.first; artmp; artmp = artmp->next) { if (artmp->regiontype == RGN_TYPE_TOOLS && artmp->flag & RGN_FLAG_HIDDEN) { chan_offs = 16; min_x += chan_offs; available_w -= chan_offs; } } /* Is there enough space for the execute / cancel buttons? */ if (is_browse_only) { loadbutton = 0; } else { const uiFontStyle *fstyle = UI_FSTYLE_WIDGET; loadbutton = UI_fontstyle_string_width(fstyle, params->title) + btn_margin; CLAMP_MIN(loadbutton, btn_minw); if (available_w <= loadbutton + separator + input_minw) { loadbutton = 0; } } if (loadbutton) { line1_w -= (loadbutton + separator); line2_w = line1_w; } /* Is there enough space for file number increment/decrement buttons? */ fnumbuttons = 2 * btn_fn_w; if (!loadbutton || line2_w <= fnumbuttons + separator + input_minw) { fnumbuttons = 0; } else { line2_w -= (fnumbuttons + separator); } /* Text input fields for directory and file. */ if (available_w > 0) { const struct direntry *file = sfile->files ? filelist_file(sfile->files, params->active_file) : NULL; int overwrite_alert = file_draw_check_exists(sfile); const bool is_active_dir = file && file->path && BLI_is_dir(file->path); /* callbacks for operator check functions */ UI_block_func_set(block, file_draw_check_cb, NULL, NULL); but = uiDefBut(block, UI_BTYPE_TEXT, -1, "", min_x, line1_y, line1_w - chan_offs, btn_h, params->dir, 0.0, (float)FILE_MAX, 0, 0, TIP_("File path")); UI_but_func_complete_set(but, autocomplete_directory, NULL); UI_but_flag_enable(but, UI_BUT_NO_UTF8); UI_but_flag_disable(but, UI_BUT_UNDO); UI_but_funcN_set(but, file_directory_enter_handle, NULL, but); /* TODO, directory editing is non-functional while a library is loaded * until this is properly supported just disable it. */ if (sfile->files && filelist_lib(sfile->files)) UI_but_flag_enable(but, UI_BUT_DISABLED); if ((params->flag & FILE_DIRSEL_ONLY) == 0) { but = uiDefBut(block, UI_BTYPE_TEXT, -1, "", min_x, line2_y, line2_w - chan_offs, btn_h, is_active_dir ? (char *)"" : params->file, 0.0, (float)FILE_MAXFILE, 0, 0, TIP_(overwrite_alert ? N_("File name, overwrite existing") : N_("File name"))); UI_but_func_complete_set(but, autocomplete_file, NULL); UI_but_flag_enable(but, UI_BUT_NO_UTF8); UI_but_flag_disable(but, UI_BUT_UNDO); /* silly workaround calling NFunc to ensure this does not get called * immediate ui_apply_but_func but only after button deactivates */ UI_but_funcN_set(but, file_filename_enter_handle, NULL, but); /* check if this overrides a file and if the operator option is used */ if (overwrite_alert) { UI_but_flag_enable(but, UI_BUT_REDALERT); } } /* clear func */ UI_block_func_set(block, NULL, NULL, NULL); } /* Filename number increment / decrement buttons. */ if (fnumbuttons && (params->flag & FILE_DIRSEL_ONLY) == 0) { UI_block_align_begin(block); but = uiDefIconButO(block, UI_BTYPE_BUT, "FILE_OT_filenum", 0, ICON_ZOOMOUT, min_x + line2_w + separator - chan_offs, line2_y, btn_fn_w, btn_h, TIP_("Decrement the filename number")); RNA_int_set(UI_but_operator_ptr_get(but), "increment", -1); but = uiDefIconButO(block, UI_BTYPE_BUT, "FILE_OT_filenum", 0, ICON_ZOOMIN, min_x + line2_w + separator + btn_fn_w - chan_offs, line2_y, btn_fn_w, btn_h, TIP_("Increment the filename number")); RNA_int_set(UI_but_operator_ptr_get(but), "increment", 1); UI_block_align_end(block); } /* Execute / cancel buttons. */ if (loadbutton) { const struct direntry *file = filelist_file(sfile->files, params->active_file); const char *str_exec = (file && file->path && BLI_is_dir(file->path)) ? /* params->title is already translated! */ IFACE_("Open Directory") : params->title; uiDefButO(block, UI_BTYPE_BUT, "FILE_OT_execute", WM_OP_EXEC_REGION_WIN, str_exec, max_x - loadbutton, line1_y, loadbutton, btn_h, ""); uiDefButO(block, UI_BTYPE_BUT, "FILE_OT_cancel", WM_OP_EXEC_REGION_WIN, IFACE_("Cancel"), max_x - loadbutton, line2_y, loadbutton, btn_h, ""); } UI_block_end(C, block); UI_block_draw(C, block); }
void file_draw_list(const bContext *C, ARegion *ar) { SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_get_params(sfile); FileLayout *layout = ED_fileselect_get_layout(sfile, ar); View2D *v2d = &ar->v2d; struct FileList *files = sfile->files; struct direntry *file; ImBuf *imb; uiBlock *block = UI_block_begin(C, ar, __func__, UI_EMBOSS); int numfiles; int numfiles_layout; int sx, sy; int offset; int textwidth, textheight; int i; bool is_icon; short align; bool do_drag; int column_space = 0.6f * UI_UNIT_X; numfiles = filelist_numfiles(files); if (params->display != FILE_IMGDISPLAY) { draw_background(layout, v2d); draw_dividers(layout, v2d); } offset = ED_fileselect_layout_offset(layout, (int)ar->v2d.cur.xmin, (int)-ar->v2d.cur.ymax); if (offset < 0) offset = 0; numfiles_layout = ED_fileselect_layout_numfiles(layout, ar); /* adjust, so the next row is already drawn when scrolling */ if (layout->flag & FILE_LAYOUT_HOR) { numfiles_layout += layout->rows; } else { numfiles_layout += layout->columns; } textwidth = (FILE_IMGDISPLAY == params->display) ? layout->tile_w : (int)layout->column_widths[COLUMN_NAME]; textheight = (int)(layout->textheight * 3.0 / 2.0 + 0.5); align = (FILE_IMGDISPLAY == params->display) ? UI_STYLE_TEXT_CENTER : UI_STYLE_TEXT_LEFT; for (i = offset; (i < numfiles) && (i < offset + numfiles_layout); i++) { ED_fileselect_layout_tilepos(layout, i, &sx, &sy); sx += (int)(v2d->tot.xmin + 0.1f * UI_UNIT_X); sy = (int)(v2d->tot.ymax - sy); file = filelist_file(files, i); UI_ThemeColor4(TH_TEXT); if (!(file->selflag & FILE_SEL_EDITING)) { if ((params->highlight_file == i) || (file->selflag & FILE_SEL_HIGHLIGHTED) || (file->selflag & FILE_SEL_SELECTED)) { int colorid = (file->selflag & FILE_SEL_SELECTED) ? TH_HILITE : TH_BACK; int shade = (params->highlight_file == i) || (file->selflag & FILE_SEL_HIGHLIGHTED) ? 35 : 0; BLI_assert(i > 0 || FILENAME_IS_CURRPAR(file->relname)); draw_tile(sx, sy - 1, layout->tile_w + 4, sfile->layout->tile_h + layout->tile_border_y, colorid, shade); } } UI_draw_roundbox_corner_set(UI_CNR_NONE); /* don't drag parent or refresh items */ do_drag = !(FILENAME_IS_CURRPAR(file->relname)); if (FILE_IMGDISPLAY == params->display) { is_icon = 0; imb = filelist_getimage(files, i); if (!imb) { imb = filelist_geticon(files, i); is_icon = 1; } file_draw_preview(block, file, sx, sy, imb, layout, is_icon, do_drag); } else { file_draw_icon(block, file->path, sx, sy - (UI_UNIT_Y / 6), get_file_icon(file), ICON_DEFAULT_WIDTH_SCALE, ICON_DEFAULT_HEIGHT_SCALE, do_drag); sx += ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X; } UI_ThemeColor4(TH_TEXT); if (file->selflag & FILE_SEL_EDITING) { uiBut *but; short width; if (params->display == FILE_SHORTDISPLAY) { width = layout->tile_w - (ICON_DEFAULT_WIDTH_SCALE + 0.2f * UI_UNIT_X); } else if (params->display == FILE_LONGDISPLAY) { width = layout->column_widths[COLUMN_NAME] + layout->column_widths[COLUMN_MODE1] + layout->column_widths[COLUMN_MODE2] + layout->column_widths[COLUMN_MODE3] + (column_space * 3.5f); } else { BLI_assert(params->display == FILE_IMGDISPLAY); width = textwidth; } but = uiDefBut(block, UI_BTYPE_TEXT, 1, "", sx, sy - layout->tile_h - 0.15f * UI_UNIT_X, width, textheight, sfile->params->renameedit, 1.0f, (float)sizeof(sfile->params->renameedit), 0, 0, ""); UI_but_func_rename_set(but, renamebutton_cb, file); UI_but_flag_enable(but, UI_BUT_NO_UTF8); /* allow non utf8 names */ UI_but_flag_disable(but, UI_BUT_UNDO); if (false == UI_but_active_only(C, ar, block, but)) { file->selflag &= ~FILE_SEL_EDITING; } } if (!(file->selflag & FILE_SEL_EDITING)) { int tpos = (FILE_IMGDISPLAY == params->display) ? sy - layout->tile_h + layout->textheight : sy; file_draw_string(sx + 1, tpos, file->relname, (float)textwidth, textheight, align); } if (params->display == FILE_SHORTDISPLAY) { sx += (int)layout->column_widths[COLUMN_NAME] + column_space; if (!(file->type & S_IFDIR)) { file_draw_string(sx, sy, file->size, layout->column_widths[COLUMN_SIZE], layout->tile_h, align); sx += (int)layout->column_widths[COLUMN_SIZE] + column_space; } } else if (params->display == FILE_LONGDISPLAY) { sx += (int)layout->column_widths[COLUMN_NAME] + column_space; #ifndef WIN32 /* rwx rwx rwx */ file_draw_string(sx, sy, file->mode1, layout->column_widths[COLUMN_MODE1], layout->tile_h, align); sx += layout->column_widths[COLUMN_MODE1] + column_space; file_draw_string(sx, sy, file->mode2, layout->column_widths[COLUMN_MODE2], layout->tile_h, align); sx += layout->column_widths[COLUMN_MODE2] + column_space; file_draw_string(sx, sy, file->mode3, layout->column_widths[COLUMN_MODE3], layout->tile_h, align); sx += layout->column_widths[COLUMN_MODE3] + column_space; file_draw_string(sx, sy, file->owner, layout->column_widths[COLUMN_OWNER], layout->tile_h, align); sx += layout->column_widths[COLUMN_OWNER] + column_space; #endif file_draw_string(sx, sy, file->date, layout->column_widths[COLUMN_DATE], layout->tile_h, align); sx += (int)layout->column_widths[COLUMN_DATE] + column_space; file_draw_string(sx, sy, file->time, layout->column_widths[COLUMN_TIME], layout->tile_h, align); sx += (int)layout->column_widths[COLUMN_TIME] + column_space; if (!(file->type & S_IFDIR)) { file_draw_string(sx, sy, file->size, layout->column_widths[COLUMN_SIZE], layout->tile_h, align); sx += (int)layout->column_widths[COLUMN_SIZE] + column_space; } } } UI_block_end(C, block); UI_block_draw(C, block); }