Code shuffle to make a bit more structure.
authorTon Roosendaal <ton@blender.org>
Wed, 19 Nov 2008 16:28:11 +0000 (16:28 +0000)
committerTon Roosendaal <ton@blender.org>
Wed, 19 Nov 2008 16:28:11 +0000 (16:28 +0000)
- operator definitions, callbacks, registry to WM and handlers for it are
  now always in a file xxxx_ops.c or xxxx_operators.c, in the bottom you
  will find the registry and handler code.

- fixed some confusing naming conventions "rip_area vs area_join" etc. Now
  stick to convention to first name subject, then operation (like UI :).
  So it's area_rip, screen_add, and so on.

- Nicely put exported calls (outside module) together in bottom: this using
  names such as ED_screen_duplicate().

- Moved Operator-Property API to new C file.

source/blender/editors/screen/screen_edit.c
source/blender/editors/screen/screen_intern.h
source/blender/editors/screen/screen_ops.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm.c
source/blender/windowmanager/intern/wm_operator_props.c [new file with mode: 0644]
source/blender/windowmanager/intern/wm_operators.c
source/blender/windowmanager/wm.h

index 9d668e79eb5101fb1fcdb6210adb447e37b03116..5c39a1b00bd8e20328b589490402ab8d255132e8 100644 (file)
@@ -31,7 +31,6 @@
 #include "DNA_vec_types.h"
 
 #include "BLI_blenlib.h"
-#include "BLI_arithb.h"
 
 #include "BKE_global.h"
 #include "BKE_library.h"
@@ -90,7 +89,7 @@ static ScrEdge *screen_addedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
 }
 
 
-static ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
+ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
 {
        ScrEdge *se;
        
@@ -102,170 +101,7 @@ static ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2)
        return NULL;
 }
 
-static ScrArea *screen_areahascursor(bScreen *scr, int x, int y)
-{
-       ScrArea *sa= NULL;
-       sa= scr->areabase.first;
-       while(sa) {
-               if(BLI_in_rcti(&sa->totrct, x, y)) break;
-               sa= sa->next;
-       }
-
-       return sa;
-}
-
-/* *************************** action zone operator ************************** */
-
-/* operator state vars used:  
-               none
-
-functions:
-
-       apply() set actionzone event
-
-       exit()  free customdata
-
-callbacks:
-
-       exec()  never used
-
-       invoke() check if in zone  
-                       add customdata, put mouseco and area in it
-                       add modal handler
-
-       modal() accept modal events while doing it
-                       call apply() with gesture info, active window, nonactive window
-                       call exit() and remove handler when LMB confirm
-
-*/
-
-typedef struct sActionzoneData {
-       ScrArea *sa1, *sa2;
-       AZone *az;
-       int x, y, gesture_dir;
-} sActionzoneData;
-
-
-static AZone *is_in_area_actionzone(ScrArea *sa, int x, int y)
-{
-       AZone *az= NULL;
-       int i= 0;
-       
-       for(az= sa->actionzones.first, i= 0; az; az= az->next, i++) {
-               if(az && az->type == AZONE_TRI) {
-                       if(IsPointInTri2DInts(az->x1, az->y1, az->x2, az->y2, x, y)) 
-                               break;
-               }
-               if(az->type == AZONE_QUAD) {
-                       if(az->x1 < x && x < az->x2 && az->y1 < y && y < az->y2) 
-                               break;
-               }
-       }
-       
-       return az;
-}
-
-static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-       AZone *az= is_in_area_actionzone(C->area, event->x, event->y);
-       sActionzoneData *sad;
-       
-       /* quick escape */
-       if(az==NULL)
-               return OPERATOR_PASS_THROUGH;
-       
-       /* ok we do the actionzone */
-       sad= op->customdata= MEM_callocN(sizeof(sActionzoneData), "sActionzoneData");
-       sad->sa1= C->area;
-       sad->az= az;
-       sad->x= event->x; sad->y= event->y;
-       
-       /* add modal handler */
-       WM_event_add_modal_handler(&C->window->handlers, op);
-       
-       return OPERATOR_RUNNING_MODAL;
-}
-
-static void actionzone_exit(bContext *C, wmOperator *op)
-{
-       if(op->customdata)
-               MEM_freeN(op->customdata);
-       op->customdata= NULL;
-}
-
-/* send EVT_ACTIONZONE event */
-static void actionzone_apply(bContext *C, wmOperator *op)
-{
-       wmEvent event;
-       
-       event= *(C->window->eventstate);        /* XXX huh huh? make api call */
-       event.type= EVT_ACTIONZONE;
-       event.customdata= op->customdata;
-       event.customdatafree= TRUE;
-       op->customdata= NULL;
-       
-       wm_event_add(C->window, &event);
-}
-
-static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event)
-{
-       sActionzoneData *sad= op->customdata;
-       int deltax, deltay;
-
-       switch(event->type) {
-               case MOUSEMOVE:
-                       /* calculate gesture direction */
-                       deltax= (event->x - sad->x);
-                       deltay= (event->y - sad->y);
-                       
-                       if(deltay > ABS(deltax))
-                               sad->gesture_dir= AZONE_N;
-                       else if(deltax > ABS(deltay))
-                               sad->gesture_dir= AZONE_E;
-                       else if(deltay < -ABS(deltax))
-                               sad->gesture_dir= AZONE_S;
-                       else
-                               sad->gesture_dir= AZONE_W;
-                       
-                       /* gesture is large enough? */
-                       if(ABS(deltax) > 12 || ABS(deltay) > 12) {
-                               
-                               /* second area, for join */
-                               sad->sa2= screen_areahascursor(C->screen, event->x, event->y);
-                               /* apply sends event */
-                               actionzone_apply(C, op);
-                               actionzone_exit(C, op);
-                               
-                               WM_event_remove_modal_handler(&C->window->handlers, op);
-                               
-                               return OPERATOR_FINISHED;
-                       }
-                       break;
-               case ESCKEY:
-               case LEFTMOUSE:
-                       actionzone_exit(C, op);
-                       WM_event_remove_modal_handler(&C->window->handlers, op);
-                       return OPERATOR_CANCELLED;
-       }
-       
-       return OPERATOR_RUNNING_MODAL;
-}
-
-void ED_SCR_OT_actionzone(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name= "Handle area action zones";
-       ot->idname= "ED_SCR_OT_actionzone";
-       
-       ot->invoke= actionzone_invoke;
-       ot->modal= actionzone_modal;
-       
-       ot->poll= ED_operator_areaactive;
-}
-
-/* ************************************** */
-
-static void removedouble_scrverts(bScreen *sc)
+void removedouble_scrverts(bScreen *sc)
 {
        ScrVert *v1, *verg;
        ScrEdge *se;
@@ -319,7 +155,7 @@ static void removedouble_scrverts(bScreen *sc)
 
 }
 
-static void removenotused_scrverts(bScreen *sc)
+void removenotused_scrverts(bScreen *sc)
 {
        ScrVert *sv, *svn;
        ScrEdge *se;
@@ -345,7 +181,7 @@ static void removenotused_scrverts(bScreen *sc)
        }
 }
 
-static void removedouble_scredges(bScreen *sc)
+void removedouble_scredges(bScreen *sc)
 {
        ScrEdge *verg, *se, *sn;
        
@@ -365,7 +201,7 @@ static void removedouble_scredges(bScreen *sc)
        }
 }
 
-static void removenotused_scredges(bScreen *sc)
+void removenotused_scredges(bScreen *sc)
 {
        ScrEdge *se, *sen;
        ScrArea *sa;
@@ -401,80 +237,6 @@ static void removenotused_scredges(bScreen *sc)
        }
 }
 
-static int scredge_is_horizontal(ScrEdge *se)
-{
-       return (se->v1->vec.y == se->v2->vec.y);
-}
-
-static ScrEdge *screen_find_active_scredge(bScreen *sc, int mx, int my)
-{
-       ScrEdge *se;
-       
-       for (se= sc->edgebase.first; se; se= se->next) {
-               if (scredge_is_horizontal(se)) {
-                       short min, max;
-                       min= MIN2(se->v1->vec.x, se->v2->vec.x);
-                       max= MAX2(se->v1->vec.x, se->v2->vec.x);
-                       
-                       if (abs(my-se->v1->vec.y)<=2 && mx>=min && mx<=max)
-                               return se;
-               } 
-               else {
-                       short min, max;
-                       min= MIN2(se->v1->vec.y, se->v2->vec.y);
-                       max= MAX2(se->v1->vec.y, se->v2->vec.y);
-                       
-                       if (abs(mx-se->v1->vec.x)<=2 && my>=min && my<=max)
-                               return se;
-               }
-       }
-       
-       return NULL;
-}
-
-/* danger: is used while areamove! */
-static void select_connected_scredge(bScreen *sc, ScrEdge *edge)
-{
-       ScrEdge *se;
-       ScrVert *sv;
-       int oneselected;
-       char dir;
-       
-       /* select connected, only in the right direction */
-       /* 'dir' is the direction of EDGE */
-       
-       if(edge->v1->vec.x==edge->v2->vec.x) dir= 'v';
-       else dir= 'h';
-       
-       sv= sc->vertbase.first;
-       while(sv) {
-               sv->flag = 0;
-               sv= sv->next;
-       }
-       
-       edge->v1->flag= 1;
-       edge->v2->flag= 1;
-       
-       oneselected= 1;
-       while(oneselected) {
-               se= sc->edgebase.first;
-               oneselected= 0;
-               while(se) {
-                       if(se->v1->flag + se->v2->flag==1) {
-                               if(dir=='h') if(se->v1->vec.y==se->v2->vec.y) {
-                                       se->v1->flag= se->v2->flag= 1;
-                                       oneselected= 1;
-                               }
-                               if(dir=='v') if(se->v1->vec.x==se->v2->vec.x) {
-                                       se->v1->flag= se->v2->flag= 1;
-                                       oneselected= 1;
-                               }
-                       }
-                       se= se->next;
-               }
-       }
-}
-
 /* adds no space data */
 static ScrArea *screen_addarea(bScreen *sc, ScrVert *v1, ScrVert *v2, ScrVert *v3, ScrVert *v4, short headertype, short spacetype)
 {
@@ -499,14 +261,108 @@ static void screen_delarea(bScreen *sc, ScrArea *sa)
        MEM_freeN(sa);
 }
 
-/* Helper function to join 2 areas, it has a return value, 0=failed 1=success
- *     used by the split, join and rip operators
- */
-int screen_join_areas(bScreen *scr, ScrArea *sa1, ScrArea *sa2);
+/* return 0: no split possible */
+/* else return (integer) screencoordinate split point */
+static short testsplitpoint(wmWindow *win, ScrArea *sa, char dir, float fac)
+{
+       short x, y;
+       
+       // area big enough?
+       if(sa->v4->vec.x- sa->v1->vec.x <= 2*AREAMINX) return 0;
+       if(sa->v2->vec.y- sa->v1->vec.y <= 2*AREAMINY) return 0;
+       
+       // to be sure
+       if(fac<0.0) fac= 0.0;
+       if(fac>1.0) fac= 1.0;
+       
+       if(dir=='h') {
+               y= sa->v1->vec.y+ fac*(sa->v2->vec.y- sa->v1->vec.y);
+               
+               if(y- sa->v1->vec.y < AREAMINY) 
+                       y= sa->v1->vec.y+ AREAMINY;
+               else if(sa->v2->vec.y- y < AREAMINY) 
+                       y= sa->v2->vec.y- AREAMINY;
+               else y-= (y % AREAGRID);
+               
+               return y;
+       }
+       else {
+               x= sa->v1->vec.x+ fac*(sa->v4->vec.x- sa->v1->vec.x);
+               
+               if(x- sa->v1->vec.x < AREAMINX) 
+                       x= sa->v1->vec.x+ AREAMINX;
+               else if(sa->v4->vec.x- x < AREAMINX) 
+                       x= sa->v4->vec.x- AREAMINX;
+               else x-= (x % AREAGRID);
+               
+               return x;
+       }
+}
+
+ScrArea *area_split(wmWindow *win, bScreen *sc, ScrArea *sa, char dir, float fac)
+{
+       ScrArea *newa=NULL;
+       ScrVert *sv1, *sv2;
+       short split;
+       
+       if(sa==0) return NULL;
+       
+       split= testsplitpoint(win, sa, dir, fac);
+       if(split==0) return NULL;
+       
+       if(dir=='h') {
+               /* new vertices */
+               sv1= screen_addvert(sc, sa->v1->vec.x, split);
+               sv2= screen_addvert(sc, sa->v4->vec.x, split);
+               
+               /* new edges */
+               screen_addedge(sc, sa->v1, sv1);
+               screen_addedge(sc, sv1, sa->v2);
+               screen_addedge(sc, sa->v3, sv2);
+               screen_addedge(sc, sv2, sa->v4);
+               screen_addedge(sc, sv1, sv2);
+               
+               /* new areas: top */
+               newa= screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->headertype, sa->spacetype);
+               area_copy_data(newa, sa, 0);
+               
+               /* area below */
+               sa->v2= sv1;
+               sa->v3= sv2;
+               
+       }
+       else {
+               /* new vertices */
+               sv1= screen_addvert(sc, split, sa->v1->vec.y);
+               sv2= screen_addvert(sc, split, sa->v2->vec.y);
+               
+               /* new edges */
+               screen_addedge(sc, sa->v1, sv1);
+               screen_addedge(sc, sv1, sa->v4);
+               screen_addedge(sc, sa->v2, sv2);
+               screen_addedge(sc, sv2, sa->v3);
+               screen_addedge(sc, sv1, sv2);
+               
+               /* new areas: left */
+               newa= screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->headertype, sa->spacetype);
+               area_copy_data(newa, sa, 0);
+               
+               /* area right */
+               sa->v1= sv1;
+               sa->v2= sv2;
+       }
+       
+       /* remove double vertices en edges */
+       removedouble_scrverts(sc);
+       removedouble_scredges(sc);
+       removenotused_scredges(sc);
+       
+       return newa;
+}
 
 /* empty screen, with 1 dummy area without spacedata */
 /* uses window size */
-static bScreen *screen_add(wmWindow *win, char *name)
+bScreen *screen_add(wmWindow *win, char *name)
 {
        bScreen *sc;
        ScrVert *sv1, *sv2, *sv3, *sv4;
@@ -581,100 +437,11 @@ static void screen_copy(bScreen *to, bScreen *from)
 
 }
 
-/* *********** Rip area operator ****************** */
-
-
-/* operator callback */
-/* (ton) removed attempt to merge ripped area with another, don't think this is desired functionality.
-                conventions: 'atomic' and 'dont think for user' :) */
-static int screen_area_rip_op(bContext *C, wmOperator *op)
-{
-       wmWindow *win;
-       bScreen *newsc;
-       rcti rect;
-       
-       /*  poll() checks area context, but we don't accept full-area windows */
-       if(C->screen->full != SCREENNORMAL) 
-               return OPERATOR_CANCELLED;
-       
-       /* adds window to WM */
-       rect= C->area->totrct;
-       BLI_translate_rcti(&rect, C->window->posx, C->window->posy);
-       win= WM_window_open(C, &rect);
-       
-       /* allocs new screen and adds to newly created window, using window size */
-       newsc= screen_add(win, C->screen->id.name+2);
-       
-       /* copy area to new screen */
-       area_copy_data((ScrArea *)newsc->areabase.first, C->area, 0);
-       
-       /* screen, areas init */
-       WM_event_add_notifier(C->wm, win, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL);
-       
-       return OPERATOR_FINISHED;
-}
-
-
-
-void ED_SCR_OT_area_rip(wmOperatorType *ot)
-{
-       ot->name= "Rip Area into New Window";
-       ot->idname= "ED_SCR_OT_area_rip";
-       
-       ot->invoke= NULL; //WM_operator_confirm;
-       ot->exec= screen_area_rip_op;
-       ot->poll= ED_operator_areaactive;
-}
-
-/* ********************************************* */
-
-bScreen *ED_screen_duplicate(wmWindow *win, bScreen *sc)
-{
-       bScreen *newsc;
-       
-       if(sc->full != SCREENNORMAL) return NULL; /* XXX handle this case! */
-       
-       /* make new empty screen: */
-       newsc= screen_add(win, sc->id.name+2);
-       /* copy all data */
-       screen_copy(newsc, sc);
-       
-       return newsc;
-}
-
-/* with sa as center, sb is located at: 0=W, 1=N, 2=E, 3=S */
-/* used with split operator */
-static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb)
-{
-       ScrVert *sav1= sa->v1;
-       ScrVert *sav2= sa->v2;
-       ScrVert *sav3= sa->v3;
-       ScrVert *sav4= sa->v4;
-       ScrVert *sbv1= sb->v1;
-       ScrVert *sbv2= sb->v2;
-       ScrVert *sbv3= sb->v3;
-       ScrVert *sbv4= sb->v4;
-       
-       if(sav1==sbv4 && sav2==sbv3) { /* sa to right of sb = W */
-               return screen_findedge(screen, sav1, sav2);
-       }
-       else if(sav2==sbv1 && sav3==sbv4) { /* sa to bottom of sb = N */
-               return screen_findedge(screen, sav2, sav3);
-       }
-       else if(sav3==sbv2 && sav4==sbv1) { /* sa to left of sb = E */
-               return screen_findedge(screen, sav3, sav4);
-       }
-       else if(sav1==sbv2 && sav4==sbv3) { /* sa on top of sb = S*/
-               return screen_findedge(screen, sav1, sav4);
-       }
-       
-       return NULL;
-}
 
 /* with sa as center, sb is located at: 0=W, 1=N, 2=E, 3=S */
 /* -1 = not valid check */
 /* used with join operator */
-static int area_getorientation(bScreen *screen, ScrArea *sa, ScrArea *sb)
+int area_getorientation(bScreen *screen, ScrArea *sa, ScrArea *sb)
 {
        ScrVert *sav1, *sav2, *sav3, *sav4;
        ScrVert *sbv1, *sbv2, *sbv3, *sbv4;
@@ -706,120 +473,15 @@ static int area_getorientation(bScreen *screen, ScrArea *sa, ScrArea *sb)
        return -1;
 }
 
-/* return 0: no split possible */
-/* else return (integer) screencoordinate split point */
-static short testsplitpoint(wmWindow *win, ScrArea *sa, char dir, float fac)
+/* Helper function to join 2 areas, it has a return value, 0=failed 1=success
+*      used by the split, join operators
+*/
+int screen_area_join(bScreen* scr, ScrArea *sa1, ScrArea *sa2) 
 {
-       short x, y;
+       int dir;
        
-       // area big enough?
-       if(sa->v4->vec.x- sa->v1->vec.x <= 2*AREAMINX) return 0;
-       if(sa->v2->vec.y- sa->v1->vec.y <= 2*AREAMINY) return 0;
-
-       // to be sure
-       if(fac<0.0) fac= 0.0;
-       if(fac>1.0) fac= 1.0;
-       
-       if(dir=='h') {
-               y= sa->v1->vec.y+ fac*(sa->v2->vec.y- sa->v1->vec.y);
-               
-               if(sa->v2->vec.y==win->sizey-1 && sa->v2->vec.y- y < HEADERY) 
-                       y= sa->v2->vec.y- HEADERY;
-
-               else if(sa->v1->vec.y==0 && y- sa->v1->vec.y < HEADERY)
-                       y= sa->v1->vec.y+ HEADERY;
-
-               else if(y- sa->v1->vec.y < AREAMINY) y= sa->v1->vec.y+ AREAMINY;
-               else if(sa->v2->vec.y- y < AREAMINY) y= sa->v2->vec.y- AREAMINY;
-               else y-= (y % AREAGRID);
-
-               return y;
-       }
-       else {
-               x= sa->v1->vec.x+ fac*(sa->v4->vec.x- sa->v1->vec.x);
-               if(x- sa->v1->vec.x < AREAMINX) x= sa->v1->vec.x+ AREAMINX;
-               else if(sa->v4->vec.x- x < AREAMINX) x= sa->v4->vec.x- AREAMINX;
-               else x-= (x % AREAGRID);
-
-               return x;
-       }
-}
-
-static ScrArea *splitarea(wmWindow *win, bScreen *sc, ScrArea *sa, char dir, float fac)
-{
-       ScrArea *newa=NULL;
-       ScrVert *sv1, *sv2;
-       short split;
-       
-       if(sa==0) return NULL;
-       
-       split= testsplitpoint(win, sa, dir, fac);
-       if(split==0) return NULL;
-       
-       //sc= G.curscreen;
-       
-       //areawinset(sa->win);
-       
-       if(dir=='h') {
-               /* new vertices */
-               sv1= screen_addvert(sc, sa->v1->vec.x, split);
-               sv2= screen_addvert(sc, sa->v4->vec.x, split);
-               
-               /* new edges */
-               screen_addedge(sc, sa->v1, sv1);
-               screen_addedge(sc, sv1, sa->v2);
-               screen_addedge(sc, sa->v3, sv2);
-               screen_addedge(sc, sv2, sa->v4);
-               screen_addedge(sc, sv1, sv2);
-               
-               /* new areas: top */
-               newa= screen_addarea(sc, sv1, sa->v2, sa->v3, sv2, sa->headertype, sa->spacetype);
-               area_copy_data(newa, sa, 0);
-
-               /* area below */
-               sa->v2= sv1;
-               sa->v3= sv2;
-               
-       }
-       else {
-               /* new vertices */
-               sv1= screen_addvert(sc, split, sa->v1->vec.y);
-               sv2= screen_addvert(sc, split, sa->v2->vec.y);
-               
-               /* new edges */
-               screen_addedge(sc, sa->v1, sv1);
-               screen_addedge(sc, sv1, sa->v4);
-               screen_addedge(sc, sa->v2, sv2);
-               screen_addedge(sc, sv2, sa->v3);
-               screen_addedge(sc, sv1, sv2);
-               
-               /* new areas: left */
-               newa= screen_addarea(sc, sa->v1, sa->v2, sv2, sv1, sa->headertype, sa->spacetype);
-               area_copy_data(newa, sa, 0);
-
-               /* area right */
-               sa->v1= sv1;
-               sa->v2= sv2;
-       }
-       
-       /* remove double vertices en edges */
-       removedouble_scrverts(sc);
-       removedouble_scredges(sc);
-       removenotused_scredges(sc);
-       
-       return newa;
-}
-
-
-/* Helper function to join 2 areas, it has a return value, 0=failed 1=success
- *     used by the split, join and rip operators
- */
-int screen_join_areas(bScreen* scr, ScrArea *sa1, ScrArea *sa2) 
-{
-       int dir;
-       
-       dir = area_getorientation(scr, sa1, sa2);
-       /*printf("dir is : %i \n", dir);*/
+       dir = area_getorientation(scr, sa1, sa2);
+       /*printf("dir is : %i \n", dir);*/
        
        if (dir < 0)
        {
@@ -860,10 +522,9 @@ int screen_join_areas(bScreen* scr, ScrArea *sa1, ScrArea *sa2)
        return 1;
 }
 
-/* *************************************************************** */
 
 /* test if screen vertices should be scaled */
-void screen_test_scale(bScreen *sc, int winsizex, int winsizey)
+static void screen_test_scale(bScreen *sc, int winsizex, int winsizey)
 {
        ScrVert *sv=NULL;
        ScrArea *sa, *san;
@@ -922,6 +583,7 @@ void screen_test_scale(bScreen *sc, int winsizex, int winsizey)
        }
 }
 
+/* *********************** DRAWING **************************************** */
 
 
 #define SCR_BACK 0.55
@@ -1135,6 +797,23 @@ static void drawscredge_area(ScrArea *sa)
        }
 }
 
+/* ****************** EXPORTED API TO OTHER MODULES *************************** */
+
+bScreen *ED_screen_duplicate(wmWindow *win, bScreen *sc)
+{
+       bScreen *newsc;
+       
+       if(sc->full != SCREENNORMAL) return NULL; /* XXX handle this case! */
+       
+       /* make new empty screen: */
+       newsc= screen_add(win, sc->id.name+2);
+       /* copy all data */
+       screen_copy(newsc, sc);
+       
+       return newsc;
+}
+
+
 void ED_screen_do_listen(wmWindow *win, wmNotifier *note)
 {
        
@@ -1169,6 +848,7 @@ void ED_screen_draw(wmWindow *win)
                drawscredge_area(sa);
        }
 
+       /* blended join arrow */
        if (sa1 && sa2) {
                dir = area_getorientation(win->screen, sa1, sa2);
                if (dir >= 0) {
@@ -1194,6 +874,7 @@ void ED_screen_draw(wmWindow *win)
                scrarea_draw_shape_dark(sa2, dir);
                scrarea_draw_shape_light(sa1, dira);
        }
+       
        if(G.f & G_DEBUG) printf("draw screen\n");
        win->screen->do_draw= 0;
 }
@@ -1301,827 +982,4 @@ void ED_screen_set_subwinactive(wmWindow *win)
        }
 }
 
-/* ****************** cursor near edge operator ********************************* */
-
-/* operator cb */
-int screen_cursor_test(bContext *C, wmOperator *op, wmEvent *event)
-{
-       if (C->screen->subwinactive==C->screen->mainwin) {
-               ScrEdge *actedge= screen_find_active_scredge(C->screen, event->x, event->y);
-               
-               if (actedge && scredge_is_horizontal(actedge)) {
-                       WM_set_cursor(C, CURSOR_Y_MOVE);
-               } else {
-                       WM_set_cursor(C, CURSOR_X_MOVE);
-               }
-       } else {
-               ScrArea *sa= NULL;
-               AZone *az= NULL;
-               for(sa= C->screen->areabase.first; sa; sa= sa->next) {
-                       az= is_in_area_actionzone(sa, event->x, event->y);
-                       if(az!=NULL) break;
-               }
-               if(az!=NULL) WM_set_cursor(C, CURSOR_EDIT);
-               else WM_set_cursor(C, CURSOR_STD);
-       }
-       
-       return OPERATOR_PASS_THROUGH;
-}
-
-/* ************** move area edge operator *********************************** */
-
-/* operator state vars used:  
-           x, y                        mouse coord near edge
-           delta            movement of edge
-
-       functions:
-
-       init()   set default property values, find edge based on mouse coords, test
-            if the edge can be moved, select edges, calculate min and max movement
-
-       apply() apply delta on selection
-
-       exit()  cleanup, send notifier
-
-       cancel() cancel moving
-
-       callbacks:
-
-       exec()   execute without any user interaction, based on properties
-            call init(), apply(), exit()
-
-       invoke() gets called on mouse click near edge
-            call init(), add handler
-
-       modal()  accept modal events while doing it
-                       call apply() with delta motion
-            call exit() and remove handler
-
-*/
-
-typedef struct sAreaMoveData {
-       int bigger, smaller, origval;
-       char dir;
-} sAreaMoveData;
-
-/* helper call to move area-edge, sets limits */
-static void move_areas_set_limits(bScreen *sc, int dir, int *bigger, int *smaller)
-{
-       ScrArea *sa;
-       
-       /* we check all areas and test for free space with MINSIZE */
-       *bigger= *smaller= 100000;
-       
-       for(sa= sc->areabase.first; sa; sa= sa->next) {
-               if(dir=='h') {
-                       int y1= sa->v2->vec.y - sa->v1->vec.y-AREAMINY;
-                       
-                       /* if top or down edge selected, test height */
-                       if(sa->v1->flag && sa->v4->flag)
-                               *bigger= MIN2(*bigger, y1);
-                       else if(sa->v2->flag && sa->v3->flag)
-                               *smaller= MIN2(*smaller, y1);
-               }
-               else {
-                       int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
-                       
-                       /* if left or right edge selected, test width */
-                       if(sa->v1->flag && sa->v2->flag)
-                               *bigger= MIN2(*bigger, x1);
-                       else if(sa->v3->flag && sa->v4->flag)
-                               *smaller= MIN2(*smaller, x1);
-               }
-       }
-}
-
-/* validate selection inside screen, set variables OK */
-/* return 0: init failed */
-static int move_areas_init (bContext *C, wmOperator *op)
-{
-       ScrEdge *actedge;
-       sAreaMoveData *md;
-       int x, y;
-
-       /* required properties */
-       if(!(OP_get_int(op, "x", &x) && OP_get_int(op, "y", &y)))
-               return 0;
-
-       /* default properties */
-       OP_verify_int(op, "delta", 0, NULL);
-
-       /* setup */
-       actedge= screen_find_active_scredge(C->screen, x, y);
-       if(actedge==NULL) return 0;
-
-       md= MEM_callocN(sizeof(sAreaMoveData), "sAreaMoveData");
-       op->customdata= md;
-
-       md->dir= scredge_is_horizontal(actedge)?'h':'v';
-       if(md->dir=='h') md->origval= actedge->v1->vec.y;
-       else md->origval= actedge->v1->vec.x;
-       
-       select_connected_scredge(C->screen, actedge);
-       /* now all vertices with 'flag==1' are the ones that can be moved. */
-
-       move_areas_set_limits(C->screen, md->dir, &md->bigger, &md->smaller);
-       
-       return 1;
-}
-
-/* moves selected screen edge amount of delta, used by split & move */
-static void move_areas_apply_do(bContext *C, int origval, int delta, int dir, int bigger, int smaller)
-{
-       ScrVert *v1;
-       
-       delta= CLAMPIS(delta, -smaller, bigger);
-       
-       for (v1= C->screen->vertbase.first; v1; v1= v1->next) {
-               if (v1->flag) {
-                       /* that way a nice AREAGRID  */
-                       if((dir=='v') && v1->vec.x>0 && v1->vec.x<C->window->sizex-1) {
-                               v1->vec.x= origval + delta;
-                               if(delta != bigger && delta != -smaller) v1->vec.x-= (v1->vec.x % AREAGRID);
-                       }
-                       if((dir=='h') && v1->vec.y>0 && v1->vec.y<C->window->sizey-1) {
-                               v1->vec.y= origval + delta;
-
-                               v1->vec.y+= AREAGRID-1;
-                               v1->vec.y-= (v1->vec.y % AREAGRID);
-                               
-                               /* prevent too small top header */
-                               if(v1->vec.y > C->window->sizey-HEADERY)
-                                       v1->vec.y= C->window->sizey-HEADERY;
-                       }
-               }
-       }
-
-       WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL);
-}
-
-static void move_areas_apply(bContext *C, wmOperator *op)
-{
-       sAreaMoveData *md= op->customdata;
-       int delta;
-       
-       OP_get_int(op, "delta", &delta);
-       move_areas_apply_do(C, md->origval, delta, md->dir, md->bigger, md->smaller);
-}
-
-static void move_areas_exit(bContext *C, wmOperator *op)
-{
-       if(op->customdata)
-               MEM_freeN(op->customdata);
-       op->customdata= NULL;
-       
-       /* this makes sure aligned edges will result in aligned grabbing */
-       removedouble_scrverts(C->screen);
-       removedouble_scredges(C->screen);
-}
-
-static int move_areas_exec(bContext *C, wmOperator *op)
-{
-       if(!move_areas_init(C, op))
-               return OPERATOR_CANCELLED;
-       
-       move_areas_apply(C, op);
-       move_areas_exit(C, op);
-       
-       return OPERATOR_FINISHED;
-}
-
-/* interaction callback */
-static int move_areas_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-       OP_verify_int(op, "x", event->x, NULL);
-       OP_verify_int(op, "y", event->y, NULL);
-
-       if(!move_areas_init(C, op)) 
-               return OPERATOR_PASS_THROUGH;
-       
-       /* add temp handler */
-       WM_event_add_modal_handler(&C->window->handlers, op);
-       
-       return OPERATOR_RUNNING_MODAL;
-}
-
-static int move_areas_cancel(bContext *C, wmOperator *op)
-{
-       WM_event_remove_modal_handler(&C->window->handlers, op);                                
-
-       OP_set_int(op, "delta", 0);
-       move_areas_apply(C, op);
-       move_areas_exit(C, op);
-
-       return OPERATOR_CANCELLED;
-}
-
-/* modal callback for while moving edges */
-static int move_areas_modal(bContext *C, wmOperator *op, wmEvent *event)
-{
-       sAreaMoveData *md;
-       int delta, x, y;
-
-       md= op->customdata;
-
-       OP_get_int(op, "x", &x);
-       OP_get_int(op, "y", &y);
-
-       /* execute the events */
-       switch(event->type) {
-               case MOUSEMOVE:
-                       delta= (md->dir == 'v')? event->x - x: event->y - y;
-                       OP_set_int(op, "delta", delta);
-
-                       move_areas_apply(C, op);
-                       break;
-                       
-               case LEFTMOUSE:
-                       if(event->val==0) {
-                               move_areas_exit(C, op);
-                               WM_event_remove_modal_handler(&C->window->handlers, op);                                
-                               return OPERATOR_FINISHED;
-                       }
-                       break;
-                       
-               case ESCKEY:
-                       return move_areas_cancel(C, op);
-       }
-       
-       return OPERATOR_RUNNING_MODAL;
-}
-
-void ED_SCR_OT_move_areas(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name= "Move area edges";
-       ot->idname= "ED_SCR_OT_move_areas";
-
-       ot->exec= move_areas_exec;
-       ot->invoke= move_areas_invoke;
-       ot->cancel= move_areas_cancel;
-       ot->modal= move_areas_modal;
-
-       ot->poll= ED_operator_screen_mainwinactive; /* when mouse is over area-edge */
-}
-
-/* ************** split area operator *********************************** */
-
-/* 
-operator state vars:  
-       fac              spit point
-       dir              direction 'v' or 'h'
-
-operator customdata:
-       area                    pointer to (active) area
-       x, y                    last used mouse pos
-       (more, see below)
-
-functions:
-
-       init()   set default property values, find area based on context
-
-       apply() split area based on state vars
-
-       exit()  cleanup, send notifier
-
-       cancel() remove duplicated area
-
-callbacks:
-
-       exec()   execute without any user interaction, based on state vars
-            call init(), apply(), exit()
-
-       invoke() gets called on mouse click in action-widget
-            call init(), add modal handler
-                       call apply() with initial motion
-
-       modal()  accept modal events while doing it
-            call move-areas code with delta motion
-            call exit() or cancel() and remove handler
-
-*/
-
-#define SPLIT_STARTED  1
-#define SPLIT_PROGRESS 2
-
-typedef struct sAreaSplitData
-{
-       int x, y;       /* last used mouse position */
-       
-       int origval;                    /* for move areas */
-       int bigger, smaller;    /* constraints for moving new edge */
-       int delta;                              /* delta move edge */
-       
-       ScrEdge *nedge;                 /* new edge */
-       ScrArea *sarea;                 /* start area */
-       ScrArea *narea;                 /* new area */
-} sAreaSplitData;
-
-/* generic init, no UI stuff here */
-static int split_area_init(bContext *C, wmOperator *op)
-{
-       sAreaSplitData *sd;
-       int dir;
-       
-       /* required context */
-       if(C->area==NULL) return 0;
-       
-       /* required properties */
-       OP_verify_float(op, "fac", 0.5f, NULL);
-       OP_verify_int(op, "dir", 'h', &dir);
-       
-       /* minimal size */
-       if(dir=='v' && C->area->winx < 2*AREAMINX) return 0;
-       if(dir=='h' && C->area->winy < 2*AREAMINY) return 0;
-          
-       /* custom data */
-       sd= (sAreaSplitData*)MEM_callocN(sizeof (sAreaSplitData), "op_split_area");
-       op->customdata= sd;
-       
-       sd->sarea= C->area;
-       
-       return 1;
-}
-
-/* do the split */
-static void split_area_apply(bContext *C, wmOperator *op)
-{
-       sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
-       float fac;
-       int dir;
-       
-       OP_get_float(op, "fac", &fac);
-       OP_get_int(op, "dir", &dir);
-
-       sd->narea= splitarea(C->window, C->screen, sd->sarea, dir, fac);
-       
-       if(sd->narea) {
-               ScrVert *sv;
-               
-               sd->nedge= area_findsharededge(C->screen, sd->sarea, sd->narea);
-       
-               /* select newly created edge, prepare for moving edge */
-               for(sv= C->screen->vertbase.first; sv; sv= sv->next)
-                       sv->flag = 0;
-               
-               sd->nedge->v1->flag= 1;
-               sd->nedge->v2->flag= 1;
-
-               if(dir=='h') sd->origval= sd->nedge->v1->vec.y;
-               else sd->origval= sd->nedge->v1->vec.x;
-
-       }               
-       
-       WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL);
-       
-}
-
-static void split_area_exit(bContext *C, wmOperator *op)
-{
-       if (op->customdata) {
-               MEM_freeN(op->customdata);
-               op->customdata = NULL;
-       }
-       
-       WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL);
-
-       /* this makes sure aligned edges will result in aligned grabbing */
-       removedouble_scrverts(C->screen);
-       removedouble_scredges(C->screen);
-}
-
-
-/* UI callback, adds new handler */
-static int split_area_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-       sAreaSplitData *sd;
-       
-       if(event->type==EVT_ACTIONZONE) {
-               sActionzoneData *sad= event->customdata;
-               int dir;
-               
-               /* verify *sad itself */
-               if(sad==NULL || sad->sa1==NULL || sad->az==NULL)
-                       return OPERATOR_PASS_THROUGH;
-               
-               /* is this our *sad? if areas not equal it should be passed on */
-               if(C->area!=sad->sa1 || sad->sa1!=sad->sa2)
-                       return OPERATOR_PASS_THROUGH;
-               
-               /* prepare operator state vars */
-               if(sad->gesture_dir==AZONE_N || sad->gesture_dir==AZONE_S) {
-                       dir= 'h';
-                       OP_set_float(op, "fac", ((float)(event->x - sad->sa1->v1->vec.x)) / (float)sad->sa1->winx);
-               }
-               else {
-                       dir= 'v';
-                       OP_set_float(op, "fac", ((float)(event->y - sad->sa1->v1->vec.y)) / (float)sad->sa1->winy);
-               }
-               OP_set_int(op, "dir", dir);
-
-               /* general init, also non-UI case, adds customdata, sets area and defaults */
-               if(!split_area_init(C, op))
-                       return OPERATOR_PASS_THROUGH;
-               
-               sd= (sAreaSplitData *)op->customdata;
-               
-               sd->x= event->x;
-               sd->y= event->y;
-               
-               /* do the split */
-               split_area_apply(C, op);
-               move_areas_set_limits(C->screen, dir, &sd->bigger, &sd->smaller);
-               
-               /* add temp handler for edge move or cancel */
-               WM_event_add_modal_handler(&C->window->handlers, op);
-               
-               return OPERATOR_RUNNING_MODAL;
-               
-       }
-       return OPERATOR_PASS_THROUGH;
-}
-
-/* function to be called outside UI context, or for redo */
-static int split_area_exec(bContext *C, wmOperator *op)
-{
-       
-       if(!split_area_init(C, op))
-               return OPERATOR_CANCELLED;
-       
-       split_area_apply(C, op);
-       split_area_exit(C, op);
-       
-       return OPERATOR_FINISHED;
-}
-
-static int split_area_cancel(bContext *C, wmOperator *op)
-{
-       sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
-
-       WM_event_remove_modal_handler(&C->window->handlers, op);
-
-       if (screen_join_areas(C->screen,sd->sarea, sd->narea)) {
-               if (C->area == sd->narea) {
-                       C->area = NULL;
-               }
-               sd->narea = NULL;
-       }
-       split_area_exit(C, op);
-
-       return OPERATOR_CANCELLED;
-}
-
-static int split_area_modal(bContext *C, wmOperator *op, wmEvent *event)
-{
-       sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
-       int dir;
-
-       /* execute the events */
-       switch(event->type) {
-               case MOUSEMOVE:
-                       
-                       OP_get_int(op, "dir", &dir);
-                       
-                       sd->delta= (dir == 'v')? event->x - sd->origval: event->y - sd->origval;
-                       move_areas_apply_do(C, sd->origval, sd->delta, dir, sd->bigger, sd->smaller);
-                       
-                       WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL);
-                       break;
-                       
-               case LEFTMOUSE:
-                       if(event->val==0) { /* mouse up */
-                               split_area_exit(C, op);
-                               WM_event_remove_modal_handler(&C->window->handlers, op);
-                               return OPERATOR_FINISHED;
-                       }
-                       break;
-               case RIGHTMOUSE: /* cancel operation */
-               case ESCKEY:
-                       return split_area_cancel(C, op);
-       }
-       
-       return OPERATOR_RUNNING_MODAL;
-}
-
-void ED_SCR_OT_split_area(wmOperatorType *ot)
-{
-       ot->name = "Split area";
-       ot->idname = "ED_SCR_OT_split_area";
-       
-       ot->exec= split_area_exec;
-       ot->invoke= split_area_invoke;
-       ot->modal= split_area_modal;
-       
-       ot->poll= ED_operator_screenactive; /* XXX should be area active */
-}
-
-/* ************** join area operator ********************************************** */
-
-/* operator state vars used:  
-                       x1, y1     mouse coord in first area, which will disappear
-                       x2, y2     mouse coord in 2nd area, which will become joined
-
-functions:
-
-   init()   find edge based on state vars 
-                       test if the edge divides two areas, 
-                       store active and nonactive area,
-            
-   apply()  do the actual join
-
-   exit()      cleanup, send notifier
-
-callbacks:
-
-   exec()      calls init, apply, exit 
-   
-   invoke() sets mouse coords in x,y
-            call init()
-            add modal handler
-
-   modal()     accept modal events while doing it
-                       call apply() with active window and nonactive window
-            call exit() and remove handler when LMB confirm
-
-*/
-
-typedef struct sAreaJoinData
-{
-       ScrArea *sa1;   /* first area to be considered */
-       ScrArea *sa2;   /* second area to be considered */
-       ScrArea *scr;   /* designed for removal */
-
-} sAreaJoinData;
-
-
-/* validate selection inside screen, set variables OK */
-/* return 0: init failed */
-/* XXX todo: find edge based on (x,y) and set other area? */
-static int join_areas_init(bContext *C, wmOperator *op)
-{
-       ScrArea *sa1, *sa2;
-       sAreaJoinData* jd= NULL;
-       int x1, y1;
-       int x2, y2;
-
-       /* required properties, make negative to get return 0 if not set by caller */
-       OP_verify_int(op, "x1", -100, &x1);
-       OP_verify_int(op, "y1", -100, &y1);
-       OP_verify_int(op, "x2", -100, &x2);
-       OP_verify_int(op, "y2", -100, &y2);
-       
-       sa1 = screen_areahascursor(C->screen, x1, y1);
-       sa2 = screen_areahascursor(C->screen, x2, y2);
-       if(sa1==NULL || sa2==NULL || sa1==sa2)
-               return 0;
-
-       jd = (sAreaJoinData*)MEM_callocN(sizeof (sAreaJoinData), "op_join_areas");
-               
-       jd->sa1 = sa1;
-       jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
-       jd->sa2 = sa2;
-       jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
-       
-       op->customdata= jd;
-       
-       return 1;
-}
-
-/* apply the join of the areas (space types) */
-static int join_areas_apply(bContext *C, wmOperator *op)
-{
-       sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
-       if (!jd) return 0;
-
-       if(!screen_join_areas(C->screen,jd->sa1,jd->sa2)){
-               return 0;
-       }
-       if (C->area == jd->sa2) {
-               C->area = NULL;
-       }
-
-       return 1;
-}
-
-/* finish operation */
-static void join_areas_exit(bContext *C, wmOperator *op)
-{
-       if (op->customdata) {
-               MEM_freeN(op->customdata);
-               op->customdata = NULL;
-       }
-
-       /* this makes sure aligned edges will result in aligned grabbing */
-       removedouble_scredges(C->screen);
-       removenotused_scredges(C->screen);
-       removenotused_scrverts(C->screen);
-}
-
-static int join_areas_exec(bContext *C, wmOperator *op)
-{
-       if(!join_areas_init(C, op)) 
-               return OPERATOR_CANCELLED;
-       
-       join_areas_apply(C, op);
-       join_areas_exit(C, op);
-
-       return OPERATOR_FINISHED;
-}
-
-/* interaction callback */
-static int join_areas_invoke(bContext *C, wmOperator *op, wmEvent *event)
-{
-
-       if(event->type==EVT_ACTIONZONE) {
-               sActionzoneData *sad= event->customdata;
-               
-               /* verify *sad itself */
-               if(sad==NULL || sad->sa1==NULL || sad->sa2==NULL)
-                       return OPERATOR_PASS_THROUGH;
-               
-               /* is this our *sad? if areas equal it should be passed on */
-               if(sad->sa1==sad->sa2)
-                       return OPERATOR_PASS_THROUGH;
-               
-               /* prepare operator state vars */
-               OP_set_int(op, "x1", sad->x);
-               OP_set_int(op, "y1", sad->y);
-               OP_set_int(op, "x2", event->x);
-               OP_set_int(op, "y2", event->y);
-
-               if(!join_areas_init(C, op)) 
-                       return OPERATOR_PASS_THROUGH;
-       
-               /* add temp handler */
-               WM_event_add_modal_handler(&C->window->handlers, op);
-       
-               return OPERATOR_RUNNING_MODAL;
-       }
-       
-       return OPERATOR_PASS_THROUGH;
-}
-
-static int join_areas_cancel(bContext *C, wmOperator *op)
-{
-       sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
-
-       if (jd->sa1) {
-               jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
-               jd->sa1->flag &= ~AREA_FLAG_DRAWJOINTO;
-       }
-       if (jd->sa2) {
-               jd->sa2->flag &= ~AREA_FLAG_DRAWJOINFROM;
-               jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
-       }
-
-       WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL);
-       WM_event_remove_modal_handler(&C->window->handlers, op);                        
-       
-       join_areas_exit(C, op);
-
-       return OPERATOR_CANCELLED;
-}
-
-/* modal callback while selecting area (space) that will be removed */
-static int join_areas_modal(bContext *C, wmOperator *op, wmEvent *event)
-{
-       sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
-       
-       /* execute the events */
-       switch(event->type) {
-                       
-               case MOUSEMOVE: 
-                       {
-                               ScrArea *sa = screen_areahascursor(C->screen, event->x, event->y);
-                               int dir;
-                               
-                               if (sa) {                                       
-                                       if (jd->sa1 != sa) {
-                                               dir = area_getorientation(C->screen, jd->sa1, sa);
-                                               if (dir >= 0) {
-                                                       if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
-                                                       jd->sa2 = sa;
-                                                       jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
-                                               } 
-                                               else {
-                                                       /* we are not bordering on the previously selected area 
-                                                          we check if area has common border with the one marked for removal
-                                                          in this case we can swap areas.
-                                                       */
-                                                       dir = area_getorientation(C->screen, sa, jd->sa2);
-                                                       if (dir >= 0) {
-                                                               if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
-                                                               if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
-                                                               jd->sa1 = jd->sa2;
-                                                               jd->sa2 = sa;
-                                                               if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
-                                                               if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
-                                                       } 
-                                                       else {
-                                                               if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
-                                                               jd->sa2 = NULL;
-                                                       }
-                                               }
-                                               WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL);
-                                       } 
-                                       else {
-                                               /* we are back in the area previously selected for keeping 
-                                                * we swap the areas if possible to allow user to choose */
-                                               if (jd->sa2 != NULL) {
-                                                       if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
-                                                       if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
-                                                       jd->sa1 = jd->sa2;
-                                                       jd->sa2 = sa;
-                                                       if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
-                                                       if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
-                                                       dir = area_getorientation(C->screen, jd->sa1, jd->sa2);
-                                                       if (dir < 0) {
-                                                               printf("oops, didn't expect that!\n");
-                                                       }
-                                               } 
-                                               else {
-                                                       dir = area_getorientation(C->screen, jd->sa1, sa);
-                                                       if (dir >= 0) {
-                                                               if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
-                                                               jd->sa2 = sa;
-                                                               jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
-                                                       }
-                                               }
-                                               WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL);
-                                       }
-                               }
-                       }
-                       break;
-               case LEFTMOUSE:
-                       if(event->val==0) {
-                               join_areas_apply(C, op);
-                               WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL);
-                               join_areas_exit(C, op);
-                               WM_event_remove_modal_handler(&C->window->handlers, op);
-                               return OPERATOR_FINISHED;
-                       }
-                       break;
-                       
-               case ESCKEY:
-                       return join_areas_cancel(C, op);
-       }
-
-       return OPERATOR_RUNNING_MODAL;
-}
-
-/* Operator for joining two areas (space types) */
-void ED_SCR_OT_join_areas(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name= "Join area";
-       ot->idname= "ED_SCR_OT_join_areas";
-       
-       /* api callbacks */
-       ot->exec= join_areas_exec;
-       ot->invoke= join_areas_invoke;
-       ot->modal= join_areas_modal;
-
-       ot->poll= ED_operator_screenactive;
-}
-
-/* ************** border select operator (test only) ***************************** */
-
-/* operator state vars used: (added by default WM callbacks)   
-       xmin, ymin     
-       xmax, ymax     
-
-       customdata: the wmGesture pointer
-
-callbacks:
-
-       exec()  has to be filled in by user
-
-       invoke() default WM function
-                        adds modal handler
-
-       modal() default WM function 
-                       accept modal events while doing it, calls exec(), handles ESC and border drawing
-       
-       poll()  has to be filled in by user for context
-*/
-
-static int border_select_do(bContext *C, wmOperator *op)
-{
-       printf("border select do\n");
-       return 1;
-}
-
-void ED_SCR_OT_border_select(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name= "Border select";
-       ot->idname= "ED_SCR_OT_border_select";
-       
-       /* api callbacks */
-       ot->exec= border_select_do;
-       ot->invoke= WM_border_select_invoke;
-       ot->modal= WM_border_select_modal;
-       
-       ot->poll= ED_operator_areaactive;
-}
 
index c1ab9266f2f63eef3e042e9f1e94f1a01dbe744d..6d8bd9e0434d23bbc59c49dedd5286a97b73820a 100644 (file)
 #define ED_SCREEN_INTERN_H
 
 /* internal exports only */
-struct wmOperator;
-struct wmEvent;
+struct wmWindow;
 
 /* area.c */
 void area_copy_data(ScrArea *sa1, ScrArea *sa2, int swap_space);
 
 /* screen_edit.c */
-int screen_cursor_test(bContext *C, wmOperator *op, wmEvent *event);
-int area_cursor_test(bContext *C, wmOperator *op, wmEvent *event);
-
-void ED_SCR_OT_move_areas(wmOperatorType *ot);
-void ED_SCR_OT_split_area(wmOperatorType *ot);
-void ED_SCR_OT_join_areas(wmOperatorType *ot);
-void ED_SCR_OT_actionzone(wmOperatorType *ot);
-void ED_SCR_OT_area_rip(wmOperatorType *ot);
-
-void ED_SCR_OT_border_select(wmOperatorType *ot);
+bScreen *screen_add(struct wmWindow *win, char *name);
+ScrEdge *screen_findedge(bScreen *sc, ScrVert *v1, ScrVert *v2);
+ScrArea *area_split(wmWindow *win, bScreen *sc, ScrArea *sa, char dir, float fac);
+int screen_area_join(bScreen* scr, ScrArea *sa1, ScrArea *sa2);
+int area_getorientation(bScreen *screen, ScrArea *sa, ScrArea *sb);
+
+void removenotused_scrverts(bScreen *sc);
+void removedouble_scrverts(bScreen *sc);
+void removedouble_scredges(bScreen *sc);
+void removenotused_scredges(bScreen *sc);
 
 #endif /* ED_SCREEN_INTERN_H */
 
index 508fc70cf921b6f4304cdf254d210d57a44e8e6f..e2680f9cb02178810d184af1b96feff213026f57 100644 (file)
@@ -27,6 +27,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "BLI_blenlib.h"
+#include "BLI_arithb.h"
 
 #include "BKE_global.h"
 #include "BKE_library.h"
 
 #include "ED_area.h"
 #include "ED_screen.h"
+#include "ED_screen_types.h"
 
 #include "screen_intern.h"     /* own module include */
 
-/* ************** Poll tests ********************** */
+/* ************** Exported Poll tests ********************** */
 
 int ED_operator_areaactive(bContext *C)
 {
@@ -68,7 +70,226 @@ int ED_operator_screen_mainwinactive(bContext *C)
        return 1;
 }
 
-/* ******************************* */
+/* *************************** action zone operator ************************** */
+
+/* operator state vars used:  
+       none
+
+functions:
+
+       apply() set actionzone event
+
+       exit()  free customdata
+       
+callbacks:
+
+       exec()  never used
+
+       invoke() check if in zone  
+               add customdata, put mouseco and area in it
+               add modal handler
+
+       modal() accept modal events while doing it
+               call apply() with gesture info, active window, nonactive window
+               call exit() and remove handler when LMB confirm
+
+*/
+
+typedef struct sActionzoneData {
+       ScrArea *sa1, *sa2;
+       AZone *az;
+       int x, y, gesture_dir;
+} sActionzoneData;
+
+/* used by other operators too */
+static ScrArea *screen_areahascursor(bScreen *scr, int x, int y)
+{
+       ScrArea *sa= NULL;
+       sa= scr->areabase.first;
+       while(sa) {
+               if(BLI_in_rcti(&sa->totrct, x, y)) break;
+               sa= sa->next;
+       }
+       
+       return sa;
+}
+
+
+static AZone *is_in_area_actionzone(ScrArea *sa, int x, int y)
+{
+       AZone *az= NULL;
+       int i= 0;
+       
+       for(az= sa->actionzones.first, i= 0; az; az= az->next, i++) {
+               if(az && az->type == AZONE_TRI) {
+                       if(IsPointInTri2DInts(az->x1, az->y1, az->x2, az->y2, x, y)) 
+                               break;
+               }
+               if(az->type == AZONE_QUAD) {
+                       if(az->x1 < x && x < az->x2 && az->y1 < y && y < az->y2) 
+                               break;
+               }
+       }
+       
+       return az;
+}
+
+static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       AZone *az= is_in_area_actionzone(C->area, event->x, event->y);
+       sActionzoneData *sad;
+       
+       /* quick escape */
+       if(az==NULL)
+               return OPERATOR_PASS_THROUGH;
+       
+       /* ok we do the actionzone */
+       sad= op->customdata= MEM_callocN(sizeof(sActionzoneData), "sActionzoneData");
+       sad->sa1= C->area;
+       sad->az= az;
+       sad->x= event->x; sad->y= event->y;
+       
+       /* add modal handler */
+       WM_event_add_modal_handler(&C->window->handlers, op);
+       
+       return OPERATOR_RUNNING_MODAL;
+}
+
+static void actionzone_exit(bContext *C, wmOperator *op)
+{
+       if(op->customdata)
+               MEM_freeN(op->customdata);
+       op->customdata= NULL;
+}
+
+/* send EVT_ACTIONZONE event */
+static void actionzone_apply(bContext *C, wmOperator *op)
+{
+       wmEvent event;
+       
+       event= *(C->window->eventstate);        /* XXX huh huh? make api call */
+       event.type= EVT_ACTIONZONE;
+       event.customdata= op->customdata;
+       event.customdatafree= TRUE;
+       op->customdata= NULL;
+       
+       wm_event_add(C->window, &event);
+}
+
+static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+       sActionzoneData *sad= op->customdata;
+       int deltax, deltay;
+       
+       switch(event->type) {
+               case MOUSEMOVE:
+                       /* calculate gesture direction */
+                       deltax= (event->x - sad->x);
+                       deltay= (event->y - sad->y);
+                       
+                       if(deltay > ABS(deltax))
+                               sad->gesture_dir= AZONE_N;
+                       else if(deltax > ABS(deltay))
+                               sad->gesture_dir= AZONE_E;
+                       else if(deltay < -ABS(deltax))
+                               sad->gesture_dir= AZONE_S;
+                       else
+                               sad->gesture_dir= AZONE_W;
+                       
+                       /* gesture is large enough? */
+                       if(ABS(deltax) > 12 || ABS(deltay) > 12) {
+                               
+                               /* second area, for join */
+                               sad->sa2= screen_areahascursor(C->screen, event->x, event->y);
+                               /* apply sends event */
+                               actionzone_apply(C, op);
+                               actionzone_exit(C, op);
+                               
+                               WM_event_remove_modal_handler(&C->window->handlers, op);
+                               
+                               return OPERATOR_FINISHED;
+                       }
+                               break;
+               case ESCKEY:
+               case LEFTMOUSE:
+                       actionzone_exit(C, op);
+                       WM_event_remove_modal_handler(&C->window->handlers, op);
+                       return OPERATOR_CANCELLED;
+       }
+       
+       return OPERATOR_RUNNING_MODAL;
+}
+
+void ED_SCR_OT_actionzone(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Handle area action zones";
+       ot->idname= "ED_SCR_OT_actionzone";
+       
+       ot->invoke= actionzone_invoke;
+       ot->modal= actionzone_modal;
+       
+       ot->poll= ED_operator_areaactive;
+}
+
+/* ****************** cursor near edge operator ********************************* */
+
+static int scredge_is_horizontal(ScrEdge *se)
+{
+       return (se->v1->vec.y == se->v2->vec.y);
+}
+
+static ScrEdge *screen_find_active_scredge(bScreen *sc, int mx, int my)
+{
+       ScrEdge *se;
+       
+       for (se= sc->edgebase.first; se; se= se->next) {
+               if (scredge_is_horizontal(se)) {
+                       short min, max;
+                       min= MIN2(se->v1->vec.x, se->v2->vec.x);
+                       max= MAX2(se->v1->vec.x, se->v2->vec.x);
+                       
+                       if (abs(my-se->v1->vec.y)<=2 && mx>=min && mx<=max)
+                               return se;
+               } 
+               else {
+                       short min, max;
+                       min= MIN2(se->v1->vec.y, se->v2->vec.y);
+                       max= MAX2(se->v1->vec.y, se->v2->vec.y);
+                       
+                       if (abs(mx-se->v1->vec.x)<=2 && my>=min && my<=max)
+                               return se;
+               }
+       }
+       
+       return NULL;
+}
+
+
+/* operator cb */
+static int screen_cursor_test(bContext *C, wmOperator *op, wmEvent *event)
+{
+       if (C->screen->subwinactive==C->screen->mainwin) {
+               ScrEdge *actedge= screen_find_active_scredge(C->screen, event->x, event->y);
+               
+               if (actedge && scredge_is_horizontal(actedge)) {
+                       WM_set_cursor(C, CURSOR_Y_MOVE);
+               } else {
+                       WM_set_cursor(C, CURSOR_X_MOVE);
+               }
+       } else {
+               ScrArea *sa= NULL;
+               AZone *az= NULL;
+               for(sa= C->screen->areabase.first; sa; sa= sa->next) {
+                       az= is_in_area_actionzone(sa, event->x, event->y);
+                       if(az!=NULL) break;
+               }
+               if(az!=NULL) WM_set_cursor(C, CURSOR_EDIT);
+               else WM_set_cursor(C, CURSOR_STD);
+       }
+       
+       return OPERATOR_PASS_THROUGH;
+}
 
 static void ED_SCR_OT_cursor_type(wmOperatorType *ot)
 {
@@ -79,6 +300,925 @@ static void ED_SCR_OT_cursor_type(wmOperatorType *ot)
     ot->poll= ED_operator_screenactive;
 }
 
+
+
+/* *********** Rip area operator ****************** */
+
+
+/* operator callback */
+/* (ton) removed attempt to merge ripped area with another, don't think this is desired functionality.
+conventions: 'atomic' and 'dont think for user' :) */
+static int screen_area_rip_op(bContext *C, wmOperator *op)
+{
+       wmWindow *win;
+       bScreen *newsc;
+       rcti rect;
+       
+       /*  poll() checks area context, but we don't accept full-area windows */
+       if(C->screen->full != SCREENNORMAL) 
+               return OPERATOR_CANCELLED;
+       
+       /* adds window to WM */
+       rect= C->area->totrct;
+       BLI_translate_rcti(&rect, C->window->posx, C->window->posy);
+       win= WM_window_open(C, &rect);
+       
+       /* allocs new screen and adds to newly created window, using window size */
+       newsc= screen_add(win, C->screen->id.name+2);
+       
+       /* copy area to new screen */
+       area_copy_data((ScrArea *)newsc->areabase.first, C->area, 0);
+       
+       /* screen, areas init */
+       WM_event_add_notifier(C->wm, win, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL);
+       
+       return OPERATOR_FINISHED;
+}
+
+void ED_SCR_OT_area_rip(wmOperatorType *ot)
+{
+       ot->name= "Rip Area into New Window";
+       ot->idname= "ED_SCR_OT_area_rip";
+       
+       ot->invoke= NULL; //WM_operator_confirm;
+       ot->exec= screen_area_rip_op;
+       ot->poll= ED_operator_areaactive;
+}
+
+
+/* ************** move area edge operator *********************************** */
+
+/* operator state vars used:  
+           x, y                        mouse coord near edge
+           delta            movement of edge
+
+       functions:
+
+       init()   set default property values, find edge based on mouse coords, test
+            if the edge can be moved, select edges, calculate min and max movement
+
+       apply() apply delta on selection
+
+       exit()  cleanup, send notifier
+
+       cancel() cancel moving
+
+       callbacks:
+
+       exec()   execute without any user interaction, based on properties
+            call init(), apply(), exit()
+
+       invoke() gets called on mouse click near edge
+            call init(), add handler
+
+       modal()  accept modal events while doing it
+                       call apply() with delta motion
+            call exit() and remove handler
+
+*/
+
+typedef struct sAreaMoveData {
+       int bigger, smaller, origval;
+       char dir;
+} sAreaMoveData;
+
+/* helper call to move area-edge, sets limits */
+static void area_move_set_limits(bScreen *sc, int dir, int *bigger, int *smaller)
+{
+       ScrArea *sa;
+       
+       /* we check all areas and test for free space with MINSIZE */
+       *bigger= *smaller= 100000;
+       
+       for(sa= sc->areabase.first; sa; sa= sa->next) {
+               if(dir=='h') {
+                       int y1= sa->v2->vec.y - sa->v1->vec.y-AREAMINY;
+                       
+                       /* if top or down edge selected, test height */
+                       if(sa->v1->flag && sa->v4->flag)
+                               *bigger= MIN2(*bigger, y1);
+                       else if(sa->v2->flag && sa->v3->flag)
+                               *smaller= MIN2(*smaller, y1);
+               }
+               else {
+                       int x1= sa->v4->vec.x - sa->v1->vec.x-AREAMINX;
+                       
+                       /* if left or right edge selected, test width */
+                       if(sa->v1->flag && sa->v2->flag)
+                               *bigger= MIN2(*bigger, x1);
+                       else if(sa->v3->flag && sa->v4->flag)
+                               *smaller= MIN2(*smaller, x1);
+               }
+       }
+}
+
+static void select_connected_scredge(bScreen *sc, ScrEdge *edge)
+{
+       ScrEdge *se;
+       ScrVert *sv;
+       int oneselected;
+       char dir;
+       
+       /* select connected, only in the right direction */
+       /* 'dir' is the direction of EDGE */
+       
+       if(edge->v1->vec.x==edge->v2->vec.x) dir= 'v';
+       else dir= 'h';
+       
+       sv= sc->vertbase.first;
+       while(sv) {
+               sv->flag = 0;
+               sv= sv->next;
+       }
+       
+       edge->v1->flag= 1;
+       edge->v2->flag= 1;
+       
+       oneselected= 1;
+       while(oneselected) {
+               se= sc->edgebase.first;
+               oneselected= 0;
+               while(se) {
+                       if(se->v1->flag + se->v2->flag==1) {
+                               if(dir=='h') if(se->v1->vec.y==se->v2->vec.y) {
+                                       se->v1->flag= se->v2->flag= 1;
+                                       oneselected= 1;
+                               }
+                                       if(dir=='v') if(se->v1->vec.x==se->v2->vec.x) {
+                                               se->v1->flag= se->v2->flag= 1;
+                                               oneselected= 1;
+                                       }
+                       }
+                               se= se->next;
+               }
+       }
+}
+
+/* validate selection inside screen, set variables OK */
+/* return 0: init failed */
+static int area_move_init (bContext *C, wmOperator *op)
+{
+       ScrEdge *actedge;
+       sAreaMoveData *md;
+       int x, y;
+
+       /* required properties */
+       if(!(OP_get_int(op, "x", &x) && OP_get_int(op, "y", &y)))
+               return 0;
+
+       /* default properties */
+       OP_verify_int(op, "delta", 0, NULL);
+
+       /* setup */
+       actedge= screen_find_active_scredge(C->screen, x, y);
+       if(actedge==NULL) return 0;
+
+       md= MEM_callocN(sizeof(sAreaMoveData), "sAreaMoveData");
+       op->customdata= md;
+
+       md->dir= scredge_is_horizontal(actedge)?'h':'v';
+       if(md->dir=='h') md->origval= actedge->v1->vec.y;
+       else md->origval= actedge->v1->vec.x;
+       
+       select_connected_scredge(C->screen, actedge);
+       /* now all vertices with 'flag==1' are the ones that can be moved. */
+
+       area_move_set_limits(C->screen, md->dir, &md->bigger, &md->smaller);
+       
+       return 1;
+}
+
+/* moves selected screen edge amount of delta, used by split & move */
+static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int bigger, int smaller)
+{
+       ScrVert *v1;
+       
+       delta= CLAMPIS(delta, -smaller, bigger);
+       
+       for (v1= C->screen->vertbase.first; v1; v1= v1->next) {
+               if (v1->flag) {
+                       /* that way a nice AREAGRID  */
+                       if((dir=='v') && v1->vec.x>0 && v1->vec.x<C->window->sizex-1) {
+                               v1->vec.x= origval + delta;
+                               if(delta != bigger && delta != -smaller) v1->vec.x-= (v1->vec.x % AREAGRID);
+                       }
+                       if((dir=='h') && v1->vec.y>0 && v1->vec.y<C->window->sizey-1) {
+                               v1->vec.y= origval + delta;
+
+                               v1->vec.y+= AREAGRID-1;
+                               v1->vec.y-= (v1->vec.y % AREAGRID);
+                               
+                               /* prevent too small top header */
+                               if(v1->vec.y > C->window->sizey-AREAMINY)
+                                       v1->vec.y= C->window->sizey-AREAMINY;
+                       }
+               }
+       }
+
+       WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL);
+}
+
+static void area_move_apply(bContext *C, wmOperator *op)
+{
+       sAreaMoveData *md= op->customdata;
+       int delta;
+       
+       OP_get_int(op, "delta", &delta);
+       area_move_apply_do(C, md->origval, delta, md->dir, md->bigger, md->smaller);
+}
+
+static void area_move_exit(bContext *C, wmOperator *op)
+{
+       if(op->customdata)
+               MEM_freeN(op->customdata);
+       op->customdata= NULL;
+       
+       /* this makes sure aligned edges will result in aligned grabbing */
+       removedouble_scrverts(C->screen);
+       removedouble_scredges(C->screen);
+}
+
+static int area_move_exec(bContext *C, wmOperator *op)
+{
+       if(!area_move_init(C, op))
+               return OPERATOR_CANCELLED;
+       
+       area_move_apply(C, op);
+       area_move_exit(C, op);
+       
+       return OPERATOR_FINISHED;
+}
+
+/* interaction callback */
+static int area_move_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       OP_verify_int(op, "x", event->x, NULL);
+       OP_verify_int(op, "y", event->y, NULL);
+
+       if(!area_move_init(C, op)) 
+               return OPERATOR_PASS_THROUGH;
+       
+       /* add temp handler */
+       WM_event_add_modal_handler(&C->window->handlers, op);
+       
+       return OPERATOR_RUNNING_MODAL;
+}
+
+static int area_move_cancel(bContext *C, wmOperator *op)
+{
+       WM_event_remove_modal_handler(&C->window->handlers, op);                                
+
+       OP_set_int(op, "delta", 0);
+       area_move_apply(C, op);
+       area_move_exit(C, op);
+
+       return OPERATOR_CANCELLED;
+}
+
+/* modal callback for while moving edges */
+static int area_move_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+       sAreaMoveData *md;
+       int delta, x, y;
+
+       md= op->customdata;
+
+       OP_get_int(op, "x", &x);
+       OP_get_int(op, "y", &y);
+
+       /* execute the events */
+       switch(event->type) {
+               case MOUSEMOVE:
+                       delta= (md->dir == 'v')? event->x - x: event->y - y;
+                       OP_set_int(op, "delta", delta);
+
+                       area_move_apply(C, op);
+                       break;
+                       
+               case LEFTMOUSE:
+                       if(event->val==0) {
+                               area_move_exit(C, op);
+                               WM_event_remove_modal_handler(&C->window->handlers, op);                                
+                               return OPERATOR_FINISHED;
+                       }
+                       break;
+                       
+               case ESCKEY:
+                       return area_move_cancel(C, op);
+       }
+       
+       return OPERATOR_RUNNING_MODAL;
+}
+
+void ED_SCR_OT_area_move(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Move area edges";
+       ot->idname= "ED_SCR_OT_area_move";
+
+       ot->exec= area_move_exec;
+       ot->invoke= area_move_invoke;
+       ot->cancel= area_move_cancel;
+       ot->modal= area_move_modal;
+
+       ot->poll= ED_operator_screen_mainwinactive; /* when mouse is over area-edge */
+}
+
+/* ************** split area operator *********************************** */
+
+/* 
+operator state vars:  
+       fac              spit point
+       dir              direction 'v' or 'h'
+
+operator customdata:
+       area                    pointer to (active) area
+       x, y                    last used mouse pos
+       (more, see below)
+
+functions:
+
+       init()   set default property values, find area based on context
+
+       apply() split area based on state vars
+
+       exit()  cleanup, send notifier
+
+       cancel() remove duplicated area
+
+callbacks:
+
+       exec()   execute without any user interaction, based on state vars
+            call init(), apply(), exit()
+
+       invoke() gets called on mouse click in action-widget
+            call init(), add modal handler
+                       call apply() with initial motion
+
+       modal()  accept modal events while doing it
+            call move-areas code with delta motion
+            call exit() or cancel() and remove handler
+
+*/
+
+#define SPLIT_STARTED  1
+#define SPLIT_PROGRESS 2
+
+typedef struct sAreaSplitData
+{
+       int x, y;       /* last used mouse position */
+       
+       int origval;                    /* for move areas */
+       int bigger, smaller;    /* constraints for moving new edge */
+       int delta;                              /* delta move edge */
+       
+       ScrEdge *nedge;                 /* new edge */
+       ScrArea *sarea;                 /* start area */
+       ScrArea *narea;                 /* new area */
+} sAreaSplitData;
+
+/* generic init, no UI stuff here */
+static int area_split_init(bContext *C, wmOperator *op)
+{
+       sAreaSplitData *sd;
+       int dir;
+       
+       /* required context */
+       if(C->area==NULL) return 0;
+       
+       /* required properties */
+       OP_verify_float(op, "fac", 0.5f, NULL);
+       OP_verify_int(op, "dir", 'h', &dir);
+       
+       /* minimal size */
+       if(dir=='v' && C->area->winx < 2*AREAMINX) return 0;
+       if(dir=='h' && C->area->winy < 2*AREAMINY) return 0;
+          
+       /* custom data */
+       sd= (sAreaSplitData*)MEM_callocN(sizeof (sAreaSplitData), "op_area_split");
+       op->customdata= sd;
+       
+       sd->sarea= C->area;
+       
+       return 1;
+}
+
+/* with sa as center, sb is located at: 0=W, 1=N, 2=E, 3=S */
+/* used with split operator */
+static ScrEdge *area_findsharededge(bScreen *screen, ScrArea *sa, ScrArea *sb)
+{
+       ScrVert *sav1= sa->v1;
+       ScrVert *sav2= sa->v2;
+       ScrVert *sav3= sa->v3;
+       ScrVert *sav4= sa->v4;
+       ScrVert *sbv1= sb->v1;
+       ScrVert *sbv2= sb->v2;
+       ScrVert *sbv3= sb->v3;
+       ScrVert *sbv4= sb->v4;
+       
+       if(sav1==sbv4 && sav2==sbv3) { /* sa to right of sb = W */
+               return screen_findedge(screen, sav1, sav2);
+       }
+       else if(sav2==sbv1 && sav3==sbv4) { /* sa to bottom of sb = N */
+               return screen_findedge(screen, sav2, sav3);
+       }
+       else if(sav3==sbv2 && sav4==sbv1) { /* sa to left of sb = E */
+               return screen_findedge(screen, sav3, sav4);
+       }
+       else if(sav1==sbv2 && sav4==sbv3) { /* sa on top of sb = S*/
+               return screen_findedge(screen, sav1, sav4);
+       }
+
+       return NULL;
+}
+
+
+/* do the split */
+static void area_split_apply(bContext *C, wmOperator *op)
+{
+       sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
+       float fac;
+       int dir;
+       
+       OP_get_float(op, "fac", &fac);
+       OP_get_int(op, "dir", &dir);
+
+       sd->narea= area_split(C->window, C->screen, sd->sarea, dir, fac);
+       
+       if(sd->narea) {
+               ScrVert *sv;
+               
+               sd->nedge= area_findsharededge(C->screen, sd->sarea, sd->narea);
+       
+               /* select newly created edge, prepare for moving edge */
+               for(sv= C->screen->vertbase.first; sv; sv= sv->next)
+                       sv->flag = 0;
+               
+               sd->nedge->v1->flag= 1;
+               sd->nedge->v2->flag= 1;
+
+               if(dir=='h') sd->origval= sd->nedge->v1->vec.y;
+               else sd->origval= sd->nedge->v1->vec.x;
+
+       }               
+       
+       WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL);
+       
+}
+
+static void area_split_exit(bContext *C, wmOperator *op)
+{
+       if (op->customdata) {
+               MEM_freeN(op->customdata);
+               op->customdata = NULL;
+       }
+       
+       WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL);
+
+       /* this makes sure aligned edges will result in aligned grabbing */
+       removedouble_scrverts(C->screen);
+       removedouble_scredges(C->screen);
+}
+
+
+/* UI callback, adds new handler */
+static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+       sAreaSplitData *sd;
+       
+       if(event->type==EVT_ACTIONZONE) {
+               sActionzoneData *sad= event->customdata;
+               int dir;
+               
+               /* verify *sad itself */
+               if(sad==NULL || sad->sa1==NULL || sad->az==NULL)
+                       return OPERATOR_PASS_THROUGH;
+               
+               /* is this our *sad? if areas not equal it should be passed on */
+               if(C->area!=sad->sa1 || sad->sa1!=sad->sa2)
+                       return OPERATOR_PASS_THROUGH;
+               
+               /* prepare operator state vars */
+               if(sad->gesture_dir==AZONE_N || sad->gesture_dir==AZONE_S) {
+                       dir= 'h';
+                       OP_set_float(op, "fac", ((float)(event->x - sad->sa1->v1->vec.x)) / (float)sad->sa1->winx);
+               }
+               else {
+                       dir= 'v';
+                       OP_set_float(op, "fac", ((float)(event->y - sad->sa1->v1->vec.y)) / (float)sad->sa1->winy);
+               }
+               OP_set_int(op, "dir", dir);
+
+               /* general init, also non-UI case, adds customdata, sets area and defaults */
+               if(!area_split_init(C, op))
+                       return OPERATOR_PASS_THROUGH;
+               
+               sd= (sAreaSplitData *)op->customdata;
+               
+               sd->x= event->x;
+               sd->y= event->y;
+               
+               /* do the split */
+               area_split_apply(C, op);
+               area_move_set_limits(C->screen, dir, &sd->bigger, &sd->smaller);
+               
+               /* add temp handler for edge move or cancel */
+               WM_event_add_modal_handler(&C->window->handlers, op);
+               
+               return OPERATOR_RUNNING_MODAL;
+               
+       }
+       return OPERATOR_PASS_THROUGH;
+}
+
+/* function to be called outside UI context, or for redo */
+static int area_split_exec(bContext *C, wmOperator *op)
+{
+       
+       if(!area_split_init(C, op))
+               return OPERATOR_CANCELLED;
+       
+       area_split_apply(C, op);
+       area_split_exit(C, op);
+       
+       return OPERATOR_FINISHED;
+}
+
+
+static int area_split_cancel(bContext *C, wmOperator *op)
+{
+       sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
+
+       WM_event_remove_modal_handler(&C->window->handlers, op);
+
+       if (screen_area_join(C->screen,sd->sarea, sd->narea)) {
+               if (C->area == sd->narea) {
+                       C->area = NULL;
+               }
+               sd->narea = NULL;
+       }
+       area_split_exit(C, op);
+
+       return OPERATOR_CANCELLED;
+}
+
+static int area_split_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+       sAreaSplitData *sd= (sAreaSplitData *)op->customdata;
+       int dir;
+
+       /* execute the events */
+       switch(event->type) {
+               case MOUSEMOVE:
+                       
+                       OP_get_int(op, "dir", &dir);
+                       
+                       sd->delta= (dir == 'v')? event->x - sd->origval: event->y - sd->origval;
+                       area_move_apply_do(C, sd->origval, sd->delta, dir, sd->bigger, sd->smaller);
+                       
+                       WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL);
+                       break;
+                       
+               case LEFTMOUSE:
+                       if(event->val==0) { /* mouse up */
+                               area_split_exit(C, op);
+                               WM_event_remove_modal_handler(&C->window->handlers, op);
+                               return OPERATOR_FINISHED;
+                       }
+                       break;
+               case RIGHTMOUSE: /* cancel operation */
+               case ESCKEY:
+                       return area_split_cancel(C, op);
+       }
+       
+       return OPERATOR_RUNNING_MODAL;
+}
+
+void ED_SCR_OT_area_split(wmOperatorType *ot)
+{
+       ot->name = "Split area";
+       ot->idname = "ED_SCR_OT_area_split";
+       
+       ot->exec= area_split_exec;
+       ot->invoke= area_split_invoke;
+       ot->modal= area_split_modal;
+       
+       ot->poll= ED_operator_screenactive; /* XXX should be area active */
+}
+
+/* ************** join area operator ********************************************** */
+
+/* operator state vars used:  
+                       x1, y1     mouse coord in first area, which will disappear
+                       x2, y2     mouse coord in 2nd area, which will become joined
+
+functions:
+
+   init()   find edge based on state vars 
+                       test if the edge divides two areas, 
+                       store active and nonactive area,
+            
+   apply()  do the actual join
+
+   exit()      cleanup, send notifier
+
+callbacks:
+
+   exec()      calls init, apply, exit 
+   
+   invoke() sets mouse coords in x,y
+            call init()
+            add modal handler
+
+   modal()     accept modal events while doing it
+                       call apply() with active window and nonactive window
+            call exit() and remove handler when LMB confirm
+
+*/
+
+typedef struct sAreaJoinData
+{
+       ScrArea *sa1;   /* first area to be considered */
+       ScrArea *sa2;   /* second area to be considered */
+       ScrArea *scr;   /* designed for removal */
+
+} sAreaJoinData;
+
+
+/* validate selection inside screen, set variables OK */
+/* return 0: init failed */
+/* XXX todo: find edge based on (x,y) and set other area? */
+static int area_join_init(bContext *C, wmOperator *op)
+{
+       ScrArea *sa1, *sa2;
+       sAreaJoinData* jd= NULL;
+       int x1, y1;
+       int x2, y2;
+
+       /* required properties, make negative to get return 0 if not set by caller */
+       OP_verify_int(op, "x1", -100, &x1);
+       OP_verify_int(op, "y1", -100, &y1);
+       OP_verify_int(op, "x2", -100, &x2);
+       OP_verify_int(op, "y2", -100, &y2);
+       
+       sa1 = screen_areahascursor(C->screen, x1, y1);
+       sa2 = screen_areahascursor(C->screen, x2, y2);
+       if(sa1==NULL || sa2==NULL || sa1==sa2)
+               return 0;
+
+       jd = (sAreaJoinData*)MEM_callocN(sizeof (sAreaJoinData), "op_area_join");
+               
+       jd->sa1 = sa1;
+       jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
+       jd->sa2 = sa2;
+       jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
+       
+       op->customdata= jd;
+       
+       return 1;
+}
+
+/* apply the join of the areas (space types) */
+static int area_join_apply(bContext *C, wmOperator *op)
+{
+       sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
+       if (!jd) return 0;
+
+       if(!screen_area_join(C->screen,jd->sa1,jd->sa2)){
+               return 0;
+       }
+       if (C->area == jd->sa2) {
+               C->area = NULL;
+       }
+
+       return 1;
+}
+
+/* finish operation */
+static void area_join_exit(bContext *C, wmOperator *op)
+{
+       if (op->customdata) {
+               MEM_freeN(op->customdata);
+               op->customdata = NULL;
+       }
+
+       /* this makes sure aligned edges will result in aligned grabbing */
+       removedouble_scredges(C->screen);
+       removenotused_scredges(C->screen);
+       removenotused_scrverts(C->screen);
+}
+
+static int area_join_exec(bContext *C, wmOperator *op)
+{
+       if(!area_join_init(C, op)) 
+               return OPERATOR_CANCELLED;
+       
+       area_join_apply(C, op);
+       area_join_exit(C, op);
+
+       return OPERATOR_FINISHED;
+}
+
+/* interaction callback */
+static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event)
+{
+
+       if(event->type==EVT_ACTIONZONE) {
+               sActionzoneData *sad= event->customdata;
+               
+               /* verify *sad itself */
+               if(sad==NULL || sad->sa1==NULL || sad->sa2==NULL)
+                       return OPERATOR_PASS_THROUGH;
+               
+               /* is this our *sad? if areas equal it should be passed on */
+               if(sad->sa1==sad->sa2)
+                       return OPERATOR_PASS_THROUGH;
+               
+               /* prepare operator state vars */
+               OP_set_int(op, "x1", sad->x);
+               OP_set_int(op, "y1", sad->y);
+               OP_set_int(op, "x2", event->x);
+               OP_set_int(op, "y2", event->y);
+
+               if(!area_join_init(C, op)) 
+                       return OPERATOR_PASS_THROUGH;
+       
+               /* add temp handler */
+               WM_event_add_modal_handler(&C->window->handlers, op);
+       
+               return OPERATOR_RUNNING_MODAL;
+       }
+       
+       return OPERATOR_PASS_THROUGH;
+}
+
+static int area_join_cancel(bContext *C, wmOperator *op)
+{
+       sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
+
+       if (jd->sa1) {
+               jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
+               jd->sa1->flag &= ~AREA_FLAG_DRAWJOINTO;
+       }
+       if (jd->sa2) {
+               jd->sa2->flag &= ~AREA_FLAG_DRAWJOINFROM;
+               jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+       }
+
+       WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL);
+       WM_event_remove_modal_handler(&C->window->handlers, op);                        
+       
+       area_join_exit(C, op);
+
+       return OPERATOR_CANCELLED;
+}
+
+/* modal callback while selecting area (space) that will be removed */
+static int area_join_modal(bContext *C, wmOperator *op, wmEvent *event)
+{
+       sAreaJoinData *jd = (sAreaJoinData *)op->customdata;
+       
+       /* execute the events */
+       switch(event->type) {
+                       
+               case MOUSEMOVE: 
+                       {
+                               ScrArea *sa = screen_areahascursor(C->screen, event->x, event->y);
+                               int dir;
+                               
+                               if (sa) {                                       
+                                       if (jd->sa1 != sa) {
+                                               dir = area_getorientation(C->screen, jd->sa1, sa);
+                                               if (dir >= 0) {
+                                                       if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+                                                       jd->sa2 = sa;
+                                                       jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
+                                               } 
+                                               else {
+                                                       /* we are not bordering on the previously selected area 
+                                                          we check if area has common border with the one marked for removal
+                                                          in this case we can swap areas.
+                                                       */
+                                                       dir = area_getorientation(C->screen, sa, jd->sa2);
+                                                       if (dir >= 0) {
+                                                               if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
+                                                               if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+                                                               jd->sa1 = jd->sa2;
+                                                               jd->sa2 = sa;
+                                                               if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
+                                                               if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
+                                                       } 
+                                                       else {
+                                                               if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+                                                               jd->sa2 = NULL;
+                                                       }
+                                               }
+                                               WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL);
+                                       } 
+                                       else {
+                                               /* we are back in the area previously selected for keeping 
+                                                * we swap the areas if possible to allow user to choose */
+                                               if (jd->sa2 != NULL) {
+                                                       if (jd->sa1) jd->sa1->flag &= ~AREA_FLAG_DRAWJOINFROM;
+                                                       if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+                                                       jd->sa1 = jd->sa2;
+                                                       jd->sa2 = sa;
+                                                       if (jd->sa1) jd->sa1->flag |= AREA_FLAG_DRAWJOINFROM;
+                                                       if (jd->sa2) jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
+                                                       dir = area_getorientation(C->screen, jd->sa1, jd->sa2);
+                                                       if (dir < 0) {
+                                                               printf("oops, didn't expect that!\n");
+                                                       }
+                                               } 
+                                               else {
+                                                       dir = area_getorientation(C->screen, jd->sa1, sa);
+                                                       if (dir >= 0) {
+                                                               if (jd->sa2) jd->sa2->flag &= ~AREA_FLAG_DRAWJOINTO;
+                                                               jd->sa2 = sa;
+                                                               jd->sa2->flag |= AREA_FLAG_DRAWJOINTO;
+                                                       }
+                                               }
+                                               WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_WINDOW_REDRAW, 0, NULL);
+                                       }
+                               }
+                       }
+                       break;
+               case LEFTMOUSE:
+                       if(event->val==0) {
+                               area_join_apply(C, op);
+                               WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL);
+                               area_join_exit(C, op);
+                               WM_event_remove_modal_handler(&C->window->handlers, op);
+                               return OPERATOR_FINISHED;
+                       }
+                       break;
+                       
+               case ESCKEY:
+                       return area_join_cancel(C, op);
+       }
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+/* Operator for joining two areas (space types) */
+void ED_SCR_OT_area_join(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Join area";
+       ot->idname= "ED_SCR_OT_area_join";
+       
+       /* api callbacks */
+       ot->exec= area_join_exec;
+       ot->invoke= area_join_invoke;
+       ot->modal= area_join_modal;
+
+       ot->poll= ED_operator_screenactive;
+}
+
+/* ************** border select operator (test only) ***************************** */
+
+/* operator state vars used: (added by default WM callbacks)   
+       xmin, ymin     
+       xmax, ymax     
+
+       customdata: the wmGesture pointer
+
+callbacks:
+
+       exec()  has to be filled in by user
+
+       invoke() default WM function
+                        adds modal handler
+
+       modal() default WM function 
+                       accept modal events while doing it, calls exec(), handles ESC and border drawing
+       
+       poll()  has to be filled in by user for context
+*/
+
+static int border_select_do(bContext *C, wmOperator *op)
+{
+       printf("border select do\n");
+       return 1;
+}
+
+void ED_SCR_OT_border_select(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Border select";
+       ot->idname= "ED_SCR_OT_border_select";
+       
+       /* api callbacks */
+       ot->exec= border_select_do;
+       ot->invoke= WM_border_select_invoke;
+       ot->modal= WM_border_select_modal;
+       
+       ot->poll= ED_operator_areaactive;
+}
+
+
+/* ****************  Assigning operatortypes to global list, adding handlers **************** */
+
 /* called in spacetypes.c */
 void ED_operatortypes_screen(void)
 {
@@ -87,9 +1227,9 @@ void ED_operatortypes_screen(void)
        WM_operatortype_append(ED_SCR_OT_actionzone);
        
        /* tools */
-       WM_operatortype_append(ED_SCR_OT_move_areas);
-       WM_operatortype_append(ED_SCR_OT_split_area);
-       WM_operatortype_append(ED_SCR_OT_join_areas);
+       WM_operatortype_append(ED_SCR_OT_area_move);
+       WM_operatortype_append(ED_SCR_OT_area_split);
+       WM_operatortype_append(ED_SCR_OT_area_join);
        WM_operatortype_append(ED_SCR_OT_area_rip);
        
        /* for test only */
@@ -102,9 +1242,9 @@ void ED_keymap_screen(wmWindowManager *wm)
        WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_cursor_type", MOUSEMOVE, 0, 0, 0);
        WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_actionzone", LEFTMOUSE, KM_PRESS, 0, 0);
        
-       WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_move_areas", LEFTMOUSE, KM_PRESS, 0, 0);
-       WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_split_area", EVT_ACTIONZONE, 0, 0, 0);      /* action tria */
-       WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_join_areas", EVT_ACTIONZONE, 0, 0, 0);      /* action tria */ 
+       WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_area_move", LEFTMOUSE, KM_PRESS, 0, 0);
+       WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_area_split", EVT_ACTIONZONE, 0, 0, 0);      /* action tria */
+       WM_keymap_verify_item(&wm->screenkeymap, "ED_SCR_OT_area_join", EVT_ACTIONZONE, 0, 0, 0);       /* action tria */ 
        WM_keymap_verify_item(&wm->windowkeymap, "ED_SCR_OT_area_rip", RKEY, KM_PRESS, KM_ALT, 0);
 
        /* for test only */
index 86e6fe77c734d7de25ce135988f5d425a104b05b..b81184df049223f76191df676195bec14fc179cf 100644 (file)
@@ -139,23 +139,23 @@ int                       WM_border_select_modal  (struct bContext *C, wmOperator *op, struct wmEvent
  *     len= 4; <---- set the size!!
  *     OP_get_int_array (op, "vector", vec, &len);
  */
-void OP_set_int(wmOperator *op, char *name, int value);
-void OP_set_float(wmOperator *op, char *name, float value);
-void OP_set_string(wmOperator *op, char *name, char *str);
-void OP_set_int_array(wmOperator *op, char *name, int *array, short len);
-void OP_set_float_array(wmOperator *op, char *name, float *array, short len);
-
-int OP_get_int(wmOperator *op, char *name, int *value);
-int OP_get_float(wmOperator *op, char *name, float *value);
-char *OP_get_string(wmOperator *op, char *name);
-int OP_get_int_array(wmOperator *op, char *name, int *array, short *len);
-int OP_get_float_array(wmOperator *op, char *name, float *array, short *len);
-
-void OP_verify_int(wmOperator *op, char *name, int value, int *result);
-void OP_verify_float(wmOperator *op, char *name, float value, int *result);
-char *OP_verify_string(wmOperator *op, char *name, char *str);
-void OP_verify_int_array(wmOperator *op, char *name, int *array, short len, int *resultarray, short *resultlen);
-void OP_verify_float_array(wmOperator *op, char *name, float *array, short len, float *resultarray, short *resultlen);
+void   OP_set_int              (wmOperator *op, char *name, int value);
+void   OP_set_float    (wmOperator *op, char *name, float value);
+void   OP_set_string   (wmOperator *op, char *name, char *str);
+void   OP_set_int_array(wmOperator *op, char *name, int *array, short len);
+void   OP_set_float_array(wmOperator *op, char *name, float *array, short len);
+
+int            OP_get_int              (wmOperator *op, char *name, int *value);
+int            OP_get_float    (wmOperator *op, char *name, float *value);
+char   *OP_get_string  (wmOperator *op, char *name);
+int            OP_get_int_array(wmOperator *op, char *name, int *array, short *len);
+int            OP_get_float_array(wmOperator *op, char *name, float *array, short *len);
+
+void   OP_verify_int   (wmOperator *op, char *name, int value, int *result);
+void   OP_verify_float (wmOperator *op, char *name, float value, int *result);
+char   *OP_verify_string(wmOperator *op, char *name, char *str);
+void   OP_verify_int_array(wmOperator *op, char *name, int *array, short len, int *resultarray, short *resultlen);
+void   OP_verify_float_array(wmOperator *op, char *name, float *array, short len, float *resultarray, short *resultlen);
 
 /*
  * Need call this function in the "exit callback"
index cafc7a7b5975f5d156de75b4fd4eeead76916bf1..165ca88ab71ab5445d3efc66cc105d3ddad98532 100644 (file)
@@ -74,17 +74,6 @@ void wm_operator_register(wmWindowManager *wm, wmOperator *op)
        }
 }
 
-/* **************** standard keymap for WM ********************** */
-
-/* default keymap for windows and screens, only call once per WM */
-static void wm_window_keymap(wmWindowManager *wm)
-{
-       /* note, this doesn't replace existing keymap items */
-       WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_window_duplicate", AKEY, KM_PRESS, 0, 0);
-       WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_save_homefile", UKEY, KM_PRESS, KM_CTRL, 0);
-       WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_window_fullscreen_toggle", FKEY, KM_PRESS, 0, 0);
-       WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_exit_blender", QKEY, KM_PRESS, KM_CTRL, 0);
-}
 
 /* ****************************************** */
 
diff --git a/source/blender/windowmanager/intern/wm_operator_props.c b/source/blender/windowmanager/intern/wm_operator_props.c
new file mode 100644 (file)
index 0000000..9ba350f
--- /dev/null
@@ -0,0 +1,298 @@
+/**
+* $Id:
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * 
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "DNA_ID.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BKE_idprop.h"
+
+#include "WM_api.h"
+
+
+/* wrapped to get property from a operator. */
+static IDProperty *op_get_property(wmOperator *op, char *name)
+{
+       IDProperty *prop;
+       
+       if(!op->properties)
+               return NULL;
+
+       prop= IDP_GetPropertyFromGroup(op->properties, name);
+       return prop;
+}
+
+/*
+ * We need create a "group" to store the operator properties.
+ * We don't have a WM_operator_new or some thing like that,
+ * so this function is called by all the OP_set_* function
+ * in case that op->properties is equal to NULL.
+ */
+static void op_init_property(wmOperator *op)
+{
+       IDPropertyTemplate val;
+       val.i = 0; /* silence MSVC warning about uninitialized var when debugging */
+       op->properties= IDP_New(IDP_GROUP, val, "property");
+}
+
+/* ***** Property API, exported ***** */
+void OP_free_property(wmOperator *op)
+{
+       if(op->properties) {
+       IDP_FreeProperty(op->properties);
+       /*
+        * This need change, when the idprop code only
+        * need call IDP_FreeProperty. (check BKE_idprop.h)
+        */
+       MEM_freeN(op->properties);
+       op->properties= NULL;
+       }
+}
+
+void OP_set_int(wmOperator *op, char *name, int value)
+{
+       IDPropertyTemplate val;
+       IDProperty *prop;
+
+       if(!op->properties)
+               op_init_property(op);
+
+       val.i= value;
+       prop= IDP_New(IDP_INT, val, name);
+       IDP_ReplaceInGroup(op->properties, prop);
+}
+
+void OP_set_float(wmOperator *op, char *name, float value)
+{
+       IDPropertyTemplate val;
+       IDProperty *prop;
+
+       if(!op->properties)
+               op_init_property(op);
+
+       val.f= value;
+       prop= IDP_New(IDP_FLOAT, val, name);
+       IDP_ReplaceInGroup(op->properties, prop);
+}
+
+void OP_set_int_array(wmOperator *op, char *name, int *array, short len)
+{
+       IDPropertyTemplate val;
+       IDProperty *prop;
+       short i;
+       int *pointer;
+
+       if(!op->properties)
+               op_init_property(op);
+
+       val.array.len= len;
+       val.array.type= IDP_INT;
+       prop= IDP_New(IDP_ARRAY, val, name);
+
+       pointer= (int *)prop->data.pointer;
+       for(i= 0; i < len; i++)
+               pointer[i]= array[i];
+       IDP_ReplaceInGroup(op->properties, prop);
+}
+
+void OP_set_float_array(wmOperator *op, char *name, float *array, short len)
+{
+       IDPropertyTemplate val;
+       IDProperty *prop;
+       short i;
+       float *pointer;
+
+       if(!op->properties)
+               op_init_property(op);
+
+       val.array.len= len;
+       val.array.type= IDP_FLOAT;
+       prop= IDP_New(IDP_ARRAY, val, name);
+
+       pointer= (float *) prop->data.pointer;
+       for(i= 0; i < len; i++)
+               pointer[i]= array[i];
+       IDP_ReplaceInGroup(op->properties, prop);
+}
+
+void OP_set_string(wmOperator *op, char *name, char *str)
+{
+       IDPropertyTemplate val;
+       IDProperty *prop;
+
+       if(!op->properties)
+               op_init_property(op);
+
+       val.str= str;
+       prop= IDP_New(IDP_STRING, val, name);
+       IDP_ReplaceInGroup(op->properties, prop);
+}
+
+int OP_get_int(wmOperator *op, char *name, int *value)
+{
+       IDProperty *prop= op_get_property(op, name);
+       int status= 0;
+
+       if ((prop) && (prop->type == IDP_INT)) {
+               (*value)= prop->data.val;
+               status= 1;
+       }
+       return (status);
+}
+
+int OP_get_float(wmOperator *op, char *name, float *value)
+{
+       IDProperty *prop= op_get_property(op, name);
+       int status= 0;
+
+       if ((prop) && (prop->type == IDP_FLOAT)) {
+               (*value)= *(float*)&prop->data.val;
+               status= 1;
+       }
+       return (status);
+}
+
+int OP_get_int_array(wmOperator *op, char *name, int *array, short *len)
+{
+       IDProperty *prop= op_get_property(op, name);
+       short i;
+       int status= 0;
+       int *pointer;
+
+       if ((prop) && (prop->type == IDP_ARRAY)) {
+               pointer= (int *) prop->data.pointer;
+
+               for(i= 0; (i < prop->len) && (i < *len); i++)
+                       array[i]= pointer[i];
+
+               (*len)= i;
+               status= 1;
+       }
+       return (status);
+}
+
+int OP_get_float_array(wmOperator *op, char *name, float *array, short *len)
+{
+       IDProperty *prop= op_get_property(op, name);
+       short i;
+       float *pointer;
+       int status= 0;
+
+       if ((prop) && (prop->type == IDP_ARRAY)) {
+               pointer= (float *) prop->data.pointer;
+
+               for(i= 0; (i < prop->len) && (i < *len); i++)
+                       array[i]= pointer[i];
+
+               (*len)= i;
+               status= 1;
+       }
+       return (status);
+}
+
+char *OP_get_string(wmOperator *op, char *name)
+{
+       IDProperty *prop= op_get_property(op, name);
+       if ((prop) && (prop->type == IDP_STRING))
+               return ((char *) prop->data.pointer);
+       return (NULL);
+}
+
+void OP_verify_int(wmOperator *op, char *name, int value, int *result)
+{
+       int rvalue;
+
+       if(OP_get_int(op, name, &rvalue))
+               value= rvalue;
+       else
+               OP_set_int(op, name, value);
+
+       if(result)
+               *result= value;
+}
+
+void OP_verify_float(wmOperator *op, char *name, float value, int *result)
+{
+       float rvalue;
+
+       if(OP_get_float(op, name, &rvalue))
+               value= rvalue;
+       else
+               OP_set_float(op, name, value);
+       
+       if(result)
+               *result= value;
+}
+
+char *OP_verify_string(wmOperator *op, char *name, char *str)
+{
+       char *result= OP_get_string(op, name);
+
+       if(!result) {
+               OP_set_string(op, name, str);
+               result= OP_get_string(op, name);
+       }
+
+       return result;
+}
+
+void OP_verify_int_array(wmOperator *op, char *name, int *array, short len, int *resultarray, short *resultlen)
+{
+       int rarray[1];
+       short rlen= 1;
+
+       if(resultarray && resultlen) {
+               if(!OP_get_int_array(op, name, resultarray, &rlen)) {
+                       OP_set_int_array(op, name, array, len);
+                       OP_get_int_array(op, name, resultarray, resultlen);
+               }
+       }
+       else {
+               if(!OP_get_int_array(op, name, rarray, &rlen))
+                       OP_set_int_array(op, name, array, len);
+       }
+}
+
+void OP_verify_float_array(wmOperator *op, char *name, float *array, short len, float *resultarray, short *resultlen)
+{
+       float rarray[1];
+       short rlen= 1;
+
+       if(resultarray && resultlen) {
+               if(!OP_get_float_array(op, name, resultarray, &rlen)) {
+                       OP_set_float_array(op, name, array, len);
+                       OP_get_float_array(op, name, resultarray, resultlen);
+               }
+       }
+       else {
+               if(!OP_get_float_array(op, name, rarray, &rlen))
+                       OP_set_float_array(op, name, array, len);
+       }
+}
+
+
index 32efa8eb71a008a3aa6c837e3403ba3837668d53..5374592180ee155167e06724055f72b96f76666c 100644 (file)
@@ -236,265 +236,13 @@ void wm_operatortype_init(void)
        WM_operatortype_append(WM_OT_exit_blender);
 }
 
-/* ******************************************************* */
-
-/* wrapped to get property from a operator. */
-IDProperty *op_get_property(wmOperator *op, char *name)
-{
-       IDProperty *prop;
-       
-       if(!op->properties)
-               return NULL;
-
-       prop= IDP_GetPropertyFromGroup(op->properties, name);
-       return prop;
-}
-
-/*
- * We need create a "group" to store the operator properties.
- * We don't have a WM_operator_new or some thing like that,
- * so this function is called by all the OP_set_* function
- * in case that op->properties is equal to NULL.
- */
-void op_init_property(wmOperator *op)
-{
-       IDPropertyTemplate val;
-       val.i = 0; /* silence MSVC warning about uninitialized var when debugging */
-       op->properties= IDP_New(IDP_GROUP, val, "property");
-}
-
-/* ***** Property API, exported ***** */
-void OP_free_property(wmOperator *op)
-{
-       if(op->properties) {
-       IDP_FreeProperty(op->properties);
-       /*
-        * This need change, when the idprop code only
-        * need call IDP_FreeProperty. (check BKE_idprop.h)
-        */
-       MEM_freeN(op->properties);
-       op->properties= NULL;
-       }
-}
-
-void OP_set_int(wmOperator *op, char *name, int value)
-{
-       IDPropertyTemplate val;
-       IDProperty *prop;
-
-       if(!op->properties)
-               op_init_property(op);
-
-       val.i= value;
-       prop= IDP_New(IDP_INT, val, name);
-       IDP_ReplaceInGroup(op->properties, prop);
-}
-
-void OP_set_float(wmOperator *op, char *name, float value)
-{
-       IDPropertyTemplate val;
-       IDProperty *prop;
-
-       if(!op->properties)
-               op_init_property(op);
-
-       val.f= value;
-       prop= IDP_New(IDP_FLOAT, val, name);
-       IDP_ReplaceInGroup(op->properties, prop);
-}
-
-void OP_set_int_array(wmOperator *op, char *name, int *array, short len)
-{
-       IDPropertyTemplate val;
-       IDProperty *prop;
-       short i;
-       int *pointer;
-
-       if(!op->properties)
-               op_init_property(op);
-
-       val.array.len= len;
-       val.array.type= IDP_INT;
-       prop= IDP_New(IDP_ARRAY, val, name);
-
-       pointer= (int *)prop->data.pointer;
-       for(i= 0; i < len; i++)
-               pointer[i]= array[i];
-       IDP_ReplaceInGroup(op->properties, prop);
-}
-
-void OP_set_float_array(wmOperator *op, char *name, float *array, short len)
-{
-       IDPropertyTemplate val;
-       IDProperty *prop;
-       short i;
-       float *pointer;
-
-       if(!op->properties)
-               op_init_property(op);
-
-       val.array.len= len;
-       val.array.type= IDP_FLOAT;
-       prop= IDP_New(IDP_ARRAY, val, name);
-
-       pointer= (float *) prop->data.pointer;
-       for(i= 0; i < len; i++)
-               pointer[i]= array[i];
-       IDP_ReplaceInGroup(op->properties, prop);
-}
-
-void OP_set_string(wmOperator *op, char *name, char *str)
-{
-       IDPropertyTemplate val;
-       IDProperty *prop;
-
-       if(!op->properties)
-               op_init_property(op);
-
-       val.str= str;
-       prop= IDP_New(IDP_STRING, val, name);
-       IDP_ReplaceInGroup(op->properties, prop);
-}
-
-int OP_get_int(wmOperator *op, char *name, int *value)
-{
-       IDProperty *prop= op_get_property(op, name);
-       int status= 0;
-
-       if ((prop) && (prop->type == IDP_INT)) {
-               (*value)= prop->data.val;
-               status= 1;
-       }
-       return (status);
-}
-
-int OP_get_float(wmOperator *op, char *name, float *value)
-{
-       IDProperty *prop= op_get_property(op, name);
-       int status= 0;
-
-       if ((prop) && (prop->type == IDP_FLOAT)) {
-               (*value)= *(float*)&prop->data.val;
-               status= 1;
-       }
-       return (status);
-}
-
-int OP_get_int_array(wmOperator *op, char *name, int *array, short *len)
-{
-       IDProperty *prop= op_get_property(op, name);
-       short i;
-       int status= 0;
-       int *pointer;
-
-       if ((prop) && (prop->type == IDP_ARRAY)) {
-               pointer= (int *) prop->data.pointer;
-
-               for(i= 0; (i < prop->len) && (i < *len); i++)
-                       array[i]= pointer[i];
-
-               (*len)= i;
-               status= 1;
-       }
-       return (status);
-}
-
-int OP_get_float_array(wmOperator *op, char *name, float *array, short *len)
-{
-       IDProperty *prop= op_get_property(op, name);
-       short i;
-       float *pointer;
-       int status= 0;
-
-       if ((prop) && (prop->type == IDP_ARRAY)) {
-               pointer= (float *) prop->data.pointer;
-
-               for(i= 0; (i < prop->len) && (i < *len); i++)
-                       array[i]= pointer[i];
-
-               (*len)= i;
-               status= 1;
-       }
-       return (status);
-}
-
-char *OP_get_string(wmOperator *op, char *name)
-{
-       IDProperty *prop= op_get_property(op, name);
-       if ((prop) && (prop->type == IDP_STRING))
-               return ((char *) prop->data.pointer);
-       return (NULL);
-}
-
-void OP_verify_int(wmOperator *op, char *name, int value, int *result)
-{
-       int rvalue;
-
-       if(OP_get_int(op, name, &rvalue))
-               value= rvalue;
-       else
-               OP_set_int(op, name, value);
-
-       if(result)
-               *result= value;
-}
-
-void OP_verify_float(wmOperator *op, char *name, float value, int *result)
-{
-       float rvalue;
-
-       if(OP_get_float(op, name, &rvalue))
-               value= rvalue;
-       else
-               OP_set_float(op, name, value);
-       
-       if(result)
-               *result= value;
-}
-
-char *OP_verify_string(wmOperator *op, char *name, char *str)
-{
-       char *result= OP_get_string(op, name);
-
-       if(!result) {
-               OP_set_string(op, name, str);
-               result= OP_get_string(op, name);
-       }
-
-       return result;
-}
-
-void OP_verify_int_array(wmOperator *op, char *name, int *array, short len, int *resultarray, short *resultlen)
-{
-       int rarray[1];
-       short rlen= 1;
-
-       if(resultarray && resultlen) {
-               if(!OP_get_int_array(op, name, resultarray, &rlen)) {
-                       OP_set_int_array(op, name, array, len);
-                       OP_get_int_array(op, name, resultarray, resultlen);
-               }
-       }
-       else {
-               if(!OP_get_int_array(op, name, rarray, &rlen))
-                       OP_set_int_array(op, name, array, len);
-       }
-}
-
-void OP_verify_float_array(wmOperator *op, char *name, float *array, short len, float *resultarray, short *resultlen)
-{
-       float rarray[1];
-       short rlen= 1;
-
-       if(resultarray && resultlen) {
-               if(!OP_get_float_array(op, name, resultarray, &rlen)) {
-                       OP_set_float_array(op, name, array, len);
-                       OP_get_float_array(op, name, resultarray, resultlen);
-               }
-       }
-       else {
-               if(!OP_get_float_array(op, name, rarray, &rlen))
-                       OP_set_float_array(op, name, array, len);
-       }
+/* default keymap for windows and screens, only call once per WM */
+void wm_window_keymap(wmWindowManager *wm)
+{
+       /* note, this doesn't replace existing keymap items */
+       WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_window_duplicate", AKEY, KM_PRESS, 0, 0);
+       WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_save_homefile", UKEY, KM_PRESS, KM_CTRL, 0);
+       WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_window_fullscreen_toggle", FKEY, KM_PRESS, 0, 0);
+       WM_keymap_verify_item(&wm->windowkeymap, "WM_OT_exit_blender", QKEY, KM_PRESS, KM_CTRL, 0);
 }
 
index 4699374a6124da1a736e0fb639cb478e1b698603..ec9c56f6404c54a7d7fea766b77c97f1d128d5c6 100644 (file)
@@ -45,6 +45,7 @@ extern void wm_report_free(wmReport *report);
 /* wm_operator.c, for init/exit */
 void wm_operatortype_free(void);
 void wm_operatortype_init(void);
+void wm_window_keymap(wmWindowManager *wm);
 
 /* wm_gesture.c */
 void wm_gesture_draw(struct wmWindow *win);