[#19688] pressing O and alt+O doesn't toggle proportional edit mode when editing...
[blender-staging.git] / source / blender / editors / space_sequencer / sequencer_select.c
1 /**
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * Contributor(s): Blender Foundation, 2003-2009, Campbell Barton
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 #include <stdlib.h>
28 #include <math.h>
29 #include <string.h>
30
31 #ifndef WIN32
32 #include <unistd.h>
33 #else
34 #include <io.h>
35 #endif
36 #include <sys/types.h>
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_blenlib.h"
41 #include "BLI_arithb.h"
42
43 #include "DNA_curve_types.h"
44 #include "DNA_scene_types.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_space_types.h"
47 #include "DNA_sequence_types.h"
48 #include "DNA_view2d_types.h"
49 #include "DNA_userdef_types.h"
50
51 #include "BKE_context.h"
52 #include "BKE_global.h"
53 #include "BKE_library.h"
54 #include "BKE_main.h"
55 #include "BKE_sequence.h"
56 #include "BKE_scene.h"
57 #include "BKE_utildefines.h"
58
59 #include "WM_api.h"
60 #include "WM_types.h"
61
62 #include "RNA_access.h"
63 #include "RNA_define.h"
64
65 /* for menu/popup icons etc etc*/
66 #include "UI_interface.h"
67 #include "UI_resources.h"
68
69 #include "ED_anim_api.h"
70 #include "ED_space_api.h"
71 #include "ED_types.h"
72 #include "ED_screen.h"
73 #include "ED_util.h"
74
75 #include "UI_interface.h"
76 #include "UI_resources.h"
77 #include "UI_view2d.h"
78
79 /* own include */
80 #include "sequencer_intern.h"
81 static void *find_nearest_marker() {return NULL;}
82 static void deselect_markers() {}
83         
84 void select_surrounding_handles(Scene *scene, Sequence *test) /* XXX BRING BACK */
85 {
86         Sequence *neighbor;
87         
88         neighbor=find_neighboring_sequence(scene, test, SEQ_SIDE_LEFT, -1);
89         if (neighbor) {
90                 neighbor->flag |= SELECT;
91                 recurs_sel_seq(neighbor);
92                 neighbor->flag |= SEQ_RIGHTSEL;
93         }
94         neighbor=find_neighboring_sequence(scene, test, SEQ_SIDE_RIGHT, -1);
95         if (neighbor) {
96                 neighbor->flag |= SELECT;
97                 recurs_sel_seq(neighbor);
98                 neighbor->flag |= SEQ_LEFTSEL;
99         }
100         test->flag |= SELECT;
101 }
102
103 /* used for mouse selection and for SEQUENCER_OT_select_active_side() */
104 static void select_active_side(ListBase *seqbase, int sel_side, int channel, int frame)
105 {
106         Sequence *seq;
107
108         for(seq= seqbase->first; seq; seq=seq->next) {
109                 if(channel==seq->machine) {
110                         switch(sel_side) {
111                         case SEQ_SIDE_LEFT:
112                                 if (frame > (seq->startdisp)) {
113                                         seq->flag &= ~(SEQ_RIGHTSEL|SEQ_LEFTSEL);
114                                         seq->flag |= SELECT;
115                                 }
116                                 break;
117                         case SEQ_SIDE_RIGHT:
118                                 if (frame < (seq->startdisp)) {
119                                         seq->flag &= ~(SEQ_RIGHTSEL|SEQ_LEFTSEL);
120                                         seq->flag |= SELECT;
121                                 }
122                                 break;
123                         case SEQ_SIDE_BOTH:
124                                 seq->flag &= ~(SEQ_RIGHTSEL|SEQ_LEFTSEL);
125                                 break;
126                         }
127                 }
128         }
129 }
130
131 #if 0 // BRING BACK
132 void select_surround_from_last(Scene *scene)
133 {
134         Sequence *seq=get_last_seq(scene);
135         
136         if (seq==NULL)
137                 return;
138         
139         select_surrounding_handles(scene, seq);
140 }
141 #endif
142
143
144 void select_single_seq(Scene *scene, Sequence *seq, int deselect_all) /* BRING BACK */
145 {
146         Editing *ed= seq_give_editing(scene, FALSE);
147         
148         if(deselect_all)
149                 deselect_all_seq(scene);
150         set_last_seq(scene, seq);
151
152         if((seq->type==SEQ_IMAGE) || (seq->type==SEQ_MOVIE)) {
153                 if(seq->strip)
154                         strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR-1);
155         }
156         else if(seq->type==SEQ_SOUND) {
157                 if(seq->strip)
158                         strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR-1);
159         }
160         seq->flag|= SELECT;
161         recurs_sel_seq(seq);
162 }
163
164 // remove this function, replace with invert operator
165 //void swap_select_seq(Scene *scene)
166
167 void select_neighbor_from_last(Scene *scene, int lr)
168 {
169         Sequence *seq=get_last_seq(scene);
170         Sequence *neighbor;
171         int change = 0;
172         if (seq) {
173                 neighbor=find_neighboring_sequence(scene, seq, lr, -1);
174                 if (neighbor) {
175                         switch (lr) {
176                         case SEQ_SIDE_LEFT:
177                                 neighbor->flag |= SELECT;
178                                 recurs_sel_seq(neighbor);
179                                 neighbor->flag |= SEQ_RIGHTSEL;
180                                 seq->flag |= SEQ_LEFTSEL;
181                                 break;
182                         case SEQ_SIDE_RIGHT:
183                                 neighbor->flag |= SELECT;
184                                 recurs_sel_seq(neighbor);
185                                 neighbor->flag |= SEQ_LEFTSEL;
186                                 seq->flag |= SEQ_RIGHTSEL;
187                                 break;
188                         }
189                 seq->flag |= SELECT;
190                 change = 1;
191                 }
192         }
193         if (change) {
194         }
195 }
196
197
198 /* (de)select operator */
199 static int sequencer_deselect_exec(bContext *C, wmOperator *op)
200 {
201         Scene *scene= CTX_data_scene(C);
202         Editing *ed= seq_give_editing(scene, FALSE);
203         Sequence *seq;
204         int desel = 0;
205
206         if(ed==NULL)
207                 return OPERATOR_CANCELLED;
208
209         for(seq= ed->seqbasep->first; seq; seq=seq->next) {
210                 if(seq->flag & SEQ_ALLSEL) {
211                         desel= 1;
212                         break;
213                 }
214         }
215
216         for(seq= ed->seqbasep->first; seq; seq=seq->next) {
217                 if (desel) {
218                         seq->flag &= SEQ_DESEL;
219                 }
220                 else {
221                         seq->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
222                         seq->flag |= SELECT;
223                 }
224         }
225         ED_area_tag_redraw(CTX_wm_area(C));
226         
227         return OPERATOR_FINISHED;
228 }
229
230 void SEQUENCER_OT_select_all_toggle(struct wmOperatorType *ot)
231 {
232         /* identifiers */
233         ot->name= "(De)Select All";
234         ot->idname= "SEQUENCER_OT_select_all_toggle";
235         ot->description="Select or deselect all strips.";
236         
237         /* api callbacks */
238         ot->exec= sequencer_deselect_exec;
239
240         ot->poll= ED_operator_sequencer_active;
241         
242         /* flags */
243         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
244 }
245
246
247 /* (de)select operator */
248 static int sequencer_select_inverse_exec(bContext *C, wmOperator *op)
249 {
250         Scene *scene= CTX_data_scene(C);
251         Editing *ed= seq_give_editing(scene, FALSE);
252         Sequence *seq;
253
254         if(ed==NULL)
255                 return OPERATOR_CANCELLED;
256
257         for(seq= ed->seqbasep->first; seq; seq=seq->next) {
258                 if (seq->flag & SELECT) {
259                         seq->flag &= SEQ_DESEL;
260                 }
261                 else {
262                         seq->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
263                         seq->flag |= SELECT;
264                 }
265         }
266         ED_area_tag_redraw(CTX_wm_area(C));
267         
268         return OPERATOR_FINISHED;
269 }
270
271 void SEQUENCER_OT_select_inverse(struct wmOperatorType *ot)
272 {
273         /* identifiers */
274         ot->name= "Select Inverse";
275         ot->idname= "SEQUENCER_OT_select_inverse";
276         ot->description="Select unselected strips.";
277         
278         /* api callbacks */
279         ot->exec= sequencer_select_inverse_exec;
280
281         ot->poll= ED_operator_sequencer_active;
282         
283         /* flags */
284         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
285 }
286
287 static int sequencer_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
288 {
289         ARegion *ar= CTX_wm_region(C);
290         View2D *v2d= UI_view2d_fromcontext(C);
291         Scene *scene= CTX_data_scene(C);
292         Editing *ed= seq_give_editing(scene, FALSE);
293         short extend= RNA_boolean_get(op->ptr, "extend");
294         short linked_handle= RNA_boolean_get(op->ptr, "linked_handle");
295         short left_right= RNA_boolean_get(op->ptr, "left_right");
296
297         short mval[2];  
298         
299         Sequence *seq,*neighbor, *act_orig;
300         int hand,sel_side;
301         TimeMarker *marker;
302
303         if(ed==NULL)
304                 return OPERATOR_CANCELLED;
305         
306         marker=find_nearest_marker(SCE_MARKERS, 1); //XXX - dummy function for now
307         
308         mval[0]= event->x - ar->winrct.xmin;
309         mval[1]= event->y - ar->winrct.ymin;
310         
311         if (marker) {
312                 int oldflag;
313                 /* select timeline marker */
314                 if (extend) {
315                         oldflag= marker->flag;
316                         if (oldflag & SELECT)
317                                 marker->flag &= ~SELECT;
318                         else
319                                 marker->flag |= SELECT;
320                 }
321                 else {
322                         deselect_markers(0, 0);
323                         marker->flag |= SELECT;                         
324                 }
325                 
326         } else if (left_right) {
327                 /* use different logic for this */
328                 float x;
329                 deselect_all_seq(scene);
330                 UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, NULL);
331
332                 SEQP_BEGIN(ed, seq) {
333                         if (x < CFRA) {
334                                 if(seq->enddisp < CFRA) {
335                                         seq->flag |= SELECT;
336                                         recurs_sel_seq(seq);
337                                 }
338                         }
339                         else {
340                                 if(seq->startdisp > CFRA) {
341                                         seq->flag |= SELECT;
342                                         recurs_sel_seq(seq);
343                                 }
344                         }
345
346                 }
347                 SEQ_END
348         } else {
349         
350                 seq= find_nearest_seq(scene, v2d, &hand, mval);
351                 act_orig= ed->act_seq;
352
353                 if(extend == 0 && linked_handle==0)
354                         deselect_all_seq(scene);
355         
356                 if(seq) {
357                         set_last_seq(scene, seq);
358         
359                         if ((seq->type == SEQ_IMAGE) || (seq->type == SEQ_MOVIE)) {
360                                 if(seq->strip) {
361                                         strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR-1);
362                                 }
363                         } else
364                         if (seq->type == SEQ_SOUND) {
365                                 if(seq->strip) {
366                                         strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR-1);
367                                 }
368                         }
369         
370                         if(extend && (seq->flag & SELECT) && ed->act_seq == act_orig ) {
371                                 switch(hand) {
372                                 case SEQ_SIDE_NONE:
373                                         if (linked_handle==0)
374                                                 seq->flag &= SEQ_DESEL;
375                                         break;
376                                 case SEQ_SIDE_LEFT:
377                                         seq->flag ^= SEQ_LEFTSEL;
378                                         break;
379                                 case SEQ_SIDE_RIGHT:
380                                         seq->flag ^= SEQ_RIGHTSEL;
381                                         break;
382                                 }
383                         }
384                         else {
385                                 seq->flag |= SELECT;
386                                 if(hand==SEQ_SIDE_LEFT)         seq->flag |= SEQ_LEFTSEL;
387                                 if(hand==SEQ_SIDE_RIGHT)        seq->flag |= SEQ_RIGHTSEL;
388                         }
389                         
390                         /* On Alt selection, select the strip and bordering handles */
391                         if (linked_handle && !ELEM(hand, SEQ_SIDE_LEFT, SEQ_SIDE_RIGHT)) {
392                                 if(extend==0) deselect_all_seq(scene);
393                                 seq->flag |= SELECT;
394                                 select_surrounding_handles(scene, seq);
395                         }
396                         else if (linked_handle && ELEM(hand, SEQ_SIDE_LEFT, SEQ_SIDE_RIGHT) && (seq->flag & SELECT)) {
397                                 /*
398                                  * First click selects adjacent handles on that side.
399                                  * Second click selects all strips in that direction.
400                                  * If there are no adjacent strips, it just selects all in that direction.
401                                  */
402                                 sel_side= hand;
403                                 neighbor=find_neighboring_sequence(scene, seq, sel_side, -1);
404                                 if (neighbor) {
405                                         switch (sel_side) {
406                                         case SEQ_SIDE_LEFT:
407                                                 if ((seq->flag & SEQ_LEFTSEL) && (neighbor->flag & SEQ_RIGHTSEL)) {
408                                                         if(extend==0) deselect_all_seq(scene);
409                                                         seq->flag |= SELECT;
410                                                         
411                                                         select_active_side(ed->seqbasep, SEQ_SIDE_LEFT, seq->machine, seq->startdisp);
412                                                 } else {
413                                                         if(extend==0) deselect_all_seq(scene);
414                                                         seq->flag |= SELECT;
415
416                                                         neighbor->flag |= SELECT;
417                                                         recurs_sel_seq(neighbor);
418                                                         neighbor->flag |= SEQ_RIGHTSEL;
419                                                         seq->flag |= SEQ_LEFTSEL;
420                                                 }
421                                                 break;
422                                         case SEQ_SIDE_RIGHT:
423                                                 if ((seq->flag & SEQ_RIGHTSEL) && (neighbor->flag & SEQ_LEFTSEL)) {
424                                                         if(extend==0) deselect_all_seq(scene);
425                                                         seq->flag |= SELECT;
426
427                                                         select_active_side(ed->seqbasep, SEQ_SIDE_RIGHT, seq->machine, seq->startdisp);
428                                                 } else {
429                                                         if(extend==0) deselect_all_seq(scene);
430                                                         seq->flag |= SELECT;
431
432                                                         neighbor->flag |= SELECT;
433                                                         recurs_sel_seq(neighbor);
434                                                         neighbor->flag |= SEQ_LEFTSEL;
435                                                         seq->flag |= SEQ_RIGHTSEL;
436                                                 }
437                                                 break;
438                                         }
439                                 } else {
440                                         if(extend==0) deselect_all_seq(scene);
441                                         select_active_side(ed->seqbasep, sel_side, seq->machine, seq->startdisp);
442                                 }
443                         }
444                         recurs_sel_seq(seq);
445                 }
446         }
447         
448         /* marker transform */
449 #if 0 // XXX probably need to redo this differently for 2.5
450         if (marker) {
451                 short mval[2], xo, yo;
452 //              getmouseco_areawin(mval);
453                 xo= mval[0]; 
454                 yo= mval[1];
455                 
456                 while(get_mbut()) {             
457 //                      getmouseco_areawin(mval);
458                         if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
459                                 transform_markers('g', 0);
460                                 return;
461                         }
462                 }
463         }
464 #endif
465         
466         ED_area_tag_redraw(CTX_wm_area(C));
467         /* allowing tweaks */
468         return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
469 }
470
471 void SEQUENCER_OT_select(wmOperatorType *ot)
472 {
473         /* identifiers */
474         ot->name= "Activate/Select";
475         ot->idname= "SEQUENCER_OT_select";
476         ot->description="Select a strip (last selected becomes the \"active strip\").";
477         
478         /* api callbacks */
479         ot->invoke= sequencer_select_invoke;
480         ot->poll= ED_operator_sequencer_active;
481         
482         /* flags */
483         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
484         
485         /* properties */
486         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection.");
487         RNA_def_boolean(ot->srna, "linked_handle", 0, "Linked Handle", "Select handles next to the active strip.");
488         /* for animation this is an enum but atm having an enum isnt useful for us */
489         RNA_def_boolean(ot->srna, "left_right", 0, "Left/Right", "select based on the frame side the cursor is on.");
490 }
491
492
493
494
495 /* run recursivly to select linked */
496 static int select_more_less_seq__internal(Scene *scene, int sel, int linked) {
497         Editing *ed= seq_give_editing(scene, FALSE);
498         Sequence *seq, *neighbor;
499         int change=0;
500         int isel;
501         
502         if(ed==NULL) return 0;
503         
504         if (sel) {
505                 sel = SELECT;
506                 isel = 0;
507         } else {
508                 sel = 0;
509                 isel = SELECT;
510         }
511         
512         if (!linked) {
513                 /* if not linked we only want to touch each seq once, newseq */
514                 for(seq= ed->seqbasep->first; seq; seq= seq->next) {
515                         seq->tmp = NULL;
516                 }
517         }
518         
519         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
520                 if((int)(seq->flag & SELECT) == sel) {
521                         if ((linked==0 && seq->tmp)==0) {
522                                 /* only get unselected nabours */
523                                 neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, isel);
524                                 if (neighbor) {
525                                         if (sel) {neighbor->flag |= SELECT; recurs_sel_seq(neighbor);}
526                                         else            neighbor->flag &= ~SELECT;
527                                         if (linked==0) neighbor->tmp = (Sequence *)1;
528                                         change = 1;
529                                 }
530                                 neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, isel);
531                                 if (neighbor) {
532                                         if (sel) {neighbor->flag |= SELECT; recurs_sel_seq(neighbor);}
533                                         else            neighbor->flag &= ~SELECT;
534                                         if (linked==0) neighbor->tmp = (void *)1;
535                                         change = 1;
536                                 }
537                         }
538                 }
539         }
540         
541         return change;
542 }
543
544
545
546 /* select more operator */
547 static int sequencer_select_more_exec(bContext *C, wmOperator *op)
548 {
549         Scene *scene= CTX_data_scene(C);
550         
551         if (select_more_less_seq__internal(scene, 0, 0)) {
552                 ED_area_tag_redraw(CTX_wm_area(C));
553         }
554         
555         return OPERATOR_FINISHED;
556 }
557
558 void SEQUENCER_OT_select_more(wmOperatorType *ot)
559 {
560         /* identifiers */
561         ot->name= "Select More";
562         ot->idname= "SEQUENCER_OT_select_more";
563         ot->description="DOC_BROKEN";
564         
565         /* api callbacks */
566         ot->exec= sequencer_select_more_exec;
567         ot->poll= ED_operator_sequencer_active;
568         
569         /* flags */
570         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
571         
572         /* properties */
573 }
574
575
576 /* select less operator */
577 static int sequencer_select_less_exec(bContext *C, wmOperator *op)
578 {
579         Scene *scene= CTX_data_scene(C);
580         
581         if (select_more_less_seq__internal(scene, 1, 0)) {
582                 ED_area_tag_redraw(CTX_wm_area(C));
583         }
584         
585         return OPERATOR_FINISHED;
586 }
587
588 void SEQUENCER_OT_select_less(wmOperatorType *ot)
589 {
590         /* identifiers */
591         ot->name= "Select less";
592         ot->idname= "SEQUENCER_OT_select_less";
593         ot->description="DOC_BROKEN";
594         
595         /* api callbacks */
596         ot->exec= sequencer_select_less_exec;
597         ot->poll= ED_operator_sequencer_active;
598         
599         /* flags */
600         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
601         
602         /* properties */
603 }
604
605
606 /* select pick linked operator (uses the mouse) */
607 static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
608 {
609         Scene *scene= CTX_data_scene(C);
610         ARegion *ar= CTX_wm_region(C);
611         View2D *v2d= UI_view2d_fromcontext(C);
612         
613         short extend= RNA_boolean_get(op->ptr, "extend");
614         short mval[2];  
615         
616         Sequence *mouse_seq;
617         int selected, hand;
618         
619         mval[0]= event->x - ar->winrct.xmin;
620         mval[1]= event->y - ar->winrct.ymin;
621         
622         /* this works like UV, not mesh */
623         mouse_seq= find_nearest_seq(scene, v2d, &hand, mval);
624         if (!mouse_seq)
625                 return OPERATOR_FINISHED; /* user error as with mesh?? */
626         
627         if (extend==0)
628                 deselect_all_seq(scene);
629         
630         mouse_seq->flag |= SELECT;
631         recurs_sel_seq(mouse_seq);
632         
633         selected = 1;
634         while (selected) {
635                 selected = select_more_less_seq__internal(scene, 1, 1);
636         }
637         
638         ED_area_tag_redraw(CTX_wm_area(C));
639         
640         return OPERATOR_FINISHED;
641 }
642
643 void SEQUENCER_OT_select_linked_pick(wmOperatorType *ot)
644 {
645         /* identifiers */
646         ot->name= "Select pick linked";
647         ot->idname= "SEQUENCER_OT_select_linked_pick";
648         ot->description="DOC_BROKEN";
649         
650         /* api callbacks */
651         ot->invoke= sequencer_select_linked_pick_invoke;
652         ot->poll= ED_operator_sequencer_active;
653         
654         /* flags */
655         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
656         
657         /* properties */
658         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "extend the selection");
659 }
660
661
662 /* select linked operator */
663 static int sequencer_select_linked_exec(bContext *C, wmOperator *op)
664 {
665         Scene *scene= CTX_data_scene(C);
666         int selected;
667
668         selected = 1;
669         while (selected) {
670                 selected = select_more_less_seq__internal(scene, 1, 1);
671         }
672
673         ED_area_tag_redraw(CTX_wm_area(C));
674
675         return OPERATOR_FINISHED;
676 }
677
678 void SEQUENCER_OT_select_linked(wmOperatorType *ot)
679 {
680         /* identifiers */
681         ot->name= "Select linked";
682         ot->idname= "SEQUENCER_OT_select_linked";
683         ot->description="DOC_BROKEN";
684         
685         /* api callbacks */
686         ot->exec= sequencer_select_linked_exec;
687         ot->poll= ED_operator_sequencer_active;
688         
689         /* flags */
690         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
691         
692         /* properties */
693 }
694
695
696 /* select handles operator */
697 static int sequencer_select_handles_exec(bContext *C, wmOperator *op)
698 {
699         Scene *scene= CTX_data_scene(C);
700         Editing *ed= seq_give_editing(scene, 0);
701         Sequence *seq;
702         int sel_side= RNA_enum_get(op->ptr, "side");
703
704         if (ed==NULL)
705                 return OPERATOR_CANCELLED;
706
707         for(seq= ed->seqbasep->first; seq; seq=seq->next) {
708                 if (seq->flag & SELECT) {
709                         switch(sel_side) {
710                         case SEQ_SIDE_LEFT:
711                                 seq->flag &= ~SEQ_RIGHTSEL;
712                                 seq->flag |= SEQ_LEFTSEL;
713                                 break;
714                         case SEQ_SIDE_RIGHT:
715                                 seq->flag &= ~SEQ_LEFTSEL;
716                                 seq->flag |= SEQ_RIGHTSEL;
717                                 break;
718                         case SEQ_SIDE_BOTH:
719                                 seq->flag |= SEQ_LEFTSEL+SEQ_RIGHTSEL;
720                                 break;
721                         }
722                 }
723         }
724
725         ED_area_tag_redraw(CTX_wm_area(C));
726
727         return OPERATOR_FINISHED;
728 }
729
730 void SEQUENCER_OT_select_handles(wmOperatorType *ot)
731 {
732         /* identifiers */
733         ot->name= "Select Handles";
734         ot->idname= "SEQUENCER_OT_select_handles";
735         ot->description="DOC_BROKEN";
736         
737         /* api callbacks */
738         ot->exec= sequencer_select_handles_exec;
739         ot->poll= ED_operator_sequencer_active;
740         
741         /* flags */
742         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
743         
744         /* properties */
745         RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side of the handle that is selected");
746 }
747
748 /* select side operator */
749 static int sequencer_select_active_side_exec(bContext *C, wmOperator *op)
750 {
751         Scene *scene= CTX_data_scene(C);
752         Editing *ed= seq_give_editing(scene, 0);
753         Sequence *seq_act=get_last_seq(scene);
754
755         if (ed==NULL || seq_act==NULL)
756                 return OPERATOR_CANCELLED;
757
758         seq_act->flag |= SELECT;
759
760         select_active_side(ed->seqbasep, RNA_enum_get(op->ptr, "side"), seq_act->machine, seq_act->startdisp);
761
762         ED_area_tag_redraw(CTX_wm_area(C));
763
764         return OPERATOR_FINISHED;
765 }
766
767 void SEQUENCER_OT_select_active_side(wmOperatorType *ot)
768 {
769         /* identifiers */
770         ot->name= "Select Active Side";
771         ot->idname= "SEQUENCER_OT_select_active_side";
772         ot->description="DOC_BROKEN";
773         
774         /* api callbacks */
775         ot->exec= sequencer_select_active_side_exec;
776         ot->poll= ED_operator_sequencer_active;
777
778         /* flags */
779         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
780
781         /* properties */
782         RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side of the handle that is selected");
783 }
784
785
786 /* borderselect operator */
787 static int sequencer_borderselect_exec(bContext *C, wmOperator *op)
788 {
789         Scene *scene= CTX_data_scene(C);
790         Editing *ed= seq_give_editing(scene, FALSE);
791         View2D *v2d= UI_view2d_fromcontext(C);
792         
793         Sequence *seq;
794         rcti rect;
795         rctf rectf, rq;
796         int val;
797         short mval[2];
798
799         if(ed==NULL)
800                 return OPERATOR_CANCELLED;
801
802         val= RNA_int_get(op->ptr, "event_type");
803         rect.xmin= RNA_int_get(op->ptr, "xmin");
804         rect.ymin= RNA_int_get(op->ptr, "ymin");
805         rect.xmax= RNA_int_get(op->ptr, "xmax");
806         rect.ymax= RNA_int_get(op->ptr, "ymax");
807         
808         mval[0]= rect.xmin;
809         mval[1]= rect.ymin;
810         UI_view2d_region_to_view(v2d, mval[0], mval[1], &rectf.xmin, &rectf.ymin);
811         mval[0]= rect.xmax;
812         mval[1]= rect.ymax;
813         UI_view2d_region_to_view(v2d, mval[0], mval[1], &rectf.xmax, &rectf.ymax);
814
815         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
816                 seq_rectf(seq, &rq);
817                 
818                 if(BLI_isect_rctf(&rq, &rectf, 0)) {
819                         if(val==LEFTMOUSE)      seq->flag |= SELECT;
820                         else                            seq->flag &= SEQ_DESEL;
821                         recurs_sel_seq(seq);
822                 }
823         }
824
825         return OPERATOR_FINISHED;
826
827
828
829 /* ****** Border Select ****** */
830 void SEQUENCER_OT_select_border(wmOperatorType *ot)
831 {
832         /* identifiers */
833         ot->name= "Border Select";
834         ot->idname= "SEQUENCER_OT_select_border";
835         ot->description="Enable border select mode.";
836         
837         /* api callbacks */
838         ot->invoke= WM_border_select_invoke;
839         ot->exec= sequencer_borderselect_exec;
840         ot->modal= WM_border_select_modal;
841         
842         ot->poll= ED_operator_sequencer_active;
843         
844         /* flags */
845         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
846         
847         /* rna */
848         RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
849         RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
850         RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
851         RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
852         RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
853 }