3c729ec1ca4b35dd0c2454da084a27fd027ecc3a
[blender.git] / source / blender / editors / screen / screen_ops.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  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 #include "MEM_guardedalloc.h"
28
29 #include "BLI_blenlib.h"
30 #include "BLI_arithb.h"
31
32 #include "BKE_context.h"
33 #include "BKE_library.h"
34 #include "BKE_main.h"
35 #include "BKE_screen.h"
36 #include "BKE_utildefines.h"
37
38 #include "DNA_scene_types.h"
39
40 #include "WM_api.h"
41 #include "WM_types.h"
42
43 #include "ED_markers.h"
44 #include "ED_screen.h"
45 #include "ED_screen_types.h"
46
47 #include "RNA_access.h"
48 #include "RNA_define.h"
49
50 #include "screen_intern.h"      /* own module include */
51
52 /* ************** Exported Poll tests ********************** */
53
54 int ED_operator_areaactive(bContext *C)
55 {
56         if(CTX_wm_window(C)==NULL) return 0;
57         if(CTX_wm_screen(C)==NULL) return 0;
58         if(CTX_wm_area(C)==NULL) return 0;
59         return 1;
60 }
61
62 int ED_operator_screenactive(bContext *C)
63 {
64         if(CTX_wm_window(C)==NULL) return 0;
65         if(CTX_wm_screen(C)==NULL) return 0;
66         return 1;
67 }
68
69 /* when mouse is over area-edge */
70 int ED_operator_screen_mainwinactive(bContext *C)
71 {
72         if(CTX_wm_window(C)==NULL) return 0;
73         if(CTX_wm_screen(C)==NULL) return 0;
74         if (CTX_wm_screen(C)->subwinactive!=CTX_wm_screen(C)->mainwin) return 0;
75         return 1;
76 }
77
78 /* *************************** action zone operator ************************** */
79
80 /* operator state vars used:  
81         none
82
83 functions:
84
85         apply() set actionzone event
86
87         exit()  free customdata
88         
89 callbacks:
90
91         exec()  never used
92
93         invoke() check if in zone  
94                 add customdata, put mouseco and area in it
95                 add modal handler
96
97         modal() accept modal events while doing it
98                 call apply() with gesture info, active window, nonactive window
99                 call exit() and remove handler when LMB confirm
100
101 */
102
103 typedef struct sActionzoneData {
104         ScrArea *sa1, *sa2;
105         AZone *az;
106         int x, y, gesture_dir;
107 } sActionzoneData;
108
109 /* used by other operators too */
110 static ScrArea *screen_areahascursor(bScreen *scr, int x, int y)
111 {
112         ScrArea *sa= NULL;
113         sa= scr->areabase.first;
114         while(sa) {
115                 if(BLI_in_rcti(&sa->totrct, x, y)) break;
116                 sa= sa->next;
117         }
118         
119         return sa;
120 }
121
122
123 AZone *is_in_area_actionzone(ScrArea *sa, int x, int y)
124 {
125         AZone *az= NULL;
126         int i= 0;
127         
128         for(az= sa->actionzones.first, i= 0; az; az= az->next, i++) {
129                 if(az->type == AZONE_TRI) {
130                         if(IsPointInTri2DInts(az->x1, az->y1, az->x2, az->y2, x, y)) 
131                                 break;
132                 }
133                 if(az->type == AZONE_QUAD) {
134                         if(az->x1 < x && x < az->x2 && az->y1 < y && y < az->y2) 
135                                 break;
136                 }
137         }
138         
139         return az;
140 }
141
142 static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event)
143 {
144         AZone *az= is_in_area_actionzone(CTX_wm_area(C), event->x, event->y);
145         sActionzoneData *sad;
146         
147         /* quick escape */
148         if(az==NULL)
149                 return OPERATOR_PASS_THROUGH;
150         
151         /* ok we do the actionzone */
152         sad= op->customdata= MEM_callocN(sizeof(sActionzoneData), "sActionzoneData");
153         sad->sa1= CTX_wm_area(C);
154         sad->az= az;
155         sad->x= event->x; sad->y= event->y;
156         
157         /* add modal handler */
158         WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
159         
160         return OPERATOR_RUNNING_MODAL;
161 }
162
163 static void actionzone_exit(bContext *C, wmOperator *op)
164 {
165         if(op->customdata)
166                 MEM_freeN(op->customdata);
167         op->customdata= NULL;
168 }
169
170 /* send EVT_ACTIONZONE event */
171 static void actionzone_apply(bContext *C, wmOperator *op)
172 {
173         wmEvent event;
174         wmWindow *win= CTX_wm_window(C);
175         
176         event= *(win->eventstate);      /* XXX huh huh? make api call */
177         event.type= EVT_ACTIONZONE;
178         event.customdata= op->customdata;
179         event.customdatafree= TRUE;
180         op->customdata= NULL;
181         
182         wm_event_add(win, &event);
183 }
184
185 static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event)
186 {
187         sActionzoneData *sad= op->customdata;
188         int deltax, deltay;
189         
190         switch(event->type) {
191                 case MOUSEMOVE:
192                         /* calculate gesture direction */
193                         deltax= (event->x - sad->x);
194                         deltay= (event->y - sad->y);
195                         
196                         if(deltay > ABS(deltax))
197                                 sad->gesture_dir= AZONE_N;
198                         else if(deltax > ABS(deltay))
199                                 sad->gesture_dir= AZONE_E;
200                         else if(deltay < -ABS(deltax))
201                                 sad->gesture_dir= AZONE_S;
202                         else
203                                 sad->gesture_dir= AZONE_W;
204                         
205                         /* gesture is large enough? */
206                         if(ABS(deltax) > 12 || ABS(deltay) > 12) {
207                                 
208                                 /* second area, for join */
209                                 sad->sa2= screen_areahascursor(CTX_wm_screen(C), event->x, event->y);
210                                 /* apply sends event */
211                                 actionzone_apply(C, op);
212                                 actionzone_exit(C, op);
213                                 
214                                 return OPERATOR_FINISHED;
215                         }
216                                 break;
217                 case ESCKEY:
218                 case LEFTMOUSE:
219                         actionzone_exit(C, op);
220                         return OPERATOR_CANCELLED;
221         }
222         
223         return OPERATOR_RUNNING_MODAL;
224 }
225
226 void ED_SCR_OT_actionzone(wmOperatorType *ot)
227 {
228         /* identifiers */
229         ot->name= "Handle area action zones";
230         ot->idname= "ED_SCR_OT_actionzone";
231         
232         ot->invoke= actionzone_invoke;
233         ot->modal= actionzone_modal;
234         
235         ot->poll= ED_operator_areaactive;
236 }
237
238
239 /* *********** Rip area operator ****************** */
240
241
242 /* operator callback */
243 /* (ton) removed attempt to merge ripped area with another, don't think this is desired functionality.
244 conventions: 'atomic' and 'dont think for user' :) */
245 static int screen_area_rip_op(bContext *C, wmOperator *op)
246 {
247         wmWindow *newwin, *win;
248         bScreen *newsc, *sc;
249         ScrArea *sa;
250         rcti rect;
251         
252         win= CTX_wm_window(C);
253         sc= CTX_wm_screen(C);
254         sa= CTX_wm_area(C);
255
256         /*  poll() checks area context, but we don't accept full-area windows */
257         if(sc->full != SCREENNORMAL) 
258                 return OPERATOR_CANCELLED;
259         
260         /* adds window to WM */
261         rect= sa->totrct;
262         BLI_translate_rcti(&rect, win->posx, win->posy);
263         newwin= WM_window_open(C, &rect);
264         
265         /* allocs new screen and adds to newly created window, using window size */
266         newsc= screen_add(newwin, sc->id.name+2);
267         newwin->screen= newsc;
268         
269         /* copy area to new screen */
270         area_copy_data((ScrArea *)newsc->areabase.first, sa, 0);
271         
272         /* screen, areas init */
273         WM_event_add_notifier(C, WM_NOTE_SCREEN_CHANGED, 0, NULL);
274         
275         return OPERATOR_FINISHED;
276 }
277
278 void ED_SCR_OT_area_rip(wmOperatorType *ot)
279 {
280         ot->name= "Rip Area into New Window";
281         ot->idname= "ED_SCR_OT_area_rip";
282         
283         ot->invoke= WM_operator_confirm;
284         ot->exec= screen_area_rip_op;
285         ot->poll= ED_operator_areaactive;
286 }
287
288
289 /* ************** move area edge operator *********************************** */
290
291 /* operator state vars used:  
292            x, y                         mouse coord near edge
293            delta            movement of edge
294
295         functions:
296
297         init()   set default property values, find edge based on mouse coords, test
298             if the edge can be moved, select edges, calculate min and max movement
299
300         apply() apply delta on selection
301
302         exit()  cleanup, send notifier
303
304         cancel() cancel moving
305
306         callbacks:
307
308         exec()   execute without any user interaction, based on properties
309             call init(), apply(), exit()
310
311         invoke() gets called on mouse click near edge
312             call init(), add handler
313
314         modal()  accept modal events while doing it
315                         call apply() with delta motion
316             call exit() and remove handler
317
318 */
319
320 typedef struct sAreaMoveData {
321         int bigger, smaller, origval;
322         char dir;
323 } sAreaMoveData;
324
325 /* helper call to move area-edge, sets limits */
326 static void area_move_set_limits(bScreen *sc, int dir, int *bigger, int *smaller)
327 {
328         ScrArea *sa;
329         
330         /* we check all areas and test for free space with MINSIZE */
331         *bigger= *smaller= 100000;
332         
333         for(sa= sc->areabase.first; sa; sa= sa->next) {
334                 if(dir=='h') {
335                         int y1= sa->v2->vec.y - sa->v1->vec.y-AREAMINY;
336                         
337                         /* if top or down edge selected, test height */
338                         if(sa->v1->flag && sa->v4->flag)
339                                 *bigger= MIN2(*bigger, y1);
340                         else if(sa->v2->flag && sa->v3->flag)
341                                 *smaller= MIN2(*smaller, y1);
342                 }
343                 else {
344                         int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
345                         
346                         /* if left or right edge selected, test width */
347                         if(sa->v1->flag && sa->v2->flag)
348                                 *bigger= MIN2(*bigger, x1);
349                         else if(sa->v3->flag && sa->v4->flag)
350                                 *smaller= MIN2(*smaller, x1);
351                 }
352         }
353 }
354
355 /* validate selection inside screen, set variables OK */
356 /* return 0: init failed */
357 static int area_move_init (bContext *C, wmOperator *op)
358 {
359         bScreen *sc= CTX_wm_screen(C);
360         ScrEdge *actedge;
361         sAreaMoveData *md;
362         int x, y;
363
364         /* required properties */
365         x= RNA_int_get(op->ptr, "x");
366         y= RNA_int_get(op->ptr, "y");
367
368         /* setup */
369         actedge= screen_find_active_scredge(sc, x, y);
370         if(actedge==NULL) return 0;
371
372         md= MEM_callocN(sizeof(sAreaMoveData), "sAreaMoveData");
373         op->customdata= md;
374
375         md->dir= scredge_is_horizontal(actedge)?'h':'v';
376         if(md->dir=='h') md->origval= actedge->v1->vec.y;
377         else md->origval= actedge->v1->vec.x;
378         
379         select_connected_scredge(sc, actedge);
380         /* now all vertices with 'flag==1' are the ones that can be moved. */
381
382         area_move_set_limits(sc, md->dir, &md->bigger, &md->smaller);
383         
384         return 1;
385 }
386
387 /* moves selected screen edge amount of delta, used by split & move */
388 static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int bigger, int smaller)
389 {
390         wmWindow *win= CTX_wm_window(C);
391         bScreen *sc= CTX_wm_screen(C);
392         ScrVert *v1;
393         
394         delta= CLAMPIS(delta, -smaller, bigger);
395         
396         for (v1= sc->vertbase.first; v1; v1= v1->next) {
397                 if (v1->flag) {
398                         /* that way a nice AREAGRID  */
399                         if((dir=='v') && v1->vec.x>0 && v1->vec.x<win->sizex-1) {
400                                 v1->vec.x= origval + delta;
401                                 if(delta != bigger && delta != -smaller) v1->vec.x-= (v1->vec.x % AREAGRID);
402                         }
403                         if((dir=='h') && v1->vec.y>0 && v1->vec.y<win->sizey-1) {
404                                 v1->vec.y= origval + delta;
405
406                                 v1->vec.y+= AREAGRID-1;
407                                 v1->vec.y-= (v1->vec.y % AREAGRID);
408                                 
409                                 /* prevent too small top header */
410                                 if(v1->vec.y > win->sizey-AREAMINY)
411                                         v1->vec.y= win->sizey-AREAMINY;
412                         }
413                 }
414         }
415
416         WM_event_add_notifier(C, WM_NOTE_SCREEN_CHANGED, 0, NULL);
417 }
418
419 static void area_move_apply(bContext *C, wmOperator *op)
420 {
421         sAreaMoveData *md= op->customdata;
422         int delta;
423         
424         delta= RNA_int_get(op->ptr, "delta");
425         area_move_apply_do(C, md->origval, delta, md->dir, md->bigger, md->smaller);
426 }
427
428 static void area_move_exit(bContext *C, wmOperator *op)
429 {
430         if(op->customdata)
431                 MEM_freeN(op->customdata);
432         op->customdata= NULL;
433         
434         /* this makes sure aligned edges will result in aligned grabbing */
435         removedouble_scrverts(CTX_wm_screen(C));
436         removedouble_scredges(CTX_wm_screen(C));
437 }
438
439 static int area_move_exec(bContext *C, wmOperator *op)
440 {
441         if(!area_move_init(C, op))
442                 return OPERATOR_CANCELLED;
443         
444         area_move_apply(C, op);
445         area_move_exit(C, op);
446         
447         return OPERATOR_FINISHED;
448 }
449
450 /* interaction callback */
451 static int area_move_invoke(bContext *C, wmOperator *op, wmEvent *event)
452 {
453         RNA_int_set(op->ptr, "x", event->x);
454         RNA_int_set(op->ptr, "y", event->y);
455
456         if(!area_move_init(C, op)) 
457                 return OPERATOR_PASS_THROUGH;
458         
459         /* add temp handler */
460         WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
461         
462         return OPERATOR_RUNNING_MODAL;
463 }
464
465 static int area_move_cancel(bContext *C, wmOperator *op)
466 {
467
468         RNA_int_set(op->ptr, "delta", 0);
469         area_move_apply(C, op);
470         area_move_exit(C, op);
471
472         return OPERATOR_CANCELLED;
473 }
474
475 /* modal callback for while moving edges */
476 static int area_move_modal(bContext *C, wmOperator *op, wmEvent *event)
477 {
478         sAreaMoveData *md;
479         int delta, x, y;
480
481         md= op->customdata;
482
483         x= RNA_int_get(op->ptr, "x");
484         y= RNA_int_get(op->ptr, "y");
485
486         /* execute the events */
487         switch(event->type) {
488                 case MOUSEMOVE:
489                         delta= (md->dir == 'v')? event->x - x: event->y - y;
490                         RNA_int_set(op->ptr, "delta", delta);
491
492                         area_move_apply(C, op);
493                         break;
494                         
495                 case LEFTMOUSE:
496                         if(event->val==0) {
497                                 area_move_exit(C, op);
498                                 return OPERATOR_FINISHED;
499                         }
500                         break;
501                         
502                 case ESCKEY:
503                         return area_move_cancel(C, op);
504         }
505         
506         return OPERATOR_RUNNING_MODAL;
507 }
508
509 void ED_SCR_OT_area_move(wmOperatorType *ot)
510 {
511         PropertyRNA *prop;
512
513         /* identifiers */
514         ot->name= "Move area edges";
515         ot->idname= "ED_SCR_OT_area_move";
516
517         ot->exec= area_move_exec;
518         ot->invoke= area_move_invoke;
519         ot->cancel= area_move_cancel;
520         ot->modal= area_move_modal;
521
522         ot->poll= ED_operator_screen_mainwinactive; /* when mouse is over area-edge */
523
524         /* rna */
525         prop= RNA_def_property(ot->srna, "x", PROP_INT, PROP_NONE);
526         prop= RNA_def_property(ot->srna, "y", PROP_INT, PROP_NONE);
527         prop= RNA_def_property(ot->srna, "delta", PROP_INT, PROP_NONE);
528 }
529
530 /* ************** split area operator *********************************** */
531
532 /* 
533 operator state vars:  
534         fac              spit point
535         dir              direction 'v' or 'h'
536
537 operator customdata:
538         area                    pointer to (active) area
539         x, y                    last used mouse pos
540         (more, see below)
541
542 functions:
543
544         init()   set default property values, find area based on context
545
546         apply() split area based on state vars
547
548         exit()  cleanup, send notifier
549
550         cancel() remove duplicated area
551
552 callbacks:
553
554         exec()   execute without any user interaction, based on state vars
555             call init(), apply(), exit()
556
557         invoke() gets called on mouse click in action-widget
558             call init(), add modal handler
559                         call apply() with initial motion
560
561         modal()  accept modal events while doing it
562             call move-areas code with delta motion
563             call exit() or cancel() and remove handler
564
565 */
566
567 #define SPLIT_STARTED   1
568 #define SPLIT_PROGRESS  2
569
570 typedef struct sAreaSplitData
571 {
572         int x, y;       /* last used mouse position */
573         
574         int origval;                    /* for move areas */
575         int bigger, smaller;    /* constraints for moving new edge */
576         int delta;                              /* delta move edge */
577         int origmin, origsize;  /* to calculate fac, for property storage */
578
579         ScrEdge *nedge;                 /* new edge */
580         ScrArea *sarea;                 /* start area */
581         ScrArea *narea;                 /* new area */
582 } sAreaSplitData;
583
584 /* generic init, no UI stuff here */
585 static int area_split_init(bContext *C, wmOperator *op)
586 {
587         ScrArea *sa= CTX_wm_area(C);
588         sAreaSplitData *sd;
589         int dir;
590         
591         /* required context */
592         if(sa==NULL) return 0;
593         
594         /* required properties */
595         dir= RNA_enum_get(op->ptr, "dir");
596         
597         /* minimal size */
598         if(dir=='v' && sa->winx < 2*AREAMINX) return 0;
599         if(dir=='h' && sa->winy < 2*AREAMINY) return 0;
600            
601         /* custom data */
602         sd= (sAreaSplitData*)MEM_callocN(sizeof (sAreaSplitData), "op_area_split");
603         op->customdata= sd;
604         
605         sd->sarea= sa;
606         sd->origsize= dir=='v' ? sa->winx:sa->winy;
607         sd->origmin = dir=='v' ? sa->totrct.xmin:sa->totrct.ymin;
608         
609         return 1;
610 }
611
612 /* with sa as center, sb is located at: 0=W, 1=N, 2=E, 3=S */
613 /* used with split operator */
614 static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb)
615 {
616         ScrVert *sav1= sa->v1;
617         ScrVert *sav2= sa->v2;
618         ScrVert *sav3= sa->v3;
619         ScrVert *sav4= sa->v4;
620         ScrVert *sbv1= sb->v1;
621         ScrVert *sbv2= sb->v2;
622         ScrVert *sbv3= sb->v3;
623         ScrVert *sbv4= sb->v4;
624         
625         if(sav1==sbv4 && sav2==sbv3) { /* sa to right of sb = W */
626                 return screen_findedge(screen, sav1, sav2);
627         }
628         else if(sav2==sbv1 && sav3==sbv4) { /* sa to bottom of sb = N */
629                 return screen_findedge(screen, sav2, sav3);
630         }
631         else if(sav3==sbv2 && sav4==sbv1) { /* sa to left of sb = E */
632                 return screen_findedge(screen, sav3, sav4);
633         }
634         else if(sav1==sbv2 && sav4==sbv3) { /* sa on top of sb = S*/
635                 return screen_findedge(screen, sav1, sav4);
636         }
637
638         return NULL;
639 }
640
641
642 /* do the split, return success */
643 static int area_split_apply(bContext *C, wmOperator *op)
644 {
645         bScreen *sc= CTX_wm_screen(C);
646         sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
647         float fac;
648         int dir;
649         
650         fac= RNA_float_get(op->ptr, "fac");
651         dir= RNA_enum_get(op->ptr, "dir");
652
653         sd->narea= area_split(CTX_wm_window(C), sc, sd->sarea, dir, fac);
654         
655         if(sd->narea) {
656                 ScrVert *sv;
657                 
658                 sd->nedge= area_findsharededge(sc, sd->sarea, sd->narea);
659         
660                 /* select newly created edge, prepare for moving edge */
661                 for(sv= sc->vertbase.first; sv; sv= sv->next)
662                         sv->flag = 0;
663                 
664                 sd->nedge->v1->flag= 1;
665                 sd->nedge->v2->flag= 1;
666
667                 if(dir=='h') sd->origval= sd->nedge->v1->vec.y;
668                 else sd->origval= sd->nedge->v1->vec.x;
669
670                 WM_event_add_notifier(C, WM_NOTE_SCREEN_CHANGED, 0, NULL);
671                 
672                 return 1;
673         }               
674         
675         return 0;
676 }
677
678 static void area_split_exit(bContext *C, wmOperator *op)
679 {
680         if (op->customdata) {
681                 MEM_freeN(op->customdata);
682                 op->customdata = NULL;
683         }
684         
685         WM_event_add_notifier(C, WM_NOTE_SCREEN_CHANGED, 0, NULL);
686
687         /* this makes sure aligned edges will result in aligned grabbing */
688         removedouble_scrverts(CTX_wm_screen(C));
689         removedouble_scredges(CTX_wm_screen(C));
690 }
691
692
693 /* UI callback, adds new handler */
694 static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event)
695 {
696         sAreaSplitData *sd;
697         
698         if(event->type==EVT_ACTIONZONE) {
699                 sActionzoneData *sad= event->customdata;
700                 int dir;
701                 
702                 /* verify *sad itself */
703                 if(sad==NULL || sad->sa1==NULL || sad->az==NULL)
704                         return OPERATOR_PASS_THROUGH;
705                 
706                 /* is this our *sad? if areas not equal it should be passed on */
707                 if(CTX_wm_area(C)!=sad->sa1 || sad->sa1!=sad->sa2)
708                         return OPERATOR_PASS_THROUGH;
709                 
710                 /* prepare operator state vars */
711                 if(sad->gesture_dir==AZONE_N || sad->gesture_dir==AZONE_S) {
712                         dir= 'h';
713                         RNA_float_set(op->ptr, "fac", ((float)(event->x - sad->sa1->v1->vec.x)) / (float)sad->sa1->winx);
714                 }
715                 else {
716                         dir= 'v';
717                         RNA_float_set(op->ptr, "fac", ((float)(event->y - sad->sa1->v1->vec.y)) / (float)sad->sa1->winy);
718                 }
719                 RNA_enum_set(op->ptr, "dir", dir);
720
721                 /* general init, also non-UI case, adds customdata, sets area and defaults */
722                 if(!area_split_init(C, op))
723                         return OPERATOR_PASS_THROUGH;
724                 
725                 sd= (sAreaSplitData *)op->customdata;
726                 
727                 sd->x= event->x;
728                 sd->y= event->y;
729                 
730                 /* do the split */
731                 if(area_split_apply(C, op)) {
732                         area_move_set_limits(CTX_wm_screen(C), dir, &sd->bigger, &sd->smaller);
733                         
734                         /* add temp handler for edge move or cancel */
735                         WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
736                         
737                         return OPERATOR_RUNNING_MODAL;
738                 }
739                 
740         }
741         else {
742                 /* nonmodal for now */
743                 return op->type->exec(C, op);
744         }
745         
746         return OPERATOR_PASS_THROUGH;
747 }
748
749 /* function to be called outside UI context, or for redo */
750 static int area_split_exec(bContext *C, wmOperator *op)
751 {
752         
753         if(!area_split_init(C, op))
754                 return OPERATOR_CANCELLED;
755         
756         area_split_apply(C, op);
757         area_split_exit(C, op);
758         
759         return OPERATOR_FINISHED;
760 }
761
762
763 static int area_split_cancel(bContext *C, wmOperator *op)
764 {
765         sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
766
767         if (screen_area_join(C, CTX_wm_screen(C), sd->sarea, sd->narea)) {
768                 if (CTX_wm_area(C) == sd->narea) {
769                         CTX_wm_area_set(C, NULL);
770                         CTX_wm_region_set(C, NULL);
771                 }
772                 sd->narea = NULL;
773         }
774         area_split_exit(C, op);
775
776         return OPERATOR_CANCELLED;
777 }
778
779 static int area_split_modal(bContext *C, wmOperator *op, wmEvent *event)
780 {
781         sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
782         float fac;
783         int dir;
784
785         /* execute the events */
786         switch(event->type) {
787                 case MOUSEMOVE:
788                         dir= RNA_enum_get(op->ptr, "dir");
789                         
790                         sd->delta= (dir == 'v')? event->x - sd->origval: event->y - sd->origval;
791                         area_move_apply_do(C, sd->origval, sd->delta, dir, sd->bigger, sd->smaller);
792                         
793                         fac= (dir == 'v') ? event->x-sd->origmin : event->y-sd->origmin;
794                         RNA_float_set(op->ptr, "fac", fac / (float)sd->origsize);
795                         
796                         WM_event_add_notifier(C, WM_NOTE_SCREEN_CHANGED, 0, NULL);
797                         break;
798                         
799                 case LEFTMOUSE:
800                         if(event->val==0) { /* mouse up */
801                                 area_split_exit(C, op);
802                                 return OPERATOR_FINISHED;
803                         }
804                         break;
805                 case RIGHTMOUSE: /* cancel operation */
806                 case ESCKEY:
807                         return area_split_cancel(C, op);
808         }
809         
810         return OPERATOR_RUNNING_MODAL;
811 }
812
813 static EnumPropertyItem prop_direction_items[] = {
814         {'h', "HORIZONTAL", "Horizontal", ""},
815         {'v', "VERTICAL", "Vertical", ""},
816         {0, NULL, NULL, NULL}};
817
818 void ED_SCR_OT_area_split(wmOperatorType *ot)
819 {
820         PropertyRNA *prop;
821
822         ot->name = "Split area";
823         ot->idname = "ED_SCR_OT_area_split";
824         
825         ot->exec= area_split_exec;
826         ot->invoke= area_split_invoke;
827         ot->modal= area_split_modal;
828         
829         ot->poll= ED_operator_areaactive;
830         ot->flag= OPTYPE_REGISTER;
831         
832         /* rna */
833         prop= RNA_def_property(ot->srna, "dir", PROP_ENUM, PROP_NONE);
834         RNA_def_property_enum_items(prop, prop_direction_items);
835         RNA_def_property_enum_default(prop, 'h');
836
837         prop= RNA_def_property(ot->srna, "fac", PROP_FLOAT, PROP_NONE);
838         RNA_def_property_range(prop, 0.0, 1.0);
839         RNA_def_property_float_default(prop, 0.5f);
840 }
841
842 /* ************** frame change operator ***************************** */
843
844
845 /* function to be called outside UI context, or for redo */
846 static int frame_offset_exec(bContext *C, wmOperator *op)
847 {
848         int delta;
849
850         delta = RNA_int_get(op->ptr, "delta");
851
852         CTX_data_scene(C)->r.cfra += delta;
853         WM_event_add_notifier(C, WM_NOTE_WINDOW_REDRAW, 0, NULL);
854         /* XXX: add WM_NOTE_TIME_CHANGED? */
855
856         return OPERATOR_FINISHED;
857 }
858
859 void ED_SCR_OT_frame_offset(wmOperatorType *ot)
860 {
861         ot->name = "Frame Offset";
862         ot->idname = "ED_SCR_OT_frame_offset";
863
864         ot->exec= frame_offset_exec;
865
866         ot->poll= ED_operator_screenactive;
867         ot->flag= OPTYPE_REGISTER;
868
869         /* rna */
870         RNA_def_property(ot->srna, "delta", PROP_INT, PROP_NONE);
871 }
872
873 /* ************** switch screen operator ***************************** */
874
875
876 /* function to be called outside UI context, or for redo */
877 static int screen_set_exec(bContext *C, wmOperator *op)
878 {
879         bScreen *screen= CTX_wm_screen(C);
880         int delta= RNA_int_get(op->ptr, "delta");
881         
882         /* this screen is 'fake', solve later XXX */
883         if(CTX_wm_area(C)->full)
884                 return OPERATOR_CANCELLED;
885         
886         if(delta==1) {
887                 screen= screen->id.next;
888                 if(screen==NULL) screen= CTX_data_main(C)->screen.first;
889         }
890         else if(delta== -1) {
891                 screen= screen->id.prev;
892                 if(screen==NULL) screen= CTX_data_main(C)->screen.last;
893         }
894         else {
895                 screen= NULL;
896         }
897         
898         if(screen) {
899                 ed_screen_set(C, screen);
900                 return OPERATOR_FINISHED;
901         }
902         return OPERATOR_CANCELLED;
903 }
904
905 void ED_SCR_OT_screen_set(wmOperatorType *ot)
906 {
907         ot->name = "Set Screen";
908         ot->idname = "ED_SCR_OT_screen_set";
909         
910         ot->exec= screen_set_exec;
911         ot->poll= ED_operator_screenactive;
912         
913         /* rna */
914         RNA_def_property(ot->srna, "screen", PROP_POINTER, PROP_NONE);
915         RNA_def_property(ot->srna, "delta", PROP_INT, PROP_NONE);
916 }
917
918 /* ************** screen full-area operator ***************************** */
919
920
921 /* function to be called outside UI context, or for redo */
922 static int screen_full_area_exec(bContext *C, wmOperator *op)
923 {
924         ed_screen_fullarea(C);
925         return OPERATOR_FINISHED;
926 }
927
928 void ED_SCR_OT_screen_full_area(wmOperatorType *ot)
929 {
930         ot->name = "Toggle Full Area in Screen";
931         ot->idname = "ED_SCR_OT_screen_full_area";
932         
933         ot->exec= screen_full_area_exec;
934         ot->poll= ED_operator_screenactive;
935 }
936
937
938
939 /* ************** join area operator ********************************************** */
940
941 /* operator state vars used:  
942                         x1, y1     mouse coord in first area, which will disappear
943                         x2, y2     mouse coord in 2nd area, which will become joined
944
945 functions:
946
947    init()   find edge based on state vars 
948                         test if the edge divides two areas, 
949                         store active and nonactive area,
950             
951    apply()  do the actual join
952
953    exit()       cleanup, send notifier
954
955 callbacks:
956
957    exec()       calls init, apply, exit 
958    
959    invoke() sets mouse coords in x,y
960             call init()
961             add modal handler
962
963    modal()      accept modal events while doing it
964                         call apply() with active window and nonactive window
965             call exit() and remove handler when LMB confirm
966
967 */
968
969 typedef struct sAreaJoinData
970 {
971         ScrArea *sa1;   /* first area to be considered */
972         ScrArea *sa2;   /* second area to be considered */
973         ScrArea *scr;   /* designed for removal */
974
975 } sAreaJoinData;
976
977
978 /* validate selection inside screen, set variables OK */
979 /* return 0: init failed */
980 /* XXX todo: find edge based on (x,y) and set other area? */
981 static int area_join_init(bContext *C, wmOperator *op)
982 {
983         ScrArea *sa1, *sa2;
984         sAreaJoinData* jd= NULL;
985         int x1, y1;
986         int x2, y2;
987
988         /* required properties, make negative to get return 0 if not set by caller */
989         x1= RNA_int_get(op->ptr, "x1");
990         y1= RNA_int_get(op->ptr, "y1");
991         x2= RNA_int_get(op->ptr, "x2");
992         y2= RNA_int_get(op->ptr, "y2");
993         
994         sa1 = screen_areahascursor(CTX_wm_screen(C), x1, y1);
995         sa2 = screen_areahascursor(CTX_wm_screen(C), x2, y2);
996         if(sa1==NULL || sa2==NULL || sa1==sa2)
997                 return 0;
998
999         jd = (sAreaJoinData*)MEM_callocN(sizeof (sAreaJoinData), "op_area_join");
1000                 
1001         jd->sa1 = sa1;
1002         jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
1003         jd->sa2 = sa2;
1004         jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
1005         
1006         op->customdata= jd;
1007         
1008         return 1;
1009 }
1010
1011 /* apply the join of the areas (space types) */
1012 static int area_join_apply(bContext *C, wmOperator *op)
1013 {
1014         sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
1015         if (!jd) return 0;
1016
1017         if(!screen_area_join(C, CTX_wm_screen(C), jd->sa1, jd->sa2)){
1018                 return 0;
1019         }
1020         if (CTX_wm_area(C) == jd->sa2) {
1021                 CTX_wm_area_set(C, NULL);
1022                 CTX_wm_region_set(C, NULL);
1023         }
1024
1025         return 1;
1026 }
1027
1028 /* finish operation */
1029 static void area_join_exit(bContext *C, wmOperator *op)
1030 {
1031         if (op->customdata) {
1032                 MEM_freeN(op->customdata);
1033                 op->customdata = NULL;
1034         }
1035
1036         /* this makes sure aligned edges will result in aligned grabbing */
1037         removedouble_scredges(CTX_wm_screen(C));
1038         removenotused_scredges(CTX_wm_screen(C));
1039         removenotused_scrverts(CTX_wm_screen(C));
1040 }
1041
1042 static int area_join_exec(bContext *C, wmOperator *op)
1043 {
1044         if(!area_join_init(C, op)) 
1045                 return OPERATOR_CANCELLED;
1046         
1047         area_join_apply(C, op);
1048         area_join_exit(C, op);
1049
1050         return OPERATOR_FINISHED;
1051 }
1052
1053 /* interaction callback */
1054 static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event)
1055 {
1056
1057         if(event->type==EVT_ACTIONZONE) {
1058                 sActionzoneData *sad= event->customdata;
1059                 
1060                 /* verify *sad itself */
1061                 if(sad==NULL || sad->sa1==NULL || sad->sa2==NULL)
1062                         return OPERATOR_PASS_THROUGH;
1063                 
1064                 /* is this our *sad? if areas equal it should be passed on */
1065                 if(sad->sa1==sad->sa2)
1066                         return OPERATOR_PASS_THROUGH;
1067                 
1068                 /* prepare operator state vars */
1069                 RNA_int_set(op->ptr, "x1", sad->x);
1070                 RNA_int_set(op->ptr, "y1", sad->y);
1071                 RNA_int_set(op->ptr, "x2", event->x);
1072                 RNA_int_set(op->ptr, "y2", event->y);
1073
1074                 if(!area_join_init(C, op)) 
1075                         return OPERATOR_PASS_THROUGH;
1076         
1077                 /* add temp handler */
1078                 WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
1079         
1080                 return OPERATOR_RUNNING_MODAL;
1081         }
1082         
1083         return OPERATOR_PASS_THROUGH;
1084 }
1085
1086 static int area_join_cancel(bContext *C, wmOperator *op)
1087 {
1088         sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
1089
1090         if (jd->sa1) {
1091                 jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
1092                 jd->sa1->flag &= ~AREA_FLAG_DRAWJOINTO;
1093         }
1094         if (jd->sa2) {
1095                 jd->sa2->flag &= ~AREA_FLAG_DRAWJOINFROM;
1096                 jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
1097         }
1098
1099         WM_event_add_notifier(C, WM_NOTE_WINDOW_REDRAW, 0, NULL);
1100         
1101         area_join_exit(C, op);
1102
1103         return OPERATOR_CANCELLED;
1104 }
1105
1106 /* modal callback while selecting area (space) that will be removed */
1107 static int area_join_modal(bContext *C, wmOperator *op, wmEvent *event)
1108 {
1109         bScreen *sc= CTX_wm_screen(C);
1110         sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
1111         
1112         /* execute the events */
1113         switch(event->type) {
1114                         
1115                 case MOUSEMOVE: 
1116                         {
1117                                 ScrArea *sa = screen_areahascursor(sc, event->x, event->y);
1118                                 int dir;
1119                                 
1120                                 if (sa) {                                       
1121                                         if (jd->sa1 != sa) {
1122                                                 dir = area_getorientation(sc, jd->sa1, sa);
1123                                                 if (dir >= 0) {
1124                                                         if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
1125                                                         jd->sa2 = sa;
1126                                                         jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
1127                                                 } 
1128                                                 else {
1129                                                         /* we are not bordering on the previously selected area 
1130                                                            we check if area has common border with the one marked for removal
1131                                                            in this case we can swap areas.
1132                                                         */
1133                                                         dir = area_getorientation(sc, sa, jd->sa2);
1134                                                         if (dir >= 0) {
1135                                                                 if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
1136                                                                 if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
1137                                                                 jd->sa1 = jd->sa2;
1138                                                                 jd->sa2 = sa;
1139                                                                 if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
1140                                                                 if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
1141                                                         } 
1142                                                         else {
1143                                                                 if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
1144                                                                 jd->sa2 = NULL;
1145                                                         }
1146                                                 }
1147                                                 WM_event_add_notifier(C, WM_NOTE_WINDOW_REDRAW, 0, NULL);
1148                                         } 
1149                                         else {
1150                                                 /* we are back in the area previously selected for keeping 
1151                                                  * we swap the areas if possible to allow user to choose */
1152                                                 if (jd->sa2 != NULL) {
1153                                                         if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
1154                                                         if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
1155                                                         jd->sa1 = jd->sa2;
1156                                                         jd->sa2 = sa;
1157                                                         if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
1158                                                         if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
1159                                                         dir = area_getorientation(sc, jd->sa1, jd->sa2);
1160                                                         if (dir < 0) {
1161                                                                 printf("oops, didn't expect that!\n");
1162                                                         }
1163                                                 } 
1164                                                 else {
1165                                                         dir = area_getorientation(sc, jd->sa1, sa);
1166                                                         if (dir >= 0) {
1167                                                                 if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
1168                                                                 jd->sa2 = sa;
1169                                                                 jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
1170                                                         }
1171                                                 }
1172                                                 WM_event_add_notifier(C, WM_NOTE_WINDOW_REDRAW, 0, NULL);
1173                                         }
1174                                 }
1175                         }
1176                         break;
1177                 case LEFTMOUSE:
1178                         if(event->val==0) {
1179                                 area_join_apply(C, op);
1180                                 WM_event_add_notifier(C, WM_NOTE_SCREEN_CHANGED, 0, NULL);
1181                                 area_join_exit(C, op);
1182                                 return OPERATOR_FINISHED;
1183                         }
1184                         break;
1185                         
1186                 case ESCKEY:
1187                         return area_join_cancel(C, op);
1188         }
1189
1190         return OPERATOR_RUNNING_MODAL;
1191 }
1192
1193 /* Operator for joining two areas (space types) */
1194 void ED_SCR_OT_area_join(wmOperatorType *ot)
1195 {
1196         PropertyRNA *prop;
1197
1198         /* identifiers */
1199         ot->name= "Join area";
1200         ot->idname= "ED_SCR_OT_area_join";
1201         
1202         /* api callbacks */
1203         ot->exec= area_join_exec;
1204         ot->invoke= area_join_invoke;
1205         ot->modal= area_join_modal;
1206
1207         ot->poll= ED_operator_screenactive;
1208
1209         /* rna */
1210         prop= RNA_def_property(ot->srna, "x1", PROP_INT, PROP_NONE);
1211         RNA_def_property_int_default(prop, -100);
1212         prop= RNA_def_property(ot->srna, "y1", PROP_INT, PROP_NONE);
1213         RNA_def_property_int_default(prop, -100);
1214         prop= RNA_def_property(ot->srna, "x2", PROP_INT, PROP_NONE);
1215         RNA_def_property_int_default(prop, -100);
1216         prop= RNA_def_property(ot->srna, "y2", PROP_INT, PROP_NONE);
1217         RNA_def_property_int_default(prop, -100);
1218 }
1219
1220 /* ************** repeat last operator ***************************** */
1221
1222 static int repeat_last_exec(bContext *C, wmOperator *op)
1223 {
1224         wmOperator *lastop= CTX_wm_manager(C)->operators.last;
1225         
1226         if(lastop) {
1227                 printf("repeat %s\n", lastop->type->idname);
1228                 lastop->type->exec(C, lastop);
1229         }
1230         
1231         return OPERATOR_FINISHED;
1232 }
1233
1234 void ED_SCR_OT_repeat_last(wmOperatorType *ot)
1235 {
1236         /* identifiers */
1237         ot->name= "Repeat Last";
1238         ot->idname= "ED_SCR_OT_repeat_last";
1239         
1240         /* api callbacks */
1241         ot->invoke= WM_operator_confirm;        
1242         ot->exec= repeat_last_exec;
1243         
1244         ot->poll= ED_operator_screenactive;
1245         
1246 }
1247
1248 /* ************** region split operator ***************************** */
1249
1250 /* insert a region in the area region list */
1251 static int region_split_exec(bContext *C, wmOperator *op)
1252 {
1253         ScrArea *sa= CTX_wm_area(C);
1254         ARegion *ar= CTX_wm_region(C);
1255         ARegion *newar= BKE_area_region_copy(ar);
1256         int dir= RNA_enum_get(op->ptr, "dir");
1257         
1258         BLI_insertlinkafter(&sa->regionbase, CTX_wm_region(C), newar);
1259         
1260         newar->alignment= ar->alignment;
1261         
1262         if(dir=='h')
1263                 ar->alignment= RGN_ALIGN_HSPLIT;
1264         else
1265                 ar->alignment= RGN_ALIGN_VSPLIT;
1266         
1267         WM_event_add_notifier(C, WM_NOTE_SCREEN_CHANGED, 0, NULL);
1268         
1269         return OPERATOR_FINISHED;
1270 }
1271
1272 void ED_SCR_OT_region_split(wmOperatorType *ot)
1273 {
1274         PropertyRNA *prop;
1275         
1276         /* identifiers */
1277         ot->name= "Split Region";
1278         ot->idname= "ED_SCR_OT_region_split";
1279         
1280         /* api callbacks */
1281         ot->invoke= WM_operator_confirm;
1282         ot->exec= region_split_exec;
1283         ot->poll= ED_operator_areaactive;
1284         
1285         prop= RNA_def_property(ot->srna, "dir", PROP_ENUM, PROP_NONE);
1286         RNA_def_property_enum_items(prop, prop_direction_items);
1287         RNA_def_property_enum_default(prop, 'h');
1288 }
1289
1290 /* ************** region flip operator ***************************** */
1291
1292 /* flip a region alignment */
1293 static int region_flip_exec(bContext *C, wmOperator *op)
1294 {
1295         ARegion *ar= CTX_wm_region(C);
1296
1297         if(ar->alignment==RGN_ALIGN_TOP)
1298                 ar->alignment= RGN_ALIGN_BOTTOM;
1299         else if(ar->alignment==RGN_ALIGN_BOTTOM)
1300                 ar->alignment= RGN_ALIGN_TOP;
1301         else if(ar->alignment==RGN_ALIGN_LEFT)
1302                 ar->alignment= RGN_ALIGN_RIGHT;
1303         else if(ar->alignment==RGN_ALIGN_RIGHT)
1304                 ar->alignment= RGN_ALIGN_LEFT;
1305         
1306         WM_event_add_notifier(C, WM_NOTE_SCREEN_CHANGED, 0, NULL);
1307         
1308         return OPERATOR_FINISHED;
1309 }
1310
1311 void ED_SCR_OT_region_flip(wmOperatorType *ot)
1312 {
1313         /* identifiers */
1314         ot->name= "Flip Region";
1315         ot->idname= "ED_SCR_OT_region_flip";
1316         
1317         /* api callbacks */
1318         ot->invoke= WM_operator_confirm;
1319         ot->exec= region_flip_exec;
1320         
1321         ot->poll= ED_operator_areaactive;
1322 }
1323
1324 /* ****************** anim player, typically with timer ***************** */
1325
1326 static int screen_animation_play(bContext *C, wmOperator *op, wmEvent *event)
1327 {
1328         wmWindow *win= CTX_wm_window(C);
1329         
1330         if(win->animtimer==event->customdata) {
1331                 Scene *scene= CTX_data_scene(C);
1332                 
1333                 scene->r.cfra++;
1334                 
1335                 /* XXX TODO: 
1336                  * 'preview' range (psfra and pefra instead of sfra and efra)
1337                  * should be used instead if set...     
1338                  */
1339                 if(scene->r.cfra > scene->r.efra)
1340                         scene->r.cfra= scene->r.sfra;
1341
1342                 WM_event_add_notifier(C, WM_NOTE_WINDOW_REDRAW, 0, NULL);
1343                 
1344                 return OPERATOR_FINISHED;
1345         }
1346         return OPERATOR_PASS_THROUGH;
1347 }
1348
1349 void ED_SCR_OT_animation_play(wmOperatorType *ot)
1350 {
1351         /* identifiers */
1352         ot->name= "Animation player";
1353         ot->idname= "ED_SCR_OT_animation_play";
1354         
1355         /* api callbacks */
1356         ot->invoke= screen_animation_play;
1357         
1358         ot->poll= ED_operator_screenactive;
1359         
1360 }
1361
1362 /* ************** border select operator (template) ***************************** */
1363
1364 /* operator state vars used: (added by default WM callbacks)   
1365         xmin, ymin     
1366         xmax, ymax     
1367
1368         customdata: the wmGesture pointer
1369
1370 callbacks:
1371
1372         exec()  has to be filled in by user
1373
1374         invoke() default WM function
1375                          adds modal handler
1376
1377         modal() default WM function 
1378                         accept modal events while doing it, calls exec(), handles ESC and border drawing
1379         
1380         poll()  has to be filled in by user for context
1381 */
1382 #if 0
1383 static int border_select_do(bContext *C, wmOperator *op)
1384 {
1385         int event_type= RNA_int_get(op->ptr, "event_type");
1386         
1387         if(event_type==LEFTMOUSE)
1388                 printf("border select do select\n");
1389         else if(event_type==RIGHTMOUSE)
1390                 printf("border select deselect\n");
1391         else 
1392                 printf("border select do something\n");
1393         
1394         return 1;
1395 }
1396
1397 void ED_SCR_OT_border_select(wmOperatorType *ot)
1398 {
1399         /* identifiers */
1400         ot->name= "Border select";
1401         ot->idname= "ED_SCR_OT_border_select";
1402         
1403         /* api callbacks */
1404         ot->exec= border_select_do;
1405         ot->invoke= WM_border_select_invoke;
1406         ot->modal= WM_border_select_modal;
1407         
1408         ot->poll= ED_operator_areaactive;
1409         
1410         /* rna */
1411         RNA_def_property(ot->srna, "event_type", PROP_INT, PROP_NONE);
1412         RNA_def_property(ot->srna, "xmin", PROP_INT, PROP_NONE);
1413         RNA_def_property(ot->srna, "xmax", PROP_INT, PROP_NONE);
1414         RNA_def_property(ot->srna, "ymin", PROP_INT, PROP_NONE);
1415         RNA_def_property(ot->srna, "ymax", PROP_INT, PROP_NONE);
1416
1417 }
1418 #endif
1419
1420 /* ****************  Assigning operatortypes to global list, adding handlers **************** */
1421
1422 /* called in spacetypes.c */
1423 void ED_operatortypes_screen(void)
1424 {
1425         /* generic UI stuff */
1426         WM_operatortype_append(ED_SCR_OT_actionzone);
1427         WM_operatortype_append(ED_SCR_OT_repeat_last);
1428         
1429         /* screen tools */
1430         WM_operatortype_append(ED_SCR_OT_area_move);
1431         WM_operatortype_append(ED_SCR_OT_area_split);
1432         WM_operatortype_append(ED_SCR_OT_area_join);
1433         WM_operatortype_append(ED_SCR_OT_area_rip);
1434         WM_operatortype_append(ED_SCR_OT_region_split);
1435         WM_operatortype_append(ED_SCR_OT_region_flip);
1436         WM_operatortype_append(ED_SCR_OT_screen_set);
1437         WM_operatortype_append(ED_SCR_OT_screen_full_area);
1438         
1439         /*frame changes*/
1440         WM_operatortype_append(ED_SCR_OT_frame_offset);
1441         WM_operatortype_append(ED_SCR_OT_animation_play);
1442         
1443         /* tools shared by more space types */
1444         ED_marker_operatortypes();      
1445         
1446 }
1447
1448 /* called in spacetypes.c */
1449 void ED_keymap_screen(wmWindowManager *wm)
1450 {
1451         ListBase *keymap= WM_keymap_listbase(wm, "Screen", 0, 0);
1452         
1453         WM_keymap_verify_item(keymap, "ED_SCR_OT_actionzone", LEFTMOUSE, KM_PRESS, 0, 0);
1454         
1455         WM_keymap_verify_item(keymap, "ED_SCR_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0);
1456         WM_keymap_verify_item(keymap, "ED_SCR_OT_area_split", EVT_ACTIONZONE, 0, 0, 0); /* action tria */
1457         WM_keymap_verify_item(keymap, "ED_SCR_OT_area_join", EVT_ACTIONZONE, 0, 0, 0);  /* action tria */ 
1458         WM_keymap_verify_item(keymap, "ED_SCR_OT_area_rip", RKEY, KM_PRESS, KM_ALT, 0);
1459         RNA_int_set(WM_keymap_add_item(keymap, "ED_SCR_OT_screen_set", RIGHTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", 1);
1460         RNA_int_set(WM_keymap_add_item(keymap, "ED_SCR_OT_screen_set", LEFTARROWKEY, KM_PRESS, KM_CTRL, 0)->ptr, "delta", -1);
1461         WM_keymap_add_item(keymap, "ED_SCR_OT_screen_full_area", UPARROWKEY, KM_PRESS, KM_CTRL, 0);
1462         WM_keymap_add_item(keymap, "ED_SCR_OT_screen_full_area", DOWNARROWKEY, KM_PRESS, KM_CTRL, 0);
1463         WM_keymap_add_item(keymap, "ED_SCR_OT_screen_full_area", SPACEKEY, KM_PRESS, KM_CTRL, 0);
1464
1465          /* tests */
1466         RNA_enum_set(WM_keymap_add_item(keymap, "ED_SCR_OT_region_split", SKEY, KM_PRESS, 0, 0)->ptr, "dir", 'h');
1467         RNA_enum_set(WM_keymap_add_item(keymap, "ED_SCR_OT_region_split", SKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "dir", 'v');
1468                                                   
1469         /*frame offsets*/
1470         WM_keymap_add_item(keymap, "ED_SCR_OT_animation_play", TIMER, KM_ANY, 0, 0);
1471         RNA_int_set(WM_keymap_add_item(keymap, "ED_SCR_OT_frame_offset", UPARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 10);
1472         RNA_int_set(WM_keymap_add_item(keymap, "ED_SCR_OT_frame_offset", DOWNARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -10);
1473         RNA_int_set(WM_keymap_add_item(keymap, "ED_SCR_OT_frame_offset", LEFTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", -1);
1474         RNA_int_set(WM_keymap_add_item(keymap, "ED_SCR_OT_frame_offset", RIGHTARROWKEY, KM_PRESS, 0, 0)->ptr, "delta", 1);
1475
1476         WM_keymap_add_item(keymap, "ED_SCR_OT_region_flip", F5KEY, KM_PRESS, 0, 0);
1477         WM_keymap_verify_item(keymap, "ED_SCR_OT_repeat_last", F4KEY, KM_PRESS, 0, 0);
1478         
1479         /* screen level global keymaps */
1480         // err...
1481         ED_marker_keymap(wm);
1482 }
1483