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