View2D - Initial commit of Pan-View Operator
[blender.git] / source / blender / editors / interface / view2d_ops.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2008 Blender Foundation.
21  * All rights reserved.
22  * 
23  * Contributor(s): Blender Foundation, Joshua Leung
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <math.h>
29
30 #include "MEM_guardedalloc.h"
31
32 #include "DNA_scene_types.h"
33 #include "DNA_screen_types.h"
34 #include "DNA_space_types.h"
35 #include "DNA_view2d_types.h"
36
37 #include "BKE_global.h"
38 #include "BKE_utildefines.h"
39
40 #include "RNA_access.h"
41 #include "RNA_define.h"
42
43 #include "WM_api.h"
44 #include "WM_types.h"
45
46 #include "BIF_gl.h"
47
48 #include "UI_resources.h"
49 #include "UI_view2d.h"
50
51 /* ********************************************************* */
52
53 /* ********************************************************* */
54 /* View Panning Operator */
55
56 /* 
57 operator state vars:  
58         (currently none) // XXX must figure out some vars to expose to user! 
59
60 operator customdata:
61         area                    pointer to (active) area
62         x, y                            last used mouse pos
63         (more, see below)
64
65 functions:
66
67         init()   set default property values, find v2d based on context
68
69         apply() split area based on state vars
70
71         exit()  cleanup, send notifier
72
73         cancel() remove duplicated area
74
75 callbacks:
76
77         exec()   execute without any user interaction, based on state vars
78             call init(), apply(), exit()
79
80         invoke() gets called on mouse click in action-widget
81             call init(), add modal handler
82                         call apply() with initial motion
83
84         modal()  accept modal events while doing it
85             call move-areas code with delta motion
86             call exit() or cancel() and remove handler
87
88 */
89
90 typedef struct v2dViewPanData {
91         ARegion *region;                /* region we're operating in */
92         View2D *v2d;                    /* view2d we're operating in */
93         
94         float facx, facy;               /* amount to move view relative to zoom */
95         
96                 /* mouse stuff... */
97         int lastx, lasty;               /* previous x/y values of mouse in area */
98         int x, y;                               /* current x/y values of mosue in area */
99 } v2dViewPanData;
100
101
102 static int pan_view_init(bContext *C, wmOperator *op)
103 {
104         v2dViewPanData *vpd;
105         ARegion *ar;
106         View2D *v2d;
107         float winx, winy;
108         
109         /* regions now have v2d-data by default, so check for region */
110         if (C->region == NULL)
111                 return 0;
112         
113         /* set custom-data for operator */
114         vpd= MEM_callocN(sizeof(v2dViewPanData), "v2dViewPanData");
115         op->customdata= vpd;
116         
117         /* set pointers to owners */
118         vpd->region= ar= C->region;
119         vpd->v2d= v2d= &C->region->v2d;
120         
121         /* calculate translation factor - based on size of view */
122         winx= (float)(ar->winrct.xmax - ar->winrct.xmin);
123         winy= (float)(ar->winrct.ymax - ar->winrct.ymin);
124         vpd->facx= (v2d->cur.xmax - v2d->cur.xmin) / winx;
125         vpd->facy= (v2d->cur.ymax - v2d->cur.ymin) / winy;
126                 
127         return 1;
128 }
129
130 static void pan_view_apply(bContext *C, wmOperator *op)
131 {
132         v2dViewPanData *vpd= op->customdata;
133         View2D *v2d= vpd->v2d;
134         float dx, dy;
135         
136         /* calculate amount to move view by */
137         dx= vpd->facx * (vpd->lastx - vpd->x);
138         dy= vpd->facy * (vpd->lasty - vpd->y);
139         
140         /* only move view on an axis if change is allowed */
141         if ((v2d->keepofs & V2D_LOCKOFS_X)==0) {
142                 v2d->cur.xmin += dx;
143                 v2d->cur.xmax += dx;
144         }
145         if ((v2d->keepofs & V2D_LOCKOFS_Y)==0) {
146                 v2d->cur.ymin += dy;
147                 v2d->cur.ymax += dy;
148         }
149         
150         vpd->lastx= vpd->x;
151         vpd->lasty= vpd->y;
152
153         WM_event_add_notifier(C->wm, C->window, 0, WM_NOTE_SCREEN_CHANGED, 0, NULL);
154         /* XXX: add WM_NOTE_TIME_CHANGED? */
155 }
156
157 static void pan_view_exit(bContext *C, wmOperator *op)
158 {
159         if (op->customdata) {
160                 MEM_freeN(op->customdata);
161                 op->customdata= NULL;
162                 WM_event_remove_modal_handler(&C->window->handlers, op);                                
163         }
164 }
165
166 static int pan_view_exec(bContext *C, wmOperator *op)
167 {
168         if (!pan_view_init(C, op))
169                 return OPERATOR_CANCELLED;
170         
171         pan_view_apply(C, op);
172         pan_view_exit(C, op);
173         return OPERATOR_FINISHED;
174 }
175
176 static int pan_view_invoke(bContext *C, wmOperator *op, wmEvent *event)
177 {
178         v2dViewPanData *vpd= op->customdata;
179         
180         pan_view_init(C, op);
181         
182         vpd= op->customdata;
183         vpd->lastx= vpd->x= event->x;
184         vpd->lasty= vpd->y= event->y;
185         
186         pan_view_apply(C, op);
187
188         /* add temp handler */
189         WM_event_add_modal_handler(&C->window->handlers, op);
190
191         return OPERATOR_RUNNING_MODAL;
192 }
193
194 static int pan_view_modal(bContext *C, wmOperator *op, wmEvent *event)
195 {
196         v2dViewPanData *vpd= op->customdata;
197         
198         /* execute the events */
199         switch(event->type) {
200                 case MOUSEMOVE:
201                         vpd->x= event->x;
202                         vpd->y= event->y;
203                         
204                         pan_view_apply(C, op);
205                         break;
206                         
207                 case MIDDLEMOUSE:
208                         if (event->val==0) {
209                                 pan_view_exit(C, op);
210                                 WM_event_remove_modal_handler(&C->window->handlers, op);                                
211                                 return OPERATOR_FINISHED;
212                         }
213                         break;
214         }
215
216         return OPERATOR_RUNNING_MODAL;
217 }
218
219 void ED_View2D_OT_view_pan(wmOperatorType *ot)
220 {
221         /* identifiers */
222         ot->name= "Pan View";
223         ot->idname= "ED_View2D_OT_view_pan";
224         
225         /* api callbacks */
226         ot->exec= pan_view_exec;
227         ot->invoke= pan_view_invoke;
228         ot->modal= pan_view_modal;
229 }
230
231 /* ********************************************************* */
232 /* Registration */
233
234 void ui_view2d_operatortypes(void)
235 {
236         WM_operatortype_append(ED_View2D_OT_view_pan);
237 }
238
239 void UI_view2d_keymap(wmWindowManager *wm)
240 {
241         ui_view2d_operatortypes();
242         
243         /* pan/scroll operators */
244         WM_keymap_add_item(&wm->view2dkeymap, "ED_View2D_OT_view_pan", MIDDLEMOUSE, KM_PRESS, 0, 0);
245         
246         //WM_keymap_add_item(&wm->view2dkeymap, "ED_View2D_OT_view_scrollright", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0);
247         //WM_keymap_add_item(&wm->view2dkeymap, "ED_View2D_OT_view_scrollleft", WHEELUPMOUSE, KM_CTRL, 0, 0);
248         
249         //WM_keymap_add_item(&wm->view2dkeymap, "ED_View2D_OT_view_scrolldown", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT, 0);
250         //WM_keymap_add_item(&wm->view2dkeymap, "ED_View2D_OT_view_scrollup", WHEELUPMOUSE, KM_SHIFT, 0, 0);
251         
252         /* zoom */
253         
254         /* scrollbars */
255         //WM_keymap_add_item(&wm->view2dkeymap, "ED_V2D_OT_scrollbar_activate", MOUSEMOVE, 0, 0, 0);
256 }
257