4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
20 * The Original Code is Copyright (C) 2010 Blender Foundation.
21 * All rights reserved.
24 * Contributor(s): Blender Foundation
26 * ***** END GPL LICENSE BLOCK *****
31 #include "DNA_windowmanager_types.h"
32 #include "DNA_screen_types.h"
34 #include "MEM_guardedalloc.h"
36 #include "BLI_blenlib.h"
39 #include "BIF_glutil.h"
41 #include "BKE_blender.h"
42 #include "BKE_context.h"
43 #include "BKE_idprop.h"
44 #include "BKE_library.h"
46 #include "BKE_screen.h"
47 #include "BKE_global.h"
49 #include "IMB_imbuf_types.h"
50 #include "IMB_imbuf.h"
52 #include "UI_interface.h"
53 #include "UI_interface_icons.h"
57 #include "wm_event_system.h"
60 #include "RNA_types.h"
62 /* ****************************************************** */
64 static ListBase dropboxes= {NULL, NULL};
66 /* drop box maps are stored global for now */
67 /* these are part of blender's UI/space specs, and not like keymaps */
68 /* when editors become configurable, they can add own dropbox definitions */
70 typedef struct wmDropBoxMap {
71 struct wmDropBoxMap *next, *prev;
74 short spaceid, regionid;
75 char idname[KMAP_MAX_NAME];
79 ListBase *WM_dropboxmap_find(char *idname, int spaceid, int regionid)
83 for(dm= dropboxes.first; dm; dm= dm->next)
84 if(dm->spaceid==spaceid && dm->regionid==regionid)
85 if(0==strncmp(idname, dm->idname, KMAP_MAX_NAME))
86 return &dm->dropboxes;
88 dm= MEM_callocN(sizeof(struct wmDropBoxMap), "dropmap list");
89 BLI_strncpy(dm->idname, idname, KMAP_MAX_NAME);
91 dm->regionid= regionid;
92 BLI_addtail(&dropboxes, dm);
94 return &dm->dropboxes;
99 wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(bContext *, wmDrag *, wmEvent *),
100 void (*copy)(wmDrag *, wmDropBox *))
102 wmDropBox *drop= MEM_callocN(sizeof(wmDropBox), "wmDropBox");
106 drop->ot= WM_operatortype_find(idname, 0);
110 printf("Error: dropbox with unknown operator: %s\n", idname);
113 WM_operator_properties_alloc(&(drop->ptr), &(drop->properties), idname);
115 BLI_addtail(lb, drop);
120 void wm_dropbox_free(void)
124 for(dm= dropboxes.first; dm; dm= dm->next) {
127 for(drop= dm->dropboxes.first; drop; drop= drop->next) {
129 WM_operator_properties_free(drop->ptr);
130 MEM_freeN(drop->ptr);
133 BLI_freelistN(&dm->dropboxes);
136 BLI_freelistN(&dropboxes);
139 /* *********************************** */
141 /* note that the pointer should be valid allocated and not on stack */
142 wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value)
144 wmWindowManager *wm= CTX_wm_manager(C);
145 wmDrag *drag= MEM_callocN(sizeof(struct wmDrag), "new drag");
147 /* keep track of future multitouch drag too, add a mousepointer id or so */
148 /* if multiple drags are added, they're drawn as list */
150 BLI_addtail(&wm->drags, drag);
153 if(type==WM_DRAG_PATH)
154 BLI_strncpy(drag->path, poin, FILE_MAX);
162 void WM_event_drag_image(wmDrag *drag, ImBuf *imb, float scale, int sx, int sy)
171 static char *dropbox_active(bContext *C, ListBase *handlers, wmDrag *drag, wmEvent *event)
173 wmEventHandler *handler= handlers->first;
174 for(; handler; handler= handler->next) {
175 if(handler->dropboxes) {
176 wmDropBox *drop= handler->dropboxes->first;
177 for(; drop; drop= drop->next) {
178 if(drop->poll(C, drag, event))
179 return drop->ot->name;
186 /* return active operator name when mouse is in box */
187 static char *wm_dropbox_active(bContext *C, wmDrag *drag, wmEvent *event)
189 wmWindow *win= CTX_wm_window(C);
190 ScrArea *sa= CTX_wm_area(C);
191 ARegion *ar= CTX_wm_region(C);
194 name= dropbox_active(C, &win->handlers, drag, event);
195 if(name) return name;
197 name= dropbox_active(C, &sa->handlers, drag, event);
198 if(name) return name;
200 name= dropbox_active(C, &ar->handlers, drag, event);
201 if(name) return name;
207 static void wm_drop_operator_options(bContext *C, wmDrag *drag, wmEvent *event)
209 wmWindow *win= CTX_wm_window(C);
211 /* for multiwin drags, we only do this if mouse inside */
212 if(event->x<0 || event->y<0 || event->x>win->sizex || event->y>win->sizey)
217 /* check buttons (XXX todo rna and value) */
218 if( UI_but_active_drop_name(C) ) {
219 strcpy(drag->opname, "Paste name");
222 char *opname= wm_dropbox_active(C, drag, event);
225 BLI_strncpy(drag->opname, opname, FILE_MAX);
226 // WM_cursor_modal(win, CURSOR_COPY);
229 // WM_cursor_restore(win);
230 /* unsure about cursor type, feels to be too much */
234 /* called in inner handler loop, region context */
235 void wm_drags_check_ops(bContext *C, wmEvent *event)
237 wmWindowManager *wm= CTX_wm_manager(C);
240 for(drag= wm->drags.first; drag; drag= drag->next) {
241 wm_drop_operator_options(C, drag, event);
245 /* ************** draw ***************** */
247 static void wm_drop_operator_draw(char *name, int x, int y)
249 int width= UI_GetStringWidth(name);
251 glColor4ub(0, 0, 0, 128);
254 uiRoundBox(x, y, x + width + 8, y + 15, 7);
256 glColor4ub(255, 255, 255, 255);
257 UI_DrawString(x+4, y+4, name);
260 static char *wm_drag_name(wmDrag *drag)
265 ID *id= (ID *)drag->poin;
271 return (char *)drag->path;
276 static void drag_rect_minmax(rcti *rect, int x1, int y1, int x2, int y2)
288 /* called in wm_draw.c */
289 /* if rect set, do not draw */
290 void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
292 wmWindowManager *wm= CTX_wm_manager(C);
294 int cursorx, cursory, x, y;
296 cursorx= win->eventstate->x;
297 cursory= win->eventstate->y;
299 rect->xmin= rect->xmax= cursorx;
300 rect->ymin= rect->ymax= cursory;
303 /* XXX todo, multiline drag draws... but maybe not, more types mixed wont work well */
305 for(drag= wm->drags.first; drag; drag= drag->next) {
309 x= cursorx - drag->sx/2;
310 y= cursory - drag->sy/2;
313 drag_rect_minmax(rect, x, y, x+drag->sx, y+drag->sy);
315 glColor4f(1.0, 1.0, 1.0, 0.65); /* this blends texture */
316 glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_UNSIGNED_BYTE, drag->imb->rect, drag->scale, drag->scale);
323 /* icons assumed to be 16 pixels */
325 drag_rect_minmax(rect, x, y, x+16, y+16);
327 UI_icon_draw_aspect(x, y, drag->icon, 1.0, 0.8);
332 x= cursorx - drag->sx/2;
333 y= cursory - drag->sy/2 - 16;
341 int w= UI_GetStringWidth(wm_drag_name(drag));
342 drag_rect_minmax(rect, x, y, x+w, y+16);
345 glColor4ub(255, 255, 255, 255);
346 UI_DrawString(x, y, wm_drag_name(drag));
349 /* operator name with roundbox */
350 if(drag->opname[0]) {
352 x= cursorx - drag->sx/2;
353 y= cursory + drag->sy/2 + 4;
361 int w= UI_GetStringWidth(wm_drag_name(drag));
362 drag_rect_minmax(rect, x, y, x+w, y+16);
365 wm_drop_operator_draw(drag->opname, x, y);