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/editors/space_outliner/outliner_edit.c')
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c122
1 files changed, 86 insertions, 36 deletions
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 842502ec82f..60b5dbdfc50 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -140,59 +140,108 @@ void OUTLINER_OT_highlight_update(wmOperatorType *ot)
/* Toggle Open/Closed ------------------------------------------- */
-static int do_outliner_item_openclose(
- bContext *C, SpaceOutliner *soops, TreeElement *te, const bool all, const float mval[2])
+/* Open or close a tree element, optionally toggling all children recursively */
+void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all)
{
+ TreeStoreElem *tselem = TREESTORE(te);
- if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) {
- TreeStoreElem *tselem = TREESTORE(te);
+ if (open) {
+ tselem->flag &= ~TSE_CLOSED;
+ }
+ else {
+ tselem->flag |= TSE_CLOSED;
+ }
- /* all below close/open? */
- if (all) {
- tselem->flag &= ~TSE_CLOSED;
- outliner_flag_set(
- &te->subtree, TSE_CLOSED, !outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1));
- }
- else {
- if (tselem->flag & TSE_CLOSED) {
- tselem->flag &= ~TSE_CLOSED;
- }
- else {
- tselem->flag |= TSE_CLOSED;
+ if (toggle_all) {
+ outliner_flag_set(&te->subtree, TSE_CLOSED, !open);
+ }
+}
+
+typedef struct OpenCloseData {
+ TreeStoreElem *prev_tselem;
+ bool open;
+ int x_location;
+} OpenCloseData;
+
+static int outliner_item_openclose_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ ARegion *ar = CTX_wm_region(C);
+ SpaceOutliner *soops = CTX_wm_space_outliner(C);
+
+ float view_mval[2];
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+
+ if (event->type == MOUSEMOVE) {
+ TreeElement *te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
+
+ OpenCloseData *data = (OpenCloseData *)op->customdata;
+
+ /* Only openclose if mouse is not over the previously toggled element */
+ if (te && TREESTORE(te) != data->prev_tselem) {
+
+ /* Only toggle openclose on the same level as the first clicked element */
+ if (te->xs == data->x_location) {
+ outliner_item_openclose(te, data->open, false);
+ ED_region_tag_redraw(ar);
}
}
- return 1;
+ if (te) {
+ data->prev_tselem = TREESTORE(te);
+ }
+ else {
+ data->prev_tselem = NULL;
+ }
}
+ else if (event->val == KM_RELEASE) {
+ MEM_freeN(op->customdata);
- for (te = te->subtree.first; te; te = te->next) {
- if (do_outliner_item_openclose(C, soops, te, all, mval)) {
- return 1;
- }
+ return OPERATOR_FINISHED;
}
- return 0;
+
+ return OPERATOR_RUNNING_MODAL;
}
-/* event can enterkey, then it opens/closes */
-static int outliner_item_openclose(bContext *C, wmOperator *op, const wmEvent *event)
+static int outliner_item_openclose_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ARegion *ar = CTX_wm_region(C);
SpaceOutliner *soops = CTX_wm_space_outliner(C);
- TreeElement *te;
- float fmval[2];
- const bool all = RNA_boolean_get(op->ptr, "all");
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
+ const bool toggle_all = RNA_boolean_get(op->ptr, "all");
- for (te = soops->tree.first; te; te = te->next) {
- if (do_outliner_item_openclose(C, soops, te, all, fmval)) {
- break;
+ float view_mval[2];
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &view_mval[0], &view_mval[1]);
+
+ TreeElement *te = outliner_find_item_at_y(soops, &soops->tree, view_mval[1]);
+
+ if (te && outliner_item_is_co_within_close_toggle(te, view_mval[0])) {
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ const bool open = (tselem->flag & TSE_CLOSED) ||
+ (toggle_all && (outliner_flag_is_any_test(&te->subtree, TSE_CLOSED, 1)));
+
+ outliner_item_openclose(te, open, toggle_all);
+ ED_region_tag_redraw(ar);
+
+ /* Only toggle once for single click toggling */
+ if (event->type == LEFTMOUSE) {
+ return OPERATOR_FINISHED;
}
- }
- ED_region_tag_redraw(ar);
+ /* Store last expanded tselem and x coordinate of disclosure triangle */
+ OpenCloseData *toggle_data = MEM_callocN(sizeof(OpenCloseData), "open_close_data");
+ toggle_data->prev_tselem = tselem;
+ toggle_data->open = open;
+ toggle_data->x_location = te->xs;
- return OPERATOR_FINISHED;
+ /* Store the first clicked on element */
+ op->customdata = toggle_data;
+
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
}
void OUTLINER_OT_item_openclose(wmOperatorType *ot)
@@ -201,11 +250,12 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot)
ot->idname = "OUTLINER_OT_item_openclose";
ot->description = "Toggle whether item under cursor is enabled or closed";
- ot->invoke = outliner_item_openclose;
+ ot->invoke = outliner_item_openclose_invoke;
+ ot->modal = outliner_item_openclose_modal;
ot->poll = ED_operator_outliner_active;
- RNA_def_boolean(ot->srna, "all", 1, "All", "Close or open all items");
+ RNA_def_boolean(ot->srna, "all", false, "All", "Close or open all items");
}
/* -------------------------------------------------------------------- */