4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2008 Blender Foundation.
21 * All rights reserved.
24 * Contributor(s): Blender Foundation
26 * ***** END GPL LICENSE BLOCK *****
31 #include "BLI_blenlib.h"
32 #include "BLI_storage_types.h"
34 #include "BLI_winstuff.h"
38 #include "BIF_glutil.h"
41 #include "BKE_colortools.h"
42 #include "BKE_context.h"
43 #include "BKE_screen.h"
44 #include "BKE_global.h"
45 #include "BKE_utildefines.h"
47 #include "DNA_space_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_screen_types.h"
50 #include "DNA_userdef_types.h"
51 #include "DNA_windowmanager_types.h"
53 #include "IMB_imbuf_types.h"
54 #include "IMB_imbuf.h"
56 #include "MEM_guardedalloc.h"
60 #include "RNA_access.h"
62 #include "ED_fileselect.h"
63 #include "ED_screen.h"
65 #include "UI_interface.h"
66 #include "UI_interface_icons.h"
67 #include "UI_resources.h"
69 #include "UI_view2d.h"
77 #include "file_intern.h" // own include
80 #define IMASEL_BUTTONS_HEIGHT 40
81 #define TILE_BORDER_X 8
82 #define TILE_BORDER_Y 8
92 /* XXX very bad, need to check font code */
93 static int gFontsize=12;
95 static void do_file_buttons(bContext *C, void *arg, int event)
99 file_exec(C, NULL); /* file_ops.c */
102 file_cancel_exec(C, NULL); /* file_ops.c */
105 file_parent_exec(C, NULL); /* file_ops.c */
110 /* note; this function uses pixelspace (0, 0, winx, winy), not view2d */
111 void file_draw_buttons(const bContext *C, ARegion *ar)
113 SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
114 FileSelectParams* params = ED_fileselect_get_params(sfile);
119 int filebuty1, filebuty2;
122 float xmax = ar->winx - 10;
124 filebuty1= ar->winy - IMASEL_BUTTONS_HEIGHT - 12;
125 filebuty2= filebuty1 + IMASEL_BUTTONS_HEIGHT/2 + 4;
128 sprintf(name, "win %p", ar);
129 block = uiBeginBlock(C, ar, name, UI_EMBOSS, UI_HELV);
130 uiBlockSetHandleFunc(block, do_file_buttons, NULL);
133 uiSetButLock( filelist_gettype(simasel->files)==FILE_MAIN && simasel->returnfunc, NULL);
136 /* space available for load/save buttons? */
137 slen = UI_GetStringWidth(G.font, sfile->params->title, 0);
138 loadbutton= slen > 60 ? slen + 20 : MAX2(80, 20+UI_GetStringWidth(G.font, params->title, 0));
139 if(ar->winx > loadbutton+20) {
140 if(params->title[0]==0) {
148 uiDefBut(block, TEX, 0 /* XXX B_FS_FILENAME */,"", xmin+2, filebuty1, xmax-xmin-loadbutton-4, 21, params->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
149 uiDefBut(block, TEX, 0 /* XXX B_FS_DIRNAME */,"", xmin+2, filebuty2, xmax-xmin-loadbutton-4, 21, params->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
152 uiSetCurFont(block, UI_HELV);
153 uiDefBut(block, BUT, B_FS_EXEC, params->title, xmax-loadbutton, filebuty2, loadbutton, 21, params->dir, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
154 uiDefBut(block, BUT, B_FS_CANCEL, "Cancel", xmax-loadbutton, filebuty1, loadbutton, 21, params->file, 0.0, (float)FILE_MAXFILE-1, 0, 0, "");
158 /* menu[0] = NULL happens when no .Bfs is there, and first time browse
159 disallow external directory browsing for databrowse */
161 if(menu[0] && (params->type != FILE_MAIN)) {
162 uiDefButS(block, MENU, 0 /* B_FS_DIR_MENU */, menu, xmin, filebuty2, fsmenubut_width, 21, ¶ms->menu, 0, 0, 0, 0, "");
163 uiDefBut(block, BUT, 0 /* B_FS_BOOKMARK */, "B", xmin, filebuty1, bookmarkbut_width, 21, 0, 0, 0, 0, 0, "Bookmark current directory");
170 uiEndBlock(C, block);
171 uiDrawBlock(C, block);
175 static void draw_tile(short sx, short sy, short width, short height, int colorid, int shade)
177 /* TODO: BIF_ThemeColor seems to need this to show the color, not sure why? - elubie */
178 //glEnable(GL_BLEND);
179 //glColor4ub(0, 0, 0, 100);
180 //glDisable(GL_BLEND);
181 /* I think it was a missing glDisable() - ton */
183 UI_ThemeColorShade(colorid, shade);
185 // glRecti(sx, sy - height, sx + width, sy);
187 uiRoundBox(sx, sy - height, sx + width, sy, 6);
190 #define FILE_SHORTEN_END 0
191 #define FILE_SHORTEN_FRONT 1
194 static float shorten_string(char* string, float w, int flag)
201 sw = UI_GetStringWidth(G.font, string,0);
202 if (flag == FILE_SHORTEN_FRONT) {
204 BLI_strncpy(temp, "...", 4);
205 pad = UI_GetStringWidth(G.font, temp,0);
206 while (s && (sw+pad>w)) {
208 sw = UI_GetStringWidth(G.font, s,0);
212 int slen = strlen(s);
213 BLI_strncpy(temp+3, s, slen+1);
215 BLI_strncpy(string, temp, slen+4);
220 int slen = strlen(string);
221 string[slen-1] = '\0';
222 sw = UI_GetStringWidth(G.font, s,0);
226 int slen = strlen(string);
228 BLI_strncpy(string+slen-3, "...", 4);
236 static int get_file_icon(struct direntry *file)
238 if (file->type & S_IFDIR)
239 return ICON_FILE_FOLDER;
240 else if (file->flags & BLENDERFILE)
241 return ICON_FILE_BLEND;
242 else if (file->flags & IMAGEFILE)
243 return ICON_FILE_IMAGE;
244 else if (file->flags & MOVIEFILE)
245 return ICON_FILE_MOVIE;
246 else if (file->flags & PYSCRIPTFILE)
247 return ICON_FILE_SCRIPT;
248 else if (file->flags & PYSCRIPTFILE)
249 return ICON_FILE_SCRIPT;
250 else if (file->flags & SOUNDFILE)
251 return ICON_FILE_SOUND;
252 else if (file->flags & FTFONTFILE)
253 return ICON_FILE_FONT;
255 return ICON_FILE_BLANK;
258 static void file_draw_icon(short sx, short sy, int icon, short width, short height)
264 y = (float)(sy-height);
266 if (icon == ICON_FILE_BLANK) blend = -80;
270 UI_icon_draw_aspect_blended(x, y, icon, 1.f, blend);
273 static void file_draw_string(short sx, short sy, const char* string, short width, short height, int flag)
276 char fname[FILE_MAXFILE];
280 BLI_strncpy(fname,string, FILE_MAXFILE);
281 sw = shorten_string(fname, width, flag );
282 soffs = (width - sw) / 2;
284 y = (float)(sy-height);
286 // XXX was using ui_rasterpos_safe
290 /* XXX TODO: handling of international fonts.
291 TODO: proper support for utf8 in languages different from ja_JP abd zh_CH
292 needs update of iconv in lib/windows to support getting the system language string
294 UI_DrawString(G.font, fname, 0);
298 void file_calc_previews(const bContext *C, ARegion *ar)
300 SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
301 View2D *v2d= &ar->v2d;
303 ED_fileselect_init_layout(sfile, ar);
304 UI_view2d_totRect_set(v2d, sfile->layout->width, sfile->layout->height);
307 void file_draw_previews(const bContext *C, ARegion *ar)
309 SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
310 FileSelectParams* params= ED_fileselect_get_params(sfile);
311 FileLayout* layout= ED_fileselect_get_layout(sfile, ar);
312 View2D *v2d= &ar->v2d;
313 struct FileList* files = sfile->files;
315 struct direntry *file;
325 filelist_imgsize(files,sfile->layout->prv_w,sfile->layout->prv_h);
326 numfiles = filelist_numfiles(files);
328 sx = v2d->cur.xmin + layout->tile_border_x;
329 sy = v2d->cur.ymax - layout->tile_border_y;
331 offset = ED_fileselect_layout_offset(layout, 0, 0);
332 if (offset<0) offset=0;
333 for (i=offset; (i < numfiles) && (i < (offset+(layout->rows+2)*layout->columns)); ++i)
335 ED_fileselect_layout_tilepos(layout, i, &sx, &sy);
336 sx += v2d->tot.xmin+2;
337 sy = v2d->tot.ymax - sy;
338 file = filelist_file(files, i);
340 if (file->flags & ACTIVE) {
342 draw_tile(sx - 1, sy, sfile->layout->tile_w + 1, sfile->layout->tile_h, colorid,0);
343 } else if (params->active_file == i) {
345 draw_tile(sx - 1, sy, sfile->layout->tile_w + 1, sfile->layout->tile_h, colorid,0);
348 if ( (file->flags & IMAGEFILE) /* || (file->flags & MOVIEFILE) */)
350 filelist_loadimage(files, i);
353 imb = filelist_getimage(files, i);
355 imb = filelist_geticon(files,i);
360 float fx = ((float)layout->prv_w - (float)imb->x)/2.0f;
361 float fy = ((float)layout->prv_h - (float)imb->y)/2.0f;
362 float dx = (fx + 0.5f + sfile->layout->prv_border_x);
363 float dy = (fy + 0.5f - sfile->layout->prv_border_y);
364 short xco = (float)sx + dx;
365 short yco = (float)sy - sfile->layout->prv_h + dy;
367 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
370 if (!is_icon && (file->flags & IMAGEFILE))
371 uiDrawBoxShadow(220, xco, yco, xco + imb->x, yco + imb->y);
376 glColor4f(1.0, 1.0, 1.0, 1.0);
377 glaDrawPixelsTex(xco, yco, imb->x, imb->y, GL_UNSIGNED_BYTE, imb->rect);
380 if (!is_icon && (file->flags & IMAGEFILE)) {
381 glColor4f(0.0f, 0.0f, 0.0f, 0.4f);
382 fdrawbox(xco, yco, xco + imb->x, yco + imb->y);
390 UI_ThemeColorShade(TH_BACK, -20);
393 if (S_ISDIR(file->type)) {
394 glColor4f(1.0f, 1.0f, 0.9f, 1.0f);
396 else if (file->flags & IMAGEFILE) {
397 UI_ThemeColor(TH_SEQ_IMAGE);
399 else if (file->flags & MOVIEFILE) {
400 UI_ThemeColor(TH_SEQ_MOVIE);
402 else if (file->flags & BLENDERFILE) {
403 UI_ThemeColor(TH_SEQ_SCENE);
406 if (params->active_file == i) {
407 UI_ThemeColor(TH_GRID); /* grid used for active text */
408 } else if (file->flags & ACTIVE) {
409 UI_ThemeColor(TH_TEXT_HI);
411 UI_ThemeColor(TH_TEXT);
415 file_draw_string(sx + layout->prv_border_x, sy+4, file->relname, layout->tile_w, layout->tile_h, FILE_SHORTEN_END);
417 if (!sfile->loadimage_timer)
418 sfile->loadimage_timer= WM_event_add_window_timer(CTX_wm_window(C), TIMER1, 1.0/30.0); /* max 30 frames/sec. */
426 void file_draw_list(const bContext *C, ARegion *ar)
428 SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
429 FileSelectParams* params = ED_fileselect_get_params(sfile);
430 FileLayout* layout= ED_fileselect_get_layout(sfile, ar);
431 View2D *v2d= &ar->v2d;
432 struct FileList* files = sfile->files;
433 struct direntry *file;
442 numfiles = filelist_numfiles(files);
443 type = filelist_gettype(files);
445 sx = ar->v2d.tot.xmin + layout->tile_border_x/2;
446 sy = ar->v2d.cur.ymax - layout->tile_border_y;
448 offset = ED_fileselect_layout_offset(layout, 0, 0);
449 if (offset<0) offset=0;
451 /* alternating flat shade background */
452 for (i=offset; (i <= numfiles); ++i)
454 ED_fileselect_layout_tilepos(layout, i, &sx, &sy);
456 sy = v2d->tot.ymax - (sy + layout->tile_border_y);
457 //sy = v2d->tot.ymax - sy;
459 if (i % 2) UI_ThemeColor(TH_BACK);
460 else UI_ThemeColorShade(TH_BACK, -7);
461 glRectf(v2d->tot.xmin, sy, v2d->tot.xmax, sy+layout->tile_h+2*layout->tile_border_y);
464 /* vertical column dividers */
465 while (sx < ar->v2d.cur.xmax) {
466 sx += (sfile->layout->tile_w+2*sfile->layout->tile_border_x);
468 UI_ThemeColorShade(TH_BACK, 30);
469 sdrawline(sx+1, ar->v2d.cur.ymax - layout->tile_border_y , sx+1, ar->v2d.cur.ymin);
470 UI_ThemeColorShade(TH_BACK, -30);
471 sdrawline(sx, ar->v2d.cur.ymax - layout->tile_border_y , sx, ar->v2d.cur.ymin);
474 sx = ar->v2d.cur.xmin + layout->tile_border_x;
475 sy = ar->v2d.cur.ymax - layout->tile_border_y;
477 for (i=offset; (i < numfiles); ++i)
479 ED_fileselect_layout_tilepos(layout, i, &sx, &sy);
480 sx += v2d->tot.xmin+2;
481 sy = v2d->tot.ymax - sy;
483 file = filelist_file(files, i);
485 if (params->active_file == i) {
486 if (file->flags & ACTIVE) colorid= TH_HILITE;
487 else colorid = TH_BACK;
488 draw_tile(sx-2, sy-3, layout->tile_w+2, sfile->layout->tile_h+layout->tile_border_y, colorid,20);
489 } else if (file->flags & ACTIVE) {
491 draw_tile(sx-2, sy-3, layout->tile_w+2, sfile->layout->tile_h+layout->tile_border_y, colorid,0);
495 draw_tile(sx, sy, sfile->tile_w, sfile->tile_h, colorid);
500 file_draw_icon(spos, sy-3, get_file_icon(file), ICON_DEFAULT_WIDTH, ICON_DEFAULT_WIDTH);
501 spos += ICON_DEFAULT_WIDTH + 4;
503 UI_ThemeColor4(TH_TEXT);
505 sw = UI_GetStringWidth(G.font, file->size, 0);
506 file_draw_string(spos, sy, file->relname, layout->tile_w - sw - 5, layout->tile_h, FILE_SHORTEN_END);
508 spos += filelist_maxnamelen(sfile->files);
509 if (params->display != FILE_SHOWSHORT) {
510 #if 0 // XXX TODO: add this for non-windows systems
513 sw = UI_GetStringWidth(G.font, file->mode1, 0);
514 file_draw_string(spos, sy, file->mode1, sw, layout->tile_h);
517 sw = UI_GetStringWidth(G.font, file->mode2, 0);
518 file_draw_string(spos, sy, file->mode2, sw, layout->tile_h);
521 sw = UI_GetStringWidth(G.font, file->mode3, 0);
522 file_draw_string(spos, sy, file->mode3, sw, layout->tile_h);
525 sw = UI_GetStringWidth(G.font, file->owner, 0);
526 file_draw_string(spos, sy, file->owner, sw, layout->tile_h);
530 sw = UI_GetStringWidth(G.font, file->date, 0);
531 file_draw_string(spos, sy, file->date, sw, layout->tile_h, FILE_SHORTEN_END);
534 sw = UI_GetStringWidth(G.font, file->time, 0);
535 file_draw_string(spos, sy, file->time, sw, layout->tile_h, FILE_SHORTEN_END);
537 sw = UI_GetStringWidth(G.font, file->size, 0);
539 file_draw_string(spos, sy, file->size, sw, layout->tile_h, FILE_SHORTEN_END);
541 file_draw_string(sx + layout->tile_w - 2*layout->tile_border_x - sw - 4, sy, file->size, layout->tile_w - layout->tile_border_x - sw - 5, layout->tile_h, FILE_SHORTEN_END);
546 static void file_draw_fsmenu_category(const bContext *C, ARegion *ar, FSMenuCategory category, const char* category_name, short *starty)
548 SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
549 char bookmark[FILE_MAX];
550 int nentries = fsmenu_get_nentries(category);
551 int linestep = gFontsize*2.0f;
552 short sx, sy, xpos, ypos;
553 int bmwidth = ar->v2d.cur.xmax - ar->v2d.cur.xmin - 2*TILE_BORDER_X - ICON_DEFAULT_WIDTH - 4;
554 int fontsize = gFontsize;
558 sx = ar->v2d.cur.xmin + TILE_BORDER_X;
561 UI_ThemeColor(TH_TEXT_HI);
562 file_draw_string(sx, sy, category_name, bmwidth, fontsize, FILE_SHORTEN_END);
566 for (i=0; i< nentries && (sy > ar->v2d.cur.ymin) ;++i) {
567 char *fname = fsmenu_get_entry(category, i);
571 BLI_strncpy(bookmark, fname, FILE_MAX);
573 sl = strlen(bookmark)-1;
574 while (bookmark[sl] == '\\' || bookmark[sl] == '/') {
578 if (fsmenu_is_selected(category, i) ) {
579 UI_ThemeColor(TH_HILITE);
580 /* uiSetRoundBox(15);
581 * uiRoundBox(sx, sy - linestep, sx + bmwidth, sy, 4.0f); */
582 glRectf(ar->v2d.cur.xmin, sy-linestep, ar->v2d.cur.xmax + 2*TILE_BORDER_X, sy);
583 UI_ThemeColor(TH_TEXT);
585 UI_ThemeColor(TH_TEXT_HI);
589 ypos = sy - (TILE_BORDER_Y * 0.5);
591 file_draw_icon(xpos, ypos, ICON_FILE_FOLDER, ICON_DEFAULT_WIDTH, ICON_DEFAULT_WIDTH);
592 xpos += ICON_DEFAULT_WIDTH + 4;
593 file_draw_string(xpos, ypos, bookmark, bmwidth, fontsize, FILE_SHORTEN_FRONT);
595 fsmenu_set_pos(category, i, xpos, ypos);
602 void file_draw_fsmenu(const bContext *C, ARegion *ar)
604 int linestep = gFontsize*2.0f;
605 short sy= ar->v2d.cur.ymax-2*TILE_BORDER_Y;
607 file_draw_fsmenu_category(C, ar, FS_CATEGORY_SYSTEM, "SYSTEM", &sy);
609 file_draw_fsmenu_category(C, ar, FS_CATEGORY_BOOKMARKS, "BOOKMARKS", &sy);
611 file_draw_fsmenu_category(C, ar, FS_CATEGORY_RECENT, "RECENT", &sy);