View2D: Cleanup of presets and fixed errors in various views
[blender-staging.git] / source / blender / editors / space_time / ed_markers.c
1 /**
2  * $Id:
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <stdlib.h>
30 #include <math.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_scene_types.h"
35 #include "DNA_screen_types.h"
36 #include "DNA_space_types.h"
37 #include "DNA_view2d_types.h"
38 #include "DNA_userdef_types.h"
39 #include "DNA_windowmanager_types.h"
40
41 #include "RNA_access.h"
42 #include "RNA_define.h"
43
44 #include "BLI_blenlib.h"
45
46 #include "BKE_global.h"
47 #include "BKE_utildefines.h"
48
49 #include "WM_api.h"
50 #include "WM_types.h"
51
52 #include "BIF_gl.h"
53 #include "BIF_glutil.h"
54
55 #include "UI_interface.h"
56 #include "UI_interface_icons.h"
57 #include "UI_view2d.h"
58 #include "UI_resources.h"
59 #include "UI_text.h"
60
61 #include "ED_markers.h"
62 #include "ED_screen.h"
63 #include "ED_types.h"
64 #include "ED_util.h"
65
66 /* ************* Marker API **************** */
67
68 static ListBase *context_get_markers(const bContext *C)
69 {
70         
71 #if 0
72         /* XXX get them from pose */
73         if ((slink->spacetype == SPACE_ACTION) && (saction->flag & SACTION_POSEMARKERS_MOVE)) {
74                 if (saction->action)
75                         markers= &saction->action->markers;
76                 else
77                         markers= NULL;
78         }
79         else
80 #endif
81         
82         return &C->scene->markers;
83 }
84
85 /* ************* Marker Drawing ************ */
86
87 /* XXX */
88 extern void ui_rasterpos_safe(float x, float y, float aspect);
89
90 /* function to draw markers */
91 static void draw_marker(View2D *v2d, TimeMarker *marker, int cfra, int flag)
92 {
93         float xpos, ypixels, xscale, yscale;
94         int icon_id= 0;
95         
96         xpos = marker->frame;
97         /* no time correction for framelen! space is drawn with old values */
98         
99         ypixels= v2d->mask.ymax-v2d->mask.ymin;
100         UI_view2d_getscale(v2d, &xscale, &yscale);
101         
102         glScalef(1.0/xscale, 1.0, 1.0);
103         
104         glEnable(GL_BLEND);
105         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);                      
106         
107         /* verticle line */
108         if (flag & DRAW_MARKERS_LINES) {
109                 setlinestyle(3);
110                 if(marker->flag & SELECT)
111                         glColor4ub(255,255,255, 96);
112                 else
113                         glColor4ub(0,0,0, 96);
114                 
115                 glBegin(GL_LINES);
116                 glVertex2f((xpos*xscale)+0.5, 12);
117                 glVertex2f((xpos*xscale)+0.5, 34*yscale); /* a bit lazy but we know it cant be greater then 34 strips high*/
118                 glEnd();
119                 setlinestyle(0);
120         }
121         
122         /* 5 px to offset icon to align properly, space / pixels corrects for zoom */
123         if (flag & DRAW_MARKERS_LOCAL) {
124                 icon_id= (marker->flag & ACTIVE) ? ICON_PMARKER_ACT : 
125                 (marker->flag & SELECT) ? ICON_PMARKER_SEL : 
126                 ICON_PMARKER;
127         }
128         else {
129                 icon_id= (marker->flag & SELECT) ? ICON_MARKER_HLT : 
130                 ICON_MARKER;
131         }
132         
133         UI_icon_draw(xpos*xscale-5.0, 16.0, icon_id);
134         
135         glBlendFunc(GL_ONE, GL_ZERO);
136         glDisable(GL_BLEND);
137         
138         /* and the marker name too, shifted slightly to the top-right */
139         if(marker->name && marker->name[0]) {
140                 if(marker->flag & SELECT) {
141                         UI_ThemeColor(TH_TEXT_HI);
142                         ui_rasterpos_safe(xpos*xscale+4.0, (ypixels<=39.0)?(ypixels-10.0):29.0, 1.0);
143                 }
144                 else {
145                         UI_ThemeColor(TH_TEXT);
146                         if((marker->frame <= cfra) && (marker->frame+5 > cfra))
147                                 ui_rasterpos_safe(xpos*xscale+4.0, (ypixels<=39.0)?(ypixels-10.0):29.0, 1.0);
148                         else
149                                 ui_rasterpos_safe(xpos*xscale+4.0, 17.0, 1.0);
150                 }
151                 UI_DrawString(G.font, marker->name, 0);
152         }
153         glScalef(xscale, 1.0, 1.0);
154 }
155
156 /* Draw Scene-Markers in time window */
157 void draw_markers_time(const bContext *C, int flag)
158 {
159         ListBase *markers= context_get_markers(C);
160         View2D *v2d= UI_view2d_fromcontext(C);
161         TimeMarker *marker;
162         
163         /* unselected markers are drawn at the first time */
164         for (marker= markers->first; marker; marker= marker->next) {
165                 if (!(marker->flag & SELECT)) draw_marker(v2d, marker, C->scene->r.cfra, flag);
166         }
167         
168         /* selected markers are drawn later */
169         for (marker= markers->first; marker; marker= marker->next) {
170                 if (marker->flag & SELECT) draw_marker(v2d, marker, C->scene->r.cfra, flag);
171         }
172 }
173
174
175
176 /* ************************** add markers *************************** */
177
178 /* add TimeMarker at curent frame */
179 static int ed_marker_add(bContext *C, wmOperator *op)
180 {
181         ListBase *markers= context_get_markers(C);
182         TimeMarker *marker;
183         int frame= C->scene->r.cfra;
184         
185         /* two markers can't be at the same place */
186         for(marker= markers->first; marker; marker= marker->next)
187                 if(marker->frame == frame) 
188                         return OPERATOR_CANCELLED;
189         
190         /* deselect all */
191         for(marker= markers->first; marker; marker= marker->next)
192                 marker->flag &= ~SELECT;
193         
194         marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
195         marker->flag= SELECT;
196         marker->frame= frame;
197         sprintf(marker->name, "Frame %d", frame); // XXX - temp code only
198         BLI_addtail(markers, marker);
199         
200         //BIF_undo_push("Add Marker");
201         
202         return OPERATOR_FINISHED;
203 }
204
205 static void ED_MARKER_OT_add(wmOperatorType *ot)
206 {
207         /* identifiers */
208         ot->name= "Add Time Marker";
209         ot->idname= "ED_MARKER_OT_add";
210         
211         /* api callbacks */
212         ot->exec= ed_marker_add;
213         ot->poll= ED_operator_areaactive;
214         
215 }
216
217 /* ************************** transform markers *************************** */
218
219
220 /* operator state vars used:  
221         frs: delta movement
222
223 functions:
224
225         init()   check selection, add customdata with old values and some lookups
226
227         apply()  do the actual movement
228
229         exit()  cleanup, send notifier
230
231     cancel() to escpae from modal
232
233 callbacks:
234
235         exec()  calls init, apply, exit 
236
237         invoke() calls init, adds modal handler
238
239         modal() accept modal events while doing it, ends with apply and exit, or cancel
240
241 */
242
243 typedef struct MarkerMove {
244         SpaceLink *slink;
245         ListBase *markers;
246         int event_type;         /* store invoke-event, to verify */
247         int *oldframe, evtx, firstx;
248 } MarkerMove;
249
250 /* copy selection to temp buffer */
251 /* return 0 if not OK */
252 static int ed_marker_move_init(bContext *C, wmOperator *op)
253 {
254         ListBase *markers= context_get_markers(C);
255         MarkerMove *mm;
256         TimeMarker *marker;
257         int totmark=0;
258         int a;
259         
260         for (marker= markers->first; marker; marker= marker->next)
261                 if (marker->flag & SELECT) totmark++;
262         
263         if (totmark==0) return 0;
264         
265         op->customdata= mm= MEM_callocN(sizeof(MarkerMove), "Markermove");
266         mm->slink= C->area->spacedata.first;
267         mm->markers= markers;
268         mm->oldframe= MEM_callocN(totmark*sizeof(int), "MarkerMove oldframe");
269         
270         for (a=0, marker= markers->first; marker; marker= marker->next) {
271                 if (marker->flag & SELECT) {
272                         mm->oldframe[a]= marker->frame;
273                         a++;
274                 }
275         }
276         
277         return 1;
278 }
279
280 /* free stuff */
281 static void ed_marker_move_exit(bContext *C, wmOperator *op)
282 {
283         MarkerMove *mm= op->customdata;
284         
285         MEM_freeN(mm->oldframe);
286         MEM_freeN(op->customdata);
287         op->customdata= NULL;
288 }
289
290 static int ed_marker_move_invoke(bContext *C, wmOperator *op, wmEvent *evt)
291 {
292         if(ed_marker_move_init(C, op)) {
293                 MarkerMove *mm= op->customdata;
294                 
295                 mm->evtx= evt->x;
296                 mm->firstx= evt->x;
297                 mm->event_type= evt->type;
298                 
299                 /* add temp handler */
300                 WM_event_add_modal_handler(C, &C->window->handlers, op);
301                 
302                 /* reset frs delta */
303                 RNA_int_set(op->ptr, "frs", 0);
304                 
305                 return OPERATOR_RUNNING_MODAL;
306         }
307         
308         return OPERATOR_CANCELLED;
309 }
310
311 /* note, init has to be called succesfully */
312 static void ed_marker_move_apply(bContext *C, wmOperator *op)
313 {
314         MarkerMove *mm= op->customdata;
315         TimeMarker *marker;
316         int a, offs;
317         
318         offs= RNA_int_get(op->ptr, "frs");
319         for (a=0, marker= mm->markers->first; marker; marker= marker->next) {
320                 if (marker->flag & SELECT) {
321                         marker->frame= mm->oldframe[a] + offs;
322                         a++;
323                 }
324         }
325 }
326
327 /* only for modal */
328 static void ed_marker_move_cancel(bContext *C, wmOperator *op)
329 {
330         
331         RNA_int_set(op->ptr, "frs", 0);
332         ed_marker_move_apply(C, op);
333         ed_marker_move_exit(C, op);     
334         
335         WM_event_add_notifier(C, WM_NOTE_MARKERS_CHANGED, 0, NULL);
336 }
337
338
339 /* for tweak handlers, check configuration for how to interpret events */
340 int WM_modal_tweak_check(wmEvent *evt, int tweak_event)
341 {
342         /* user preset?? dunno... */
343         int tweak_modal= 1;
344         
345         switch(tweak_event) {
346                 case EVT_TWEAK_L:
347                 case EVT_TWEAK_M:
348                 case EVT_TWEAK_R:
349                         if(evt->val==tweak_modal)
350                                 return 1;
351                 default:
352                         /* this case is when modal callcback didnt get started with a tweak */
353                         if(evt->val)
354                                 return 1;
355         }
356         return 0;
357 }
358
359 static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt)
360 {
361         MarkerMove *mm= op->customdata;
362         View2D *v2d= UI_view2d_fromcontext(C);
363         TimeMarker *marker, *selmarker=NULL;
364         float dx, fac;
365         char str[256];
366                 
367         switch(evt->type) {
368                 case ESCKEY:
369                         ed_marker_move_cancel(C, op);
370                         return OPERATOR_CANCELLED;
371
372                 case LEFTMOUSE:
373                 case MIDDLEMOUSE:
374                 case RIGHTMOUSE:
375                         if(WM_modal_tweak_check(evt, mm->event_type)) {
376                                 ed_marker_move_exit(C, op);
377                                 WM_event_add_notifier(C, WM_NOTE_MARKERS_CHANGED, 0, NULL);
378                                 return OPERATOR_FINISHED;
379                         }
380                         
381                         break;
382                 case MOUSEMOVE:
383         
384                         dx= v2d->mask.xmax-v2d->mask.xmin;
385                         dx= (v2d->cur.xmax-v2d->cur.xmin)/dx;
386                         
387                         if (evt->x != mm->evtx) {       /* XXX maybe init for firsttime */
388                                 int a, offs, totmark=0;
389                                 
390                                 mm->evtx= evt->x;
391                                 
392                                 fac= ((float)(evt->x - mm->firstx)*dx);
393                                 
394                                 if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) 
395                                         apply_keyb_grid(&fac, 0.0, FPS, 0.1*FPS, 0);
396                                 else
397                                         apply_keyb_grid(&fac, 0.0, 1.0, 0.1, U.flag & USER_AUTOGRABGRID);
398                                 
399                                 offs= (int)fac;
400                                 RNA_int_set(op->ptr, "frs", offs);
401                                 ed_marker_move_apply(C, op);
402                                 
403                                 /* cruft below is for header print */
404                                 for (a=0, marker= mm->markers->first; marker; marker= marker->next) {
405                                         if (marker->flag & SELECT) {
406                                                 selmarker= marker;
407                                                 a++; totmark++;
408                                         }
409                                 }
410                                 
411                                 if (totmark==1) {       
412                                         /* we print current marker value */
413                                         if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) {
414                                                 SpaceTime *stime= (SpaceTime *)mm->slink;
415                                                 if (stime->flag & TIME_DRAWFRAMES) 
416                                                         sprintf(str, "Marker %d offset %d", selmarker->frame, offs);
417                                                 else 
418                                                         sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
419                                         }
420                                         else if (mm->slink->spacetype == SPACE_ACTION) {
421 #if 0                                           
422 XXX                                             if (saction->flag & SACTION_DRAWTIME)
423                                                         sprintf(str, "Marker %.2f offset %.2f", FRA2TIME(selmarker->frame), FRA2TIME(offs));
424                                                 else
425                                                         sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
426 #endif                                  
427                                         }
428                                         else {
429                                                 sprintf(str, "Marker %.2f offset %.2f", (double)(selmarker->frame), (double)(offs));
430                                         }
431                                 }
432                                 else {
433                                         /* we only print the offset */
434                                         if (ELEM(mm->slink->spacetype, SPACE_TIME, SPACE_SOUND)) { 
435                                                 SpaceTime *stime= (SpaceTime *)mm->slink;
436                                                 if (stime->flag & TIME_DRAWFRAMES) 
437                                                         sprintf(str, "Marker offset %d ", offs);
438                                                 else 
439                                                         sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
440                                         }
441 #if 0                                   
442 XXX                                     else if (mm->slink->spacetype == SPACE_ACTION) {
443                                                 if (saction->flag & SACTION_DRAWTIME)
444                                                         sprintf(str, "Marker offset %.2f ", FRA2TIME(offs));
445                                                 else
446                                                         sprintf(str, "Marker offset %.2f ", (double)(offs));
447                                         }
448 #endif                                  
449                                         else {
450                                                 sprintf(str, "Marker offset %.2f ", (double)(offs));
451                                         }
452                                 }
453                                 
454                                 WM_event_add_notifier(C, WM_NOTE_MARKERS_CHANGED, 0, NULL);
455                                 // headerprint(str); XXX
456                         }
457         }
458
459         return OPERATOR_RUNNING_MODAL;
460 }
461
462 static int ed_marker_move_exec(bContext *C, wmOperator *op)
463 {
464         if(ed_marker_move_init(C, op)) {
465                 ed_marker_move_apply(C, op);
466                 ed_marker_move_exit(C, op);
467                 return OPERATOR_FINISHED;
468         }
469         return OPERATOR_CANCELLED;
470 }
471
472 static void ED_MARKER_OT_move(wmOperatorType *ot)
473 {
474         /* identifiers */
475         ot->name= "Move Time Marker";
476         ot->idname= "ED_MARKER_OT_move";
477         
478         /* api callbacks */
479         ot->exec= ed_marker_move_exec;
480         ot->invoke= ed_marker_move_invoke;
481         ot->modal= ed_marker_move_modal;
482         ot->poll= ED_operator_areaactive;
483         
484         /* rna storage */
485         RNA_def_property(ot->srna, "frs", PROP_INT, PROP_NONE);
486 }
487
488 /* ************************** duplicate markers *************************** */
489
490 /* operator state vars used:  
491         frs: delta movement
492
493 functions:
494
495         apply()  do the actual duplicate
496
497 callbacks:
498
499         exec()  calls apply, move_exec
500
501         invoke() calls apply, move_invoke
502
503         modal() uses move_modal
504
505 */
506
507
508 /* duplicate selected TimeMarkers */
509 static void ed_marker_duplicate_apply(bContext *C, wmOperator *op)
510 {
511         ListBase *markers= context_get_markers(C);
512         TimeMarker *marker, *newmarker;
513         
514         /* go through the list of markers, duplicate selected markers and add duplicated copies
515         * to the begining of the list (unselect original markers) */
516         for(marker= markers->first; marker; marker= marker->next) {
517                 if(marker->flag & SELECT){
518                         /* unselect selected marker */
519                         marker->flag &= ~SELECT;
520                         /* create and set up new marker */
521                         newmarker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
522                         newmarker->flag= SELECT;
523                         newmarker->frame= marker->frame;
524                         BLI_strncpy(newmarker->name, marker->name, sizeof(marker->name));
525                         /* new marker is added to the begining of list */
526                         BLI_addhead(markers, newmarker);
527                 }
528         }
529 }
530
531 static int ed_marker_duplicate_exec(bContext *C, wmOperator *op)
532 {
533         ed_marker_duplicate_apply(C, op);
534         ed_marker_move_exec(C, op);     /* assumes frs delta set */
535         
536         return OPERATOR_FINISHED;
537         
538 }
539
540 static int ed_marker_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *evt)
541 {
542         ed_marker_duplicate_apply(C, op);
543         return ed_marker_move_invoke(C, op, evt);
544 }
545
546 static void ED_MARKER_OT_duplicate(wmOperatorType *ot)
547 {
548         /* identifiers */
549         ot->name= "Duplicate Time Marker";
550         ot->idname= "ED_MARKER_OT_duplicate";
551         
552         /* api callbacks */
553         ot->exec= ed_marker_duplicate_exec;
554         ot->invoke= ed_marker_duplicate_invoke;
555         ot->modal= ed_marker_move_modal;
556         ot->poll= ED_operator_areaactive;
557         
558         /* rna storage */
559         RNA_def_property(ot->srna, "frs", PROP_INT, PROP_NONE);
560 }
561
562 /* ************************** selection ************************************/
563
564 /* select/deselect TimeMarker at current frame */
565 static void select_timeline_marker_frame(int frame, unsigned char shift)
566 {
567         TimeMarker *marker;
568         int select=0;
569         
570         for(marker= G.scene->markers.first; marker; marker= marker->next) {
571                 /* if Shift is not set, then deselect Markers */
572                 if(!shift) marker->flag &= ~SELECT;
573                 /* this way a not-shift select will allways give 1 selected marker */
574                 if((marker->frame == frame) && (!select)) {
575                         if(marker->flag & SELECT) 
576                                 marker->flag &= ~SELECT;
577                         else
578                                 marker->flag |= SELECT;
579                         select = 1;
580                 }
581         }
582 }
583
584 static int find_nearest_marker_time(ListBase *markers, float dx)
585 {
586         TimeMarker *marker, *nearest= NULL;
587         float dist, min_dist= 1000000;
588         
589         for(marker= markers->first; marker; marker= marker->next) {
590                 dist = ABS((float)marker->frame - dx);
591                 if(dist < min_dist){
592                         min_dist= dist;
593                         nearest= marker;
594                 }
595         }
596         
597         if(nearest) return nearest->frame;
598         else return (int)floor(dx); /* hrmf? */
599 }
600
601
602 static int ed_marker_select(bContext *C, wmEvent *evt, int extend)
603 {
604         ListBase *markers= context_get_markers(C);
605         View2D *v2d= UI_view2d_fromcontext(C);
606         float viewx;
607         int x, y, cfra;
608         
609         x= evt->x - C->region->winrct.xmin;
610         y= evt->y - C->region->winrct.ymin;
611         
612         UI_view2d_region_to_view(v2d, x, y, &viewx, NULL);      
613         
614         cfra= find_nearest_marker_time(markers, viewx);
615         
616         if (extend)
617                 select_timeline_marker_frame(cfra, 1);
618         else
619                 select_timeline_marker_frame(cfra, 0);
620         
621         WM_event_add_notifier(C, WM_NOTE_MARKERS_CHANGED, 0, NULL);
622
623         return OPERATOR_PASS_THROUGH;
624 }
625
626 static int ed_marker_select_extend_invoke(bContext *C, wmOperator *op, wmEvent *evt)
627 {
628         return ed_marker_select(C, evt, 1);
629 }
630
631 static int ed_marker_select_invoke(bContext *C, wmOperator *op, wmEvent *evt)
632 {
633         return ed_marker_select(C, evt, 0);
634 }
635
636 static void ED_MARKER_OT_mouseselect(wmOperatorType *ot)
637 {
638         /* identifiers */
639         ot->name= "Select Time Marker";
640         ot->idname= "ED_MARKER_OT_mouseselect";
641         
642         /* api callbacks */
643         ot->invoke= ed_marker_select_invoke;
644         ot->poll= ED_operator_areaactive;
645 }
646
647 static void ED_MARKER_OT_mouseselect_extend(wmOperatorType *ot)
648 {
649         /* identifiers */
650         ot->name= "Extend Select Time Marker";
651         ot->idname= "ED_MARKER_OT_mouseselect_extend";
652         
653         /* api callbacks */
654         ot->invoke= ed_marker_select_extend_invoke;
655         ot->poll= ED_operator_areaactive;
656 }
657
658 /* *************************** border select markers **************** */
659
660 /* operator state vars used: (added by default WM callbacks)   
661         xmin, ymin     
662         xmax, ymax     
663
664 customdata: the wmGesture pointer, with subwindow
665
666 callbacks:
667
668         exec()  has to be filled in by user
669
670         invoke() default WM function
671                         adds modal handler
672
673         modal() default WM function 
674                         accept modal events while doing it, calls exec(), handles ESC and border drawing
675
676         poll()  has to be filled in by user for context
677 */
678
679 static int ed_marker_border_select_exec(bContext *C, wmOperator *op)
680 {
681         View2D *v2d= UI_view2d_fromcontext(C);
682         ListBase *markers= context_get_markers(C);
683         TimeMarker *marker;
684         float xminf, xmaxf, yminf, ymaxf;
685         int event_type= RNA_int_get(op->ptr, "event_type");
686         int xmin= RNA_int_get(op->ptr, "xmin");
687         int xmax= RNA_int_get(op->ptr, "xmax");
688         int ymin= RNA_int_get(op->ptr, "ymin");
689         int ymax= RNA_int_get(op->ptr, "ymax");
690         
691         UI_view2d_region_to_view(v2d, xmin, ymin, &xminf, &yminf);      
692         UI_view2d_region_to_view(v2d, xmax, ymax, &xmaxf, &ymaxf);      
693         
694         /* XXX disputable */
695         if(yminf > 30.0f || ymaxf < 0.0f)
696                 return 0;
697         
698         /* XXX marker context */
699         for(marker= markers->first; marker; marker= marker->next) {
700                 if ((marker->frame > xminf) && (marker->frame <= xmaxf)) {
701                         switch (event_type) {
702                                 case LEFTMOUSE:
703                                         if ((marker->flag & SELECT) == 0) 
704                                                 marker->flag |= SELECT;
705                                         break;
706                                 case RIGHTMOUSE:
707                                         if (marker->flag & SELECT) 
708                                                 marker->flag &= ~SELECT;
709                                         break;
710                         }
711                 }
712         }
713         
714         WM_event_add_notifier(C, WM_NOTE_MARKERS_CHANGED, 0, NULL);
715
716         return 1;
717 }
718
719 static void ED_MARKER_OT_border_select(wmOperatorType *ot)
720 {
721         /* identifiers */
722         ot->name= "Marker Border select";
723         ot->idname= "ED_MARKER_OT_border_select";
724         
725         /* api callbacks */
726         ot->exec= ed_marker_border_select_exec;
727         ot->invoke= WM_border_select_invoke;
728         ot->modal= WM_border_select_modal;
729         
730         ot->poll= ED_operator_areaactive;
731         
732         /* rna */
733         RNA_def_property(ot->srna, "event_type", PROP_INT, PROP_NONE);
734         RNA_def_property(ot->srna, "xmin", PROP_INT, PROP_NONE);
735         RNA_def_property(ot->srna, "xmax", PROP_INT, PROP_NONE);
736         RNA_def_property(ot->srna, "ymin", PROP_INT, PROP_NONE);
737         RNA_def_property(ot->srna, "ymax", PROP_INT, PROP_NONE);
738         
739 }
740
741 /* *********************** (de)select all ***************** */
742
743 static int ed_marker_select_all_exec(bContext *C, wmOperator *op)
744 {
745         ListBase *markers= context_get_markers(C);
746         TimeMarker *marker;
747         int select= RNA_int_get(op->ptr, "select_type");
748         
749         if(RNA_int_get(op->ptr, "select_swap")) {
750                 for(marker= markers->first; marker; marker= marker->next) {
751                         if(marker->flag & SELECT)
752                                 break;
753                 }
754                 if(marker)
755                         select= 0;
756                 else
757                         select= 1;
758         }
759         
760         for(marker= markers->first; marker; marker= marker->next) {
761                 if(select)
762                         marker->flag |= SELECT;
763                 else
764                         marker->flag &= ~SELECT;
765         }
766         
767         WM_event_add_notifier(C, WM_NOTE_MARKERS_CHANGED, 0, NULL);
768
769         return OPERATOR_FINISHED;
770 }
771
772 static int ed_marker_select_all_invoke(bContext *C, wmOperator *op, wmEvent *evt)
773 {
774         RNA_int_set(op->ptr, "select_swap", 1);
775         
776         return ed_marker_select_all_exec(C, op);
777 }
778
779 static void ED_MARKER_OT_select_all(wmOperatorType *ot)
780 {
781         /* identifiers */
782         ot->name= "(De)select all markers";
783         ot->idname= "ED_MARKER_OT_select_all";
784         
785         /* api callbacks */
786         ot->exec= ed_marker_select_all_exec;
787         ot->invoke= ed_marker_select_all_invoke;
788         ot->poll= ED_operator_areaactive;
789         
790         /* rna */
791         RNA_def_property(ot->srna, "select_swap", PROP_INT, PROP_NONE);
792         RNA_def_property(ot->srna, "select_type", PROP_INT, PROP_NONE);
793         
794 }
795
796 /* ******************************* remove marker ***************** */
797
798 /* remove selected TimeMarkers */
799 static int ed_marker_delete_exec(bContext *C, wmOperator *op)
800 {
801         ListBase *markers= context_get_markers(C);
802         TimeMarker *marker, *nmarker;
803         short changed= 0;
804         
805         for(marker= markers->first; marker; marker= nmarker) {
806                 nmarker= marker->next;
807                 if(marker->flag & SELECT) {
808                         BLI_freelinkN(markers, marker);
809                         changed= 1;
810                 }
811         }
812         
813         if(changed) {
814                 WM_event_add_notifier(C, WM_NOTE_MARKERS_CHANGED, 0, NULL);
815         }
816         return OPERATOR_FINISHED;
817 }
818
819
820 static void ED_MARKER_OT_delete(wmOperatorType *ot)
821 {
822         /* identifiers */
823         ot->name= "Delete Markers";
824         ot->idname= "ED_MARKER_OT_delete";
825         
826         /* api callbacks */
827         ot->exec= ed_marker_delete_exec;
828         ot->poll= ED_operator_areaactive;
829         
830 }
831
832 /* ************************** registration **********************************/
833
834 /* called in ED_operatortypes_screen() */
835 void ED_marker_operatortypes(void)
836 {
837         WM_operatortype_append(ED_MARKER_OT_add);
838         WM_operatortype_append(ED_MARKER_OT_move);
839         WM_operatortype_append(ED_MARKER_OT_duplicate);
840         WM_operatortype_append(ED_MARKER_OT_mouseselect);
841         WM_operatortype_append(ED_MARKER_OT_mouseselect_extend);
842         WM_operatortype_append(ED_MARKER_OT_border_select);
843         WM_operatortype_append(ED_MARKER_OT_select_all);
844         WM_operatortype_append(ED_MARKER_OT_delete);
845 }
846
847