1
0
mirror of https://github.com/ocornut/imgui.git synced 2025-02-21 12:52:19 +01:00

MultiSelect: Remove the need for using IsItemToggledSelection(). Update comments.

This is the simple version that past our tests. MultiSelectItemFooter() is in need of a cleanup.
This commit is contained in:
ocornut 2023-06-29 17:00:43 +02:00
parent 6ef70a97fd
commit 1ea9ca748c
3 changed files with 23 additions and 22 deletions

View File

@ -2772,8 +2772,8 @@ enum ImGuiMultiSelectFlags_
// This is because for range-selection we need to know if we are currently "inside" or "outside" the range. // This is because for range-selection we need to know if we are currently "inside" or "outside" the range.
// If you are using integer indices everywhere, this is easy to compute: if (clipper.DisplayStart > (int)data->RangeSrcItem) { data->RangeSrcPassedBy = true; } // If you are using integer indices everywhere, this is easy to compute: if (clipper.DisplayStart > (int)data->RangeSrcItem) { data->RangeSrcPassedBy = true; }
// 4) Submit your items with SetNextItemSelectionUserData() + Selectable()/TreeNode() calls. // 4) Submit your items with SetNextItemSelectionUserData() + Selectable()/TreeNode() calls.
// Call IsItemToggledSelection() to query if the selection state has been toggled, if you need the info immediately for your display (before EndMultiSelect()). // (You may optionally call IsItemToggledSelection() to query if the selection state has been toggled for a given item, if you need that info immediately for your display (before EndMultiSelect()).)
// When cannot provide a "IsItemSelected()" value because we need to consider clipped/unprocessed items, this is why we return a "Toggled" event instead. // (When cannot provide a "IsItemSelected()" value because we need to consider clipped/unprocessed items, this is why we return a "Toggled" event instead.)
// End // End
// 5) Call EndMultiSelect(). Save the value of ->RangeSrcItem for the next frame (you may convert the value in a format that is safe for persistance) // 5) Call EndMultiSelect(). Save the value of ->RangeSrcItem for the next frame (you may convert the value in a format that is safe for persistance)
// 6) Honor Clear/SelectAll/SetRange requests by updating your selection data. Always process them in this order (as you will receive Clear+SetRange request simultaneously) // 6) Honor Clear/SelectAll/SetRange requests by updating your selection data. Always process them in this order (as you will receive Clear+SetRange request simultaneously)

View File

@ -2888,8 +2888,6 @@ static void ShowDemoWindowMultiSelect()
bool item_is_selected = selection.GetSelected(n); bool item_is_selected = selection.GetSelected(n);
ImGui::SetNextItemSelectionUserData(n); ImGui::SetNextItemSelectionUserData(n);
ImGui::Selectable(label, item_is_selected); ImGui::Selectable(label, item_is_selected);
if (ImGui::IsItemToggledSelection())
selection.SetSelected(n, !item_is_selected);
} }
// Apply multi-select requests // Apply multi-select requests
@ -2929,8 +2927,6 @@ static void ShowDemoWindowMultiSelect()
bool item_is_selected = selection->GetSelected(n); bool item_is_selected = selection->GetSelected(n);
ImGui::SetNextItemSelectionUserData(n); ImGui::SetNextItemSelectionUserData(n);
ImGui::Selectable(label, item_is_selected); ImGui::Selectable(label, item_is_selected);
if (ImGui::IsItemToggledSelection())
selection->SetSelected(n, !item_is_selected);
} }
// Apply multi-select requests // Apply multi-select requests
@ -3032,8 +3028,6 @@ static void ShowDemoWindowMultiSelect()
if (widget_type == WidgetType_Selectable) if (widget_type == WidgetType_Selectable)
{ {
ImGui::Selectable(label, item_is_selected); ImGui::Selectable(label, item_is_selected);
if (ImGui::IsItemToggledSelection())
selection.SetSelected(n, !item_is_selected);
if (use_drag_drop && ImGui::BeginDragDropSource()) if (use_drag_drop && ImGui::BeginDragDropSource())
{ {
ImGui::Text("(Dragging %d items)", selection.GetSize()); ImGui::Text("(Dragging %d items)", selection.GetSize());
@ -3047,8 +3041,6 @@ static void ShowDemoWindowMultiSelect()
if (item_is_selected) if (item_is_selected)
tree_node_flags |= ImGuiTreeNodeFlags_Selected; tree_node_flags |= ImGuiTreeNodeFlags_Selected;
bool open = ImGui::TreeNodeEx(label, tree_node_flags); bool open = ImGui::TreeNodeEx(label, tree_node_flags);
if (ImGui::IsItemToggledSelection())
selection.SetSelected(n, !item_is_selected);
if (use_drag_drop && ImGui::BeginDragDropSource()) if (use_drag_drop && ImGui::BeginDragDropSource())
{ {
ImGui::Text("(Dragging %d items)", selection.GetSize()); ImGui::Text("(Dragging %d items)", selection.GetSize());

View File

@ -7156,7 +7156,8 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, void* r
ms->BeginIO.RangeSelected = ms->EndIO.RangeSelected = range_ref_is_selected; ms->BeginIO.RangeSelected = ms->EndIO.RangeSelected = range_ref_is_selected;
} }
// Auto clear when using Navigation to move within the selection (we compare SelectScopeId so it possible to use multiple lists inside a same window) // Auto clear when using Navigation to move within the selection
// (we compare FocusScopeId so it possible to use multiple selections inside a same window)
if (g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == ms->FocusScopeId && g.NavJustMovedToHasSelectionData) if (g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == ms->FocusScopeId && g.NavJustMovedToHasSelectionData)
{ {
if (ms->KeyMods & ImGuiMod_Shift) if (ms->KeyMods & ImGuiMod_Shift)
@ -7255,8 +7256,7 @@ void ImGui::MultiSelectItemHeader(ImGuiID id, bool* p_selected)
// For this to work, IF the user is clipping items, they need to set RangeSrcPassedBy = true to notify the system. // For this to work, IF the user is clipping items, they need to set RangeSrcPassedBy = true to notify the system.
if (ms->IsSetRange) if (ms->IsSetRange)
{ {
IM_ASSERT(id != 0); IM_ASSERT(id != 0 && (ms->KeyMods & ImGuiMod_Shift) != 0);
IM_ASSERT((ms->KeyMods & ImGuiMod_Shift) != 0);
const bool is_range_src = (ms->BeginIO.RangeSrcItem == item_data); const bool is_range_src = (ms->BeginIO.RangeSrcItem == item_data);
const bool is_range_dst = !ms->RangeDstPassedBy && g.NavJustMovedToId == id; // Assume that g.NavJustMovedToId is not clipped. const bool is_range_dst = !ms->RangeDstPassedBy && g.NavJustMovedToId == id; // Assume that g.NavJustMovedToId is not clipped.
if (is_range_dst) if (is_range_dst)
@ -7315,15 +7315,22 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
// Alter selection // Alter selection
if (pressed && (!enter_pressed || !selected)) if (pressed && (!enter_pressed || !selected))
{ {
//------------------------------------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------
// ACTION | Begin | Item Old | Item New | End // ACTION | Begin | Pressed/Activated | End
//------------------------------------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------
// Keys Navigated, Ctrl=0, Shift=0 | In.Clear | Clear -> Sel=0 | Src=item, Pressed -> Sel=1 | // Keys Navigated: | Clear | Src=item, Sel=1 SetRange 1
// Keys Navigated, Ctrl=0, Shift=1 | n/a | n/a | Dst=item, Pressed -> Sel=1, Out.Clear, Out.SetRange=1 | Clear + SetRange // Keys Navigated: Ctrl | n/a | n/a
// Keys Navigated, Ctrl=1, Shift=1 | n/a | n/a | Dst=item, Pressed -> Sel=Src, Out.Clear, Out.SetRange=Src | Clear + SetRange // Keys Navigated: Shift | n/a | Dst=item, Sel=1, => Clear + SetRange 1
// Mouse Pressed, Ctrl=0, Shift=0 | n/a | n/a (Sel=1) | Src=item, Pressed -> Sel=1, Out.Clear, Out.SetRange=1 | Clear + SetRange // Keys Navigated: Ctrl+Shift | n/a | Dst=item, Sel=Src => Clear + SetRange Src-Dst
// Mouse Pressed, Ctrl=0, Shift=1 | n/a | n/a | Dst=item, Pressed -> Sel=1, Out.Clear, Out.SetRange=1 | Clear + SetRange // Keys Activated: | n/a | Src=item, Sel=1 => Clear + SetRange 1
//------------------------------------------------------------------------------------------------------------------------------------------------- // Keys Activated: Ctrl | n/a | Src=item, Sel=!Sel => SetSange 1
// Keys Activated: Shift | n/a | Dst=item, Sel=1 => Clear + SetSange 1
//----------------------------------------------------------------------------------------
// Mouse Pressed: | n/a | Src=item, Sel=1, => Clear + SetRange 1
// Mouse Pressed: Ctrl | n/a | Src=item, Sel=!Sel => SetRange 1
// Mouse Pressed: Shift | n/a | Dst=item, Sel=1, => Clear + SetRange 1
// Mouse Pressed: Ctrl+Shift | n/a | Dst=item, Sel=!Sel => SetRange Src-Dst
//----------------------------------------------------------------------------------------
ImGuiInputSource input_source = (g.NavJustMovedToId == id || g.NavActivateId == id) ? g.NavInputSource : ImGuiInputSource_Mouse; ImGuiInputSource input_source = (g.NavJustMovedToId == id || g.NavActivateId == id) ? g.NavInputSource : ImGuiInputSource_Mouse;
if (is_shift && is_multiselect) if (is_shift && is_multiselect)
@ -7341,6 +7348,8 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
selected = is_ctrl ? !selected : true; selected = is_ctrl ? !selected : true;
ms->EndIO.RangeSrcItem = ms->EndIO.RangeDstItem = item_data; ms->EndIO.RangeSrcItem = ms->EndIO.RangeDstItem = item_data;
ms->EndIO.RangeSelected = selected; ms->EndIO.RangeSelected = selected;
ms->EndIO.RequestSetRange = true;
ms->EndIO.RangeDirection = +1;
} }
if (input_source == ImGuiInputSource_Mouse || g.NavActivateId == id) if (input_source == ImGuiInputSource_Mouse || g.NavActivateId == id)