remove unused rna includes
[blender.git] / source / blender / windowmanager / intern / wm_dragdrop.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2010 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include "string.h"
30
31 #include "DNA_windowmanager_types.h"
32 #include "DNA_screen_types.h"
33
34 #include "MEM_guardedalloc.h"
35
36 #include "BLI_blenlib.h"
37
38 #include "BIF_gl.h"
39 #include "BIF_glutil.h"
40
41 #include "BKE_blender.h"
42 #include "BKE_context.h"
43 #include "BKE_idprop.h"
44 #include "BKE_library.h"
45 #include "BKE_main.h"
46 #include "BKE_screen.h"
47 #include "BKE_global.h"
48
49 #include "IMB_imbuf_types.h"
50 #include "IMB_imbuf.h"
51
52 #include "UI_interface.h"
53 #include "UI_interface_icons.h"
54
55 #include "WM_api.h"
56 #include "WM_types.h"
57 #include "wm_event_system.h"
58 #include "wm.h"
59
60
61 /* ****************************************************** */
62
63 static ListBase dropboxes= {NULL, NULL};
64
65 /* drop box maps are stored global for now */
66 /* these are part of blender's UI/space specs, and not like keymaps */
67 /* when editors become configurable, they can add own dropbox definitions */
68
69 typedef struct wmDropBoxMap {
70         struct wmDropBoxMap *next, *prev;
71         
72         ListBase dropboxes;
73         short spaceid, regionid;
74         char idname[KMAP_MAX_NAME];
75         
76 } wmDropBoxMap;
77
78 ListBase *WM_dropboxmap_find(char *idname, int spaceid, int regionid)
79 {
80         wmDropBoxMap *dm;
81         
82         for(dm= dropboxes.first; dm; dm= dm->next)
83                 if(dm->spaceid==spaceid && dm->regionid==regionid)
84                         if(0==strncmp(idname, dm->idname, KMAP_MAX_NAME))
85                                 return &dm->dropboxes;
86         
87         dm= MEM_callocN(sizeof(struct wmDropBoxMap), "dropmap list");
88         BLI_strncpy(dm->idname, idname, KMAP_MAX_NAME);
89         dm->spaceid= spaceid;
90         dm->regionid= regionid;
91         BLI_addtail(&dropboxes, dm);
92         
93         return &dm->dropboxes;
94 }
95
96
97
98 wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(bContext *, wmDrag *, wmEvent *),
99                                                   void (*copy)(wmDrag *, wmDropBox *))
100 {
101         wmDropBox *drop= MEM_callocN(sizeof(wmDropBox), "wmDropBox");
102         
103         drop->poll= poll;
104         drop->copy= copy;
105         drop->ot= WM_operatortype_find(idname, 0);
106         
107         if(drop->ot==NULL) {
108                 MEM_freeN(drop);
109                 printf("Error: dropbox with unknown operator: %s\n", idname);
110                 return NULL;
111         }
112         WM_operator_properties_alloc(&(drop->ptr), &(drop->properties), idname);
113         
114         BLI_addtail(lb, drop);
115         
116         return drop;
117 }
118
119 void wm_dropbox_free(void)
120 {
121         wmDropBoxMap *dm;
122         
123         for(dm= dropboxes.first; dm; dm= dm->next) {
124                 wmDropBox *drop;
125                 
126                 for(drop= dm->dropboxes.first; drop; drop= drop->next) {
127                         if(drop->ptr) {
128                                 WM_operator_properties_free(drop->ptr);
129                                 MEM_freeN(drop->ptr);
130                         }
131                 }
132                 BLI_freelistN(&dm->dropboxes);
133         }
134         
135         BLI_freelistN(&dropboxes);              
136 }
137
138 /* *********************************** */
139
140 /* note that the pointer should be valid allocated and not on stack */
141 wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value)
142 {
143         wmWindowManager *wm= CTX_wm_manager(C);
144         wmDrag *drag= MEM_callocN(sizeof(struct wmDrag), "new drag");
145         
146         /* keep track of future multitouch drag too, add a mousepointer id or so */
147         /* if multiple drags are added, they're drawn as list */
148         
149         BLI_addtail(&wm->drags, drag);
150         drag->icon= icon;
151         drag->type= type;
152         if(type==WM_DRAG_PATH)
153                 BLI_strncpy(drag->path, poin, FILE_MAX);
154         else
155                 drag->poin= poin;
156         drag->value= value;
157         
158         return drag;
159 }
160
161 void WM_event_drag_image(wmDrag *drag, ImBuf *imb, float scale, int sx, int sy)
162 {
163         drag->imb= imb;
164         drag->scale= scale;
165         drag->sx= sx;
166         drag->sy= sy;
167 }
168
169
170 static char *dropbox_active(bContext *C, ListBase *handlers, wmDrag *drag, wmEvent *event)
171 {
172         wmEventHandler *handler= handlers->first;
173         for(; handler; handler= handler->next) {
174                 if(handler->dropboxes) {
175                         wmDropBox *drop= handler->dropboxes->first;
176                         for(; drop; drop= drop->next) {
177                                 if(drop->poll(C, drag, event)) 
178                                         return drop->ot->name;
179                         }
180                 }
181         }
182         return NULL;
183 }
184
185 /* return active operator name when mouse is in box */
186 static char *wm_dropbox_active(bContext *C, wmDrag *drag, wmEvent *event)
187 {
188         wmWindow *win= CTX_wm_window(C);
189         ScrArea *sa= CTX_wm_area(C);
190         ARegion *ar= CTX_wm_region(C);
191         char *name;
192         
193         name= dropbox_active(C, &win->handlers, drag, event);
194         if(name) return name;
195         
196         name= dropbox_active(C, &sa->handlers, drag, event);
197         if(name) return name;
198         
199         name= dropbox_active(C, &ar->handlers, drag, event);
200         if(name) return name;
201
202         return NULL;
203 }
204
205
206 static void wm_drop_operator_options(bContext *C, wmDrag *drag, wmEvent *event)
207 {
208         wmWindow *win= CTX_wm_window(C);
209         
210         /* for multiwin drags, we only do this if mouse inside */
211         if(event->x<0 || event->y<0 || event->x>win->sizex || event->y>win->sizey)
212                 return;
213         
214         drag->opname[0]= 0;
215         
216         /* check buttons (XXX todo rna and value) */
217         if( UI_but_active_drop_name(C) ) {
218                 strcpy(drag->opname, "Paste name");
219         }
220         else {
221                 char *opname= wm_dropbox_active(C, drag, event);
222                 
223                 if(opname) {
224                         BLI_strncpy(drag->opname, opname, FILE_MAX);
225                         // WM_cursor_modal(win, CURSOR_COPY);
226                 }
227                 // else
228                 //      WM_cursor_restore(win);
229                 /* unsure about cursor type, feels to be too much */
230         }
231 }
232
233 /* called in inner handler loop, region context */
234 void wm_drags_check_ops(bContext *C, wmEvent *event)
235 {
236         wmWindowManager *wm= CTX_wm_manager(C);
237         wmDrag *drag;
238         
239         for(drag= wm->drags.first; drag; drag= drag->next) {
240                 wm_drop_operator_options(C, drag, event);
241         }
242 }
243
244 /* ************** draw ***************** */
245
246 static void wm_drop_operator_draw(char *name, int x, int y)
247 {
248         int width= UI_GetStringWidth(name);
249         
250         glColor4ub(0, 0, 0, 128);
251         
252         uiSetRoundBox(15);      
253         uiRoundBox(x, y, x + width + 8, y + 15, 7);
254         
255         glColor4ub(255, 255, 255, 255);
256         UI_DrawString(x+4, y+4, name);
257 }
258
259 static char *wm_drag_name(wmDrag *drag)
260 {
261         switch(drag->type) {
262                 case WM_DRAG_ID:
263                 {
264                         ID *id= (ID *)drag->poin;
265                         return id->name+2;
266                 }
267                 case WM_DRAG_PATH:
268                         return drag->path;
269                 case WM_DRAG_NAME:
270                         return (char *)drag->path;
271         }
272         return "";
273 }
274
275 static void drag_rect_minmax(rcti *rect, int x1, int y1, int x2, int y2)
276 {
277         if(rect->xmin > x1)
278                 rect->xmin= x1;
279         if(rect->xmax < x2)
280                 rect->xmax= x2;
281         if(rect->ymin > y1)
282                 rect->ymin= y1;
283         if(rect->ymax < y2)
284                 rect->ymax= y2;
285 }
286
287 /* called in wm_draw.c */
288 /* if rect set, do not draw */
289 void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
290 {
291         wmWindowManager *wm= CTX_wm_manager(C);
292         wmDrag *drag;
293         int cursorx, cursory, x, y;
294         
295         cursorx= win->eventstate->x;
296         cursory= win->eventstate->y;
297         if(rect) {
298                 rect->xmin= rect->xmax= cursorx;
299                 rect->ymin= rect->ymax= cursory;
300         }
301         
302         /* XXX todo, multiline drag draws... but maybe not, more types mixed wont work well */
303         glEnable(GL_BLEND);
304         for(drag= wm->drags.first; drag; drag= drag->next) {
305                 
306                 /* image or icon */
307                 if(drag->imb) {
308                         x= cursorx - drag->sx/2;
309                         y= cursory - drag->sy/2;
310                         
311                         if(rect)
312                                 drag_rect_minmax(rect, x, y, x+drag->sx, y+drag->sy);
313                         else {
314                                 glColor4f(1.0, 1.0, 1.0, 0.65); /* this blends texture */
315                                 glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_UNSIGNED_BYTE, drag->imb->rect, drag->scale, drag->scale);
316                         }
317                 }
318                 else {
319                         x= cursorx - 8;
320                         y= cursory - 2;
321                         
322                         /* icons assumed to be 16 pixels */
323                         if(rect)
324                                 drag_rect_minmax(rect, x, y, x+16, y+16);
325                         else
326                                 UI_icon_draw_aspect(x, y, drag->icon, 1.0, 0.8);
327                 }
328                 
329                 /* item name */
330                 if(drag->imb) {
331                         x= cursorx - drag->sx/2;
332                         y= cursory - drag->sy/2 - 16;
333                 }
334                 else {
335                         x= cursorx + 10;
336                         y= cursory + 1;
337                 }
338                 
339                 if(rect) {
340                         int w=  UI_GetStringWidth(wm_drag_name(drag));
341                         drag_rect_minmax(rect, x, y, x+w, y+16);
342                 }
343                 else {
344                         glColor4ub(255, 255, 255, 255);
345                         UI_DrawString(x, y, wm_drag_name(drag));
346                 }
347                 
348                 /* operator name with roundbox */
349                 if(drag->opname[0]) {
350                         if(drag->imb) {
351                                 x= cursorx - drag->sx/2;
352                                 y= cursory + drag->sy/2 + 4;
353                         }
354                         else {
355                                 x= cursorx - 8;
356                                 y= cursory + 16;
357                         }
358                         
359                         if(rect) {
360                                 int w=  UI_GetStringWidth(wm_drag_name(drag));
361                                 drag_rect_minmax(rect, x, y, x+w, y+16);
362                         }
363                         else 
364                                 wm_drop_operator_draw(drag->opname, x, y);
365                         
366                 }
367         }
368         glDisable(GL_BLEND);
369 }