code cleanup: use const events for modal and invoke operators.
[blender.git] / source / blender / editors / space_sequencer / space_sequencer.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_sequencer/space_sequencer.c
28  *  \ingroup spseq
29  */
30
31
32 #include <string.h>
33 #include <stdio.h>
34
35 #include "DNA_scene_types.h"
36 #include "DNA_mask_types.h"
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_math.h"
42 #include "BLI_utildefines.h"
43
44 #include "BKE_context.h"
45 #include "BKE_screen.h"
46 #include "BKE_sequencer.h"
47 #include "BKE_global.h"
48
49 #include "ED_space_api.h"
50 #include "ED_sequencer.h"
51 #include "ED_screen.h"
52 #include "ED_view3d.h" /* only for sequencer view3d drawing callback */
53
54 #include "WM_api.h"
55 #include "WM_types.h"
56
57 #include "UI_resources.h"
58 #include "UI_view2d.h"
59
60 #include "IMB_imbuf.h"
61
62 #include "sequencer_intern.h"   // own include
63
64 /**************************** common state *****************************/
65
66 static void sequencer_scopes_tag_refresh(ScrArea *sa)
67 {
68         SpaceSeq *sseq = (SpaceSeq *)sa->spacedata.first;
69
70         sseq->scopes.reference_ibuf = NULL;
71 }
72
73 /* ******************** manage regions ********************* */
74
75 ARegion *sequencer_has_buttons_region(ScrArea *sa)
76 {
77         ARegion *ar, *arnew;
78
79         ar = BKE_area_find_region_type(sa, RGN_TYPE_UI);
80         if (ar) return ar;
81         
82         /* add subdiv level; after header */
83         ar = BKE_area_find_region_type(sa, RGN_TYPE_HEADER);
84
85         /* is error! */
86         if (ar == NULL) return NULL;
87         
88         arnew = MEM_callocN(sizeof(ARegion), "buttons for sequencer");
89         
90         BLI_insertlinkafter(&sa->regionbase, ar, arnew);
91         arnew->regiontype = RGN_TYPE_UI;
92         arnew->alignment = RGN_ALIGN_RIGHT;
93         
94         arnew->flag = RGN_FLAG_HIDDEN;
95         
96         return arnew;
97 }
98
99 static ARegion *sequencer_find_region(ScrArea *sa, short type)
100 {
101         ARegion *ar = NULL;
102         
103         for (ar = sa->regionbase.first; ar; ar = ar->next)
104                 if (ar->regiontype == type)
105                         return ar;
106
107         return ar;
108 }
109
110 /* ******************** default callbacks for sequencer space ***************** */
111
112 static SpaceLink *sequencer_new(const bContext *C)
113 {
114         Scene *scene = CTX_data_scene(C);
115         ARegion *ar;
116         SpaceSeq *sseq;
117         
118         sseq = MEM_callocN(sizeof(SpaceSeq), "initsequencer");
119         sseq->spacetype = SPACE_SEQ;
120         sseq->chanshown = 0;
121         sseq->view = SEQ_VIEW_SEQUENCE;
122         sseq->mainb = SEQ_DRAW_IMG_IMBUF;
123         sseq->flag = SEQ_SHOW_GPENCIL | SEQ_USE_ALPHA;
124
125         /* header */
126         ar = MEM_callocN(sizeof(ARegion), "header for sequencer");
127         
128         BLI_addtail(&sseq->regionbase, ar);
129         ar->regiontype = RGN_TYPE_HEADER;
130         ar->alignment = RGN_ALIGN_BOTTOM;
131         
132         /* buttons/list view */
133         ar = MEM_callocN(sizeof(ARegion), "buttons for sequencer");
134         
135         BLI_addtail(&sseq->regionbase, ar);
136         ar->regiontype = RGN_TYPE_UI;
137         ar->alignment = RGN_ALIGN_RIGHT;
138         ar->flag = RGN_FLAG_HIDDEN;
139         
140         /* preview area */
141         /* NOTE: if you change values here, also change them in sequencer_init_preview_region */
142         ar = MEM_callocN(sizeof(ARegion), "preview area for sequencer");
143         BLI_addtail(&sseq->regionbase, ar);
144         ar->regiontype = RGN_TYPE_PREVIEW;
145         ar->alignment = RGN_ALIGN_TOP;
146         ar->flag |= RGN_FLAG_HIDDEN;
147         /* for now, aspect ratio should be maintained, and zoom is clamped within sane default limits */
148         ar->v2d.keepzoom = V2D_KEEPASPECT | V2D_KEEPZOOM;
149         ar->v2d.minzoom = 0.00001f;
150         ar->v2d.maxzoom = 100000.0f;
151         ar->v2d.tot.xmin = -960.0f; /* 1920 width centered */
152         ar->v2d.tot.ymin = -540.0f; /* 1080 height centered */
153         ar->v2d.tot.xmax = 960.0f;
154         ar->v2d.tot.ymax = 540.0f;
155         ar->v2d.min[0] = 0.0f;
156         ar->v2d.min[1] = 0.0f;
157         ar->v2d.max[0] = 12000.0f;
158         ar->v2d.max[1] = 12000.0f;
159         ar->v2d.cur = ar->v2d.tot;
160         ar->v2d.align = V2D_ALIGN_FREE;
161         ar->v2d.keeptot = V2D_KEEPTOT_FREE;
162
163
164         /* main area */
165         ar = MEM_callocN(sizeof(ARegion), "main area for sequencer");
166         
167         BLI_addtail(&sseq->regionbase, ar);
168         ar->regiontype = RGN_TYPE_WINDOW;
169         
170         
171         /* seq space goes from (0,8) to (0, efra) */
172         
173         ar->v2d.tot.xmin = 0.0f;
174         ar->v2d.tot.ymin = 0.0f;
175         ar->v2d.tot.xmax = scene->r.efra;
176         ar->v2d.tot.ymax = 8.0f;
177         
178         ar->v2d.cur = ar->v2d.tot;
179         
180         ar->v2d.min[0] = 10.0f;
181         ar->v2d.min[1] = 0.5f;
182         
183         ar->v2d.max[0] = MAXFRAMEF;
184         ar->v2d.max[1] = MAXSEQ;
185         
186         ar->v2d.minzoom = 0.01f;
187         ar->v2d.maxzoom = 100.0f;
188
189         ar->v2d.scroll |= (V2D_SCROLL_BOTTOM | V2D_SCROLL_SCALE_HORIZONTAL);
190         ar->v2d.scroll |= (V2D_SCROLL_LEFT | V2D_SCROLL_SCALE_VERTICAL);
191         ar->v2d.keepzoom = 0;
192         ar->v2d.keeptot = 0;
193         ar->v2d.align = V2D_ALIGN_NO_NEG_Y;
194
195         return (SpaceLink *)sseq;
196 }
197
198 /* not spacelink itself */
199 static void sequencer_free(SpaceLink *sl)
200 {       
201         SpaceSeq *sseq = (SpaceSeq *) sl;
202         SequencerScopes *scopes = &sseq->scopes;
203
204 // XXX  if (sseq->gpd) BKE_gpencil_free(sseq->gpd);
205
206         if (scopes->zebra_ibuf)
207                 IMB_freeImBuf(scopes->zebra_ibuf);
208
209         if (scopes->waveform_ibuf)
210                 IMB_freeImBuf(scopes->waveform_ibuf);
211
212         if (scopes->sep_waveform_ibuf)
213                 IMB_freeImBuf(scopes->sep_waveform_ibuf);
214
215         if (scopes->vector_ibuf)
216                 IMB_freeImBuf(scopes->vector_ibuf);
217
218         if (scopes->histogram_ibuf)
219                 IMB_freeImBuf(scopes->histogram_ibuf);
220 }
221
222
223 /* spacetype; init callback */
224 static void sequencer_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
225 {
226         
227 }
228
229 static void sequencer_refresh(const bContext *C, ScrArea *sa)
230 {
231         wmWindowManager *wm = CTX_wm_manager(C);
232         wmWindow *window = CTX_wm_window(C);
233         SpaceSeq *sseq = (SpaceSeq *)sa->spacedata.first;
234         ARegion *ar_main = sequencer_find_region(sa, RGN_TYPE_WINDOW);
235         ARegion *ar_preview = sequencer_find_region(sa, RGN_TYPE_PREVIEW);
236         int view_changed = 0;
237
238         switch (sseq->view) {
239                 case SEQ_VIEW_SEQUENCE:
240                         if (ar_main && (ar_main->flag & RGN_FLAG_HIDDEN)) {
241                                 ar_main->flag &= ~RGN_FLAG_HIDDEN;
242                                 ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
243                                 view_changed = 1;
244                         }
245                         if (ar_preview && !(ar_preview->flag & RGN_FLAG_HIDDEN)) {
246                                 ar_preview->flag |= RGN_FLAG_HIDDEN;
247                                 ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
248                                 WM_event_remove_handlers((bContext *)C, &ar_preview->handlers);
249                                 view_changed = 1;
250                         }
251                         if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
252                                 ar_main->alignment = RGN_ALIGN_NONE;
253                                 view_changed = 1;
254                         }
255                         if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
256                                 ar_preview->alignment = RGN_ALIGN_NONE;
257                                 view_changed = 1;
258                         }
259                         break;
260                 case SEQ_VIEW_PREVIEW:
261                         if (ar_main && !(ar_main->flag & RGN_FLAG_HIDDEN)) {
262                                 ar_main->flag |= RGN_FLAG_HIDDEN;
263                                 ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
264                                 WM_event_remove_handlers((bContext *)C, &ar_main->handlers);
265                                 view_changed = 1;
266                         }
267                         if (ar_preview && (ar_preview->flag & RGN_FLAG_HIDDEN)) {
268                                 ar_preview->flag &= ~RGN_FLAG_HIDDEN;
269                                 ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
270                                 ar_preview->v2d.cur = ar_preview->v2d.tot;
271                                 view_changed = 1;
272                         }
273                         if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
274                                 ar_main->alignment = RGN_ALIGN_NONE;
275                                 view_changed = 1;
276                         }
277                         if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) {
278                                 ar_preview->alignment = RGN_ALIGN_NONE;
279                                 view_changed = 1;
280                         }
281                         break;
282                 case SEQ_VIEW_SEQUENCE_PREVIEW:
283                         if (ar_main && (ar_main->flag & RGN_FLAG_HIDDEN)) {
284                                 ar_main->flag &= ~RGN_FLAG_HIDDEN;
285                                 ar_main->v2d.flag &= ~V2D_IS_INITIALISED;
286                                 view_changed = 1;
287                         }
288                         if (ar_preview && (ar_preview->flag & RGN_FLAG_HIDDEN)) {
289                                 ar_preview->flag &= ~RGN_FLAG_HIDDEN;
290                                 ar_preview->v2d.flag &= ~V2D_IS_INITIALISED;
291                                 ar_preview->v2d.cur = ar_preview->v2d.tot;
292                                 view_changed = 1;
293                         }
294                         if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) {
295                                 ar_main->alignment = RGN_ALIGN_NONE;
296                                 view_changed = 1;
297                         }
298                         if (ar_preview && ar_preview->alignment != RGN_ALIGN_TOP) {
299                                 ar_preview->alignment = RGN_ALIGN_TOP;
300                                 view_changed = 1;
301                         }
302                         break;
303         }
304
305         if (view_changed) {
306                 ED_area_initialize(wm, window, sa);
307                 ED_area_tag_redraw(sa);
308         }
309 }
310
311 static SpaceLink *sequencer_duplicate(SpaceLink *sl)
312 {
313         SpaceSeq *sseqn = MEM_dupallocN(sl);
314         
315         /* clear or remove stuff from old */
316 // XXX  sseq->gpd = gpencil_data_duplicate(sseq->gpd);
317
318         return (SpaceLink *)sseqn;
319 }
320
321 static void sequencer_listener(ScrArea *sa, wmNotifier *wmn)
322 {
323         /* context changes */
324         switch (wmn->category) {
325                 case NC_SCENE:
326                         switch (wmn->data) {
327                                 case ND_FRAME:
328                                 case ND_SEQUENCER:
329                                         sequencer_scopes_tag_refresh(sa);
330                                         break;
331                         }
332                         break;
333                 case NC_SPACE:
334                         if (wmn->data == ND_SPACE_SEQUENCER)
335                                 sequencer_scopes_tag_refresh(sa);
336                         break;
337         }
338 }
339
340 /* *********************** sequencer (main) region ************************ */
341 /* add handlers, stuff you only do once or on area/region changes */
342 static void sequencer_main_area_init(wmWindowManager *wm, ARegion *ar)
343 {
344         wmKeyMap *keymap;
345         ListBase *lb;
346         
347         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
348
349 //      keymap = WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0);
350 //      WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
351
352         keymap = WM_keymap_find(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
353         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
354         
355         /* own keymap */
356         keymap = WM_keymap_find(wm->defaultconf, "Sequencer", SPACE_SEQ, 0);
357         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
358         
359         /* add drop boxes */
360         lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
361         
362         WM_event_add_dropbox_handler(&ar->handlers, lb);
363         
364 }
365
366 static void sequencer_main_area_draw(const bContext *C, ARegion *ar)
367 {
368 //      ScrArea *sa = CTX_wm_area(C);
369         
370         /* NLE - strip editing timeline interface */
371         draw_timeline_seq(C, ar);
372 }
373
374 /* ************* dropboxes ************* */
375
376 static int image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
377 {
378         ARegion *ar = CTX_wm_region(C);
379         Scene *scene = CTX_data_scene(C);
380         int hand;
381
382         if (drag->type == WM_DRAG_PATH)
383                 if (ELEM(drag->icon, ICON_FILE_IMAGE, ICON_FILE_BLANK)) /* rule might not work? */
384                         if (find_nearest_seq(scene, &ar->v2d, &hand, event->mval) == NULL)
385                                 return 1;
386
387         return 0;
388 }
389
390 static int movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
391 {
392         ARegion *ar = CTX_wm_region(C);
393         Scene *scene = CTX_data_scene(C);
394         int hand;
395
396         if (drag->type == WM_DRAG_PATH)
397                 if (ELEM3(drag->icon, 0, ICON_FILE_MOVIE, ICON_FILE_BLANK)) /* rule might not work? */
398                         if (find_nearest_seq(scene, &ar->v2d, &hand, event->mval) == NULL)
399                                 return 1;
400         return 0;
401 }
402
403 static int sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
404 {
405         ARegion *ar = CTX_wm_region(C);
406         Scene *scene = CTX_data_scene(C);
407         int hand;
408
409         if (drag->type == WM_DRAG_PATH)
410                 if (ELEM(drag->icon, ICON_FILE_SOUND, ICON_FILE_BLANK)) /* rule might not work? */
411                         if (find_nearest_seq(scene, &ar->v2d, &hand, event->mval) == NULL)
412                                 return 1;
413         return 0;
414 }
415
416 static void sequencer_drop_copy(wmDrag *drag, wmDropBox *drop)
417 {
418         /* copy drag path to properties */
419         if (RNA_struct_find_property(drop->ptr, "filepath"))
420                 RNA_string_set(drop->ptr, "filepath", drag->path);
421
422         if (RNA_struct_find_property(drop->ptr, "directory")) {
423                 PointerRNA itemptr;
424                 char dir[FILE_MAX], file[FILE_MAX];
425
426                 BLI_split_dirfile(drag->path, dir, file, sizeof(dir), sizeof(file));
427                 
428                 RNA_string_set(drop->ptr, "directory", dir);
429
430                 RNA_collection_clear(drop->ptr, "files");
431                 RNA_collection_add(drop->ptr, "files", &itemptr);
432                 RNA_string_set(&itemptr, "name", file);
433         }
434 }
435
436 /* this region dropbox definition */
437 static void sequencer_dropboxes(void)
438 {
439         ListBase *lb = WM_dropboxmap_find("Sequencer", SPACE_SEQ, RGN_TYPE_WINDOW);
440         
441         WM_dropbox_add(lb, "SEQUENCER_OT_image_strip_add", image_drop_poll, sequencer_drop_copy);
442         WM_dropbox_add(lb, "SEQUENCER_OT_movie_strip_add", movie_drop_poll, sequencer_drop_copy);
443         WM_dropbox_add(lb, "SEQUENCER_OT_sound_strip_add", sound_drop_poll, sequencer_drop_copy);
444 }
445
446 /* ************* end drop *********** */
447
448 const char *sequencer_context_dir[] = {"edit_mask", NULL};
449
450 static int sequencer_context(const bContext *C, const char *member, bContextDataResult *result)
451 {
452         Scene *scene = CTX_data_scene(C);
453
454         if (CTX_data_dir(member)) {
455                 CTX_data_dir_set(result, sequencer_context_dir);
456
457                 return TRUE;
458         }
459         else if (CTX_data_equals(member, "edit_mask")) {
460                 Mask *mask = BKE_sequencer_mask_get(scene);
461                 if (mask) {
462                         CTX_data_id_pointer_set(result, &mask->id);
463                 }
464                 return TRUE;
465         }
466
467         return FALSE;
468 }
469
470
471 /* add handlers, stuff you only do once or on area/region changes */
472 static void sequencer_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar)
473 {
474         ED_region_header_init(ar);
475 }
476
477 static void sequencer_header_area_draw(const bContext *C, ARegion *ar)
478 {
479         ED_region_header(C, ar);
480 }
481
482 static void sequencer_main_area_listener(ARegion *ar, wmNotifier *wmn)
483 {
484         /* context changes */
485         switch (wmn->category) {
486                 case NC_SCENE:
487                         switch (wmn->data) {
488                                 case ND_FRAME:
489                                 case ND_FRAME_RANGE:
490                                 case ND_MARKERS:
491                                 case ND_RENDER_OPTIONS: /* for FPS and FPS Base */
492                                 case ND_SEQUENCER:
493                                         ED_region_tag_redraw(ar);
494                                         break;
495                         }
496                         break;
497                 case NC_SPACE:
498                         if (wmn->data == ND_SPACE_SEQUENCER)
499                                 ED_region_tag_redraw(ar);
500                         break;
501                 case NC_ID:
502                         if (wmn->action == NA_RENAME)
503                                 ED_region_tag_redraw(ar);
504                         break;
505                 case NC_SCREEN:
506                         if (ELEM(wmn->data, ND_SCREENCAST, ND_ANIMPLAY))
507                                 ED_region_tag_redraw(ar);
508                         break;
509         }
510 }
511
512 /* *********************** preview region ************************ */
513 static void sequencer_preview_area_init(wmWindowManager *wm, ARegion *ar)
514 {
515         wmKeyMap *keymap;
516
517         UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy);
518         
519 //      keymap = WM_keymap_find(wm->defaultconf, "Mask Editing", 0, 0);
520 //      WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
521
522         keymap = WM_keymap_find(wm->defaultconf, "SequencerCommon", SPACE_SEQ, 0);
523         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
524
525         /* own keymap */
526         keymap = WM_keymap_find(wm->defaultconf, "SequencerPreview", SPACE_SEQ, 0);
527         WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct);
528 }
529
530 static void sequencer_preview_area_draw(const bContext *C, ARegion *ar)
531 {
532         ScrArea *sa = CTX_wm_area(C);
533         SpaceSeq *sseq = sa->spacedata.first;
534         Scene *scene = CTX_data_scene(C);
535         int show_split = scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW && sseq->mainb == SEQ_DRAW_IMG_IMBUF;
536         
537         /* XXX temp fix for wrong setting in sseq->mainb */
538         if (sseq->mainb == SEQ_DRAW_SEQUENCE) sseq->mainb = SEQ_DRAW_IMG_IMBUF;
539
540         if (!show_split || sseq->overlay_type != SEQ_DRAW_OVERLAY_REFERENCE)
541                 draw_image_seq(C, scene, ar, sseq, scene->r.cfra, 0, FALSE);
542
543         if (show_split && sseq->overlay_type != SEQ_DRAW_OVERLAY_CURRENT) {
544                 int over_cfra;
545
546                 if (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS)
547                         over_cfra = scene->ed->over_cfra;
548                 else
549                         over_cfra = scene->r.cfra + scene->ed->over_ofs;
550
551                 if (over_cfra != scene->r.cfra || sseq->overlay_type != SEQ_DRAW_OVERLAY_RECT)
552                         draw_image_seq(C, scene, ar, sseq, scene->r.cfra, over_cfra - scene->r.cfra, TRUE);
553         }
554
555 }
556
557 static void sequencer_preview_area_listener(ARegion *ar, wmNotifier *wmn)
558 {
559         /* context changes */
560         switch (wmn->category) {
561                 case NC_GPENCIL:
562                         if (wmn->action == NA_EDITED) {
563                                 ED_region_tag_redraw(ar);
564                         }
565                         break;
566                 case NC_SCENE:
567                         switch (wmn->data) {
568                                 case ND_FRAME:
569                                 case ND_MARKERS:
570                                 case ND_SEQUENCER:
571                                 case ND_RENDER_OPTIONS:
572                                         ED_region_tag_redraw(ar);
573                                         break;
574                         }
575                         break;
576                 case NC_SPACE:
577                         if (wmn->data == ND_SPACE_SEQUENCER)
578                                 ED_region_tag_redraw(ar);
579                         break;
580                 case NC_ID:
581                         switch (wmn->data) {
582                                 case NA_RENAME:
583                                         ED_region_tag_redraw(ar);
584                                         break;
585                         }
586                         break;
587
588                 case NC_MASK:
589                         if (wmn->action == NA_EDITED) {
590                                 ED_region_tag_redraw(ar);
591                         }
592                         break;
593         }
594 }
595
596 /* *********************** buttons region ************************ */
597
598 /* add handlers, stuff you only do once or on area/region changes */
599 static void sequencer_buttons_area_init(wmWindowManager *wm, ARegion *ar)
600 {
601         
602         ED_region_panels_init(wm, ar);
603         
604 }
605
606 static void sequencer_buttons_area_draw(const bContext *C, ARegion *ar)
607 {
608         ED_region_panels(C, ar, 1, NULL, -1);
609 }
610
611 static void sequencer_buttons_area_listener(ARegion *ar, wmNotifier *wmn)
612 {
613         /* context changes */
614         switch (wmn->category) {
615                 case NC_GPENCIL:
616                         if (wmn->data == ND_DATA) {
617                                 ED_region_tag_redraw(ar);
618                         }
619                         break;
620                 case NC_SCENE:
621                         switch (wmn->data) {
622                                 case ND_FRAME:
623                                 case ND_SEQUENCER:
624                                         ED_region_tag_redraw(ar);
625                                         break;
626                         }
627                         break;
628                 case NC_SPACE:
629                         if (wmn->data == ND_SPACE_SEQUENCER)
630                                 ED_region_tag_redraw(ar);
631                         break;
632                 case NC_ID:
633                         if (wmn->action == NA_RENAME)
634                                 ED_region_tag_redraw(ar);
635                         break;
636         }
637 }
638 /* ************************************* */
639
640 /* only called once, from space/spacetypes.c */
641 void ED_spacetype_sequencer(void)
642 {
643         SpaceType *st = MEM_callocN(sizeof(SpaceType), "spacetype sequencer");
644         ARegionType *art;
645         
646         st->spaceid = SPACE_SEQ;
647         strncpy(st->name, "Sequencer", BKE_ST_MAXNAME);
648         
649         st->new = sequencer_new;
650         st->free = sequencer_free;
651         st->init = sequencer_init;
652         st->duplicate = sequencer_duplicate;
653         st->operatortypes = sequencer_operatortypes;
654         st->keymap = sequencer_keymap;
655         st->context = sequencer_context;
656         st->dropboxes = sequencer_dropboxes;
657         st->refresh = sequencer_refresh;
658         st->listener = sequencer_listener;
659
660         /* regions: main window */
661         art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
662         art->regionid = RGN_TYPE_WINDOW;
663         art->init = sequencer_main_area_init;
664         art->draw = sequencer_main_area_draw;
665         art->listener = sequencer_main_area_listener;
666         art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_FRAMES | ED_KEYMAP_ANIMATION;
667
668         BLI_addhead(&st->regiontypes, art);
669
670         /* preview */
671         art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
672         art->regionid = RGN_TYPE_PREVIEW;
673         art->prefsizey = 240; // XXX
674         art->init = sequencer_preview_area_init;
675         art->draw = sequencer_preview_area_draw;
676         art->listener = sequencer_preview_area_listener;
677         art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_GPENCIL;
678         BLI_addhead(&st->regiontypes, art);
679         
680         /* regions: listview/buttons */
681         art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
682         art->regionid = RGN_TYPE_UI;
683         art->prefsizex = 220; // XXX
684         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
685         art->listener = sequencer_buttons_area_listener;
686         art->init = sequencer_buttons_area_init;
687         art->draw = sequencer_buttons_area_draw;
688         BLI_addhead(&st->regiontypes, art);
689         
690         sequencer_buttons_register(art);
691
692         /* regions: header */
693         art = MEM_callocN(sizeof(ARegionType), "spacetype sequencer region");
694         art->regionid = RGN_TYPE_HEADER;
695         art->prefsizey = HEADERY;
696         art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
697         
698         art->init = sequencer_header_area_init;
699         art->draw = sequencer_header_area_draw;
700         art->listener = sequencer_main_area_listener;
701         
702         BLI_addhead(&st->regiontypes, art);
703         
704         BKE_spacetype_register(st);
705
706         /* set the sequencer callback when not in background mode */
707         if (G.background == 0) {
708                 sequencer_view3d_cb = ED_view3d_draw_offscreen_imbuf_simple;
709         }
710 }