1
0
mirror of https://github.com/ocornut/imgui.git synced 2024-11-24 07:40:22 +01:00

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

This commit is contained in:
ocornut 2024-05-29 14:33:41 +02:00
parent 9435a3185a
commit 65ebc0513b

View File

@ -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