MultiSelect: (Breaking) RequestSetRange's parameter are RangeFirstItem...RangeLastItem (which was always ordered unlike RangeSrcItem...RangeDstItme). Removed RangeDstItem. Removed RangeDirection.

This commit is contained in:
ocornut 2023-08-21 19:20:51 +02:00
parent af83a3eea4
commit ff95fdb668
3 changed files with 16 additions and 14 deletions

14
imgui.h
View File

@ -2758,7 +2758,7 @@ enum ImGuiMultiSelectFlags_
// About ImGuiSelectionUserData:
// - This is your application-defined identifier in a selection set:
// - For each item is submitted by your calls to SetNextItemSelectionUserData().
// - In return we store them into RangeSrcItem/RangeDstItem and other fields ImGuiMultiSelectIO.
// - In return we store them into RangeSrcItem/RangeFirstItem/RangeLastItem and other fields in ImGuiMultiSelectIO.
// - Most applications will store an object INDEX, hence the chosen name and type.
// Storing an integer index is the easiest thing to do, as SetRange requests will give you two end points
// and you will need to interpolate between them to honor range selection.
@ -2787,20 +2787,20 @@ struct ImGuiMultiSelectIO
// REQUESTS --------------------------------// BEGIN / LOOP / END
bool RequestClear; // ms:w, app:r / / ms:w, app:r // 1. Request app/user to clear selection.
bool RequestSelectAll; // ms:w, app:r / / ms:w, app:r // 2. Request app/user to select all.
bool RequestSetRange; // / / ms:w, app:r // 3. Request app/user to select/unselect [RangeSrcItem..RangeDstItem] items, based on RangeSelected. In practice, only EndMultiSelect() request this, app code can read after BeginMultiSelect() and it will always be false.
bool RequestSetRange; // / / ms:w, app:r // 3. Request app/user to select/unselect [RangeFirstItem..RangeLastItem] items, based on RangeSelected. Only EndMultiSelect() request this, app code can read after BeginMultiSelect() and it will always be false.
ImGuiSelectionUserData RequestFocusItem; // app:w / app:r / app:r // (If using deletion) 4. Request user to focus item. This is actually only manipulated in user-space, but we provide storage to facilitate implementing a deletion idiom (see demo).
// STATE/ARGUMENTS -------------------------// BEGIN / LOOP / END
ImGuiSelectionUserData RangeSrcItem; // ms:w / app:r / ms:w, app:r // Begin: Last known SetNextItemSelectionUserData() value for RangeSrcItem. End: parameter from RequestSetRange request.
ImGuiSelectionUserData RangeDstItem; // / / ms:w, app:r // End: parameter from RequestSetRange request.
ImS8 RangeDirection; // / / ms:w, app:r // End: parameter from RequestSetRange request. +1 if RangeSrcItem came before RangeDstItem, -1 otherwise. Available as an indicator in case you cannot infer order from the void* values. If your void* values are storing indices you will never need this.
bool RangeSelected; // / / ms:w, app:r // End: parameter from RequestSetRange request. true = Select Range, false = Unselect Range.
ImGuiSelectionUserData RangeSrcItem; // ms:w / app:r / // (If using clipper) Begin: Source item (generally the first selected item when multi-selecting, which is used as a reference point). Read during loop in order for user code to set RangeSrcPassedBy.
ImGuiSelectionUserData RangeFirstItem; // / / ms:w, app:r // End: parameter for RequestSetRange request (this is generally == RangeSrcItem when shift selecting from top to bottom)
ImGuiSelectionUserData RangeLastItem; // / / ms:w, app:r // End: parameter for RequestSetRange request (this is generally == RangeSrcItem when shift selecting from bottom to top)
bool RangeSelected; // / / ms:w, app:r // End: parameter for RequestSetRange request. true = Select Range, false = Unselect Range.
bool RangeSrcPassedBy; // / ms:rw app:w / ms:r // (If using clipper) Need to be set by app/user if RangeSrcItem was part of the clipped set before submitting the visible items. Ignore if not clipping.
bool RangeSrcReset; // app:w / app:w / ms:r // (If using deletion) Set before EndMultiSelect() to reset ResetSrcItem (e.g. if deleted selection).
bool NavIdSelected; // ms:w, app:r / / // (If using deletion) Last known selection state for NavId (if part of submitted items).
ImGuiSelectionUserData NavIdItem; // ms:w, app:r / / // (If using deletion) Last known SetNextItemSelectionUserData() value for NavId (if part of submitted items).
ImGuiMultiSelectIO() { Clear(); }
void Clear() { memset(this, 0, sizeof(*this)); RequestFocusItem = NavIdItem = RangeSrcItem = RangeDstItem = (ImGuiSelectionUserData)-1; }
void Clear() { memset(this, 0, sizeof(*this)); RequestFocusItem = NavIdItem = RangeSrcItem = RangeFirstItem = RangeLastItem = (ImGuiSelectionUserData)-1; }
};
//-----------------------------------------------------------------------------

View File

@ -2793,7 +2793,7 @@ struct ExampleSelection
// you will need a way to iterate from one item to the other item given the ID you use.
// You are likely to need some kind of data structure to convert 'view index' <> 'object ID' (FIXME-MULTISELECT: Would be worth providing a demo of doing this).
// Note: This implementation of SetRange() is inefficient because it doesn't take advantage of the fact that ImGuiStorage stores sorted key.
void SetRange(int a, int b, bool v) { if (b < a) { int tmp = b; b = a; a = tmp; } for (int n = a; n <= b; n++) SetSelected(n, v); }
void SetRange(int a, int b, bool v) { for (int n = a; n <= b; n++) SetSelected(n, v); }
void SelectAll(int count) { Storage.Data.resize(count); for (int idx = 0; idx < count; idx++) Storage.Data[idx] = ImGuiStoragePair((ImGuiID)idx, 1); SelectionSize = count; } // This could be using SetRange(), but it this way is faster.
// Apply requests coming from BeginMultiSelect() and EndMultiSelect(). Must be done in this order! Clear->SelectAll->SetRange.
@ -2802,7 +2802,7 @@ struct ExampleSelection
{
if (ms_io->RequestClear) { Clear(); }
if (ms_io->RequestSelectAll) { SelectAll(items_count); }
if (ms_io->RequestSetRange) { SetRange((int)ms_io->RangeSrcItem, (int)ms_io->RangeDstItem, ms_io->RangeSelected ? 1 : 0); }
if (ms_io->RequestSetRange) { SetRange((int)ms_io->RangeFirstItem, (int)ms_io->RangeLastItem, ms_io->RangeSelected ? 1 : 0); }
}
void DebugTooltip()

View File

@ -7129,7 +7129,7 @@ static void DebugLogMultiSelectRequests(const char* function, const ImGuiMultiSe
ImGuiContext& g = *GImGui;
if (data->RequestClear) IMGUI_DEBUG_LOG_SELECTION("[selection] %s: RequestClear\n", function);
if (data->RequestSelectAll) IMGUI_DEBUG_LOG_SELECTION("[selection] %s: RequestSelectAll\n", function);
if (data->RequestSetRange) IMGUI_DEBUG_LOG_SELECTION("[selection] %s: RequestSetRange %" IM_PRId64 "..%" IM_PRId64 " (0x%" IM_PRIX64 "..0x%" IM_PRIX64 ") = %d (dir %+d)\n", function, data->RangeSrcItem, data->RangeDstItem, data->RangeSrcItem, data->RangeDstItem, data->RangeSelected, data->RangeDirection);
if (data->RequestSetRange) IMGUI_DEBUG_LOG_SELECTION("[selection] %s: RequestSetRange %" IM_PRId64 "..%" IM_PRId64 " (0x%" IM_PRIX64 "..0x%" IM_PRIX64 ") = %d\n", function, data->RangeFirstItem, data->RangeLastItem, data->RangeFirstItem, data->RangeLastItem, data->RangeSelected);
}
// Return ImGuiMultiSelectIO structure. Lifetime: valid until corresponding call to EndMultiSelect().
@ -7159,7 +7159,6 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags)
storage->Window = window;
ms->Storage = storage;
// FIXME-MULTISELECT: Index vs Pointers.
// We want EndIO's NavIdItem/NavIdSelected to match BeginIO's one, so the value never changes after EndMultiSelect()
ms->BeginIO.RangeSrcItem = ms->EndIO.RangeSrcItem = storage->RangeSrcItem;
ms->BeginIO.NavIdItem = ms->EndIO.NavIdItem = storage->NavIdItem;
@ -7398,8 +7397,8 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
//----------------------------------------------------------------------------------------
ImGuiInputSource input_source = (g.NavJustMovedToId == id || g.NavActivateId == id) ? g.NavInputSource : ImGuiInputSource_Mouse;
int range_direction;
ms->EndIO.RequestSetRange = true;
ms->EndIO.RangeDstItem = item_data;
if (is_shift && is_multiselect)
{
// Shift+Arrow always select
@ -7407,7 +7406,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
//IM_ASSERT(storage->HasRangeSrc && storage->HasRangeValue);
ms->EndIO.RangeSrcItem = (storage->RangeSrcItem != ImGuiSelectionUserData_Invalid) ? storage->RangeSrcItem : item_data;
ms->EndIO.RangeSelected = (is_ctrl && storage->RangeSelected != -1) ? (storage->RangeSelected != 0) : true;
ms->EndIO.RangeDirection = ms->BeginIO.RangeSrcPassedBy ? +1 : -1;
range_direction = ms->BeginIO.RangeSrcPassedBy ? +1 : -1;
}
else
{
@ -7415,8 +7414,11 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
selected = is_ctrl ? !selected : true;
ms->EndIO.RangeSrcItem = storage->RangeSrcItem = item_data;
ms->EndIO.RangeSelected = selected;
ms->EndIO.RangeDirection = +1;
range_direction = +1;
}
ImGuiSelectionUserData range_dst_item = item_data;
ms->EndIO.RangeFirstItem = (range_direction > 0) ? ms->EndIO.RangeSrcItem : range_dst_item;
ms->EndIO.RangeLastItem = (range_direction > 0) ? range_dst_item : ms->EndIO.RangeSrcItem;
if (!is_multiselect)
{