svn merge -r 21041:21301 https://svn.blender.org/svnroot/bf-blender/branches/blender2...
[blender.git] / source / blender / editors / space_file / file_ops.c
index 4725014a4b1db55f8eb157b494636d44100c0d3f..aaa1793efbb4782c7d3d7e06e3bca6379b346506 100644 (file)
@@ -42,6 +42,8 @@
 #include "ED_screen.h"
 #include "ED_fileselect.h"
 
+#include "MEM_guardedalloc.h"
+
 #include "RNA_access.h"
 #include "RNA_define.h"
 
@@ -66,7 +68,7 @@
 
 /* ---------- FILE SELECTION ------------ */
 
-static int find_file_mouse_hor(SpaceFile *sfile, struct ARegion* ar, short x, short y)
+static int find_file_mouse(SpaceFile *sfile, struct ARegion* ar, short x, short y, short clamp)
 {
        float fx,fy;
        int active_file = -1;
@@ -77,33 +79,19 @@ static int find_file_mouse_hor(SpaceFile *sfile, struct ARegion* ar, short x, sh
 
        active_file = ED_fileselect_layout_offset(sfile->layout, v2d->tot.xmin + fx, v2d->tot.ymax - fy);
 
-       printf("FINDFILE %d\n", active_file);
-       if ( (active_file < 0) || (active_file >= numfiles) )
-       {
-               active_file = -1;
+       if(active_file < 0) {
+               if(clamp)       active_file=  0;
+               else            active_file= -1;
        }
-       return active_file;
-}
-
-
-static int find_file_mouse_vert(SpaceFile *sfile, struct ARegion* ar, short x, short y)
-{
-       float fx,fy;
-       int active_file = -1;
-       int numfiles = filelist_numfiles(sfile->files);
-       View2D* v2d = &ar->v2d;
-
-       UI_view2d_region_to_view(v2d, x, y, &fx, &fy);
-       
-       active_file = ED_fileselect_layout_offset(sfile->layout, v2d->tot.xmin + fx, v2d->tot.ymax - fy);
-
-       if ( (active_file < 0) || (active_file >= numfiles) )
-       {
-               active_file = -1;
+       else if(active_file >= numfiles) {
+               if(clamp)       active_file=  numfiles-1;
+               else            active_file= -1;
        }
+       
        return active_file;
 }
 
+
 static void file_deselect_all(SpaceFile* sfile)
 {
        int numfiles = filelist_numfiles(sfile->files);
@@ -117,23 +105,20 @@ static void file_deselect_all(SpaceFile* sfile)
        }
 }
 
-static void file_select(SpaceFile* sfile, FileSelectParams* params, ARegion* ar, const rcti* rect, short val)
+static void file_select(SpaceFile* sfile, ARegion* ar, const rcti* rect, short val)
 {
        int first_file = -1;
        int last_file = -1;
        int act_file;
        short selecting = (val == LEFTMOUSE);
+       FileSelectParams *params = ED_fileselect_get_params(sfile);
+       // FileLayout *layout = ED_fileselect_get_layout(sfile, ar);
 
        int numfiles = filelist_numfiles(sfile->files);
 
        params->selstate = NOTACTIVE;
-       if  ( (params->display == FILE_IMGDISPLAY) || (params->display == FILE_LONGDISPLAY) ) {
-               first_file = find_file_mouse_hor(sfile, ar, rect->xmin, rect->ymax);
-               last_file = find_file_mouse_hor(sfile, ar, rect->xmax, rect->ymin);
-       } else {
-               first_file = find_file_mouse_vert(sfile, ar, rect->xmin, rect->ymax);
-               last_file = find_file_mouse_vert(sfile, ar, rect->xmax, rect->ymin);
-       }
+       first_file = find_file_mouse(sfile, ar, rect->xmin, rect->ymax, 1);
+       last_file = find_file_mouse(sfile, ar, rect->xmax, rect->ymin, 1);
        
        /* select all valid files between first and last indicated */
        if ( (first_file >= 0) && (first_file < numfiles) && (last_file >= 0) && (last_file < numfiles) ) {
@@ -145,31 +130,22 @@ static void file_select(SpaceFile* sfile, FileSelectParams* params, ARegion* ar,
                                file->flags &= ~ACTIVE;
                }
        }
-       
-       printf("Selecting %d %d\n", first_file, last_file);
 
        /* make the last file active */
-       if (last_file >= 0 && last_file < numfiles) {
+       if (selecting && (last_file >= 0 && last_file < numfiles)) {
                struct direntry* file = filelist_file(sfile->files, last_file);
                params->active_file = last_file;
 
                if(file && S_ISDIR(file->type)) {
-                       /* the path is too long and we are not going up! */
-                       if (strcmp(file->relname, ".") &&
-                               strcmp(file->relname, "..") &&
-                               strlen(params->dir) + strlen(file->relname) >= FILE_MAX ) 
+                       /* the path is too long! */
+                       if (strlen(params->dir) + strlen(file->relname) >= FILE_MAX ) 
                        {
                                // XXX error("Path too long, cannot enter this directory");
                        } else {
-                               if (strcmp(file->relname, "..")==0) {
-                                       /* avoids /../../ */
-                                       BLI_parent_dir(params->dir);
-                               } else {
-                                       strcat(params->dir, file->relname);
-                                       strcat(params->dir,"/");
-                                       params->file[0] = '\0';
-                                       BLI_cleanup_dir(G.sce, params->dir);
-                               }
+                               strcat(params->dir, file->relname);
+                               strcat(params->dir,"/");
+                               params->file[0] = '\0';
+                               BLI_cleanup_dir(G.sce, params->dir);
                                filelist_setdir(sfile->files, params->dir);
                                filelist_free(sfile->files);
                                params->active_file = -1;
@@ -209,16 +185,18 @@ static int file_border_select_exec(bContext *C, wmOperator *op)
        rect.xmax= RNA_int_get(op->ptr, "xmax");
        rect.ymax= RNA_int_get(op->ptr, "ymax");
 
-       file_select(sfile, sfile->params, ar, &rect, val );
+       BLI_isect_rcti(&(ar->v2d.mask), &rect, &rect);
+       
+       file_select(sfile, ar, &rect, val );
        WM_event_add_notifier(C, NC_WINDOW, NULL);
        return OPERATOR_FINISHED;
 }
 
-void FILE_OT_border_select(wmOperatorType *ot)
+void FILE_OT_select_border(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Activate/Select File";
-       ot->idname= "FILE_OT_border_select";
+       ot->idname= "FILE_OT_select_border";
        
        /* api callbacks */
        ot->invoke= WM_border_select_invoke;
@@ -250,8 +228,8 @@ static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
                /* single select, deselect all selected first */
                file_deselect_all(sfile);
-               file_select(sfile, sfile->params, ar, &rect, val );
-               WM_event_add_notifier(C, NC_WINDOW, NULL);
+               file_select(sfile, ar, &rect, val );
+               WM_event_add_notifier(C, NC_FILE|ND_PARAMS, NULL);
        }
        return OPERATOR_FINISHED;
 }
@@ -300,11 +278,11 @@ static int file_select_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
        return OPERATOR_FINISHED;
 }
 
-void FILE_OT_select_all(wmOperatorType *ot)
+void FILE_OT_select_all_toggle(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Select/Deselect all files";
-       ot->idname= "FILE_OT_select_all";
+       ot->idname= "FILE_OT_select_all_toggle";
        
        /* api callbacks */
        ot->invoke= file_select_all_invoke;
@@ -316,105 +294,106 @@ void FILE_OT_select_all(wmOperatorType *ot)
 
 /* ---------- BOOKMARKS ----------- */
 
-static void set_active_bookmark(FileSelectParams* params, struct ARegion* ar, short x, short y)
+static int bookmark_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-       int nentries = fsmenu_get_nentries(FS_CATEGORY_BOOKMARKS);
-       float fx, fy;
-       short posy;
+       SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
 
-       UI_view2d_region_to_view(&ar->v2d, x, y, &fx, &fy);
+       if(RNA_struct_find_property(op->ptr, "dir")) {
+               char entry[256];
+               FileSelectParams* params = sfile->params;
 
-       posy = ar->v2d.cur.ymax - 2*TILE_BORDER_Y - fy;
-       posy -= U.fontsize*2.0f;        /* header */
-       
-       params->active_bookmark = ((float)posy / (U.fontsize*2.0f));
-       if (params->active_bookmark < 0 || params->active_bookmark > nentries) {
-               params->active_bookmark = -1;
+               RNA_string_get(op->ptr, "dir", entry);
+               BLI_strncpy(params->dir, entry, sizeof(params->dir));
+               BLI_cleanup_dir(G.sce, params->dir);
+               filelist_free(sfile->files);    
+               filelist_setdir(sfile->files, params->dir);
+               params->file[0] = '\0';                 
+               params->active_file = -1;
+
+               WM_event_add_notifier(C, NC_FILE|ND_PARAMS, NULL);
        }
+       
+       return OPERATOR_FINISHED;
 }
 
-static int file_select_bookmark_category(SpaceFile* sfile, ARegion* ar, short x, short y, FSMenuCategory category)
+void FILE_OT_select_bookmark(wmOperatorType *ot)
 {
-       int nentries = fsmenu_get_nentries(category);
-       int linestep = U.fontsize*2.0f;
-       short xs, ys;
-       int i;
-       int selected = -1;
+       /* identifiers */
+       ot->name= "Select Directory";
+       ot->idname= "FILE_OT_select_bookmark";
+       
+       /* api callbacks */
+       ot->invoke= bookmark_select_invoke;
+       ot->poll= ED_operator_file_active;
 
-       for (i=0; i < nentries; ++i) {
-               fsmenu_get_pos(category, i, &xs, &ys);
-               if ( (y<=ys) && (y>ys-linestep) ) {
-                       fsmenu_select_entry(category, i);
-                       selected = i;
-                       break;
-               }
-       }
-       return selected;
+       RNA_def_string(ot->srna, "dir", "", 256, "Dir", "");
 }
 
-static void file_select_bookmark(SpaceFile* sfile, ARegion* ar, short x, short y)
+static int bookmark_add_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
-       float fx, fy;
-       int selected;
-       FSMenuCategory category = FS_CATEGORY_SYSTEM;
-
-       if (BLI_in_rcti(&ar->v2d.mask, x, y)) {
-               char *entry;
+       ScrArea *sa= CTX_wm_area(C);
+       SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+       struct FSMenu* fsmenu = fsmenu_get();
+       struct FileSelectParams* params= ED_fileselect_get_params(sfile);
 
-               UI_view2d_region_to_view(&ar->v2d, x, y, &fx, &fy);
-               selected = file_select_bookmark_category(sfile, ar, fx, fy, FS_CATEGORY_SYSTEM);
-               if (selected<0) {
-                       category = FS_CATEGORY_BOOKMARKS;
-                       selected = file_select_bookmark_category(sfile, ar, fx, fy, category);
-               }
-               if (selected<0) {
-                       category = FS_CATEGORY_RECENT;
-                       selected = file_select_bookmark_category(sfile, ar, fx, fy, category);
-               }
-               
-               if (selected>=0) {
-                       entry= fsmenu_get_entry(category, selected);                    
-                       /* which string */
-                       if (entry) {
-                               FileSelectParams* params = sfile->params;
-                               BLI_strncpy(params->dir, entry, sizeof(params->dir));
-                               BLI_cleanup_dir(G.sce, params->dir);
-                               filelist_free(sfile->files);    
-                               filelist_setdir(sfile->files, params->dir);
-                               params->file[0] = '\0';                 
-                               params->active_file = -1;
-                       }
-               }
+       if (params->dir[0] != '\0') {
+               char name[FILE_MAX];
+       
+               fsmenu_insert_entry(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir, 0, 1);
+               BLI_make_file_string("/", name, BLI_gethome(), ".Bfs");
+               fsmenu_write_file(fsmenu, name);
        }
+
+       ED_area_tag_redraw(sa);
+       return OPERATOR_FINISHED;
 }
 
-static int bookmark_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+void FILE_OT_add_bookmark(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Add Bookmark";
+       ot->idname= "FILE_OT_add_bookmark";
+       
+       /* api callbacks */
+       ot->invoke= bookmark_add_invoke;
+       ot->poll= ED_operator_file_active;
+}
+
+static int bookmark_delete_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        ScrArea *sa= CTX_wm_area(C);
-       ARegion *ar= CTX_wm_region(C);  
        SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+       struct FSMenu* fsmenu = fsmenu_get();
+       int nentries = fsmenu_get_nentries(fsmenu, FS_CATEGORY_BOOKMARKS);
+       if(RNA_struct_find_property(op->ptr, "index")) {
+               int index = RNA_int_get(op->ptr, "index");
+               if ( (index >-1) && (index < nentries)) {
+                       char name[FILE_MAX];
+                       
+                       fsmenu_remove_entry(fsmenu, FS_CATEGORY_BOOKMARKS, index);
+                       BLI_make_file_string("/", name, BLI_gethome(), ".Bfs");
+                       fsmenu_write_file(fsmenu, name);
+                       ED_area_tag_redraw(sa);
+               }
+       }
 
-       short x, y;
-
-       x = event->x - ar->winrct.xmin;
-       y = event->y - ar->winrct.ymin;
-
-       file_select_bookmark(sfile, ar, x, y);
-       ED_area_tag_redraw(sa);
        return OPERATOR_FINISHED;
 }
 
-void FILE_OT_select_bookmark(wmOperatorType *ot)
+void FILE_OT_delete_bookmark(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Select Directory";
-       ot->idname= "FILE_OT_select_bookmark";
+       ot->name= "Delete Bookmark";
+       ot->idname= "FILE_OT_delete_bookmark";
        
        /* api callbacks */
-       ot->invoke= bookmark_select_invoke;
+       ot->invoke= bookmark_delete_invoke;
        ot->poll= ED_operator_file_active;
+
+       RNA_def_int(ot->srna, "index", -1, -1, 20000, "Index", "", -1, 20000);
 }
 
+
 static int loadimages_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        ScrArea *sa= CTX_wm_area(C);
@@ -451,17 +430,14 @@ int file_hilight_set(SpaceFile *sfile, ARegion *ar, int mx, int my)
        
        numfiles = filelist_numfiles(sfile->files);
        params = ED_fileselect_get_params(sfile);
+
+       actfile = find_file_mouse(sfile, ar, mx , my, 0);
        
-       if ( (params->display == FILE_IMGDISPLAY) || (params->display == FILE_LONGDISPLAY)) {
-               actfile = find_file_mouse_hor(sfile, ar, mx , my);
-       } else {
-               actfile = find_file_mouse_vert(sfile, ar, mx, my);
-       }
-       
-       if (actfile >= 0 && actfile < numfiles ) {
+       if (params && (actfile >= 0) && (actfile < numfiles) ) {
                params->active_file=actfile;
                return 1;
-       }
+       } 
+       params->active_file= -1;
        return 0;
 }
 
@@ -523,6 +499,39 @@ int file_exec(bContext *C, wmOperator *unused)
                strcat(name, sfile->params->file);
                RNA_string_set(op->ptr, "filename", name);
                
+               /* some ops have multiple files to select */
+               {
+                       PointerRNA itemptr;
+                       int i, numfiles = filelist_numfiles(sfile->files);
+                       struct direntry *file;
+                       if(RNA_struct_find_property(op->ptr, "files")) {
+                               for (i=0; i<numfiles; i++) {
+                                       file = filelist_file(sfile->files, i);
+                                       if(file->flags & ACTIVE) {
+                                               if ((file->type & S_IFDIR)==0) {
+                                                       RNA_collection_add(op->ptr, "files", &itemptr);
+                                                       RNA_string_set(&itemptr, "name", file->relname);
+                                               }
+                                       }
+                               }
+                       }
+                       
+                       if(RNA_struct_find_property(op->ptr, "dirs")) {
+                               for (i=0; i<numfiles; i++) {
+                                       file = filelist_file(sfile->files, i);
+                                       if(file->flags & ACTIVE) {
+                                               if ((file->type & S_IFDIR)) {
+                                                       RNA_collection_add(op->ptr, "dirs", &itemptr);
+                                                       RNA_string_set(&itemptr, "name", file->relname);
+                                               }
+                                       }
+                               }
+                       }
+               }
+               
+               fsmenu_insert_entry(fsmenu_get(), FS_CATEGORY_RECENT, sfile->params->dir,0, 1);
+               BLI_make_file_string(G.sce, name, BLI_gethome(), ".Bfs");
+               fsmenu_write_file(fsmenu_get(), name);
                WM_event_fileselect_event(C, op, EVT_FILESELECT_EXEC);
        }
                                
@@ -551,7 +560,7 @@ int file_parent_exec(bContext *C, wmOperator *unused)
                filelist_free(sfile->files);
                sfile->params->active_file = -1;
        }               
-       ED_area_tag_redraw(CTX_wm_area(C));
+       WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL);
 
        return OPERATOR_FINISHED;
 
@@ -578,8 +587,8 @@ int file_refresh_exec(bContext *C, wmOperator *unused)
                filelist_setdir(sfile->files, sfile->params->dir);
                filelist_free(sfile->files);
                sfile->params->active_file = -1;
-       }               
-       ED_area_tag_redraw(CTX_wm_area(C));
+       }
+       WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL);
 
        return OPERATOR_FINISHED;
 
@@ -597,14 +606,58 @@ void FILE_OT_refresh(struct wmOperatorType *ot)
        ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
 }
 
+int file_hidedot_exec(bContext *C, wmOperator *unused)
+{
+       SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
+       
+       if(sfile->params) {
+               sfile->params->flag ^= FILE_HIDE_DOT;
+               filelist_free(sfile->files);
+               sfile->params->active_file = -1;
+               WM_event_add_notifier(C, NC_FILE|ND_FILELIST, NULL);
+       }
+       
+       return OPERATOR_FINISHED;
+
+}
+
+
+void FILE_OT_hidedot(struct wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Toggle Hide Dot Files";
+       ot->idname= "FILE_OT_hidedot";
+       
+       /* api callbacks */
+       ot->exec= file_hidedot_exec;
+       ot->poll= ED_operator_file_active; /* <- important, handler is on window level */
+}
+
 struct ARegion *file_buttons_region(struct ScrArea *sa)
 {
-       ARegion *ar;
+       ARegion *ar, *arnew;
        
        for(ar= sa->regionbase.first; ar; ar= ar->next)
                if(ar->regiontype==RGN_TYPE_CHANNELS)
                        return ar;
-       return NULL;
+
+       /* add subdiv level; after header */
+       for(ar= sa->regionbase.first; ar; ar= ar->next)
+               if(ar->regiontype==RGN_TYPE_HEADER)
+                       break;
+       
+       /* is error! */
+       if(ar==NULL) return NULL;
+       
+       arnew= MEM_callocN(sizeof(ARegion), "buttons for file panels");
+       
+       BLI_insertlinkafter(&sa->regionbase, ar, arnew);
+       arnew->regiontype= RGN_TYPE_CHANNELS;
+       arnew->alignment= RGN_ALIGN_LEFT;
+       
+       arnew->flag = RGN_FLAG_HIDDEN;
+       
+       return arnew;
 }
 
 int file_bookmark_toggle_exec(bContext *C, wmOperator *unused)