Commit: e519bfea37212cbec3668978db73bb647754225a
Author: Julian Eisel
Date:   Mon Apr 16 19:09:14 2018 +0200
Branches: temp-tab_drag_drop
https://developer.blender.org/rBe519bfea37212cbec3668978db73bb647754225a

Initial working drag & drop for workspace tabs

Had to do quite some changes to get this to work, mainly because we'd
want to have the customized order written to files. Also wanted to use
existing wmDrag and wmDropBox code but modify it for our needs.
And of course, this should not just work for a single case, code should
be applicable to other areas as well.

Note that file read/write is not working (yet), neither is versioning, region
copying and deleting workspaces working.
Code is also very WIP, much of it is placed in temporary places and
such.

Once the basics are done, we can add nicer feeback during drag & drop.

===================================================================

M       source/blender/blenkernel/BKE_screen.h
M       source/blender/blenkernel/intern/screen.c
M       source/blender/editors/include/UI_interface.h
M       source/blender/editors/interface/CMakeLists.txt
M       source/blender/editors/interface/interface.c
M       source/blender/editors/interface/interface_handlers.c
A       source/blender/editors/interface/interface_init_exit.c
M       source/blender/editors/interface/interface_intern.h
M       source/blender/editors/interface/interface_ops.c
M       source/blender/editors/interface/interface_templates.c
M       source/blender/editors/screen/workspace_edit.c
M       source/blender/makesdna/DNA_screen_types.h
M       source/blender/windowmanager/WM_api.h
M       source/blender/windowmanager/WM_types.h
M       source/blender/windowmanager/intern/wm.c
M       source/blender/windowmanager/intern/wm_dragdrop.c
M       source/blender/windowmanager/intern/wm_event_system.c
M       source/blender/windowmanager/intern/wm_window.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_screen.h 
b/source/blender/blenkernel/BKE_screen.h
index 774c1c8be12..3fee98bd60f 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -58,6 +58,9 @@ struct wmWindowManager;
 struct WorkSpace;
 struct GPUFXSettings;
 struct wmMsgBus;
+struct uiBlock;
+struct uiButtonGroup;
+struct uiButtonGroupItemInfo;
 
 #include "BLI_compiler_attrs.h"
 
@@ -237,6 +240,18 @@ typedef struct uiListType {
        ExtensionRNA ext;
 } uiListType;
 
+typedef bool (*uiButtonGroupIdentifyFunc)(struct uiButtonGroup *, void *);
+typedef void (*uiButtonGroupItemsFunc)(struct uiButtonGroup *, void *, 
ListBase *);
+typedef void (*uiButtonGroupItemDrawFunc)(struct uiBlock *, void *, struct 
uiButtonGroupItemInfo *);
+
+typedef struct uiButtonGroupType {
+       const char *idname;
+
+       uiButtonGroupIdentifyFunc identify;
+       uiButtonGroupItemsFunc items;
+       uiButtonGroupItemDrawFunc item_draw;
+} uiButtonGroupType;
+
 /* header types */
 
 typedef struct HeaderType {
diff --git a/source/blender/blenkernel/intern/screen.c 
b/source/blender/blenkernel/intern/screen.c
index 35055a59243..cea9366b907 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -378,10 +378,16 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar)
                }
        }
 
+       for (uiButtonGroup *group = ar->button_groups.first; group; group = 
group->next) {
+               BLI_freelistN(&group->items);
+               MEM_SAFE_FREE(group->reordered_indices);
+       }
+
        if (ar->manipulator_map != NULL) {
                region_free_manipulatormap_callback(ar->manipulator_map);
        }
 
+       BLI_freelistN(&ar->button_groups);
        BLI_freelistN(&ar->ui_lists);
        BLI_freelistN(&ar->ui_previews);
        BLI_freelistN(&ar->panels_category);
diff --git a/source/blender/editors/include/UI_interface.h 
b/source/blender/editors/include/UI_interface.h
index ed6a1de83c5..414f78a9021 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -74,6 +74,7 @@ struct wmDrag;
 struct wmEvent;
 struct wmManipulator;
 struct wmMsgBus;
+struct uiButtonGroup;
 
 typedef struct uiBut uiBut;
 typedef struct uiBlock uiBlock;
@@ -512,6 +513,7 @@ void    UI_but_drag_set_rna(uiBut *but, struct PointerRNA 
*ptr);
 void    UI_but_drag_set_path(uiBut *but, const char *path, const bool 
use_free);
 void    UI_but_drag_set_name(uiBut *but, const char *name);
 void    UI_but_drag_set_value(uiBut *but);
+void    UI_but_drag_set_reorder(uiBut *but);
 void    UI_but_drag_set_image(
                 uiBut *but, const char *path, int icon, struct ImBuf *ima, 
float scale, const bool use_free);
 
@@ -625,6 +627,7 @@ enum {
        BUT_GET_RNA_LABEL,
        BUT_GET_RNAENUM_LABEL,
        BUT_GET_RNA_LABEL_CONTEXT, /* Context specified in CTX_XXX_ macros are 
just unreachable! */
+       BUT_GET_VALUE,
        BUT_GET_TIP,
        BUT_GET_RNA_TIP,
        BUT_GET_RNAENUM_TIP,
@@ -778,6 +781,9 @@ void UI_but_focus_on_enter_event(struct wmWindow *win, 
uiBut *but);
 
 void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN);
 
+void UI_block_button_group_begin(uiBlock *block, struct uiButtonGroup *group);
+void UI_block_button_group_end(uiBlock *block);
+
 /* Autocomplete
  *
  * Tab complete helper functions, for use in uiButCompleteFunc callbacks.
diff --git a/source/blender/editors/interface/CMakeLists.txt 
b/source/blender/editors/interface/CMakeLists.txt
index c023816b52c..2302b6f9d5b 100644
--- a/source/blender/editors/interface/CMakeLists.txt
+++ b/source/blender/editors/interface/CMakeLists.txt
@@ -52,6 +52,7 @@ set(SRC
        interface_eyedropper_driver.c
        interface_handlers.c
        interface_icons.c
+       interface_init_exit.c
        interface_layout.c
        interface_ops.c
        interface_panel.c
diff --git a/source/blender/editors/interface/interface.c 
b/source/blender/editors/interface/interface.c
index bb33956a01d..c0c55270141 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -507,6 +507,7 @@ static int ui_but_calc_float_precision(uiBut *but, double 
value)
        return UI_calc_float_precision(prec, value);
 }
 
+
 /* ************** LINK LINE DRAWING  ************* */
 
 /* link line drawing is not part of buttons or theme.. so we stick with it 
here */
@@ -3369,8 +3370,12 @@ static uiBut *ui_def_but(
 
        BLI_addtail(&block->buttons, but);
        
-       if (block->curlayout)
+       if (block->curlayout) {
                ui_layout_add_but(block->curlayout, but);
+       }
+       if (block->current_group) {
+               but->group = block->current_group;
+       }
 
 #ifdef WITH_PYTHON
        /* if the 'UI_OT_editsource' is running, extract the source info from 
the button  */
@@ -4239,6 +4244,12 @@ void UI_but_drag_set_value(uiBut *but)
        but->dragtype = WM_DRAG_VALUE;
 }
 
+void UI_but_drag_set_reorder(uiBut *but)
+{
+       but->dragtype = WM_DRAG_BUT_REORDER;
+       but->dragpoin = but; /* Assign the button itself, later wmDrag can 
access it then. */
+}
+
 void UI_but_drag_set_image(uiBut *but, const char *path, int icon, struct 
ImBuf *imb, float scale, const bool use_free)
 {
        but->dragtype = WM_DRAG_PATH;
@@ -4658,21 +4669,23 @@ void UI_but_string_info_get(bContext *C, uiBut *but, 
...)
                int type = si->type;
                char *tmp = NULL;
 
-               if (type == BUT_GET_LABEL) {
-                       if (but->str) {
+               if (ELEM(type, BUT_GET_LABEL, BUT_GET_VALUE)) {
+                       char *but_str = (type == BUT_GET_LABEL) ? but->str : 
but->drawstr;
+
+                       if (but_str && but_str[0]) {
                                const char *str_sep;
                                size_t str_len;
 
                                if ((but->flag & UI_BUT_HAS_SEP_CHAR) &&
-                                   (str_sep = strrchr(but->str, UI_SEP_CHAR)))
+                                   (str_sep = strrchr(but_str, UI_SEP_CHAR)))
                                {
-                                       str_len = (str_sep - but->str);
+                                       str_len = (str_sep - but_str);
                                }
                                else {
-                                       str_len = strlen(but->str);
+                                       str_len = strlen(but_str);
                                }
 
-                               tmp = BLI_strdupn(but->str, str_len);
+                               tmp = BLI_strdupn(but_str, str_len);
                        }
                        else {
                                type = BUT_GET_RNA_LABEL;  /* Fail-safe 
solution... */
@@ -4833,11 +4846,22 @@ void UI_but_string_info_get(bContext *C, uiBut *but, 
...)
        }
 }
 
+void UI_block_button_group_begin(uiBlock *block, uiButtonGroup *group)
+{
+       BLI_assert(block->current_group == NULL);
+       block->current_group = group;
+}
+void UI_block_button_group_end(uiBlock *block)
+{
+       block->current_group = NULL;
+}
+
 /* Program Init/Exit */
 
 void UI_init(void)
 {
        ui_resources_init();
+       ui_init_button_group_types();
 }
 
 /* after reading userdef file */
@@ -4857,5 +4881,6 @@ void UI_exit(void)
 {
        ui_resources_free();
        ui_but_clipboard_free();
+       ui_exit_button_group_types();
 }
 
diff --git a/source/blender/editors/interface/interface_handlers.c 
b/source/blender/editors/interface/interface_handlers.c
index 81f579732cf..210ce28ca33 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -1703,6 +1703,12 @@ static bool ui_but_contains_point_px_icon(uiBut *but, 
ARegion *ar, const wmEvent
        return BLI_rcti_isect_pt(&rect, x, y);
 }
 
+static void ui_but_drop_handler(wmDrag *drag, const wmEvent *event);
+struct uiButDrag {
+       uiBut *dragged_but;
+       uiButStore *but_store;
+       int drag_start_xy[2];
+};
 static bool ui_but_drag_init(
         bContext *C, uiBut *but,
         uiHandleButtonData *data, const wmEvent *event)
@@ -1776,6 +1782,22 @@ static bool ui_but_drag_init(
                                return false;
                        }
                }
+               /* Allow reordering buttons via drag & drop */
+               else if (but->group) {
+                       ListBase *dropbox_list = WM_dropboxmap_find("User 
Interface", 0, 0);
+                       struct uiButDrag *but_drag = 
MEM_mallocN(sizeof(*but_drag), "uiButDrag");
+
+                       but_drag->dragged_but = but;
+                       but_drag->but_store = UI_butstore_create(but->block);
+                       copy_v2_v2_int(but_drag->drag_start_xy, &event->x);
+
+                       UI_butstore_register(but_drag->but_store, 
&but_drag->dragged_but);
+                       WM_event_start_drag(C, but->icon, but->dragtype, 
but_drag, ui_but_value_get(but),
+                                           WM_DRAG_FREE_DATA | WM_DRAG_NOP);
+                       WM_dropbox_add_custom_drop_handler(dropbox_list, 
ui_but_drop_handler);
+
+                       return true;
+               }
                else {
                        wmDrag *drag = WM_event_start_drag(
                                C, but->icon, but->dragtype, but->dragpoin,
@@ -2220,6 +2242,98 @@ static void ui_apply_but(bContext *C, uiBlock *block, 
uiBut *but, uiHandleButton
 
 /* ******************* drop event ********************  */
 
+enum ReinsertPosition {
+       BUT_REINSERT_BEFORE,
+       BUT_REINSERT_AFTER,
+};
+static void ui_but_find_to_reinsert_next_to(
+        const wmEvent *event, const uiBut *dragged_but, const int 
drag_start_xy[2],
+        uiBut **r_but, enum ReinsertPosition *r_reinsert_position)
+{
+       uiBut *but_candidate = NULL;
+
+       if (event->x < drag_start_xy[0]) {
+               for (uiBut *but_iter = dragged_but->prev; but_iter; but_iter = 
but_iter->prev) {
+                       if ((but_iter->group == dragged_but->group) && 
(event->x < BLI_rctf_cent_x(&but_iter->rect))) {
+                               but_candidate = but_iter;
+                       }
+               }
+
+               *r_reinsert_position = BUT_REINSERT_BEFORE;
+       }
+       else {
+               for (uiBut *but_iter = dragged_but->next; but_iter; but_iter = 
but_iter->next) {
+                       if ((but_iter->group == dragged_but->group) && 
(event->x > BLI_rctf_cent_x(&but_iter->rect))) {
+                               but_candidate = but_iter;
+                       }
+               }
+
+               *r_reinsert_position = BUT_REINSERT_AFTER;
+       }
+
+       *r_but = but_candidate;
+}
+
+static uiButtonGroupItemInfo *ui_block_button_group_find_item_from_data(
+        const uiButtonGroup *group,
+        const void *data)
+{
+       return BLI_findptr(&group->items, data, offsetof(uiButtonGroupItemInfo, 
data));
+}
+
+static void ui_but_drop_handler(wmDrag *drag, const wmEvent *event)
+{
+       if (drag->type == WM_DRAG_BUT_REORDER) {
+               struct uiButDrag *but_drag = drag->poin;
+               uiBut *dragged_but = but_drag->dragged_but;
+               uiBut *drop_neighbor;
+               enum ReinsertPosition reinsert_pos;
+
+               ui_but_find_to_reinsert_next_to(event, dragged_but, 
but_drag->drag_start_xy,
+                                               &drop_neighbor, &reinsert_pos);
+               if (drop_neighbor) {
+                       uiButtonGroup *group = dragged_but->group;
+                       uiButtonGroupItemInfo *dragged_item = 
ui_block_button_group_find_item_from_data(
+                                                                 group, 
dragged_but->custom_data);
+                       uiButtonGroupItemInfo *drop_neighbor_item = 
ui_block_button_group_find_item_from_data(
+                              

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to