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