FileBrowser: Editable Bookmarks.
[blender-staging.git] / source / blender / editors / space_file / space_file.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2008 Blender Foundation.
19  * All rights reserved.
20  *
21  * 
22  * Contributor(s): Blender Foundation
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/editors/space_file/space_file.c
28  *  \ingroup spfile
29  */
30
31 #include <string.h>
32 #include <stdio.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BIF_gl.h"
37
38 #include "BLI_blenlib.h"
39 #include "BLI_utildefines.h"
40 #include "BLI_fileops_types.h"
41
42
43 #include "BKE_appdir.h"
44 #include "BKE_context.h"
45 #include "BKE_screen.h"
46 #include "BKE_global.h"
47
48 #include "RNA_access.h"
49
50 #include "WM_api.h"
51 #include "WM_types.h"
52
53 #include "ED_space_api.h"
54 #include "ED_screen.h"
55 #include "ED_fileselect.h"
56
57 #include "IMB_imbuf_types.h"
58 #include "IMB_thumbs.h"
59
60 #include "UI_resources.h"
61 #include "UI_view2d.h"
62
63
64 #include "file_intern.h"    // own include
65 #include "fsmenu.h"
66 #include "filelist.h"
67
68 /* ******************** default callbacks for file space ***************** */
69
70 static SpaceLink *file_new(const bContext *UNUSED(C))
71 {
72         ARegion *ar;
73         SpaceFile *sfile;
74
75         sfile = MEM_callocN(sizeof(SpaceFile), "initfile");
76         sfile->spacetype = SPACE_FILE;
77
78         /* header */
79         ar = MEM_callocN(sizeof(ARegion), "header for file");
80         BLI_addtail(&sfile->regionbase, ar);
81         ar->regiontype = RGN_TYPE_HEADER;
82         ar->alignment = RGN_ALIGN_TOP;
83
84         /* Tools region */
85         ar = MEM_callocN(sizeof(ARegion), "tools area for file");
86         BLI_addtail(&sfile->regionbase, ar);
87         ar->regiontype = RGN_TYPE_TOOLS;
88         ar->alignment = RGN_ALIGN_LEFT;
89
90         /* Tool props (aka operator) region */
91         ar = MEM_callocN(sizeof(ARegion), "tool props area for file");
92         BLI_addtail(&sfile->regionbase, ar);
93         ar->regiontype = RGN_TYPE_TOOL_PROPS;
94         ar->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV;
95
96         /* ui list region */
97         ar = MEM_callocN(sizeof(ARegion), "ui area for file");
98         BLI_addtail(&sfile->regionbase, ar);
99         ar->regiontype = RGN_TYPE_UI;
100         ar->alignment = RGN_ALIGN_TOP;
101
102         /* main area */
103         ar = MEM_callocN(sizeof(ARegion), "main area for file");
104         BLI_addtail(&sfile->regionbase, ar);
105         ar->regiontype = RGN_TYPE_WINDOW;
106         ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
107         ar->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
108         ar->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
109         ar->v2d.keeptot = V2D_KEEPTOT_STRICT;
110         ar->v2d.minzoom = ar->v2d.maxzoom = 1.0f;
111
112         return (SpaceLink *)sfile;
113 }
114
115 /* not spacelink itself */
116 static void file_free(SpaceLink *sl)
117 {       
118         SpaceFile *sfile = (SpaceFile *) sl;
119         
120         if (sfile->files) {
121                 // XXXXX would need to do thumbnails_stop here, but no context available
122                 filelist_freelib(sfile->files);
123                 filelist_free(sfile->files);
124                 MEM_freeN(sfile->files);
125                 sfile->files = NULL;
126         }
127
128         if (sfile->folders_prev) {
129                 folderlist_free(sfile->folders_prev);
130                 MEM_freeN(sfile->folders_prev);
131                 sfile->folders_prev = NULL;
132         }
133
134         if (sfile->folders_next) {
135                 folderlist_free(sfile->folders_next);
136                 MEM_freeN(sfile->folders_next);
137                 sfile->folders_next = NULL;
138         }
139
140         if (sfile->params) {
141                 MEM_freeN(sfile->params);
142                 sfile->params = NULL;
143         }
144
145         if (sfile->layout) {
146                 MEM_freeN(sfile->layout);
147                 sfile->layout = NULL;
148         }
149 }
150
151
152 /* spacetype; init callback, area size changes, screen set, etc */
153 static void file_init(wmWindowManager *UNUSED(wm), ScrArea *sa)
154 {
155         SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
156
157         /* refresh system directory list */
158         fsmenu_refresh_system_category(ED_fsmenu_get());
159
160         if (sfile->layout) sfile->layout->dirty = true;
161 }
162
163 static void file_exit(wmWindowManager *wm, ScrArea *sa)
164 {
165         SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
166
167         ED_fileselect_exit(wm, sfile);
168 }
169
170 static SpaceLink *file_duplicate(SpaceLink *sl)
171 {
172         SpaceFile *sfileo = (SpaceFile *)sl;
173         SpaceFile *sfilen = MEM_dupallocN(sl);
174         
175         /* clear or remove stuff from old */
176         sfilen->op = NULL; /* file window doesn't own operators */
177
178         if (sfileo->params) {
179                 sfilen->files = filelist_new(sfileo->params->type);
180                 sfilen->params = MEM_dupallocN(sfileo->params);
181                 filelist_setdir(sfilen->files, sfilen->params->dir);
182         }
183
184         if (sfileo->folders_prev)
185                 sfilen->folders_prev = folderlist_duplicate(sfileo->folders_prev);
186
187         if (sfileo->folders_next)
188                 sfilen->folders_next = folderlist_duplicate(sfileo->folders_next);
189         
190         if (sfileo->layout) {
191                 sfilen->layout = MEM_dupallocN(sfileo->layout);
192         }
193         return (SpaceLink *)sfilen;
194 }
195
196 static void file_refresh(const bContext *C, ScrArea *sa)
197 {
198         wmWindowManager *wm = CTX_wm_manager(C);
199         SpaceFile *sfile = CTX_wm_space_file(C);
200         FileSelectParams *params = ED_fileselect_get_params(sfile);
201         struct FSMenu *fsmenu = ED_fsmenu_get();
202
203         if (!sfile->folders_prev) {
204                 sfile->folders_prev = folderlist_new();
205         }
206         if (!sfile->files) {
207                 sfile->files = filelist_new(params->type);
208                 filelist_setdir(sfile->files, params->dir);
209                 params->active_file = -1; /* added this so it opens nicer (ton) */
210         }
211         filelist_setsorting(sfile->files, params->sort);
212         filelist_setfilter_options(sfile->files, params->flag & FILE_HIDE_DOT,
213                                                  false, /* TODO hide_parent, should be controllable? */
214                                                  params->flag & FILE_FILTER ? params->filter : 0,
215                                                  params->filter_glob,
216                                                  params->filter_search);
217
218         /* Update the active indices of bookmarks & co. */
219         sfile->systemnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_SYSTEM, params->dir);
220         sfile->system_bookmarknr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, params->dir);
221         sfile->bookmarknr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_BOOKMARKS, params->dir);
222         sfile->recentnr = fsmenu_get_active_indices(fsmenu, FS_CATEGORY_RECENT, params->dir);
223
224         if (filelist_empty(sfile->files)) {
225                 thumbnails_stop(wm, sfile->files);
226                 filelist_readdir(sfile->files);
227                 filelist_sort(sfile->files);
228                 BLI_strncpy(params->dir, filelist_dir(sfile->files), FILE_MAX);
229         }
230         else if (filelist_need_sorting(sfile->files)) {
231                 thumbnails_stop(wm, sfile->files);
232                 filelist_sort(sfile->files);
233         }
234
235         if ((params->display == FILE_IMGDISPLAY) && filelist_need_thumbnails(sfile->files)) {
236                 if (!thumbnails_running(wm, sfile->files)) {
237                         thumbnails_start(sfile->files, C);
238                 }
239         }
240         else {
241                 /* stop any running thumbnail jobs if we're not displaying them - speedup for NFS */
242                 thumbnails_stop(wm, sfile->files);
243         }
244
245         filelist_filter(sfile->files);
246
247         if (params->renamefile[0] != '\0') {
248                 int idx = filelist_find(sfile->files, params->renamefile);
249                 if (idx >= 0) {
250                         struct direntry *file = filelist_file(sfile->files, idx);
251                         if (file) {
252                                 file->selflag |= FILE_SEL_EDITING;
253                         }
254                 }
255                 BLI_strncpy(sfile->params->renameedit, sfile->params->renamefile, sizeof(sfile->params->renameedit));
256                 params->renamefile[0] = '\0';
257         }
258
259         if (sfile->layout) {
260                 sfile->layout->dirty = true;
261         }
262
263         if (BKE_area_find_region_type(sa, RGN_TYPE_TOOLS) == NULL) {
264                 /* Create TOOLS/TOOL_PROPS regions. */
265                 file_tools_region(sa);
266
267                 ED_area_initialize(wm, CTX_wm_window(C), sa);
268                 ED_area_tag_redraw(sa);
269         }
270 }
271
272 static void file_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
273 {
274         /* SpaceFile *sfile = (SpaceFile *)sa->spacedata.first; */
275
276         /* context changes */
277         switch (wmn->category) {
278                 case NC_SPACE:
279                         switch (wmn->data) {
280                                 case ND_SPACE_FILE_LIST:
281                                         ED_area_tag_refresh(sa);
282                                         ED_area_tag_redraw(sa);
283                                         break;
284                                 case ND_SPACE_FILE_PARAMS:
285                                         ED_area_tag_refresh(sa);
286                                         ED_area_tag_redraw(sa);
287                                         break;
288                         }
289                         break;
290         }
291 }
292
293 /* add handlers, stuff you only do once or on area/region changes */
294 static void file_main_area_init(wmWindowManager *wm, ARegion *ar)
295 {
296         wmKeyMap *keymap;
297         
298         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
299         
300         /* own keymaps */
301         keymap = WM_keymap_find(wm->defaultconf, "File Browser", SPACE_FILE, 0);
302         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
303
304         keymap = WM_keymap_find(wm->defaultconf, "File Browser Main", SPACE_FILE, 0);
305         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
306 }
307
308 static void file_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
309 {
310         /* context changes */
311         switch (wmn->category) {
312                 case NC_SPACE:
313                         switch (wmn->data) {
314                                 case ND_SPACE_FILE_LIST:
315                                         ED_region_tag_redraw(ar);
316                                         break;
317                                 case ND_SPACE_FILE_PARAMS:
318                                         ED_region_tag_redraw(ar);
319                                         break;
320                         }
321                         break;
322         }
323 }
324
325 static void file_main_area_draw(const bContext *C, ARegion *ar)
326 {
327         /* draw entirely, view changes should be handled here */
328         SpaceFile *sfile = CTX_wm_space_file(C);
329         FileSelectParams *params = ED_fileselect_get_params(sfile);
330
331         View2D *v2d = &ar->v2d;
332         View2DScrollers *scrollers;
333         float col[3];
334
335         /* Needed, because filelist is not initialized on loading */
336         if (!sfile->files || filelist_empty(sfile->files))
337                 file_refresh(C, NULL);
338
339         /* clear and setup matrix */
340         UI_GetThemeColor3fv(TH_BACK, col);
341         glClearColor(col[0], col[1], col[2], 0.0);
342         glClear(GL_COLOR_BUFFER_BIT);
343         
344         /* Allow dynamically sliders to be set, saves notifiers etc. */
345         
346         if (params->display == FILE_IMGDISPLAY) {
347                 v2d->scroll = V2D_SCROLL_RIGHT;
348                 v2d->keepofs &= ~V2D_LOCKOFS_Y;
349                 v2d->keepofs |= V2D_LOCKOFS_X;
350         }
351         else {
352                 v2d->scroll = V2D_SCROLL_BOTTOM;
353                 v2d->keepofs &= ~V2D_LOCKOFS_X;
354                 v2d->keepofs |= V2D_LOCKOFS_Y;
355                 
356                 /* XXX this happens on scaling down Screen (like from startup.blend) */
357                 /* view2d has no type specific for filewindow case, which doesnt scroll vertically */
358                 if (v2d->cur.ymax < 0) {
359                         v2d->cur.ymin -= v2d->cur.ymax;
360                         v2d->cur.ymax = 0;
361                 }
362         }
363         /* v2d has initialized flag, so this call will only set the mask correct */
364         UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
365
366         /* sets tile/border settings in sfile */
367         file_calc_previews(C, ar);
368
369         /* set view */
370         UI_view2d_view_ortho(v2d);
371         
372         /* on first read, find active file */
373         if (params->active_file == -1) {
374                 wmEvent *event = CTX_wm_window(C)->eventstate;
375                 file_highlight_set(sfile, ar, event->x, event->y);
376         }
377         
378         file_draw_list(C, ar);
379         
380         /* reset view matrix */
381         UI_view2d_view_restore(C);
382         
383         /* scrollers */
384         scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
385         UI_view2d_scrollers_draw(C, v2d, scrollers);
386         UI_view2d_scrollers_free(scrollers);
387
388 }
389
390 static void file_operatortypes(void)
391 {
392         WM_operatortype_append(FILE_OT_select);
393         WM_operatortype_append(FILE_OT_select_all_toggle);
394         WM_operatortype_append(FILE_OT_select_border);
395         WM_operatortype_append(FILE_OT_select_bookmark);
396         WM_operatortype_append(FILE_OT_highlight);
397         WM_operatortype_append(FILE_OT_execute);
398         WM_operatortype_append(FILE_OT_cancel);
399         WM_operatortype_append(FILE_OT_parent);
400         WM_operatortype_append(FILE_OT_previous);
401         WM_operatortype_append(FILE_OT_next);
402         WM_operatortype_append(FILE_OT_refresh);
403         WM_operatortype_append(FILE_OT_bookmark_toggle);
404         WM_operatortype_append(FILE_OT_bookmark_add);
405         WM_operatortype_append(FILE_OT_bookmark_delete);
406         WM_operatortype_append(FILE_OT_bookmark_move);
407         WM_operatortype_append(FILE_OT_reset_recent);
408         WM_operatortype_append(FILE_OT_hidedot);
409         WM_operatortype_append(FILE_OT_filenum);
410         WM_operatortype_append(FILE_OT_directory_new);
411         WM_operatortype_append(FILE_OT_delete);
412         WM_operatortype_append(FILE_OT_rename);
413         WM_operatortype_append(FILE_OT_smoothscroll);
414 }
415
416 /* NOTE: do not add .blend file reading on this level */
417 static void file_keymap(struct wmKeyConfig *keyconf)
418 {
419         wmKeyMapItem *kmi;
420         /* keys for all areas */
421         wmKeyMap *keymap = WM_keymap_find(keyconf, "File Browser", SPACE_FILE, 0);
422         WM_keymap_add_item(keymap, "FILE_OT_bookmark_toggle", TKEY, KM_PRESS, 0, 0);
423         WM_keymap_add_item(keymap, "FILE_OT_parent", PKEY, KM_PRESS, 0, 0);
424         WM_keymap_add_item(keymap, "FILE_OT_bookmark_add", BKEY, KM_PRESS, KM_CTRL, 0);
425         WM_keymap_add_item(keymap, "FILE_OT_hidedot", HKEY, KM_PRESS, 0, 0);
426         WM_keymap_add_item(keymap, "FILE_OT_previous", BACKSPACEKEY, KM_PRESS, 0, 0);
427         WM_keymap_add_item(keymap, "FILE_OT_next", BACKSPACEKEY, KM_PRESS, KM_SHIFT, 0);
428         WM_keymap_add_item(keymap, "FILE_OT_directory_new", IKEY, KM_PRESS, 0, 0);
429         WM_keymap_add_item(keymap, "FILE_OT_delete", XKEY, KM_PRESS, 0, 0);
430         WM_keymap_add_item(keymap, "FILE_OT_delete", DELKEY, KM_PRESS, 0, 0);
431         WM_keymap_verify_item(keymap, "FILE_OT_smoothscroll", TIMER1, KM_ANY, KM_ANY, 0);
432
433         /* keys for main area */
434         keymap = WM_keymap_find(keyconf, "File Browser Main", SPACE_FILE, 0);
435         kmi = WM_keymap_add_item(keymap, "FILE_OT_execute", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
436         RNA_boolean_set(kmi->ptr, "need_active", true);
437
438         /* left mouse selects and opens */
439         WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, 0, 0);
440         kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_SHIFT, 0);
441         RNA_boolean_set(kmi->ptr, "extend", true);
442         kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_CTRL | KM_SHIFT, 0);
443         RNA_boolean_set(kmi->ptr, "extend", true);
444         RNA_boolean_set(kmi->ptr, "fill", true);
445
446         /* right mouse selects without opening */
447         kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, 0, 0);
448         RNA_boolean_set(kmi->ptr, "open", false);
449         kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, KM_SHIFT, 0);
450         RNA_boolean_set(kmi->ptr, "extend", true);
451         RNA_boolean_set(kmi->ptr, "open", false);
452         kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, KM_ALT, 0);
453         RNA_boolean_set(kmi->ptr, "extend", true);
454         RNA_boolean_set(kmi->ptr, "fill", true);
455         RNA_boolean_set(kmi->ptr, "open", false);
456
457         /* front and back mouse folder navigation */
458         WM_keymap_add_item(keymap, "FILE_OT_previous", BUTTON4MOUSE, KM_CLICK, 0, 0);
459         WM_keymap_add_item(keymap, "FILE_OT_next", BUTTON5MOUSE, KM_CLICK, 0, 0);
460
461         WM_keymap_add_item(keymap, "FILE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
462         WM_keymap_add_item(keymap, "FILE_OT_refresh", PADPERIOD, KM_PRESS, 0, 0);
463         WM_keymap_add_item(keymap, "FILE_OT_select_border", BKEY, KM_PRESS, 0, 0);
464         WM_keymap_add_item(keymap, "FILE_OT_select_border", EVT_TWEAK_L, KM_ANY, 0, 0);
465         WM_keymap_add_item(keymap, "FILE_OT_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
466         WM_keymap_add_item(keymap, "FILE_OT_highlight", MOUSEMOVE, KM_ANY, KM_ANY, 0);
467         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, 0, 0);
468         RNA_int_set(kmi->ptr, "increment", 1);
469         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, KM_SHIFT, 0);
470         RNA_int_set(kmi->ptr, "increment", 10);
471         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
472         RNA_int_set(kmi->ptr, "increment", 100);
473         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADMINUS, KM_PRESS, 0, 0);
474         RNA_int_set(kmi->ptr, "increment", -1);
475         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADMINUS, KM_PRESS, KM_SHIFT, 0);
476         RNA_int_set(kmi->ptr, "increment", -10);
477         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADMINUS, KM_PRESS, KM_CTRL, 0);
478         RNA_int_set(kmi->ptr, "increment", -100);
479         
480         
481         /* keys for button area (top) */
482         keymap = WM_keymap_find(keyconf, "File Browser Buttons", SPACE_FILE, 0);
483         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, 0, 0);
484         RNA_int_set(kmi->ptr, "increment", 1);
485         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, KM_SHIFT, 0);
486         RNA_int_set(kmi->ptr, "increment", 10);
487         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
488         RNA_int_set(kmi->ptr, "increment", 100);
489         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADMINUS, KM_PRESS, 0, 0);
490         RNA_int_set(kmi->ptr, "increment", -1);
491         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADMINUS, KM_PRESS, KM_SHIFT, 0);
492         RNA_int_set(kmi->ptr, "increment", -10);
493         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADMINUS, KM_PRESS, KM_CTRL, 0);
494         RNA_int_set(kmi->ptr, "increment", -100);
495 }
496
497
498 static void file_tools_area_init(wmWindowManager *wm, ARegion *ar)
499 {
500         wmKeyMap *keymap;
501
502         ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
503         ED_region_panels_init(wm, ar);
504
505         /* own keymaps */
506         keymap = WM_keymap_find(wm->defaultconf, "File Browser", SPACE_FILE, 0);
507         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
508 }
509
510 static void file_tools_area_draw(const bContext *C, ARegion *ar)
511 {
512         ED_region_panels(C, ar, 1, NULL, -1);
513 }
514
515 static void file_tools_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
516 {
517 #if 0
518         /* context changes */
519         switch (wmn->category) {
520                 
521         }
522 #endif
523 }
524
525 /* add handlers, stuff you only do once or on area/region changes */
526 static void file_header_area_init(wmWindowManager *wm, ARegion *ar)
527 {
528         wmKeyMap *keymap;
529         
530         ED_region_header_init(ar);
531         
532         keymap = WM_keymap_find(wm->defaultconf, "File Browser", SPACE_FILE, 0);
533         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
534 }
535
536 static void file_header_area_draw(const bContext *C, ARegion *ar)
537 {
538         ED_region_header(C, ar);
539 }
540
541 /* add handlers, stuff you only do once or on area/region changes */
542 static void file_ui_area_init(wmWindowManager *wm, ARegion *ar)
543 {
544         wmKeyMap *keymap;
545
546         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
547
548         /* own keymap */
549         keymap = WM_keymap_find(wm->defaultconf, "File Browser", SPACE_FILE, 0);
550         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
551
552         keymap = WM_keymap_find(wm->defaultconf, "File Browser Buttons", SPACE_FILE, 0);
553         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
554 }
555
556 static void file_ui_area_draw(const bContext *C, ARegion *ar)
557 {
558         float col[3];
559         /* clear */
560         UI_GetThemeColor3fv(TH_BACK, col);
561         glClearColor(col[0], col[1], col[2], 0.0);
562         glClear(GL_COLOR_BUFFER_BIT);
563
564         /* scrolling here is just annoying, disable it */
565         ar->v2d.cur.ymax = BLI_rctf_size_y(&ar->v2d.cur);
566         ar->v2d.cur.ymin = 0;
567
568         /* set view2d view matrix for scrolling (without scrollers) */
569         UI_view2d_view_ortho(&ar->v2d);
570
571
572         file_draw_buttons(C, ar);
573
574         UI_view2d_view_restore(C);
575 }
576
577 static void file_ui_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
578 {
579         /* context changes */
580         switch (wmn->category) {
581                 case NC_SPACE:
582                         switch (wmn->data) {
583                                 case ND_SPACE_FILE_LIST:
584                                         ED_region_tag_redraw(ar);
585                                         break;
586                         }
587                         break;
588         }
589 }
590
591 /* only called once, from space/spacetypes.c */
592 void ED_spacetype_file(void)
593 {
594         SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype file");
595         ARegionType *art;
596         
597         st->spaceid = SPACE_FILE;
598         strncpy(st->name, "File", BKE_ST_MAXNAME);
599         
600         st->new = file_new;
601         st->free = file_free;
602         st->init = file_init;
603         st->exit = file_exit;
604         st->duplicate = file_duplicate;
605         st->refresh = file_refresh;
606         st->listener = file_listener;
607         st->operatortypes = file_operatortypes;
608         st->keymap = file_keymap;
609         
610         /* regions: main window */
611         art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
612         art->regionid = RGN_TYPE_WINDOW;
613         art->init = file_main_area_init;
614         art->draw = file_main_area_draw;
615         art->listener = file_main_area_listener;
616         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
617         BLI_addhead(&st->regiontypes, art);
618         
619         /* regions: header */
620         art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
621         art->regionid = RGN_TYPE_HEADER;
622         art->prefsizey = HEADERY;
623         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
624         art->init = file_header_area_init;
625         art->draw = file_header_area_draw;
626         // art->listener = file_header_area_listener;
627         BLI_addhead(&st->regiontypes, art);
628         
629         /* regions: ui */
630         art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
631         art->regionid = RGN_TYPE_UI;
632         art->prefsizey = 60;
633         art->keymapflag = ED_KEYMAP_UI;
634         art->listener = file_ui_area_listener;
635         art->init = file_ui_area_init;
636         art->draw = file_ui_area_draw;
637         BLI_addhead(&st->regiontypes, art);
638
639         /* regions: channels (directories) */
640         art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
641         art->regionid = RGN_TYPE_TOOLS;
642         art->prefsizex = 240;
643         art->prefsizey = 60;
644         art->keymapflag = ED_KEYMAP_UI;
645         art->listener = file_tools_area_listener;
646         art->init = file_tools_area_init;
647         art->draw = file_tools_area_draw;
648         BLI_addhead(&st->regiontypes, art);
649
650         /* regions: tool properties */
651         art = MEM_callocN(sizeof(ARegionType), "spacetype file operator region");
652         art->regionid = RGN_TYPE_TOOL_PROPS;
653         art->prefsizex = 0;
654         art->prefsizey = 240;
655         art->keymapflag = ED_KEYMAP_UI;
656         art->listener = file_tools_area_listener;
657         art->init = file_tools_area_init;
658         art->draw = file_tools_area_draw;
659         BLI_addhead(&st->regiontypes, art);
660         file_panels_register(art);
661
662         BKE_spacetype_register(st);
663
664 }
665
666 void ED_file_init(void)
667 {
668         ED_file_read_bookmarks();
669
670         if (G.background == false) {
671                 filelist_init_icons();
672         }
673
674         IMB_thumb_makedirs();
675 }
676
677 void ED_file_exit(void)
678 {
679         fsmenu_free();
680
681         if (G.background == false) {
682                 filelist_free_icons();
683         }
684 }
685
686 void ED_file_read_bookmarks(void)
687 {
688         const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
689         
690         fsmenu_free();
691
692         fsmenu_read_system(ED_fsmenu_get(), true);
693
694         if (cfgdir) {
695                 char name[FILE_MAX];
696                 BLI_make_file_string("/", name, cfgdir, BLENDER_BOOKMARK_FILE);
697                 fsmenu_read_bookmarks(ED_fsmenu_get(), name);
698         }
699 }
700