3f21e561546110b9b165d5f3e23613cb6404aac6
[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         /* channel list region */
85         ar = MEM_callocN(sizeof(ARegion), "channel area for file");
86         BLI_addtail(&sfile->regionbase, ar);
87         ar->regiontype = RGN_TYPE_CHANNELS;
88         ar->alignment = RGN_ALIGN_LEFT;
89
90         /* ui list region */
91         ar = MEM_callocN(sizeof(ARegion), "ui area for file");
92         BLI_addtail(&sfile->regionbase, ar);
93         ar->regiontype = RGN_TYPE_UI;
94         ar->alignment = RGN_ALIGN_TOP;
95
96         /* main area */
97         ar = MEM_callocN(sizeof(ARegion), "main area for file");
98         BLI_addtail(&sfile->regionbase, ar);
99         ar->regiontype = RGN_TYPE_WINDOW;
100         ar->v2d.scroll = (V2D_SCROLL_RIGHT | V2D_SCROLL_BOTTOM);
101         ar->v2d.align = (V2D_ALIGN_NO_NEG_X | V2D_ALIGN_NO_POS_Y);
102         ar->v2d.keepzoom = (V2D_LOCKZOOM_X | V2D_LOCKZOOM_Y | V2D_LIMITZOOM | V2D_KEEPASPECT);
103         ar->v2d.keeptot = V2D_KEEPTOT_STRICT;
104         ar->v2d.minzoom = ar->v2d.maxzoom = 1.0f;
105
106         return (SpaceLink *)sfile;
107 }
108
109 /* not spacelink itself */
110 static void file_free(SpaceLink *sl)
111 {       
112         SpaceFile *sfile = (SpaceFile *) sl;
113         
114         if (sfile->files) {
115                 // XXXXX would need to do thumbnails_stop here, but no context available
116                 filelist_freelib(sfile->files);
117                 filelist_free(sfile->files);
118                 MEM_freeN(sfile->files);
119                 sfile->files = NULL;
120         }
121
122         if (sfile->folders_prev) {
123                 folderlist_free(sfile->folders_prev);
124                 MEM_freeN(sfile->folders_prev);
125                 sfile->folders_prev = NULL;
126         }
127
128         if (sfile->folders_next) {
129                 folderlist_free(sfile->folders_next);
130                 MEM_freeN(sfile->folders_next);
131                 sfile->folders_next = NULL;
132         }
133
134         if (sfile->params) {
135                 MEM_freeN(sfile->params);
136                 sfile->params = NULL;
137         }
138
139         if (sfile->layout) {
140                 MEM_freeN(sfile->layout);
141                 sfile->layout = NULL;
142         }
143 }
144
145
146 /* spacetype; init callback, area size changes, screen set, etc */
147 static void file_init(wmWindowManager *UNUSED(wm), ScrArea *sa)
148 {
149         SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
150
151         /* refresh system directory list */
152         fsmenu_refresh_system_category(fsmenu_get());
153
154         if (sfile->layout) sfile->layout->dirty = true;
155 }
156
157 static void file_exit(wmWindowManager *wm, ScrArea *sa)
158 {
159         SpaceFile *sfile = (SpaceFile *)sa->spacedata.first;
160
161         ED_fileselect_exit(wm, sfile);
162 }
163
164 static SpaceLink *file_duplicate(SpaceLink *sl)
165 {
166         SpaceFile *sfileo = (SpaceFile *)sl;
167         SpaceFile *sfilen = MEM_dupallocN(sl);
168         
169         /* clear or remove stuff from old */
170         sfilen->op = NULL; /* file window doesn't own operators */
171
172         if (sfileo->params) {
173                 sfilen->files = filelist_new(sfileo->params->type);
174                 sfilen->params = MEM_dupallocN(sfileo->params);
175                 filelist_setdir(sfilen->files, sfilen->params->dir);
176         }
177
178         if (sfileo->folders_prev)
179                 sfilen->folders_prev = folderlist_duplicate(sfileo->folders_prev);
180
181         if (sfileo->folders_next)
182                 sfilen->folders_next = folderlist_duplicate(sfileo->folders_next);
183         
184         if (sfileo->layout) {
185                 sfilen->layout = MEM_dupallocN(sfileo->layout);
186         }
187         return (SpaceLink *)sfilen;
188 }
189
190 static void file_refresh(const bContext *C, ScrArea *UNUSED(sa))
191 {
192         wmWindowManager *wm = CTX_wm_manager(C);
193         SpaceFile *sfile = CTX_wm_space_file(C);
194         FileSelectParams *params = ED_fileselect_get_params(sfile);
195
196         if (!sfile->folders_prev) {
197                 sfile->folders_prev = folderlist_new();
198         }
199         if (!sfile->files) {
200                 sfile->files = filelist_new(params->type);
201                 filelist_setdir(sfile->files, params->dir);
202                 params->active_file = -1; // added this so it opens nicer (ton)
203         }
204         filelist_setsorting(sfile->files, params->sort);
205         filelist_setfilter_options(sfile->files, params->flag & FILE_HIDE_DOT,
206                                                  false, /* TODO hide_parent, should be controllable? */
207                                                  params->flag & FILE_FILTER ? params->filter : 0,
208                                                  params->filter_glob);
209
210         if (filelist_empty(sfile->files)) {
211                 thumbnails_stop(wm, sfile->files);
212                 filelist_readdir(sfile->files);
213                 filelist_sort(sfile->files);
214                 BLI_strncpy(params->dir, filelist_dir(sfile->files), FILE_MAX);
215         }
216         else if (filelist_need_sorting(sfile->files)) {
217                 thumbnails_stop(wm, sfile->files);
218                 filelist_sort(sfile->files);
219         }
220
221         if ((params->display == FILE_IMGDISPLAY) && filelist_need_thumbnails(sfile->files)) {
222                 if (!thumbnails_running(wm, sfile->files)) {
223                         thumbnails_start(sfile->files, C);
224                 }
225         }
226         else {
227                 /* stop any running thumbnail jobs if we're not displaying them - speedup for NFS */
228                 thumbnails_stop(wm, sfile->files);
229         }
230
231         filelist_filter(sfile->files);
232
233         if (params->renamefile[0] != '\0') {
234                 int idx = filelist_find(sfile->files, params->renamefile);
235                 if (idx >= 0) {
236                         struct direntry *file = filelist_file(sfile->files, idx);
237                         if (file) {
238                                 file->selflag |= EDITING_FILE;
239                         }
240                 }
241                 BLI_strncpy(sfile->params->renameedit, sfile->params->renamefile, sizeof(sfile->params->renameedit));
242                 params->renamefile[0] = '\0';
243         }
244
245         if (sfile->layout) {
246                 sfile->layout->dirty = true;
247         }
248 }
249
250 static void file_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
251 {
252         /* SpaceFile *sfile = (SpaceFile *)sa->spacedata.first; */
253
254         /* context changes */
255         switch (wmn->category) {
256                 case NC_SPACE:
257                         switch (wmn->data) {
258                                 case ND_SPACE_FILE_LIST:
259                                         ED_area_tag_refresh(sa);
260                                         ED_area_tag_redraw(sa);
261                                         break;
262                                 case ND_SPACE_FILE_PARAMS:
263                                         ED_area_tag_refresh(sa);
264                                         ED_area_tag_redraw(sa);
265                                         break;
266                         }
267                         break;
268         }
269 }
270
271 /* add handlers, stuff you only do once or on area/region changes */
272 static void file_main_area_init(wmWindowManager *wm, ARegion *ar)
273 {
274         wmKeyMap *keymap;
275         
276         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
277         
278         /* own keymaps */
279         keymap = WM_keymap_find(wm->defaultconf, "File Browser", SPACE_FILE, 0);
280         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
281
282         keymap = WM_keymap_find(wm->defaultconf, "File Browser Main", SPACE_FILE, 0);
283         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
284 }
285
286 static void file_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
287 {
288         /* context changes */
289         switch (wmn->category) {
290                 case NC_SPACE:
291                         switch (wmn->data) {
292                                 case ND_SPACE_FILE_LIST:
293                                         ED_region_tag_redraw(ar);
294                                         break;
295                                 case ND_SPACE_FILE_PARAMS:
296                                         ED_region_tag_redraw(ar);
297                                         break;
298                         }
299                         break;
300         }
301 }
302
303 static void file_main_area_draw(const bContext *C, ARegion *ar)
304 {
305         /* draw entirely, view changes should be handled here */
306         SpaceFile *sfile = CTX_wm_space_file(C);
307         FileSelectParams *params = ED_fileselect_get_params(sfile);
308
309         View2D *v2d = &ar->v2d;
310         View2DScrollers *scrollers;
311         float col[3];
312
313         /* Needed, because filelist is not initialized on loading */
314         if (!sfile->files || filelist_empty(sfile->files))
315                 file_refresh(C, NULL);
316
317         /* clear and setup matrix */
318         UI_GetThemeColor3fv(TH_BACK, col);
319         glClearColor(col[0], col[1], col[2], 0.0);
320         glClear(GL_COLOR_BUFFER_BIT);
321         
322         /* Allow dynamically sliders to be set, saves notifiers etc. */
323         
324         if (params->display == FILE_IMGDISPLAY) {
325                 v2d->scroll = V2D_SCROLL_RIGHT;
326                 v2d->keepofs &= ~V2D_LOCKOFS_Y;
327                 v2d->keepofs |= V2D_LOCKOFS_X;
328         }
329         else {
330                 v2d->scroll = V2D_SCROLL_BOTTOM;
331                 v2d->keepofs &= ~V2D_LOCKOFS_X;
332                 v2d->keepofs |= V2D_LOCKOFS_Y;
333                 
334                 /* XXX this happens on scaling down Screen (like from startup.blend) */
335                 /* view2d has no type specific for filewindow case, which doesnt scroll vertically */
336                 if (v2d->cur.ymax < 0) {
337                         v2d->cur.ymin -= v2d->cur.ymax;
338                         v2d->cur.ymax = 0;
339                 }
340         }
341         /* v2d has initialized flag, so this call will only set the mask correct */
342         UI_view2d_region_reinit(v2d, V2D_COMMONVIEW_LIST, ar->winx, ar->winy);
343
344         /* sets tile/border settings in sfile */
345         file_calc_previews(C, ar);
346
347         /* set view */
348         UI_view2d_view_ortho(v2d);
349         
350         /* on first read, find active file */
351         if (params->active_file == -1) {
352                 wmEvent *event = CTX_wm_window(C)->eventstate;
353                 file_highlight_set(sfile, ar, event->x, event->y);
354         }
355         
356         file_draw_list(C, ar);
357         
358         /* reset view matrix */
359         UI_view2d_view_restore(C);
360         
361         /* scrollers */
362         scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
363         UI_view2d_scrollers_draw(C, v2d, scrollers);
364         UI_view2d_scrollers_free(scrollers);
365
366 }
367
368 static void file_operatortypes(void)
369 {
370         WM_operatortype_append(FILE_OT_select);
371         WM_operatortype_append(FILE_OT_select_all_toggle);
372         WM_operatortype_append(FILE_OT_select_border);
373         WM_operatortype_append(FILE_OT_select_bookmark);
374         WM_operatortype_append(FILE_OT_highlight);
375         WM_operatortype_append(FILE_OT_execute);
376         WM_operatortype_append(FILE_OT_cancel);
377         WM_operatortype_append(FILE_OT_parent);
378         WM_operatortype_append(FILE_OT_previous);
379         WM_operatortype_append(FILE_OT_next);
380         WM_operatortype_append(FILE_OT_refresh);
381         WM_operatortype_append(FILE_OT_bookmark_toggle);
382         WM_operatortype_append(FILE_OT_bookmark_add);
383         WM_operatortype_append(FILE_OT_bookmark_delete);
384         WM_operatortype_append(FILE_OT_reset_recent);
385         WM_operatortype_append(FILE_OT_hidedot);
386         WM_operatortype_append(FILE_OT_filenum);
387         WM_operatortype_append(FILE_OT_directory_new);
388         WM_operatortype_append(FILE_OT_delete);
389         WM_operatortype_append(FILE_OT_rename);
390         WM_operatortype_append(FILE_OT_smoothscroll);
391 }
392
393 /* NOTE: do not add .blend file reading on this level */
394 static void file_keymap(struct wmKeyConfig *keyconf)
395 {
396         wmKeyMapItem *kmi;
397         /* keys for all areas */
398         wmKeyMap *keymap = WM_keymap_find(keyconf, "File Browser", SPACE_FILE, 0);
399         WM_keymap_add_item(keymap, "FILE_OT_bookmark_toggle", TKEY, KM_PRESS, 0, 0);
400         WM_keymap_add_item(keymap, "FILE_OT_parent", PKEY, KM_PRESS, 0, 0);
401         WM_keymap_add_item(keymap, "FILE_OT_bookmark_add", BKEY, KM_PRESS, KM_CTRL, 0);
402         WM_keymap_add_item(keymap, "FILE_OT_hidedot", HKEY, KM_PRESS, 0, 0);
403         WM_keymap_add_item(keymap, "FILE_OT_previous", BACKSPACEKEY, KM_PRESS, 0, 0);
404         WM_keymap_add_item(keymap, "FILE_OT_next", BACKSPACEKEY, KM_PRESS, KM_SHIFT, 0);
405         WM_keymap_add_item(keymap, "FILE_OT_directory_new", IKEY, KM_PRESS, 0, 0);
406         WM_keymap_add_item(keymap, "FILE_OT_delete", XKEY, KM_PRESS, 0, 0);
407         WM_keymap_add_item(keymap, "FILE_OT_delete", DELKEY, KM_PRESS, 0, 0);
408         WM_keymap_verify_item(keymap, "FILE_OT_smoothscroll", TIMER1, KM_ANY, KM_ANY, 0);
409
410         /* keys for main area */
411         keymap = WM_keymap_find(keyconf, "File Browser Main", SPACE_FILE, 0);
412         kmi = WM_keymap_add_item(keymap, "FILE_OT_execute", LEFTMOUSE, KM_DBL_CLICK, 0, 0);
413         RNA_boolean_set(kmi->ptr, "need_active", true);
414
415         /* left mouse selects and opens */
416         WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, 0, 0);
417         kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_SHIFT, 0);
418         RNA_boolean_set(kmi->ptr, "extend", true);
419         kmi = WM_keymap_add_item(keymap, "FILE_OT_select", LEFTMOUSE, KM_CLICK, KM_CTRL | KM_SHIFT, 0);
420         RNA_boolean_set(kmi->ptr, "extend", true);
421         RNA_boolean_set(kmi->ptr, "fill", true);
422
423         /* right mouse selects without opening */
424         kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, 0, 0);
425         RNA_boolean_set(kmi->ptr, "open", false);
426         kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, KM_SHIFT, 0);
427         RNA_boolean_set(kmi->ptr, "extend", true);
428         RNA_boolean_set(kmi->ptr, "open", false);
429         kmi = WM_keymap_add_item(keymap, "FILE_OT_select", RIGHTMOUSE, KM_CLICK, KM_ALT, 0);
430         RNA_boolean_set(kmi->ptr, "extend", true);
431         RNA_boolean_set(kmi->ptr, "fill", true);
432         RNA_boolean_set(kmi->ptr, "open", false);
433
434         /* front and back mouse folder navigation */
435         WM_keymap_add_item(keymap, "FILE_OT_previous", BUTTON4MOUSE, KM_CLICK, 0, 0);
436         WM_keymap_add_item(keymap, "FILE_OT_next", BUTTON5MOUSE, KM_CLICK, 0, 0);
437
438         WM_keymap_add_item(keymap, "FILE_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
439         WM_keymap_add_item(keymap, "FILE_OT_refresh", PADPERIOD, KM_PRESS, 0, 0);
440         WM_keymap_add_item(keymap, "FILE_OT_select_border", BKEY, KM_PRESS, 0, 0);
441         WM_keymap_add_item(keymap, "FILE_OT_select_border", EVT_TWEAK_L, KM_ANY, 0, 0);
442         WM_keymap_add_item(keymap, "FILE_OT_rename", LEFTMOUSE, KM_PRESS, KM_CTRL, 0);
443         WM_keymap_add_item(keymap, "FILE_OT_highlight", MOUSEMOVE, KM_ANY, KM_ANY, 0);
444         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, 0, 0);
445         RNA_int_set(kmi->ptr, "increment", 1);
446         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, KM_SHIFT, 0);
447         RNA_int_set(kmi->ptr, "increment", 10);
448         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
449         RNA_int_set(kmi->ptr, "increment", 100);
450         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADMINUS, KM_PRESS, 0, 0);
451         RNA_int_set(kmi->ptr, "increment", -1);
452         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADMINUS, KM_PRESS, KM_SHIFT, 0);
453         RNA_int_set(kmi->ptr, "increment", -10);
454         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADMINUS, KM_PRESS, KM_CTRL, 0);
455         RNA_int_set(kmi->ptr, "increment", -100);
456         
457         
458         /* keys for button area (top) */
459         keymap = WM_keymap_find(keyconf, "File Browser Buttons", SPACE_FILE, 0);
460         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, 0, 0);
461         RNA_int_set(kmi->ptr, "increment", 1);
462         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, KM_SHIFT, 0);
463         RNA_int_set(kmi->ptr, "increment", 10);
464         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
465         RNA_int_set(kmi->ptr, "increment", 100);
466         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADMINUS, KM_PRESS, 0, 0);
467         RNA_int_set(kmi->ptr, "increment", -1);
468         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADMINUS, KM_PRESS, KM_SHIFT, 0);
469         RNA_int_set(kmi->ptr, "increment", -10);
470         kmi = WM_keymap_add_item(keymap, "FILE_OT_filenum", PADMINUS, KM_PRESS, KM_CTRL, 0);
471         RNA_int_set(kmi->ptr, "increment", -100);
472 }
473
474
475 static void file_channel_area_init(wmWindowManager *wm, ARegion *ar)
476 {
477         wmKeyMap *keymap;
478
479         ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE;
480         ED_region_panels_init(wm, ar);
481
482         /* own keymaps */
483         keymap = WM_keymap_find(wm->defaultconf, "File Browser", SPACE_FILE, 0);
484         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
485 }
486
487 static void file_channel_area_draw(const bContext *C, ARegion *ar)
488 {
489         ED_region_panels(C, ar, 1, NULL, -1);
490 }
491
492 static void file_channel_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *UNUSED(ar), wmNotifier *UNUSED(wmn))
493 {
494 #if 0
495         /* context changes */
496         switch (wmn->category) {
497                 
498         }
499 #endif
500 }
501
502 /* add handlers, stuff you only do once or on area/region changes */
503 static void file_header_area_init(wmWindowManager *wm, ARegion *ar)
504 {
505         wmKeyMap *keymap;
506         
507         ED_region_header_init(ar);
508         
509         keymap = WM_keymap_find(wm->defaultconf, "File Browser", SPACE_FILE, 0);
510         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
511 }
512
513 static void file_header_area_draw(const bContext *C, ARegion *ar)
514 {
515         ED_region_header(C, ar);
516 }
517
518 /* add handlers, stuff you only do once or on area/region changes */
519 static void file_ui_area_init(wmWindowManager *wm, ARegion *ar)
520 {
521         wmKeyMap *keymap;
522
523         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy);
524
525         /* own keymap */
526         keymap = WM_keymap_find(wm->defaultconf, "File Browser", SPACE_FILE, 0);
527         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
528
529         keymap = WM_keymap_find(wm->defaultconf, "File Browser Buttons", SPACE_FILE, 0);
530         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
531 }
532
533 static void file_ui_area_draw(const bContext *C, ARegion *ar)
534 {
535         float col[3];
536         /* clear */
537         UI_GetThemeColor3fv(TH_BACK, col);
538         glClearColor(col[0], col[1], col[2], 0.0);
539         glClear(GL_COLOR_BUFFER_BIT);
540
541         /* scrolling here is just annoying, disable it */
542         ar->v2d.cur.ymax = BLI_rctf_size_y(&ar->v2d.cur);
543         ar->v2d.cur.ymin = 0;
544
545         /* set view2d view matrix for scrolling (without scrollers) */
546         UI_view2d_view_ortho(&ar->v2d);
547
548
549         file_draw_buttons(C, ar);
550
551         UI_view2d_view_restore(C);
552 }
553
554 static void file_ui_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
555 {
556         /* context changes */
557         switch (wmn->category) {
558                 case NC_SPACE:
559                         switch (wmn->data) {
560                                 case ND_SPACE_FILE_LIST:
561                                         ED_region_tag_redraw(ar);
562                                         break;
563                         }
564                         break;
565         }
566 }
567
568 /* only called once, from space/spacetypes.c */
569 void ED_spacetype_file(void)
570 {
571         SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype file");
572         ARegionType *art;
573         
574         st->spaceid = SPACE_FILE;
575         strncpy(st->name, "File", BKE_ST_MAXNAME);
576         
577         st->new = file_new;
578         st->free = file_free;
579         st->init = file_init;
580         st->exit = file_exit;
581         st->duplicate = file_duplicate;
582         st->refresh = file_refresh;
583         st->listener = file_listener;
584         st->operatortypes = file_operatortypes;
585         st->keymap = file_keymap;
586         
587         /* regions: main window */
588         art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
589         art->regionid = RGN_TYPE_WINDOW;
590         art->init = file_main_area_init;
591         art->draw = file_main_area_draw;
592         art->listener = file_main_area_listener;
593         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D;
594         BLI_addhead(&st->regiontypes, art);
595         
596         /* regions: header */
597         art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
598         art->regionid = RGN_TYPE_HEADER;
599         art->prefsizey = HEADERY;
600         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_HEADER;
601         art->init = file_header_area_init;
602         art->draw = file_header_area_draw;
603         // art->listener = file_header_area_listener;
604         BLI_addhead(&st->regiontypes, art);
605         
606         /* regions: ui */
607         art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
608         art->regionid = RGN_TYPE_UI;
609         art->prefsizey = 60;
610         art->keymapflag = ED_KEYMAP_UI;
611         art->listener = file_ui_area_listener;
612         art->init = file_ui_area_init;
613         art->draw = file_ui_area_draw;
614         BLI_addhead(&st->regiontypes, art);
615
616         /* regions: channels (directories) */
617         art = MEM_callocN(sizeof(ARegionType), "spacetype file region");
618         art->regionid = RGN_TYPE_CHANNELS;
619         art->prefsizex = 240;
620         art->keymapflag = ED_KEYMAP_UI;
621         art->listener = file_channel_area_listener;
622         art->init = file_channel_area_init;
623         art->draw = file_channel_area_draw;
624         BLI_addhead(&st->regiontypes, art);
625         file_panels_register(art);
626
627         BKE_spacetype_register(st);
628
629 }
630
631 void ED_file_init(void)
632 {
633         ED_file_read_bookmarks();
634
635         if (G.background == false) {
636                 filelist_init_icons();
637         }
638
639         IMB_thumb_makedirs();
640 }
641
642 void ED_file_exit(void)
643 {
644         fsmenu_free();
645
646         if (G.background == false) {
647                 filelist_free_icons();
648         }
649 }
650
651 void ED_file_read_bookmarks(void)
652 {
653         const char * const cfgdir = BKE_appdir_folder_id(BLENDER_USER_CONFIG, NULL);
654         
655         fsmenu_free();
656
657         fsmenu_read_system(fsmenu_get(), true);
658
659         if (cfgdir) {
660                 char name[FILE_MAX];
661                 BLI_make_file_string("/", name, cfgdir, BLENDER_BOOKMARK_FILE);
662                 fsmenu_read_bookmarks(fsmenu_get(), name);
663         }
664 }
665