2.5 - Start of filebrowser.
[blender-staging.git] / source / blender / editors / space_file / file_ops.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
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. 
10  *
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.
15  *
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.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Andrea Weikert (c) 2008 Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include "BKE_context.h"
30 #include "BKE_screen.h"
31 #include "BKE_global.h"
32
33 #include "BLI_blenlib.h"
34 #include "BLI_storage_types.h"
35 #ifdef WIN32
36 #include "BLI_winstuff.h"
37 #endif
38 #include "DNA_space_types.h"
39 #include "DNA_userdef_types.h"
40
41 #include "ED_space_api.h"
42 #include "ED_screen.h"
43 #include "ED_fileselect.h"
44
45 #include "WM_api.h"
46 #include "WM_types.h"
47
48 #include "file_intern.h"
49 #include "filelist.h"
50 #include "fsmenu.h"
51
52 #include <stdlib.h>
53 #include <string.h>
54 #include <stdio.h>
55
56 /* for events */
57 #define NOTACTIVE                       0
58 #define ACTIVATE                        1
59 #define INACTIVATE                      2
60
61
62 static void set_active_file_thumbs(SpaceFile *sfile, FileSelectParams* params, struct ARegion* ar, short mval[])
63 {
64         float x,y;
65         int active_file = -1;
66         int stridex, stridey;
67         struct direntry* file;
68         int offsetx, offsety;
69         int numfiles = filelist_numfiles(params->files);
70         int columns;
71
72         View2D* v2d = &ar->v2d;
73         UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
74         
75         offsetx = (x - (v2d->cur.xmin+sfile->tile_border_x))/(sfile->tile_w + sfile->tile_border_x);
76         offsety = (-y+sfile->tile_border_y)/(sfile->tile_h + sfile->tile_border_y);
77         columns = (v2d->cur.xmax - v2d->cur.xmin) / (sfile->tile_w+ sfile->tile_border_x);
78
79         printf("tile (%d, %d, %d)\n", offsetx, offsety, columns);
80         active_file = offsetx + columns*offsety;
81
82         if (active_file >= 0 && active_file < numfiles )
83         {
84                 printf("active file: %d\n", active_file);
85                 params->active_file = active_file;
86                 if (params->selstate & ACTIVATE) {
87                         file = filelist_file(params->files, params->active_file);
88                         printf("active file: %s\n", file->relname);
89                         file->flags |= ACTIVE;
90                 }                       
91         }
92 }
93
94
95 static void set_active_file(SpaceFile *sfile, FileSelectParams* params, struct ARegion* ar, short mval[])
96 {
97         int offsetx, offsety;
98         float x,y;
99         int active_file = -1;
100         int numfiles = filelist_numfiles(params->files);
101         int rows;
102         struct direntry* file;
103
104         View2D* v2d = &ar->v2d;
105         UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y);
106         
107         offsetx = (x-sfile->tile_border_x)/(sfile->tile_w + sfile->tile_border_x);
108         offsety = (v2d->cur.ymax-y-sfile->tile_border_y)/(sfile->tile_h + sfile->tile_border_y);
109         rows = (v2d->cur.ymax - v2d->cur.ymin - 2*sfile->tile_border_y) / (sfile->tile_h+sfile->tile_border_y);
110         active_file = rows*offsetx + offsety;
111         printf("offsets (%d, %d)\n", offsetx, offsety);
112         printf("active_file (%d)\n", active_file);
113         if ( (active_file >= 0) && (active_file < numfiles) )
114         {
115                 params->active_file = active_file;
116                 if (params->selstate & ACTIVATE) {
117                         file = filelist_file(params->files, params->active_file);
118                         file->flags |= ACTIVE;
119                 }                       
120         } 
121 }
122
123
124 static void set_active_bookmark(SpaceFile *sfile, FileSelectParams* params, struct ARegion* ar, short y)
125 {
126         int nentries = fsmenu_get_nentries();
127         short posy = ar->v2d.mask.ymax - TILE_BORDER_Y - y;
128         params->active_bookmark = ((float)posy / (U.fontsize*3.0f/2.0f));
129         printf("active bookmark: %d\n", params->active_bookmark);
130         if (params->active_bookmark < 0 || params->active_bookmark > nentries) {
131                 params->active_bookmark = -1;
132         }
133 }
134
135 static void mouse_select(SpaceFile* sfile, FileSelectParams* params, ARegion* ar, short *mval)
136 {
137         int numfiles = filelist_numfiles(params->files);
138         if(mval[0]>ar->v2d.mask.xmin && mval[0]<ar->v2d.mask.xmax
139                 && mval[1]>ar->v2d.mask.ymin && mval[1]<ar->v2d.mask.ymax) {
140                         params->selstate = NOTACTIVE;
141                         if (params->display) {
142                                 set_active_file_thumbs(sfile, params, ar, mval);
143                         } else {
144                                 set_active_file(sfile, params, ar, mval);
145                         }
146                         if (params->active_file >= 0 && params->active_file < numfiles) {
147                                 struct direntry* file = filelist_file(params->files, params->active_file);
148                                 
149                                 if(file && S_ISDIR(file->type)) {
150                                         /* the path is too long and we are not going up! */
151                                         if (strcmp(file->relname, ".") &&
152                                                 strcmp(file->relname, "..") &&
153                                                 strlen(params->dir) + strlen(file->relname) >= FILE_MAX ) 
154                                         {
155                                                 // XXX error("Path too long, cannot enter this directory");
156                                         } else {
157                                                 if (strcmp(file->relname, "..")==0) {
158                                                         /* avoids /../../ */
159                                                         BLI_parent_dir(params->dir);
160                                                 } else {
161                                                         strcat(params->dir, file->relname);
162                                                         strcat(params->dir,"/");
163                                                         params->file[0] = '\0';
164                                                         BLI_cleanup_dir(G.sce, params->dir);
165                                                 }
166                                                 filelist_setdir(params->files, params->dir);
167                                                 filelist_free(params->files);
168                                                 params->active_file = -1;
169                                         }
170                                 }
171                                 else if (file)
172                                 {
173                                         if (file->relname) {
174                                                 BLI_strncpy(params->file, file->relname, FILE_MAXFILE);
175                                                 /* XXX
176                                                 if(event==MIDDLEMOUSE && filelist_gettype(sfile->files)) 
177                                                         imasel_execute(sfile);
178                                                 */
179                                         }
180                                         
181                                 }       
182                                 /* XXX
183                                 if(BIF_filelist_gettype(sfile->files)==FILE_MAIN) {
184                                         active_imasel_object(sfile);
185                                 }
186                                 */
187                         }
188                 }
189 }
190
191 static void mouse_select_bookmark(SpaceFile* sfile, ARegion* ar, short *mval)
192 {
193         if(mval[0]>ar->v2d.mask.xmin && mval[0]<ar->v2d.mask.xmax
194         && mval[1]>ar->v2d.mask.ymin && mval[1]<ar->v2d.mask.ymax) {                    
195                 int nentries = fsmenu_get_nentries();
196                 char *selected;
197                 printf("selecting...\n");
198                 set_active_bookmark(sfile, sfile->params, ar, mval[1]);
199                 selected= fsmenu_get_entry(sfile->params->active_bookmark);                     
200                 /* which string */
201                 if (selected) {
202                         FileSelectParams* params = sfile->params;
203                         BLI_strncpy(params->dir, selected, sizeof(params->dir));
204                         BLI_cleanup_dir(G.sce, params->dir);
205                         filelist_free(params->files);   
206                         filelist_setdir(params->files, params->dir);
207                         params->file[0] = '\0';                 
208                         params->active_file = -1;
209                 }
210         }
211 }
212
213 static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
214 {
215         ScrArea *sa= CTX_wm_area(C);
216         ARegion *ar= CTX_wm_region(C);
217         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
218         short mval[2];
219         
220         /* note; otherwise opengl select won't work. do this for every glSelectBuffer() */
221         wmSubWindowSet(CTX_wm_window(C), ar->swinid);
222         
223         mval[0]= event->x - ar->winrct.xmin;
224         mval[1]= event->y - ar->winrct.ymin;
225         mouse_select(sfile, sfile->params, ar, mval);
226         WM_event_add_notifier(C, NC_WINDOW, 0, NULL);
227         return OPERATOR_FINISHED;
228 }
229
230
231 void ED_FILE_OT_select(wmOperatorType *ot)
232 {
233         /* identifiers */
234         ot->name= "Activate/Select File";
235         ot->idname= "ED_FILE_OT_select";
236         
237         /* api callbacks */
238         ot->invoke= file_select_invoke;
239         ot->poll= ED_operator_file_active;
240 }
241
242
243 static int bookmark_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
244 {
245         ScrArea *sa= CTX_wm_area(C);
246         ARegion *ar= CTX_wm_region(C);
247         SpaceFile *sfile= (SpaceFile*)CTX_wm_space_data(C);
248         short mval[2];
249         
250         /* note; otherwise opengl select won't work. do this for every glSelectBuffer() */
251         wmSubWindowSet(CTX_wm_window(C), ar->swinid);
252         
253         mval[0]= event->x - ar->winrct.xmin;
254         mval[1]= event->y - ar->winrct.ymin;
255         mouse_select_bookmark(sfile, ar, mval);
256         ED_area_tag_redraw(sa);
257         return OPERATOR_FINISHED;
258 }
259
260 void ED_FILE_OT_select_bookmark(wmOperatorType *ot)
261 {
262         /* identifiers */
263         ot->name= "Select Directory";
264         ot->idname= "ED_FILE_OT_select_bookmark";
265         
266         /* api callbacks */
267         ot->invoke= bookmark_select_invoke;
268         ot->poll= ED_operator_file_active;
269 }