Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/windowmanager/intern/wm_dragdrop.c')
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.c370
1 files changed, 370 insertions, 0 deletions
diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c
new file mode 100644
index 00000000000..d976c42bb8c
--- /dev/null
+++ b/source/blender/windowmanager/intern/wm_dragdrop.c
@@ -0,0 +1,370 @@
+/**
+ * $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) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "string.h"
+
+#include "DNA_windowmanager_types.h"
+#include "DNA_screen_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "BKE_blender.h"
+#include "BKE_context.h"
+#include "BKE_idprop.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_screen.h"
+#include "BKE_global.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "UI_interface.h"
+#include "UI_interface_icons.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+#include "wm_event_system.h"
+#include "wm.h"
+
+#include "RNA_types.h"
+
+/* ****************************************************** */
+
+static ListBase dropboxes= {NULL, NULL};
+
+/* drop box maps are stored global for now */
+/* these are part of blender's UI/space specs, and not like keymaps */
+/* when editors become configurable, they can add own dropbox definitions */
+
+typedef struct wmDropBoxMap {
+ struct wmDropBoxMap *next, *prev;
+
+ ListBase dropboxes;
+ short spaceid, regionid;
+ char idname[KMAP_MAX_NAME];
+
+} wmDropBoxMap;
+
+ListBase *WM_dropboxmap_find(char *idname, int spaceid, int regionid)
+{
+ wmDropBoxMap *dm;
+
+ for(dm= dropboxes.first; dm; dm= dm->next)
+ if(dm->spaceid==spaceid && dm->regionid==regionid)
+ if(0==strncmp(idname, dm->idname, KMAP_MAX_NAME))
+ return &dm->dropboxes;
+
+ dm= MEM_callocN(sizeof(struct wmDropBoxMap), "dropmap list");
+ BLI_strncpy(dm->idname, idname, KMAP_MAX_NAME);
+ dm->spaceid= spaceid;
+ dm->regionid= regionid;
+ BLI_addtail(&dropboxes, dm);
+
+ return &dm->dropboxes;
+}
+
+
+
+wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(bContext *, wmDrag *, wmEvent *),
+ void (*copy)(wmDrag *, wmDropBox *))
+{
+ wmDropBox *drop= MEM_callocN(sizeof(wmDropBox), "wmDropBox");
+
+ drop->poll= poll;
+ drop->copy= copy;
+ drop->ot= WM_operatortype_find(idname, 0);
+
+ if(drop->ot==NULL) {
+ MEM_freeN(drop);
+ printf("Error: dropbox with unknown operator: %s\n", idname);
+ return NULL;
+ }
+ WM_operator_properties_alloc(&(drop->ptr), &(drop->properties), idname);
+
+ BLI_addtail(lb, drop);
+
+ return drop;
+}
+
+void wm_dropbox_free(void)
+{
+ wmDropBoxMap *dm;
+
+ for(dm= dropboxes.first; dm; dm= dm->next) {
+ wmDropBox *drop;
+
+ for(drop= dm->dropboxes.first; drop; drop= drop->next) {
+ if(drop->ptr) {
+ WM_operator_properties_free(drop->ptr);
+ MEM_freeN(drop->ptr);
+ }
+ }
+ BLI_freelistN(&dm->dropboxes);
+ }
+
+ BLI_freelistN(&dropboxes);
+}
+
+/* *********************************** */
+
+/* note that the pointer should be valid allocated and not on stack */
+wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value)
+{
+ wmWindowManager *wm= CTX_wm_manager(C);
+ wmDrag *drag= MEM_callocN(sizeof(struct wmDrag), "new drag");
+
+ /* keep track of future multitouch drag too, add a mousepointer id or so */
+ /* if multiple drags are added, they're drawn as list */
+
+ BLI_addtail(&wm->drags, drag);
+ drag->icon= icon;
+ drag->type= type;
+ if(type==WM_DRAG_PATH)
+ BLI_strncpy(drag->path, poin, FILE_MAX);
+ else
+ drag->poin= poin;
+ drag->value= value;
+
+ return drag;
+}
+
+void WM_event_drag_image(wmDrag *drag, ImBuf *imb, float scale, int sx, int sy)
+{
+ drag->imb= imb;
+ drag->scale= scale;
+ drag->sx= sx;
+ drag->sy= sy;
+}
+
+
+static char *dropbox_active(bContext *C, ListBase *handlers, wmDrag *drag, wmEvent *event)
+{
+ wmEventHandler *handler= handlers->first;
+ for(; handler; handler= handler->next) {
+ if(handler->dropboxes) {
+ wmDropBox *drop= handler->dropboxes->first;
+ for(; drop; drop= drop->next) {
+ if(drop->poll(C, drag, event))
+ return drop->ot->name;
+ }
+ }
+ }
+ return NULL;
+}
+
+/* return active operator name when mouse is in box */
+static char *wm_dropbox_active(bContext *C, wmDrag *drag, wmEvent *event)
+{
+ wmWindow *win= CTX_wm_window(C);
+ ScrArea *sa= CTX_wm_area(C);
+ ARegion *ar= CTX_wm_region(C);
+ char *name;
+
+ name= dropbox_active(C, &win->handlers, drag, event);
+ if(name) return name;
+
+ name= dropbox_active(C, &sa->handlers, drag, event);
+ if(name) return name;
+
+ name= dropbox_active(C, &ar->handlers, drag, event);
+ if(name) return name;
+
+ return NULL;
+}
+
+
+static void wm_drop_operator_options(bContext *C, wmDrag *drag, wmEvent *event)
+{
+ wmWindow *win= CTX_wm_window(C);
+
+ /* for multiwin drags, we only do this if mouse inside */
+ if(event->x<0 || event->y<0 || event->x>win->sizex || event->y>win->sizey)
+ return;
+
+ drag->opname[0]= 0;
+
+ /* check buttons (XXX todo rna and value) */
+ if( UI_but_active_drop_name(C) ) {
+ strcpy(drag->opname, "Paste name");
+ }
+ else {
+ char *opname= wm_dropbox_active(C, drag, event);
+
+ if(opname) {
+ BLI_strncpy(drag->opname, opname, FILE_MAX);
+ // WM_cursor_modal(win, CURSOR_COPY);
+ }
+ // else
+ // WM_cursor_restore(win);
+ /* unsure about cursor type, feels to be too much */
+ }
+}
+
+/* called in inner handler loop, region context */
+void wm_drags_check_ops(bContext *C, wmEvent *event)
+{
+ wmWindowManager *wm= CTX_wm_manager(C);
+ wmDrag *drag;
+
+ for(drag= wm->drags.first; drag; drag= drag->next) {
+ wm_drop_operator_options(C, drag, event);
+ }
+}
+
+/* ************** draw ***************** */
+
+static void wm_drop_operator_draw(char *name, int x, int y)
+{
+ int width= UI_GetStringWidth(name);
+
+ glColor4ub(0, 0, 0, 128);
+
+ uiSetRoundBox(15);
+ uiRoundBox(x, y, x + width + 8, y + 15, 7);
+
+ glColor4ub(255, 255, 255, 255);
+ UI_DrawString(x+4, y+4, name);
+}
+
+static char *wm_drag_name(wmDrag *drag)
+{
+ switch(drag->type) {
+ case WM_DRAG_ID:
+ {
+ ID *id= (ID *)drag->poin;
+ return id->name+2;
+ }
+ case WM_DRAG_PATH:
+ return drag->path;
+ case WM_DRAG_NAME:
+ return (char *)drag->path;
+ }
+ return "";
+}
+
+static void drag_rect_minmax(rcti *rect, int x1, int y1, int x2, int y2)
+{
+ if(rect->xmin > x1)
+ rect->xmin= x1;
+ if(rect->xmax < x2)
+ rect->xmax= x2;
+ if(rect->ymin > y1)
+ rect->ymin= y1;
+ if(rect->ymax < y2)
+ rect->ymax= y2;
+}
+
+/* called in wm_draw.c */
+/* if rect set, do not draw */
+void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect)
+{
+ wmWindowManager *wm= CTX_wm_manager(C);
+ wmDrag *drag;
+ int cursorx, cursory, x, y;
+
+ cursorx= win->eventstate->x;
+ cursory= win->eventstate->y;
+ if(rect) {
+ rect->xmin= rect->xmax= cursorx;
+ rect->ymin= rect->ymax= cursory;
+ }
+
+ /* XXX todo, multiline drag draws... but maybe not, more types mixed wont work well */
+ glEnable(GL_BLEND);
+ for(drag= wm->drags.first; drag; drag= drag->next) {
+
+ /* image or icon */
+ if(drag->imb) {
+ x= cursorx - drag->sx/2;
+ y= cursory - drag->sy/2;
+
+ if(rect)
+ drag_rect_minmax(rect, x, y, x+drag->sx, y+drag->sy);
+ else {
+ glColor4f(1.0, 1.0, 1.0, 0.65); /* this blends texture */
+ glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_UNSIGNED_BYTE, drag->imb->rect, drag->scale, drag->scale);
+ }
+ }
+ else {
+ x= cursorx - 8;
+ y= cursory - 2;
+
+ /* icons assumed to be 16 pixels */
+ if(rect)
+ drag_rect_minmax(rect, x, y, x+16, y+16);
+ else
+ UI_icon_draw_aspect(x, y, drag->icon, 1.0, 0.8);
+ }
+
+ /* item name */
+ if(drag->imb) {
+ x= cursorx - drag->sx/2;
+ y= cursory - drag->sy/2 - 16;
+ }
+ else {
+ x= cursorx + 10;
+ y= cursory + 1;
+ }
+
+ if(rect) {
+ int w= UI_GetStringWidth(wm_drag_name(drag));
+ drag_rect_minmax(rect, x, y, x+w, y+16);
+ }
+ else {
+ glColor4ub(255, 255, 255, 255);
+ UI_DrawString(x, y, wm_drag_name(drag));
+ }
+
+ /* operator name with roundbox */
+ if(drag->opname[0]) {
+ if(drag->imb) {
+ x= cursorx - drag->sx/2;
+ y= cursory + drag->sy/2 + 4;
+ }
+ else {
+ x= cursorx - 8;
+ y= cursory + 16;
+ }
+
+ if(rect) {
+ int w= UI_GetStringWidth(wm_drag_name(drag));
+ drag_rect_minmax(rect, x, y, x+w, y+16);
+ }
+ else
+ wm_drop_operator_draw(drag->opname, x, y);
+
+ }
+ }
+ glDisable(GL_BLEND);
+}