浏览代码

MultiSelect: Box-Select: minor refactor, tidying up.

ocornut 1 年之前
父节点
当前提交
65ebc0513b
共有 1 个文件被更改,包括 53 次插入41 次删除
  1. 53 41
      imgui_widgets.cpp

+ 53 - 41
imgui_widgets.cpp

@@ -7131,13 +7131,18 @@ void ImGui::DebugNodeTypingSelectState(ImGuiTypingSelectState* data)
 // [SECTION] Widgets: Box-Select support
 // This has been extracted away from Multi-Select logic in the hope that it could eventually be used elsewhere, but hasn't been yet.
 //-------------------------------------------------------------------------
-// - BoxSelectStartDrag() [Internal]
+// Extra logic in MultiSelectItemFooter() and ImGuiListClipper::Step()
+//-------------------------------------------------------------------------
+// - BoxSelectPreStartDrag() [Internal]
+// - BoxSelectActivateDrag() [Internal]
+// - BoxSelectDeactivateDrag() [Internal]
 // - BoxSelectScrollWithMouseDrag() [Internal]
 // - BeginBoxSelect() [Internal]
 // - EndBoxSelect() [Internal]
 //-------------------------------------------------------------------------
 
-static void BoxSelectStartDrag(ImGuiID id, ImGuiSelectionUserData clicked_item)
+// Call on the initial click.
+static void BoxSelectPreStartDrag(ImGuiID id, ImGuiSelectionUserData clicked_item)
 {
     ImGuiContext& g = *GImGui;
     ImGuiBoxSelectState* bs = &g.BoxSelectState;
@@ -7149,10 +7154,33 @@ static void BoxSelectStartDrag(ImGuiID id, ImGuiSelectionUserData clicked_item)
     bs->ScrollAccum = ImVec2(0.0f, 0.0f);
 }
 
-static void BoxSelectScrollWithMouseDrag(ImGuiWindow* window, const ImRect& inner_r)
+static void BoxSelectActivateDrag(ImGuiBoxSelectState* bs, ImGuiWindow* window)
+{
+    ImGuiContext& g = *GImGui;
+    IMGUI_DEBUG_LOG_SELECTION("[selection] BeginBoxSelect() 0X%08X: Activate\n", bs->ID);
+    bs->IsActive = true;
+    bs->Window = window;
+    bs->IsStarting = false;
+    ImGui::SetActiveID(bs->ID, window);
+    if (bs->IsStartedFromVoid && (bs->KeyMods & (ImGuiMod_Ctrl | ImGuiMod_Shift)) == 0)
+        bs->RequestClear = true;
+}
+
+static void BoxSelectDeactivateDrag(ImGuiBoxSelectState* bs)
+{
+    ImGuiContext& g = *GImGui;
+    bs->IsActive = bs->IsStarting = false;
+    if (g.ActiveId == bs->ID)
+    {
+        IMGUI_DEBUG_LOG_SELECTION("[selection] BeginBoxSelect() 0X%08X: Deactivate\n", bs->ID);
+        ImGui::ClearActiveID();
+    }
+    bs->ID = 0;
+}
+
+static void BoxSelectScrollWithMouseDrag(ImGuiBoxSelectState* bs, ImGuiWindow* window, const ImRect& inner_r)
 {
     ImGuiContext& g = *GImGui;
-    ImGuiBoxSelectState* bs = &g.BoxSelectState;
     IM_ASSERT(bs->Window == window);
     for (int n = 0; n < 2; n++) // each axis
     {
@@ -7186,30 +7214,13 @@ bool ImGui::BeginBoxSelect(ImGuiWindow* window, ImGuiID box_select_id, ImGuiMult
     if (bs->ID != box_select_id)
         return false;
 
+    // IsStarting is set by MultiSelectItemFooter() when considering a possible box-select. We validate it here and lock geometry.
     bs->UnclipMode = false;
     bs->RequestClear = false;
-
-    // IsStarting is set by MultiSelectItemFooter() when considering a possible box-select. We validate it here and lock geometry.
     if (bs->IsStarting && IsMouseDragPastThreshold(0))
-    {
-        IMGUI_DEBUG_LOG_SELECTION("[selection] BeginBoxSelect() 0X%08X: Started.\n", box_select_id);
-        bs->IsActive = true;
-        bs->Window = window;
-        bs->IsStarting = false;
-        SetActiveID(bs->ID, window);
-        if (bs->IsStartedFromVoid && (bs->KeyMods & (ImGuiMod_Ctrl | ImGuiMod_Shift)) == 0)
-            bs->RequestClear = true;
-    }
+        BoxSelectActivateDrag(bs, window);
     else if ((bs->IsStarting || bs->IsActive) && g.IO.MouseDown[0] == false)
-    {
-        bs->IsActive = bs->IsStarting = false;
-        if (g.ActiveId == bs->ID)
-        {
-            IMGUI_DEBUG_LOG_SELECTION("[selection] BeginBoxSelect() 0X%08X: Ended.\n", box_select_id);
-            ClearActiveID();
-        }
-        bs->ID = 0;
-    }
+        BoxSelectDeactivateDrag(bs);
     if (!bs->IsActive)
         return false;
 
@@ -7264,7 +7275,7 @@ void ImGui::EndBoxSelect(const ImRect& scope_rect, bool enable_scroll)
         scroll_r.Expand(-g.FontSize);
         //GetForegroundDrawList()->AddRect(scroll_r.Min, scroll_r.Max, IM_COL32(0, 255, 0, 255));
         if (!scroll_r.Contains(g.IO.MousePos))
-            BoxSelectScrollWithMouseDrag(window, scroll_r);
+            BoxSelectScrollWithMouseDrag(bs, window, scroll_r);
     }
 }
 
@@ -7447,7 +7458,7 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect()
         {
             if (!g.BoxSelectState.IsActive && !g.BoxSelectState.IsStarting && g.IO.MouseClickedCount[0] == 1)
             {
-                BoxSelectStartDrag(ms->BoxSelectId, ImGuiSelectionUserData_Invalid);
+                BoxSelectPreStartDrag(ms->BoxSelectId, ImGuiSelectionUserData_Invalid);
                 FocusWindow(window, ImGuiFocusRequestFlags_UnlessBelowModal);
                 SetHoveredID(ms->BoxSelectId);
                 if (ms->Flags & ImGuiMultiSelectFlags_ScopeRect)
@@ -7634,22 +7645,23 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
     }
 
     // Box-select toggle handling
-    if (ImGuiBoxSelectState* bs = GetBoxSelectState(ms->BoxSelectId))
-    {
-        const bool rect_overlap_curr = bs->BoxSelectRectCurr.Overlaps(g.LastItemData.Rect);
-        const bool rect_overlap_prev = bs->BoxSelectRectPrev.Overlaps(g.LastItemData.Rect);
-        if ((rect_overlap_curr && !rect_overlap_prev && !selected) || (rect_overlap_prev && !rect_overlap_curr))
+    if (ms->BoxSelectId != 0)
+        if (ImGuiBoxSelectState* bs = GetBoxSelectState(ms->BoxSelectId))
         {
-            selected = !selected;
-            ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetRange, selected, item_data, item_data };
-            ImGuiSelectionRequest* prev_req = (ms->IO.Requests.Size > 0) ? &ms->IO.Requests.Data[ms->IO.Requests.Size - 1] : NULL;
-            if (prev_req && prev_req->Type == ImGuiSelectionRequestType_SetRange && prev_req->RangeLastItem == ms->BoxSelectLastitem && prev_req->Selected == selected)
-                prev_req->RangeLastItem = item_data; // Merge span into same request
-            else
-                ms->IO.Requests.push_back(req);
+            const bool rect_overlap_curr = bs->BoxSelectRectCurr.Overlaps(g.LastItemData.Rect);
+            const bool rect_overlap_prev = bs->BoxSelectRectPrev.Overlaps(g.LastItemData.Rect);
+            if ((rect_overlap_curr && !rect_overlap_prev && !selected) || (rect_overlap_prev && !rect_overlap_curr))
+            {
+                selected = !selected;
+                ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetRange, selected, item_data, item_data };
+                ImGuiSelectionRequest* prev_req = (ms->IO.Requests.Size > 0) ? &ms->IO.Requests.Data[ms->IO.Requests.Size - 1] : NULL;
+                if (prev_req && prev_req->Type == ImGuiSelectionRequestType_SetRange && prev_req->RangeLastItem == ms->BoxSelectLastitem && prev_req->Selected == selected)
+                    prev_req->RangeLastItem = item_data; // Merge span into same request
+                else
+                    ms->IO.Requests.push_back(req);
+            }
+            ms->BoxSelectLastitem = item_data;
         }
-        ms->BoxSelectLastitem = item_data;
-    }
 
     // Right-click handling.
     // FIXME-MULTISELECT: Currently filtered out by ImGuiMultiSelectFlags_NoAutoSelect but maybe should be moved to Selectable(). See https://github.com/ocornut/imgui/pull/5816
@@ -7677,7 +7689,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
         ImGuiInputSource input_source = (g.NavJustMovedToId == id || g.NavActivateId == id) ? g.NavInputSource : ImGuiInputSource_Mouse;
         if (flags & ImGuiMultiSelectFlags_BoxSelect)
             if (selected == false && !g.BoxSelectState.IsActive && !g.BoxSelectState.IsStarting && input_source == ImGuiInputSource_Mouse && g.IO.MouseClickedCount[0] == 1)
-                BoxSelectStartDrag(ms->BoxSelectId, item_data);
+                BoxSelectPreStartDrag(ms->BoxSelectId, item_data);
 
         //----------------------------------------------------------------------------------------
         // ACTION                      | Begin  | Pressed/Activated  | End