2.5: X11
[blender.git] / source / blender / editors / interface / view2d_ops.c
index b45d8ea6cbbc4b6ee5a8734a2e2d89a43866f147..14872f05f8a16be37b7d5bd69bbfdddaec58d3d9 100644 (file)
@@ -33,6 +33,7 @@
 #include "DNA_screen_types.h"
 #include "DNA_space_types.h"
 #include "DNA_userdef_types.h"
+#include "DNA_vec_types.h"
 #include "DNA_view2d_types.h"
 
 #include "BLI_blenlib.h"
 #include "UI_resources.h"
 #include "UI_view2d.h"
 
-/* ********************************************************* */
-/* General Polling Funcs */
-
-/* Check if mouse is within scrollbars 
- *     - Returns appropriate code for match
- *             'h' = in horizontal scrollbar
- *             'v' = in vertical scrollbar
- *             0 = not in scrollbar
- *     
- *     - x,y   = mouse coordinates in screen (not region) space
- */
-static short mouse_in_v2d_scrollers (const bContext *C, View2D *v2d, int x, int y)
+static int view2d_poll(bContext *C)
 {
        ARegion *ar= CTX_wm_region(C);
-       int co[2];
-       
-       /* clamp x,y to region-coordinates first */
-       co[0]= x - ar->winrct.xmin;
-       co[1]= y - ar->winrct.ymin;
-       
-       /* check if within scrollbars */
-       if (v2d->scroll & V2D_SCROLL_HORIZONTAL) {
-               if (IN_2D_HORIZ_SCROLL(v2d, co)) return 'h';
-       }
-       if (v2d->scroll & V2D_SCROLL_VERTICAL) {
-               if (IN_2D_VERT_SCROLL(v2d, co)) return 'v';
-       }       
-       
-       /* not found */
-       return 0;
-} 
 
+       return (ar != NULL) && (ar->v2d.flag & V2D_IS_INITIALISED);
+}
 
 /* ********************************************************* */
 /* VIEW PANNING OPERATOR                                                                */
@@ -101,6 +76,8 @@ static short mouse_in_v2d_scrollers (const bContext *C, View2D *v2d, int x, int
  
 /* temp customdata for operator */
 typedef struct v2dViewPanData {
+       bScreen *sc;                    /* screen where view pan was initiated */
+       ScrArea *sa;                    /* area where view pan was initiated */
        View2D *v2d;                    /* view2d we're operating in */
        
        float facx, facy;               /* amount to move view relative to zoom */
@@ -123,17 +100,24 @@ static int view_pan_init(bContext *C, wmOperator *op)
        /* regions now have v2d-data by default, so check for region */
        if (ar == NULL)
                return 0;
+               
+       /* check if panning is allowed at all */
+       v2d= &ar->v2d;
+       if ((v2d->keepofs & V2D_LOCKOFS_X) && (v2d->keepofs & V2D_LOCKOFS_Y))
+               return 0;
        
        /* set custom-data for operator */
        vpd= MEM_callocN(sizeof(v2dViewPanData), "v2dViewPanData");
        op->customdata= vpd;
        
        /* set pointers to owners */
-       vpd->v2d= v2d= &ar->v2d;
+       vpd->sc= CTX_wm_screen(C);
+       vpd->sa= CTX_wm_area(C);
+       vpd->v2d= v2d;
        
        /* calculate translation factor - based on size of view */
-       winx= (float)(ar->winrct.xmax - ar->winrct.xmin);
-       winy= (float)(ar->winrct.ymax - ar->winrct.ymin);
+       winx= (float)(ar->winrct.xmax - ar->winrct.xmin + 1);
+       winy= (float)(ar->winrct.ymax - ar->winrct.ymin + 1);
        vpd->facx= (v2d->cur.xmax - v2d->cur.xmin) / winx;
        vpd->facy= (v2d->cur.ymax - v2d->cur.ymin) / winy;
        
@@ -165,8 +149,8 @@ static void view_pan_apply(bContext *C, wmOperator *op)
        UI_view2d_curRect_validate(v2d);
        
        /* request updates to be done... */
-       ED_area_tag_redraw(CTX_wm_area(C));
-       UI_view2d_sync(CTX_wm_screen(C), v2d, V2D_LOCK_COPY);
+       ED_area_tag_redraw(vpd->sa);
+       UI_view2d_sync(vpd->sc, vpd->sa, v2d, V2D_LOCK_COPY);
 }
 
 /* cleanup temp customdata  */
@@ -200,7 +184,7 @@ static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event)
        
        /* set up customdata */
        if (!view_pan_init(C, op))
-               return OPERATOR_CANCELLED;
+               return OPERATOR_PASS_THROUGH;
        
        vpd= op->customdata;
        v2d= vpd->v2d;
@@ -261,13 +245,11 @@ static int view_pan_modal(bContext *C, wmOperator *op, wmEvent *event)
        return OPERATOR_RUNNING_MODAL;
 }
 
-void ED_View2D_OT_view_pan(wmOperatorType *ot)
+void VIEW2D_OT_pan(wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-       
        /* identifiers */
        ot->name= "Pan View";
-       ot->idname= "ED_View2D_OT_view_pan";
+       ot->idname= "VIEW2D_OT_pan";
        
        /* api callbacks */
        ot->exec= view_pan_exec;
@@ -275,11 +257,11 @@ void ED_View2D_OT_view_pan(wmOperatorType *ot)
        ot->modal= view_pan_modal;
        
        /* operator is repeatable */
-       ot->flag= OPTYPE_REGISTER;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_BLOCKING;
        
        /* rna - must keep these in sync with the other operators */
-       prop= RNA_def_property(ot->srna, "deltax", PROP_INT, PROP_NONE);
-       prop= RNA_def_property(ot->srna, "deltay", PROP_INT, PROP_NONE);
+       RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
 }
 
 /* ------------------ Scrollwheel Versions (2) ---------------------- */
@@ -287,9 +269,18 @@ void ED_View2D_OT_view_pan(wmOperatorType *ot)
 /* this operator only needs this single callback, where it callsthe view_pan_*() methods */
 static int view_scrollright_exec(bContext *C, wmOperator *op)
 {
+       v2dViewPanData *vpd;
+       
        /* initialise default settings (and validate if ok to run) */
        if (!view_pan_init(C, op))
-               return OPERATOR_CANCELLED;
+               return OPERATOR_PASS_THROUGH;
+               
+       /* also, check if can pan in horizontal axis */
+       vpd= op->customdata;
+       if (vpd->v2d->keepofs & V2D_LOCKOFS_X) {
+               view_pan_exit(C, op);
+               return OPERATOR_PASS_THROUGH;
+       }
        
        /* set RNA-Props - only movement in positive x-direction */
        RNA_int_set(op->ptr, "deltax", 20);
@@ -302,13 +293,11 @@ static int view_scrollright_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void ED_View2D_OT_view_scrollright(wmOperatorType *ot)
+void VIEW2D_OT_scroll_right(wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-       
        /* identifiers */
        ot->name= "Scroll Right";
-       ot->idname= "ED_View2D_OT_view_rightscroll";
+       ot->idname= "VIEW2D_OT_scroll_right";
        
        /* api callbacks */
        ot->exec= view_scrollright_exec;
@@ -317,8 +306,8 @@ void ED_View2D_OT_view_scrollright(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER;
        
        /* rna - must keep these in sync with the other operators */
-       prop= RNA_def_property(ot->srna, "deltax", PROP_INT, PROP_NONE);
-       prop= RNA_def_property(ot->srna, "deltay", PROP_INT, PROP_NONE);
+       RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
 }
 
 
@@ -326,9 +315,18 @@ void ED_View2D_OT_view_scrollright(wmOperatorType *ot)
 /* this operator only needs this single callback, where it callsthe view_pan_*() methods */
 static int view_scrollleft_exec(bContext *C, wmOperator *op)
 {
+       v2dViewPanData *vpd;
+       
        /* initialise default settings (and validate if ok to run) */
        if (!view_pan_init(C, op))
-               return OPERATOR_CANCELLED;
+               return OPERATOR_PASS_THROUGH;
+               
+       /* also, check if can pan in horizontal axis */
+       vpd= op->customdata;
+       if (vpd->v2d->keepofs & V2D_LOCKOFS_X) {
+               view_pan_exit(C, op);
+               return OPERATOR_PASS_THROUGH;
+       }
        
        /* set RNA-Props - only movement in negative x-direction */
        RNA_int_set(op->ptr, "deltax", -20);
@@ -341,13 +339,11 @@ static int view_scrollleft_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void ED_View2D_OT_view_scrollleft(wmOperatorType *ot)
+void VIEW2D_OT_scroll_left(wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-       
        /* identifiers */
        ot->name= "Scroll Left";
-       ot->idname= "ED_View2D_OT_view_leftscroll";
+       ot->idname= "VIEW2D_OT_scroll_left";
        
        /* api callbacks */
        ot->exec= view_scrollleft_exec;
@@ -356,18 +352,28 @@ void ED_View2D_OT_view_scrollleft(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER;
        
        /* rna - must keep these in sync with the other operators */
-       prop= RNA_def_property(ot->srna, "deltax", PROP_INT, PROP_NONE);
-       prop= RNA_def_property(ot->srna, "deltay", PROP_INT, PROP_NONE);
+       RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
 }
 
+
 /* this operator only needs this single callback, where it callsthe view_pan_*() methods */
 static int view_scrolldown_exec(bContext *C, wmOperator *op)
 {
+       v2dViewPanData *vpd;
+       
        /* initialise default settings (and validate if ok to run) */
        if (!view_pan_init(C, op))
-               return OPERATOR_CANCELLED;
+               return OPERATOR_PASS_THROUGH;
+               
+       /* also, check if can pan in vertical axis */
+       vpd= op->customdata;
+       if (vpd->v2d->keepofs & V2D_LOCKOFS_Y) {
+               view_pan_exit(C, op);
+               return OPERATOR_PASS_THROUGH;
+       }
        
-       /* set RNA-Props - only movement in positive x-direction */
+       /* set RNA-Props */
        RNA_int_set(op->ptr, "deltax", 0);
        RNA_int_set(op->ptr, "deltay", -20);
        
@@ -378,13 +384,11 @@ static int view_scrolldown_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void ED_View2D_OT_view_scrolldown(wmOperatorType *ot)
+void VIEW2D_OT_scroll_down(wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-       
        /* identifiers */
        ot->name= "Scroll Down";
-       ot->idname= "ED_View2D_OT_view_downscroll";
+       ot->idname= "VIEW2D_OT_scroll_down";
        
        /* api callbacks */
        ot->exec= view_scrolldown_exec;
@@ -393,8 +397,8 @@ void ED_View2D_OT_view_scrolldown(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER;
        
        /* rna - must keep these in sync with the other operators */
-       prop= RNA_def_property(ot->srna, "deltax", PROP_INT, PROP_NONE);
-       prop= RNA_def_property(ot->srna, "deltay", PROP_INT, PROP_NONE);
+       RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
 }
 
 
@@ -402,11 +406,20 @@ void ED_View2D_OT_view_scrolldown(wmOperatorType *ot)
 /* this operator only needs this single callback, where it callsthe view_pan_*() methods */
 static int view_scrollup_exec(bContext *C, wmOperator *op)
 {
+       v2dViewPanData *vpd;
+       
        /* initialise default settings (and validate if ok to run) */
        if (!view_pan_init(C, op))
-               return OPERATOR_CANCELLED;
+               return OPERATOR_PASS_THROUGH;
+               
+       /* also, check if can pan in vertical axis */
+       vpd= op->customdata;
+       if (vpd->v2d->keepofs & V2D_LOCKOFS_Y) {
+               view_pan_exit(C, op);
+               return OPERATOR_PASS_THROUGH;
+       }
        
-       /* set RNA-Props - only movement in negative x-direction */
+       /* set RNA-Props */
        RNA_int_set(op->ptr, "deltax", 0);
        RNA_int_set(op->ptr, "deltay", 20);
        
@@ -417,13 +430,11 @@ static int view_scrollup_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void ED_View2D_OT_view_scrollup(wmOperatorType *ot)
+void VIEW2D_OT_scroll_up(wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-       
        /* identifiers */
        ot->name= "Scroll Up";
-       ot->idname= "ED_View2D_OT_view_upscroll";
+       ot->idname= "VIEW2D_OT_scroll_up";
        
        /* api callbacks */
        ot->exec= view_scrollup_exec;
@@ -432,8 +443,8 @@ void ED_View2D_OT_view_scrollup(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER;
        
        /* rna - must keep these in sync with the other operators */
-       prop= RNA_def_property(ot->srna, "deltax", PROP_INT, PROP_NONE);
-       prop= RNA_def_property(ot->srna, "deltay", PROP_INT, PROP_NONE);
+       RNA_def_int(ot->srna, "deltax", 0, INT_MIN, INT_MAX, "Delta X", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "deltay", 0, INT_MIN, INT_MAX, "Delta Y", "", INT_MIN, INT_MAX);
 }
 
 /* ********************************************************* */
@@ -482,14 +493,24 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op)
        dx= (v2d->cur.xmax - v2d->cur.xmin) * (float)RNA_float_get(op->ptr, "zoomfacx");
        dy= (v2d->cur.ymax - v2d->cur.ymin) * (float)RNA_float_get(op->ptr, "zoomfacy");
        
-       /* only move view on an axis if change is allowed */
-       if ((v2d->keepzoom & V2D_LOCKOFS_X)==0) {
-               v2d->cur.xmin += dx;
-               v2d->cur.xmax -= dx;
+       /* only resize view on an axis if change is allowed */
+       if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) {
+               if (v2d->keepofs & V2D_LOCKOFS_X) {
+                       v2d->cur.xmax -= 2*dx;
+               }
+               else {
+                       v2d->cur.xmin += dx;
+                       v2d->cur.xmax -= dx;
+               }
        }
-       if ((v2d->keepzoom & V2D_LOCKOFS_Y)==0) {
-               v2d->cur.ymin += dy;
-               v2d->cur.ymax -= dy;
+       if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) {
+               if (v2d->keepofs & V2D_LOCKOFS_Y) {
+                       v2d->cur.ymax -= 2*dy;
+               }
+               else {
+                       v2d->cur.ymin += dy;
+                       v2d->cur.ymax -= dy;
+               }
        }
        
        /* validate that view is in valid configuration after this operation */
@@ -497,7 +518,7 @@ static void view_zoomstep_apply(bContext *C, wmOperator *op)
        
        /* request updates to be done... */
        ED_area_tag_redraw(CTX_wm_area(C));
-       UI_view2d_sync(CTX_wm_screen(C), v2d, V2D_LOCK_COPY);
+       UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
 }
 
 /* --------------- Individual Operators ------------------- */
@@ -507,7 +528,7 @@ static int view_zoomin_exec(bContext *C, wmOperator *op)
 {
        /* check that there's an active region, as View2D data resides there */
        if (!view_zoomstep_ok(C))
-               return OPERATOR_CANCELLED;
+               return OPERATOR_PASS_THROUGH;
        
        /* set RNA-Props - zooming in by uniform factor */
        RNA_float_set(op->ptr, "zoomfacx", 0.0375f);
@@ -519,13 +540,11 @@ static int view_zoomin_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void ED_View2D_OT_view_zoomin(wmOperatorType *ot)
+void VIEW2D_OT_zoom_in(wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-       
        /* identifiers */
        ot->name= "Zoom In";
-       ot->idname= "ED_View2D_OT_view_zoomin";
+       ot->idname= "VIEW2D_OT_zoom_in";
        
        /* api callbacks */
        ot->exec= view_zoomin_exec;
@@ -534,8 +553,8 @@ void ED_View2D_OT_view_zoomin(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER;
        
        /* rna - must keep these in sync with the other operators */
-       prop= RNA_def_property(ot->srna, "zoomfacx", PROP_FLOAT, PROP_NONE);
-       prop= RNA_def_property(ot->srna, "zoomfacy", PROP_FLOAT, PROP_NONE);
+       RNA_def_float(ot->srna, "zoomfacx", 0, -FLT_MAX, FLT_MAX, "Zoom Factor X", "", -FLT_MAX, FLT_MAX);
+       RNA_def_float(ot->srna, "zoomfacy", 0, -FLT_MAX, FLT_MAX, "Zoom Factor Y", "", -FLT_MAX, FLT_MAX);
 }
 
 
@@ -545,7 +564,7 @@ static int view_zoomout_exec(bContext *C, wmOperator *op)
 {
        /* check that there's an active region, as View2D data resides there */
        if (!view_zoomstep_ok(C))
-               return OPERATOR_CANCELLED;
+               return OPERATOR_PASS_THROUGH;
        
        /* set RNA-Props - zooming in by uniform factor */
        RNA_float_set(op->ptr, "zoomfacx", -0.0375f);
@@ -557,13 +576,11 @@ static int view_zoomout_exec(bContext *C, wmOperator *op)
        return OPERATOR_FINISHED;
 }
 
-void ED_View2D_OT_view_zoomout(wmOperatorType *ot)
+void VIEW2D_OT_zoom_out(wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-       
        /* identifiers */
        ot->name= "Zoom Out";
-       ot->idname= "ED_View2D_OT_view_zoomout";
+       ot->idname= "VIEW2D_OT_zoom_out";
        
        /* api callbacks */
        ot->exec= view_zoomout_exec;
@@ -572,17 +589,14 @@ void ED_View2D_OT_view_zoomout(wmOperatorType *ot)
        ot->flag= OPTYPE_REGISTER;
        
        /* rna - must keep these in sync with the other operators */
-       prop= RNA_def_property(ot->srna, "zoomfacx", PROP_FLOAT, PROP_NONE);
-       prop= RNA_def_property(ot->srna, "zoomfacy", PROP_FLOAT, PROP_NONE);
+       RNA_def_float(ot->srna, "zoomfacx", 0, -FLT_MAX, FLT_MAX, "Zoom Factor X", "", -FLT_MAX, FLT_MAX);
+       RNA_def_float(ot->srna, "zoomfacy", 0, -FLT_MAX, FLT_MAX, "Zoom Factor Y", "", -FLT_MAX, FLT_MAX);
 }
 
 /* ********************************************************* */
 /* DRAG-ZOOM OPERATOR                                                                   */
 
-/*     This group of operators come in several forms:
- *             1) MMB Drag - allows non-uniform scaling by dragging mouse
- *                                - method of scaling depends upon U.viewzoom setting (Continue, Dolly, Scale)
- *                                     XXX should we store this info as RNA prop?
+/*     MMB Drag - allows non-uniform scaling by dragging mouse
  *
  *     In order to make sure this works, each operator must define the following RNA-Operator Props:
  *             deltax, deltay  - amounts to add to each side of the 'cur' rect
@@ -637,12 +651,22 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
        
        /* only move view on an axis if change is allowed */
        if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) {
-               v2d->cur.xmin += dx;
-               v2d->cur.xmax -= dx;
+               if (v2d->keepofs & V2D_LOCKOFS_X) {
+                       v2d->cur.xmax -= 2*dx;
+               }
+               else {
+                       v2d->cur.xmin += dx;
+                       v2d->cur.xmax -= dx;
+               }
        }
        if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) {
-               v2d->cur.ymin += dy;
-               v2d->cur.ymax -= dy;
+               if (v2d->keepofs & V2D_LOCKOFS_Y) {
+                       v2d->cur.ymax -= 2*dy;
+               }
+               else {
+                       v2d->cur.ymin += dy;
+                       v2d->cur.ymax -= dy;
+               }
        }
        
        /* validate that view is in valid configuration after this operation */
@@ -650,7 +674,7 @@ static void view_zoomdrag_apply(bContext *C, wmOperator *op)
        
        /* request updates to be done... */
        ED_area_tag_redraw(CTX_wm_area(C));
-       UI_view2d_sync(CTX_wm_screen(C), v2d, V2D_LOCK_COPY);
+       UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
 }
 
 /* cleanup temp customdata  */
@@ -666,7 +690,7 @@ static void view_zoomdrag_exit(bContext *C, wmOperator *op)
 static int view_zoomdrag_exec(bContext *C, wmOperator *op)
 {
        if (!view_zoomdrag_init(C, op))
-               return OPERATOR_CANCELLED;
+               return OPERATOR_PASS_THROUGH;
        
        view_zoomdrag_apply(C, op);
        view_zoomdrag_exit(C, op);
@@ -682,7 +706,7 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event)
        
        /* set up customdata */
        if (!view_zoomdrag_init(C, op))
-               return OPERATOR_CANCELLED;
+               return OPERATOR_PASS_THROUGH;
        
        vzd= op->customdata;
        v2d= vzd->v2d;
@@ -725,12 +749,12 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event)
                                
                                /* x-axis transform */
                                dist = (v2d->mask.xmax - v2d->mask.xmin) / 2.0f;
-                               dx= 1.0f - (fabs(vzd->lastx - dist) + 2.0f) / (fabs(event->x - dist) + 2.0f);
+                               dx= 1.0f - ((float)fabs(vzd->lastx - dist) + 2.0f) / ((float)fabs(event->x - dist) + 2.0f);
                                dx*= 0.5f * (v2d->cur.xmax - v2d->cur.xmin);
                                
                                /* y-axis transform */
                                dist = (v2d->mask.ymax - v2d->mask.ymin) / 2.0f;
-                               dy= 1.0f - (fabs(vzd->lasty - dist) + 2.0) / (fabs(event->y - dist) + 2.0f);
+                               dy= 1.0f - ((float)fabs(vzd->lasty - dist) + 2.0f) / ((float)fabs(event->y - dist) + 2.0f);
                                dy*= 0.5f * (v2d->cur.ymax - v2d->cur.ymin);
                        }
                        else {
@@ -796,13 +820,11 @@ static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event)
        return OPERATOR_RUNNING_MODAL;
 }
 
-void ED_View2D_OT_view_zoom(wmOperatorType *ot)
+void VIEW2D_OT_zoom(wmOperatorType *ot)
 {
-       PropertyRNA *prop;
-       
        /* identifiers */
        ot->name= "Zoom View";
-       ot->idname= "ED_View2D_OT_view_zoom";
+       ot->idname= "VIEW2D_OT_zoom";
        
        /* api callbacks */
        ot->exec= view_zoomdrag_exec;
@@ -810,11 +832,111 @@ void ED_View2D_OT_view_zoom(wmOperatorType *ot)
        ot->modal= view_zoomdrag_modal;
        
        /* operator is repeatable */
-       ot->flag= OPTYPE_REGISTER;
+       ot->flag= OPTYPE_REGISTER|OPTYPE_BLOCKING;
        
        /* rna - must keep these in sync with the other operators */
-       prop= RNA_def_property(ot->srna, "deltax", PROP_FLOAT, PROP_NONE);
-       prop= RNA_def_property(ot->srna, "deltay", PROP_FLOAT, PROP_NONE);
+       RNA_def_float(ot->srna, "deltax", 0, -FLT_MAX, FLT_MAX, "Delta X", "", -FLT_MAX, FLT_MAX);
+       RNA_def_float(ot->srna, "deltay", 0, -FLT_MAX, FLT_MAX, "Delta Y", "", -FLT_MAX, FLT_MAX);
+}
+
+/* ********************************************************* */
+/* BORDER-ZOOM */
+
+/* The user defines a rect using standard borderselect tools, and we use this rect to 
+ * define the new zoom-level of the view in the following ways:
+ *     1) LEFTMOUSE - zoom in to view
+ *     2) RIGHTMOUSE - zoom out of view
+ *
+ * Currently, these key mappings are hardcoded, but it shouldn't be too important to
+ * have custom keymappings for this...
+ */
+static int view_borderzoom_exec(bContext *C, wmOperator *op)
+{
+       ARegion *ar= CTX_wm_region(C);
+       View2D *v2d= &ar->v2d;
+       rctf rect;
+       int event_type;
+       
+       /* convert coordinates of rect to 'tot' rect coordinates */
+       UI_view2d_region_to_view(v2d, RNA_int_get(op->ptr, "xmin"), RNA_int_get(op->ptr, "ymin"), &rect.xmin, &rect.ymin);
+       UI_view2d_region_to_view(v2d, RNA_int_get(op->ptr, "xmax"), RNA_int_get(op->ptr, "ymax"), &rect.xmax, &rect.ymax);
+       
+       /* check if zooming in/out view */
+       // XXX hardcoded for now!
+       event_type= RNA_int_get(op->ptr, "event_type");
+       
+       if (event_type == LEFTMOUSE) {
+               /* zoom in: 
+                *      - 'cur' rect will be defined by the coordinates of the border region 
+                *      - just set the 'cur' rect to have the same coordinates as the border region
+                *        if zoom is allowed to be changed
+                */
+               if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) {
+                       v2d->cur.xmin= rect.xmin;
+                       v2d->cur.xmax= rect.xmax;
+               }
+               if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) {
+                       v2d->cur.ymin= rect.ymin;
+                       v2d->cur.ymax= rect.ymax;
+               }
+       }
+       else {
+               /* zoom out:
+                *      - the current 'cur' rect coordinates are going to end upwhere the 'rect' ones are, 
+                *        but the 'cur' rect coordinates will need to be adjusted to take in more of the view
+                *      - calculate zoom factor, and adjust using center-point
+                */
+               float zoom, center, size;
+               
+               // TODO: is this zoom factor calculation valid? It seems to produce same results everytime...
+               if ((v2d->keepzoom & V2D_LOCKZOOM_X)==0) {
+                       size= (v2d->cur.xmax - v2d->cur.xmin);
+                       zoom= size / (rect.xmax - rect.xmin);
+                       center= (v2d->cur.xmax + v2d->cur.xmin) * 0.5f;
+                       
+                       v2d->cur.xmin= center - (size * zoom);
+                       v2d->cur.xmax= center + (size * zoom);
+               }
+               if ((v2d->keepzoom & V2D_LOCKZOOM_Y)==0) {
+                       size= (v2d->cur.ymax - v2d->cur.ymin);
+                       zoom= size / (rect.ymax - rect.ymin);
+                       center= (v2d->cur.ymax + v2d->cur.ymin) * 0.5f;
+                       
+                       v2d->cur.ymin= center - (size * zoom);
+                       v2d->cur.ymax= center + (size * zoom);
+               }
+       }
+       
+       /* validate that view is in valid configuration after this operation */
+       UI_view2d_curRect_validate(v2d);
+       
+       /* request updates to be done... */
+       ED_area_tag_redraw(CTX_wm_area(C));
+       UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+       
+       return OPERATOR_FINISHED;
+} 
+
+void VIEW2D_OT_zoom_border(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Zoom to Border";
+       ot->idname= "VIEW2D_OT_zoom_border";
+       
+       /* api callbacks */
+       ot->invoke= WM_border_select_invoke;
+       ot->exec= view_borderzoom_exec;
+       ot->modal= WM_border_select_modal;
+       
+       ot->poll= ED_operator_areaactive;
+       
+       /* rna */
+       RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
+       RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
 }
 
 /* ********************************************************* */
@@ -888,15 +1010,7 @@ static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_
        
        
        if (in_view == 0) {
-               /* handles are only activated if the mouse is within the relative quater lengths of the scroller */
-               int qLen = (sc_max + sc_min) / 4;
-               
-               if (mouse >= (sc_max - qLen))
-                       return SCROLLHANDLE_MAX;
-               else if (mouse <= qLen)
-                       return SCROLLHANDLE_MIN;
-               else
-                       return SCROLLHANDLE_BAR;
+               return SCROLLHANDLE_BAR;
        }
        
        /* check if mouse is in or past either handle */
@@ -973,15 +1087,23 @@ static void scroller_activate_init(bContext *C, wmOperator *op, wmEvent *event,
                        vsm->zone= mouse_in_scroller_handle(y, v2d->vert.ymin, v2d->vert.ymax, scrollers->vert_min, scrollers->vert_max); 
                }
        }
+       
        UI_view2d_scrollers_free(scrollers);
+       ED_region_tag_redraw(ar);
 }
 
 /* cleanup temp customdata  */
 static void scroller_activate_exit(bContext *C, wmOperator *op)
 {
        if (op->customdata) {
+               v2dScrollerMove *vsm= op->customdata;
+
+               vsm->v2d->scroll_ui &= ~(V2D_SCROLL_H_ACTIVE|V2D_SCROLL_V_ACTIVE);
+               
                MEM_freeN(op->customdata);
-               op->customdata= NULL;                           
+               op->customdata= NULL;           
+               
+               ED_region_tag_redraw(CTX_wm_region(C));
        }
 } 
 
@@ -998,14 +1120,14 @@ static void scroller_activate_apply(bContext *C, wmOperator *op)
        /* type of movement */
        switch (vsm->zone) {
                case SCROLLHANDLE_MIN:
+               case SCROLLHANDLE_MAX:
+                       
                        /* only expand view on axis if zoom is allowed */
                        if ((vsm->scroller == 'h') && !(v2d->keepzoom & V2D_LOCKZOOM_X))
                                v2d->cur.xmin -= temp;
                        if ((vsm->scroller == 'v') && !(v2d->keepzoom & V2D_LOCKZOOM_Y))
                                v2d->cur.ymin -= temp;
-                       break;
                
-               case SCROLLHANDLE_MAX:
                        /* only expand view on axis if zoom is allowed */
                        if ((vsm->scroller == 'h') && !(v2d->keepzoom & V2D_LOCKZOOM_X))
                                v2d->cur.xmax += temp;
@@ -1031,7 +1153,7 @@ static void scroller_activate_apply(bContext *C, wmOperator *op)
        
        /* request updates to be done... */
        ED_area_tag_redraw(CTX_wm_area(C));
-       UI_view2d_sync(CTX_wm_screen(C), v2d, V2D_LOCK_COPY);
+       UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
 }
 
 /* handle user input for scrollers - calculations of mouse-movement need to be done here, not in the apply callback! */
@@ -1091,18 +1213,11 @@ static int scroller_activate_modal(bContext *C, wmOperator *op, wmEvent *event)
 static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        ARegion *ar= CTX_wm_region(C);
-       View2D *v2d= NULL;
+       View2D *v2d= &ar->v2d;
        short in_scroller= 0;
-       
-       /* firstly, check context to see if mouse is actually in region */
-       // XXX isn't this the job of poll() callbacks which can't check events, but only context?
-       if (ar == NULL) 
-               return OPERATOR_PASS_THROUGH;//OPERATOR_CANCELLED;
-       else
-               v2d= &ar->v2d;
                
        /* check if mouse in scrollbars, if they're enabled */
-       in_scroller= mouse_in_v2d_scrollers(C, v2d, event->x, event->y);
+       in_scroller= UI_view2d_mouse_in_scrollers(C, v2d, event->x, event->y);
        
        /* if in a scroller, init customdata then set modal handler which will catch mousedown to start doing useful stuff */
        if (in_scroller) {
@@ -1125,6 +1240,11 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event)
                        }                       
                }
                
+               if(vsm->scroller=='h')
+                       v2d->scroll_ui |= V2D_SCROLL_H_ACTIVE;
+               else
+                       v2d->scroll_ui |= V2D_SCROLL_V_ACTIVE;
+               
                /* still ok, so can add */
                WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op);
                return OPERATOR_RUNNING_MODAL;
@@ -1136,15 +1256,83 @@ static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event)
 }
 
 /* LMB-Drag in Scrollers - not repeatable operator! */
-void ED_View2D_OT_scroller_activate(wmOperatorType *ot)
+void VIEW2D_OT_scroller_activate(wmOperatorType *ot)
 {
        /* identifiers */
        ot->name= "Scroller Activate";
-       ot->idname= "ED_View2D_OT_scroller_activate";
+       ot->idname= "VIEW2D_OT_scroller_activate";
+
+       /* flags */
+       ot->flag= OPTYPE_BLOCKING;
        
        /* api callbacks */
        ot->invoke= scroller_activate_invoke;
        ot->modal= scroller_activate_modal;
+       ot->poll= view2d_poll;
+}
+
+/* ********************************************************* */
+/* RESET */
+
+static int reset_exec(bContext *C, wmOperator *op)
+{
+       uiStyle *style= U.uistyles.first;
+       ARegion *ar= CTX_wm_region(C);
+       View2D *v2d= &ar->v2d;
+       int winx, winy;
+
+       /* zoom 1.0 */
+       winx= (float)(v2d->mask.xmax - v2d->mask.xmin + 1);
+       winy= (float)(v2d->mask.ymax - v2d->mask.ymin + 1);
+
+       v2d->cur.xmax= v2d->cur.xmin + winx;
+       v2d->cur.ymax= v2d->cur.ymin + winy;
+       
+       /* align */
+       if(v2d->align) {
+               /* posx and negx flags are mutually exclusive, so watch out */
+               if ((v2d->align & V2D_ALIGN_NO_POS_X) && !(v2d->align & V2D_ALIGN_NO_NEG_X)) {
+                       v2d->cur.xmax= 0.0f;
+                       v2d->cur.xmin= v2d->winx*style->panelzoom;
+               }
+               else if ((v2d->align & V2D_ALIGN_NO_NEG_X) && !(v2d->align & V2D_ALIGN_NO_POS_X)) {
+                       v2d->cur.xmax= (v2d->cur.xmax - v2d->cur.xmin)*style->panelzoom;
+                       v2d->cur.xmin= 0.0f;
+               }
+
+               /* - posx and negx flags are mutually exclusive, so watch out */
+               if ((v2d->align & V2D_ALIGN_NO_POS_Y) && !(v2d->align & V2D_ALIGN_NO_NEG_Y)) {
+                       v2d->cur.ymax= 0.0f;
+                       v2d->cur.ymin= -v2d->winy*style->panelzoom;
+               }
+               else if ((v2d->align & V2D_ALIGN_NO_NEG_Y) && !(v2d->align & V2D_ALIGN_NO_POS_Y)) {
+                       v2d->cur.ymax= (v2d->cur.ymax - v2d->cur.ymin)*style->panelzoom;
+                       v2d->cur.ymin= 0.0f;
+               }
+       }
+
+       /* validate that view is in valid configuration after this operation */
+       UI_view2d_curRect_validate(v2d);
+       
+       /* request updates to be done... */
+       ED_area_tag_redraw(CTX_wm_area(C));
+       UI_view2d_sync(CTX_wm_screen(C), CTX_wm_area(C), v2d, V2D_LOCK_COPY);
+       
+       return OPERATOR_FINISHED;
+}
+void VIEW2D_OT_reset(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Reset View";
+       ot->idname= "VIEW2D_OT_reset";
+       
+       /* api callbacks */
+       ot->exec= reset_exec;
+       ot->poll= view2d_poll;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
  
 /* ********************************************************* */
@@ -1152,19 +1340,22 @@ void ED_View2D_OT_scroller_activate(wmOperatorType *ot)
 
 void ui_view2d_operatortypes(void)
 {
-       WM_operatortype_append(ED_View2D_OT_view_pan);
+       WM_operatortype_append(VIEW2D_OT_pan);
        
-       WM_operatortype_append(ED_View2D_OT_view_scrollleft);
-       WM_operatortype_append(ED_View2D_OT_view_scrollright);
-       WM_operatortype_append(ED_View2D_OT_view_scrollup);
-       WM_operatortype_append(ED_View2D_OT_view_scrolldown);
+       WM_operatortype_append(VIEW2D_OT_scroll_left);
+       WM_operatortype_append(VIEW2D_OT_scroll_right);
+       WM_operatortype_append(VIEW2D_OT_scroll_up);
+       WM_operatortype_append(VIEW2D_OT_scroll_down);
        
-       WM_operatortype_append(ED_View2D_OT_view_zoomin);
-       WM_operatortype_append(ED_View2D_OT_view_zoomout);
+       WM_operatortype_append(VIEW2D_OT_zoom_in);
+       WM_operatortype_append(VIEW2D_OT_zoom_out);
        
-       WM_operatortype_append(ED_View2D_OT_view_zoom);
+       WM_operatortype_append(VIEW2D_OT_zoom);
+       WM_operatortype_append(VIEW2D_OT_zoom_border);
        
-       WM_operatortype_append(ED_View2D_OT_scroller_activate);
+       WM_operatortype_append(VIEW2D_OT_scroller_activate);
+
+       WM_operatortype_append(VIEW2D_OT_reset);
 }
 
 void UI_view2d_keymap(wmWindowManager *wm)
@@ -1172,24 +1363,46 @@ void UI_view2d_keymap(wmWindowManager *wm)
        ListBase *keymap= WM_keymap_listbase(wm, "View2D", 0, 0);
        
        /* pan/scroll */
-       WM_keymap_add_item(keymap, "ED_View2D_OT_view_pan", MIDDLEMOUSE, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MIDDLEMOUSE, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0);
        
-       WM_keymap_add_item(keymap, "ED_View2D_OT_view_rightscroll", WHEELDOWNMOUSE, KM_ANY, KM_CTRL, 0);
-       WM_keymap_add_item(keymap, "ED_View2D_OT_view_leftscroll", WHEELUPMOUSE, KM_ANY, KM_CTRL, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_right", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_left", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0);
        
-       WM_keymap_add_item(keymap, "ED_View2D_OT_view_downscroll", WHEELDOWNMOUSE, KM_ANY, KM_SHIFT, 0);
-       WM_keymap_add_item(keymap, "ED_View2D_OT_view_upscroll", WHEELUPMOUSE, KM_ANY, KM_SHIFT, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0);
        
        /* zoom - single step */
-       WM_keymap_add_item(keymap, "ED_View2D_OT_view_zoomout", WHEELUPMOUSE, KM_ANY, 0, 0);
-       WM_keymap_add_item(keymap, "ED_View2D_OT_view_zoomin", WHEELDOWNMOUSE, KM_ANY, 0, 0);
-       WM_keymap_add_item(keymap, "ED_View2D_OT_view_zoomout", PADMINUS, KM_PRESS, 0, 0);
-       WM_keymap_add_item(keymap, "ED_View2D_OT_view_zoomin", PADPLUSKEY, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", PADMINUS, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
+       
+       /* scroll up/down - no modifiers, only when zoom fails */
+               /* these may fail if zoom is disallowed, in which case they should pass on event */
+       WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, 0, 0);
+               /* these may be necessary if vertical scroll is disallowed */
+       WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_right", WHEELDOWNMOUSE, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_left", WHEELUPMOUSE, KM_PRESS, 0, 0);
        
        /* zoom - drag */
-       WM_keymap_add_item(keymap, "ED_View2D_OT_view_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
+       
+       /* borderzoom - drag */
+       WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_border", BKEY, KM_PRESS, KM_SHIFT, 0);
        
        /* scrollers */
-       WM_keymap_add_item(keymap, "ED_View2D_OT_scroller_activate", LEFTMOUSE, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_scroller_activate", LEFTMOUSE, KM_PRESS, 0, 0);
+
+       /* Alternative keymap for buttons listview */
+       keymap= WM_keymap_listbase(wm, "View2D Buttons List", 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_pan", MIDDLEMOUSE, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_down", WHEELDOWNMOUSE, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_scroll_up", WHEELUPMOUSE, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_zoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_out", PADMINUS, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0);
+       WM_keymap_add_item(keymap, "VIEW2D_OT_reset", HOMEKEY, KM_PRESS, 0, 0);
 }