batch remove .'s used with RNA_def_struct_ui_text
[blender.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_math.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_sequencer.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 /* used for mouse selection and for SEQUENCER_OT_select_active_side() */
132 static void select_linked_time(ListBase *seqbase, Sequence *seq_link)
133 {
134         Sequence *seq;
135
136         for(seq= seqbase->first; seq; seq=seq->next) {
137                 if(seq_link->machine != seq->machine) {
138                         int left_match = (seq->startdisp == seq_link->startdisp) ? 1:0;
139                         int right_match = (seq->enddisp == seq_link->enddisp) ? 1:0;
140
141                         if(left_match && right_match) {
142                                 /* a direct match, copy the selection settinhs */
143                                 seq->flag &= ~(SELECT|SEQ_LEFTSEL|SEQ_RIGHTSEL);
144                                 seq->flag |= seq_link->flag & (SELECT|SEQ_LEFTSEL|SEQ_RIGHTSEL);
145
146                                 recurs_sel_seq(seq);
147                         }
148                         else if(seq_link->flag & SELECT && (left_match || right_match)) {
149
150                                 /* clear for reselection */
151                                 seq->flag &= ~(SEQ_LEFTSEL|SEQ_RIGHTSEL);
152
153                                 if(left_match && seq_link->flag & SEQ_LEFTSEL)
154                                         seq->flag |= SELECT|SEQ_LEFTSEL;
155
156                                 if(right_match && seq_link->flag & SEQ_RIGHTSEL)
157                                         seq->flag |= SELECT|SEQ_RIGHTSEL;
158
159                                 recurs_sel_seq(seq);
160                         }
161                 }
162         }
163 }
164
165 #if 0 // BRING BACK
166 void select_surround_from_last(Scene *scene)
167 {
168         Sequence *seq=get_last_seq(scene);
169         
170         if (seq==NULL)
171                 return;
172         
173         select_surrounding_handles(scene, seq);
174 }
175 #endif
176
177
178 void select_single_seq(Scene *scene, Sequence *seq, int deselect_all) /* BRING BACK */
179 {
180         Editing *ed= seq_give_editing(scene, FALSE);
181         
182         if(deselect_all)
183                 deselect_all_seq(scene);
184         active_seq_set(scene, seq);
185
186         if((seq->type==SEQ_IMAGE) || (seq->type==SEQ_MOVIE)) {
187                 if(seq->strip)
188                         strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR-1);
189         }
190         else if(seq->type==SEQ_SOUND) {
191                 if(seq->strip)
192                         strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR-1);
193         }
194         seq->flag|= SELECT;
195         recurs_sel_seq(seq);
196 }
197
198 // remove this function, replace with invert operator
199 //void swap_select_seq(Scene *scene)
200
201 void select_neighbor_from_last(Scene *scene, int lr)
202 {
203         Sequence *seq= active_seq_get(scene);
204         Sequence *neighbor;
205         int change = 0;
206         if (seq) {
207                 neighbor=find_neighboring_sequence(scene, seq, lr, -1);
208                 if (neighbor) {
209                         switch (lr) {
210                         case SEQ_SIDE_LEFT:
211                                 neighbor->flag |= SELECT;
212                                 recurs_sel_seq(neighbor);
213                                 neighbor->flag |= SEQ_RIGHTSEL;
214                                 seq->flag |= SEQ_LEFTSEL;
215                                 break;
216                         case SEQ_SIDE_RIGHT:
217                                 neighbor->flag |= SELECT;
218                                 recurs_sel_seq(neighbor);
219                                 neighbor->flag |= SEQ_LEFTSEL;
220                                 seq->flag |= SEQ_RIGHTSEL;
221                                 break;
222                         }
223                 seq->flag |= SELECT;
224                 change = 1;
225                 }
226         }
227         if (change) {
228         }
229 }
230
231
232 /* (de)select operator */
233 static int sequencer_deselect_exec(bContext *C, wmOperator *op)
234 {
235         Scene *scene= CTX_data_scene(C);
236         Editing *ed= seq_give_editing(scene, FALSE);
237         Sequence *seq;
238         int desel = 0;
239
240         if(ed==NULL)
241                 return OPERATOR_CANCELLED;
242
243         for(seq= ed->seqbasep->first; seq; seq=seq->next) {
244                 if(seq->flag & SEQ_ALLSEL) {
245                         desel= 1;
246                         break;
247                 }
248         }
249
250         for(seq= ed->seqbasep->first; seq; seq=seq->next) {
251                 if (desel) {
252                         seq->flag &= SEQ_DESEL;
253                 }
254                 else {
255                         seq->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
256                         seq->flag |= SELECT;
257                 }
258         }
259
260         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER_SELECT, scene);
261         
262         return OPERATOR_FINISHED;
263 }
264
265 void SEQUENCER_OT_select_all_toggle(struct wmOperatorType *ot)
266 {
267         /* identifiers */
268         ot->name= "(De)Select All";
269         ot->idname= "SEQUENCER_OT_select_all_toggle";
270         ot->description="Select or deselect all strips";
271         
272         /* api callbacks */
273         ot->exec= sequencer_deselect_exec;
274
275         ot->poll= ED_operator_sequencer_active;
276         
277         /* flags */
278         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
279 }
280
281
282 /* (de)select operator */
283 static int sequencer_select_inverse_exec(bContext *C, wmOperator *op)
284 {
285         Scene *scene= CTX_data_scene(C);
286         Editing *ed= seq_give_editing(scene, FALSE);
287         Sequence *seq;
288
289         if(ed==NULL)
290                 return OPERATOR_CANCELLED;
291
292         for(seq= ed->seqbasep->first; seq; seq=seq->next) {
293                 if (seq->flag & SELECT) {
294                         seq->flag &= SEQ_DESEL;
295                 }
296                 else {
297                         seq->flag &= ~(SEQ_LEFTSEL+SEQ_RIGHTSEL);
298                         seq->flag |= SELECT;
299                 }
300         }
301
302         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER_SELECT, scene);
303         
304         return OPERATOR_FINISHED;
305 }
306
307 void SEQUENCER_OT_select_inverse(struct wmOperatorType *ot)
308 {
309         /* identifiers */
310         ot->name= "Select Inverse";
311         ot->idname= "SEQUENCER_OT_select_inverse";
312         ot->description="Select unselected strips";
313         
314         /* api callbacks */
315         ot->exec= sequencer_select_inverse_exec;
316
317         ot->poll= ED_operator_sequencer_active;
318         
319         /* flags */
320         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
321 }
322
323 static int sequencer_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
324 {
325         ARegion *ar= CTX_wm_region(C);
326         View2D *v2d= UI_view2d_fromcontext(C);
327         Scene *scene= CTX_data_scene(C);
328         Editing *ed= seq_give_editing(scene, FALSE);
329         short extend= RNA_boolean_get(op->ptr, "extend");
330         short linked_handle= RNA_boolean_get(op->ptr, "linked_handle");
331         short left_right= RNA_boolean_get(op->ptr, "left_right");
332         short linked_time= RNA_boolean_get(op->ptr, "linked_time");
333
334         short mval[2];  
335         
336         Sequence *seq,*neighbor, *act_orig;
337         int hand,sel_side;
338         TimeMarker *marker;
339
340         if(ed==NULL)
341                 return OPERATOR_CANCELLED;
342         
343         marker=find_nearest_marker(SCE_MARKERS, 1); //XXX - dummy function for now
344         
345         mval[0]= event->x - ar->winrct.xmin;
346         mval[1]= event->y - ar->winrct.ymin;
347         
348         seq= find_nearest_seq(scene, v2d, &hand, mval);
349
350         // XXX - not nice, Ctrl+RMB needs to do left_right only when not over a strip
351         if(seq && linked_time && left_right)
352                 left_right= FALSE;
353
354
355         if (marker) {
356                 int oldflag;
357                 /* select timeline marker */
358                 if (extend) {
359                         oldflag= marker->flag;
360                         if (oldflag & SELECT)
361                                 marker->flag &= ~SELECT;
362                         else
363                                 marker->flag |= SELECT;
364                 }
365                 else {
366                         deselect_markers(0, 0);
367                         marker->flag |= SELECT;                         
368                 }
369                 
370         } else if (left_right) {
371                 /* use different logic for this */
372                 float x;
373                 deselect_all_seq(scene);
374                 UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, NULL);
375
376                 SEQP_BEGIN(ed, seq) {
377                         if (x < CFRA) {
378                                 if(seq->enddisp < CFRA) {
379                                         seq->flag |= SELECT;
380                                         recurs_sel_seq(seq);
381                                 }
382                         }
383                         else {
384                                 if(seq->startdisp > CFRA) {
385                                         seq->flag |= SELECT;
386                                         recurs_sel_seq(seq);
387                                 }
388                         }
389                 }
390                 SEQ_END
391         } else {
392                 // seq= find_nearest_seq(scene, v2d, &hand, mval);
393
394                 act_orig= ed->act_seq;
395
396                 if(extend == 0 && linked_handle==0)
397                         deselect_all_seq(scene);
398         
399                 if(seq) {
400                         active_seq_set(scene, seq);
401         
402                         if ((seq->type == SEQ_IMAGE) || (seq->type == SEQ_MOVIE)) {
403                                 if(seq->strip) {
404                                         strncpy(ed->act_imagedir, seq->strip->dir, FILE_MAXDIR-1);
405                                 }
406                         } else
407                         if (seq->type == SEQ_SOUND) {
408                                 if(seq->strip) {
409                                         strncpy(ed->act_sounddir, seq->strip->dir, FILE_MAXDIR-1);
410                                 }
411                         }
412         
413                         if(extend && (seq->flag & SELECT) && ed->act_seq == act_orig ) {
414                                 switch(hand) {
415                                 case SEQ_SIDE_NONE:
416                                         if (linked_handle==0)
417                                                 seq->flag &= SEQ_DESEL;
418                                         break;
419                                 case SEQ_SIDE_LEFT:
420                                         seq->flag ^= SEQ_LEFTSEL;
421                                         break;
422                                 case SEQ_SIDE_RIGHT:
423                                         seq->flag ^= SEQ_RIGHTSEL;
424                                         break;
425                                 }
426                         }
427                         else {
428                                 seq->flag |= SELECT;
429                                 if(hand==SEQ_SIDE_LEFT)         seq->flag |= SEQ_LEFTSEL;
430                                 if(hand==SEQ_SIDE_RIGHT)        seq->flag |= SEQ_RIGHTSEL;
431                         }
432                         
433                         /* On Alt selection, select the strip and bordering handles */
434                         if (linked_handle && !ELEM(hand, SEQ_SIDE_LEFT, SEQ_SIDE_RIGHT)) {
435                                 if(extend==0) deselect_all_seq(scene);
436                                 seq->flag |= SELECT;
437                                 select_surrounding_handles(scene, seq);
438                         }
439                         else if (linked_handle && ELEM(hand, SEQ_SIDE_LEFT, SEQ_SIDE_RIGHT) && (seq->flag & SELECT)) {
440                                 /*
441                                  * First click selects adjacent handles on that side.
442                                  * Second click selects all strips in that direction.
443                                  * If there are no adjacent strips, it just selects all in that direction.
444                                  */
445                                 sel_side= hand;
446                                 neighbor=find_neighboring_sequence(scene, seq, sel_side, -1);
447                                 if (neighbor) {
448                                         switch (sel_side) {
449                                         case SEQ_SIDE_LEFT:
450                                                 if ((seq->flag & SEQ_LEFTSEL) && (neighbor->flag & SEQ_RIGHTSEL)) {
451                                                         if(extend==0) deselect_all_seq(scene);
452                                                         seq->flag |= SELECT;
453                                                         
454                                                         select_active_side(ed->seqbasep, SEQ_SIDE_LEFT, seq->machine, seq->startdisp);
455                                                 } else {
456                                                         if(extend==0) deselect_all_seq(scene);
457                                                         seq->flag |= SELECT;
458
459                                                         neighbor->flag |= SELECT;
460                                                         recurs_sel_seq(neighbor);
461                                                         neighbor->flag |= SEQ_RIGHTSEL;
462                                                         seq->flag |= SEQ_LEFTSEL;
463                                                 }
464                                                 break;
465                                         case SEQ_SIDE_RIGHT:
466                                                 if ((seq->flag & SEQ_RIGHTSEL) && (neighbor->flag & SEQ_LEFTSEL)) {
467                                                         if(extend==0) deselect_all_seq(scene);
468                                                         seq->flag |= SELECT;
469
470                                                         select_active_side(ed->seqbasep, SEQ_SIDE_RIGHT, seq->machine, seq->startdisp);
471                                                 } else {
472                                                         if(extend==0) deselect_all_seq(scene);
473                                                         seq->flag |= SELECT;
474
475                                                         neighbor->flag |= SELECT;
476                                                         recurs_sel_seq(neighbor);
477                                                         neighbor->flag |= SEQ_LEFTSEL;
478                                                         seq->flag |= SEQ_RIGHTSEL;
479                                                 }
480                                                 break;
481                                         }
482                                 } else {
483                                         if(extend==0) deselect_all_seq(scene);
484                                         select_active_side(ed->seqbasep, sel_side, seq->machine, seq->startdisp);
485                                 }
486                         }
487                         recurs_sel_seq(seq);
488
489                         if(linked_time) {
490                                 select_linked_time(ed->seqbasep, seq);
491                         }
492                 }
493         }
494         
495         /* marker transform */
496 #if 0 // XXX probably need to redo this differently for 2.5
497         if (marker) {
498                 short mval[2], xo, yo;
499 //              getmouseco_areawin(mval);
500                 xo= mval[0]; 
501                 yo= mval[1];
502                 
503                 while(get_mbut()) {             
504 //                      getmouseco_areawin(mval);
505                         if(abs(mval[0]-xo)+abs(mval[1]-yo) > 4) {
506                                 transform_markers('g', 0);
507                                 return;
508                         }
509                 }
510         }
511 #endif
512         
513         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER_SELECT, scene);
514
515         /* allowing tweaks */
516         return OPERATOR_FINISHED|OPERATOR_PASS_THROUGH;
517 }
518
519 void SEQUENCER_OT_select(wmOperatorType *ot)
520 {
521         /* identifiers */
522         ot->name= "Activate/Select";
523         ot->idname= "SEQUENCER_OT_select";
524         ot->description="Select a strip (last selected becomes the \"active strip\")";
525         
526         /* api callbacks */
527         ot->invoke= sequencer_select_invoke;
528         ot->poll= ED_operator_sequencer_active;
529         
530         /* flags */
531         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
532         
533         /* properties */
534         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend the selection.");
535         RNA_def_boolean(ot->srna, "linked_handle", 0, "Linked Handle", "Select handles next to the active strip.");
536         /* for animation this is an enum but atm having an enum isnt useful for us */
537         RNA_def_boolean(ot->srna, "left_right", 0, "Left/Right", "select based on the frame side the cursor is on.");
538         RNA_def_boolean(ot->srna, "linked_time", 0, "Linked Time", "Select other strips at the same time.");
539 }
540
541
542
543
544 /* run recursivly to select linked */
545 static int select_more_less_seq__internal(Scene *scene, int sel, int linked) {
546         Editing *ed= seq_give_editing(scene, FALSE);
547         Sequence *seq, *neighbor;
548         int change=0;
549         int isel;
550         
551         if(ed==NULL) return 0;
552         
553         if (sel) {
554                 sel = SELECT;
555                 isel = 0;
556         } else {
557                 sel = 0;
558                 isel = SELECT;
559         }
560         
561         if (!linked) {
562                 /* if not linked we only want to touch each seq once, newseq */
563                 for(seq= ed->seqbasep->first; seq; seq= seq->next) {
564                         seq->tmp = NULL;
565                 }
566         }
567         
568         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
569                 if((int)(seq->flag & SELECT) == sel) {
570                         if ((linked==0 && seq->tmp)==0) {
571                                 /* only get unselected nabours */
572                                 neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_LEFT, isel);
573                                 if (neighbor) {
574                                         if (sel) {neighbor->flag |= SELECT; recurs_sel_seq(neighbor);}
575                                         else            neighbor->flag &= ~SELECT;
576                                         if (linked==0) neighbor->tmp = (Sequence *)1;
577                                         change = 1;
578                                 }
579                                 neighbor = find_neighboring_sequence(scene, seq, SEQ_SIDE_RIGHT, isel);
580                                 if (neighbor) {
581                                         if (sel) {neighbor->flag |= SELECT; recurs_sel_seq(neighbor);}
582                                         else            neighbor->flag &= ~SELECT;
583                                         if (linked==0) neighbor->tmp = (void *)1;
584                                         change = 1;
585                                 }
586                         }
587                 }
588         }
589         
590         return change;
591 }
592
593
594
595 /* select more operator */
596 static int sequencer_select_more_exec(bContext *C, wmOperator *op)
597 {
598         Scene *scene= CTX_data_scene(C);
599         
600         if(!select_more_less_seq__internal(scene, 0, 0))
601                 return OPERATOR_CANCELLED;
602
603         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER_SELECT, scene);
604         
605         return OPERATOR_FINISHED;
606 }
607
608 void SEQUENCER_OT_select_more(wmOperatorType *ot)
609 {
610         /* identifiers */
611         ot->name= "Select More";
612         ot->idname= "SEQUENCER_OT_select_more";
613         ot->description="DOC_BROKEN";
614         
615         /* api callbacks */
616         ot->exec= sequencer_select_more_exec;
617         ot->poll= ED_operator_sequencer_active;
618         
619         /* flags */
620         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
621         
622         /* properties */
623 }
624
625
626 /* select less operator */
627 static int sequencer_select_less_exec(bContext *C, wmOperator *op)
628 {
629         Scene *scene= CTX_data_scene(C);
630         
631         if(!select_more_less_seq__internal(scene, 1, 0))
632                 return OPERATOR_CANCELLED;
633  
634         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER_SELECT, scene);
635         
636         return OPERATOR_FINISHED;
637 }
638
639 void SEQUENCER_OT_select_less(wmOperatorType *ot)
640 {
641         /* identifiers */
642         ot->name= "Select less";
643         ot->idname= "SEQUENCER_OT_select_less";
644         ot->description="DOC_BROKEN";
645         
646         /* api callbacks */
647         ot->exec= sequencer_select_less_exec;
648         ot->poll= ED_operator_sequencer_active;
649         
650         /* flags */
651         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
652         
653         /* properties */
654 }
655
656
657 /* select pick linked operator (uses the mouse) */
658 static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event)
659 {
660         Scene *scene= CTX_data_scene(C);
661         ARegion *ar= CTX_wm_region(C);
662         View2D *v2d= UI_view2d_fromcontext(C);
663         
664         short extend= RNA_boolean_get(op->ptr, "extend");
665         short mval[2];  
666         
667         Sequence *mouse_seq;
668         int selected, hand;
669         
670         mval[0]= event->x - ar->winrct.xmin;
671         mval[1]= event->y - ar->winrct.ymin;
672         
673         /* this works like UV, not mesh */
674         mouse_seq= find_nearest_seq(scene, v2d, &hand, mval);
675         if (!mouse_seq)
676                 return OPERATOR_FINISHED; /* user error as with mesh?? */
677         
678         if (extend==0)
679                 deselect_all_seq(scene);
680         
681         mouse_seq->flag |= SELECT;
682         recurs_sel_seq(mouse_seq);
683         
684         selected = 1;
685         while (selected) {
686                 selected = select_more_less_seq__internal(scene, 1, 1);
687         }
688         
689         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER_SELECT, scene);
690         
691         return OPERATOR_FINISHED;
692 }
693
694 void SEQUENCER_OT_select_linked_pick(wmOperatorType *ot)
695 {
696         /* identifiers */
697         ot->name= "Select pick linked";
698         ot->idname= "SEQUENCER_OT_select_linked_pick";
699         ot->description="DOC_BROKEN";
700         
701         /* api callbacks */
702         ot->invoke= sequencer_select_linked_pick_invoke;
703         ot->poll= ED_operator_sequencer_active;
704         
705         /* flags */
706         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
707         
708         /* properties */
709         RNA_def_boolean(ot->srna, "extend", 0, "Extend", "extend the selection");
710 }
711
712
713 /* select linked operator */
714 static int sequencer_select_linked_exec(bContext *C, wmOperator *op)
715 {
716         Scene *scene= CTX_data_scene(C);
717         int selected;
718
719         selected = 1;
720         while (selected) {
721                 selected = select_more_less_seq__internal(scene, 1, 1);
722         }
723
724         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER_SELECT, scene);
725
726         return OPERATOR_FINISHED;
727 }
728
729 void SEQUENCER_OT_select_linked(wmOperatorType *ot)
730 {
731         /* identifiers */
732         ot->name= "Select linked";
733         ot->idname= "SEQUENCER_OT_select_linked";
734         ot->description="DOC_BROKEN";
735         
736         /* api callbacks */
737         ot->exec= sequencer_select_linked_exec;
738         ot->poll= ED_operator_sequencer_active;
739         
740         /* flags */
741         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
742         
743         /* properties */
744 }
745
746
747 /* select handles operator */
748 static int sequencer_select_handles_exec(bContext *C, wmOperator *op)
749 {
750         Scene *scene= CTX_data_scene(C);
751         Editing *ed= seq_give_editing(scene, 0);
752         Sequence *seq;
753         int sel_side= RNA_enum_get(op->ptr, "side");
754
755         if (ed==NULL)
756                 return OPERATOR_CANCELLED;
757
758         for(seq= ed->seqbasep->first; seq; seq=seq->next) {
759                 if (seq->flag & SELECT) {
760                         switch(sel_side) {
761                         case SEQ_SIDE_LEFT:
762                                 seq->flag &= ~SEQ_RIGHTSEL;
763                                 seq->flag |= SEQ_LEFTSEL;
764                                 break;
765                         case SEQ_SIDE_RIGHT:
766                                 seq->flag &= ~SEQ_LEFTSEL;
767                                 seq->flag |= SEQ_RIGHTSEL;
768                                 break;
769                         case SEQ_SIDE_BOTH:
770                                 seq->flag |= SEQ_LEFTSEL+SEQ_RIGHTSEL;
771                                 break;
772                         }
773                 }
774         }
775
776         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER_SELECT, scene);
777
778         return OPERATOR_FINISHED;
779 }
780
781 void SEQUENCER_OT_select_handles(wmOperatorType *ot)
782 {
783         /* identifiers */
784         ot->name= "Select Handles";
785         ot->idname= "SEQUENCER_OT_select_handles";
786         ot->description="DOC_BROKEN";
787         
788         /* api callbacks */
789         ot->exec= sequencer_select_handles_exec;
790         ot->poll= ED_operator_sequencer_active;
791         
792         /* flags */
793         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
794         
795         /* properties */
796         RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side of the handle that is selected");
797 }
798
799 /* select side operator */
800 static int sequencer_select_active_side_exec(bContext *C, wmOperator *op)
801 {
802         Scene *scene= CTX_data_scene(C);
803         Editing *ed= seq_give_editing(scene, 0);
804         Sequence *seq_act= active_seq_get(scene);
805
806         if (ed==NULL || seq_act==NULL)
807                 return OPERATOR_CANCELLED;
808
809         seq_act->flag |= SELECT;
810
811         select_active_side(ed->seqbasep, RNA_enum_get(op->ptr, "side"), seq_act->machine, seq_act->startdisp);
812
813         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER_SELECT, scene);
814
815         return OPERATOR_FINISHED;
816 }
817
818 void SEQUENCER_OT_select_active_side(wmOperatorType *ot)
819 {
820         /* identifiers */
821         ot->name= "Select Active Side";
822         ot->idname= "SEQUENCER_OT_select_active_side";
823         ot->description="DOC_BROKEN";
824         
825         /* api callbacks */
826         ot->exec= sequencer_select_active_side_exec;
827         ot->poll= ED_operator_sequencer_active;
828
829         /* flags */
830         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
831
832         /* properties */
833         RNA_def_enum(ot->srna, "side", prop_side_types, SEQ_SIDE_BOTH, "Side", "The side of the handle that is selected");
834 }
835
836
837 /* borderselect operator */
838 static int sequencer_borderselect_exec(bContext *C, wmOperator *op)
839 {
840         Scene *scene= CTX_data_scene(C);
841         Editing *ed= seq_give_editing(scene, FALSE);
842         View2D *v2d= UI_view2d_fromcontext(C);
843         
844         Sequence *seq;
845         rcti rect;
846         rctf rectf, rq;
847         short selecting = (RNA_int_get(op->ptr, "gesture_mode")==GESTURE_MODAL_SELECT);
848         short mval[2];
849
850         if(ed==NULL)
851                 return OPERATOR_CANCELLED;
852
853         rect.xmin= RNA_int_get(op->ptr, "xmin");
854         rect.ymin= RNA_int_get(op->ptr, "ymin");
855         rect.xmax= RNA_int_get(op->ptr, "xmax");
856         rect.ymax= RNA_int_get(op->ptr, "ymax");
857         
858         mval[0]= rect.xmin;
859         mval[1]= rect.ymin;
860         UI_view2d_region_to_view(v2d, mval[0], mval[1], &rectf.xmin, &rectf.ymin);
861         mval[0]= rect.xmax;
862         mval[1]= rect.ymax;
863         UI_view2d_region_to_view(v2d, mval[0], mval[1], &rectf.xmax, &rectf.ymax);
864
865         for(seq= ed->seqbasep->first; seq; seq= seq->next) {
866                 seq_rectf(seq, &rq);
867                 
868                 if(BLI_isect_rctf(&rq, &rectf, 0)) {
869                         if(selecting)           seq->flag |= SELECT;
870                         else                            seq->flag &= SEQ_DESEL;
871                         recurs_sel_seq(seq);
872                 }
873         }
874
875         WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER_SELECT, scene);
876
877         return OPERATOR_FINISHED;
878
879
880
881 /* ****** Border Select ****** */
882 void SEQUENCER_OT_select_border(wmOperatorType *ot)
883 {
884         /* identifiers */
885         ot->name= "Border Select";
886         ot->idname= "SEQUENCER_OT_select_border";
887         ot->description="Enable border select mode";
888         
889         /* api callbacks */
890         ot->invoke= WM_border_select_invoke;
891         ot->exec= sequencer_borderselect_exec;
892         ot->modal= WM_border_select_modal;
893         
894         ot->poll= ED_operator_sequencer_active;
895         
896         /* flags */
897         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
898         
899         /* rna */
900         WM_operator_properties_gesture_border(ot, FALSE);
901 }