mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-15 01:17:00 +00:00
RangeSelect/MultiSelect: Transition to use FocusScope bits merged in master.
Preserve ability to shift+arrow into an item that is part of FocusScope but doesn't carry a selection without breaking selection.
This commit is contained in:
parent
abfa8487eb
commit
dd52a2854c
@ -4554,7 +4554,6 @@ void ImGui::Shutdown(ImGuiContext* context)
|
|||||||
g.ClipboardHandlerData.clear();
|
g.ClipboardHandlerData.clear();
|
||||||
g.MenusIdSubmittedThisFrame.clear();
|
g.MenusIdSubmittedThisFrame.clear();
|
||||||
g.InputTextState.ClearFreeMemory();
|
g.InputTextState.ClearFreeMemory();
|
||||||
g.MultiSelectScopeWindow = NULL;
|
|
||||||
|
|
||||||
g.SettingsWindows.clear();
|
g.SettingsWindows.clear();
|
||||||
g.SettingsHandlers.clear();
|
g.SettingsHandlers.clear();
|
||||||
@ -9735,6 +9734,7 @@ static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result)
|
|||||||
result->FocusScopeId = window->DC.NavFocusScopeIdCurrent;
|
result->FocusScopeId = window->DC.NavFocusScopeIdCurrent;
|
||||||
result->InFlags = g.LastItemData.InFlags;
|
result->InFlags = g.LastItemData.InFlags;
|
||||||
result->RectRel = WindowRectAbsToRel(window, g.LastItemData.NavRect);
|
result->RectRel = WindowRectAbsToRel(window, g.LastItemData.NavRect);
|
||||||
|
result->HasSelectionData = (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasSelectionData) != 0; // FIXME: Bizarre but valid we are calling NavApplyItemToResult() before clering the NextItemData
|
||||||
}
|
}
|
||||||
|
|
||||||
// We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above)
|
// We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above)
|
||||||
@ -10491,6 +10491,7 @@ void ImGui::NavMoveRequestApplyResult()
|
|||||||
g.NavJustMovedToId = result->ID;
|
g.NavJustMovedToId = result->ID;
|
||||||
g.NavJustMovedToFocusScopeId = result->FocusScopeId;
|
g.NavJustMovedToFocusScopeId = result->FocusScopeId;
|
||||||
g.NavJustMovedToKeyMods = g.NavMoveKeyMods;
|
g.NavJustMovedToKeyMods = g.NavMoveKeyMods;
|
||||||
|
g.NavJustMovedToHasSelectionData = result->HasSelectionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Focus
|
// Focus
|
||||||
|
@ -1084,7 +1084,8 @@ enum ImGuiNextItemDataFlags_
|
|||||||
{
|
{
|
||||||
ImGuiNextItemDataFlags_None = 0,
|
ImGuiNextItemDataFlags_None = 0,
|
||||||
ImGuiNextItemDataFlags_HasWidth = 1 << 0,
|
ImGuiNextItemDataFlags_HasWidth = 1 << 0,
|
||||||
ImGuiNextItemDataFlags_HasOpen = 1 << 1
|
ImGuiNextItemDataFlags_HasOpen = 1 << 1,
|
||||||
|
ImGuiNextItemDataFlags_HasSelectionData = 1 << 2
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImGuiNextItemData
|
struct ImGuiNextItemData
|
||||||
@ -1094,7 +1095,6 @@ struct ImGuiNextItemData
|
|||||||
ImGuiID FocusScopeId; // Set by SetNextItemMultiSelectData() (!= 0 signify value has been set, so it's an alternate version of HasSelectionData, we don't use Flags for this because they are cleared too early. This is mostly used for debugging)
|
ImGuiID FocusScopeId; // Set by SetNextItemMultiSelectData() (!= 0 signify value has been set, so it's an alternate version of HasSelectionData, we don't use Flags for this because they are cleared too early. This is mostly used for debugging)
|
||||||
ImGuiCond OpenCond;
|
ImGuiCond OpenCond;
|
||||||
bool OpenVal; // Set by SetNextItemOpen()
|
bool OpenVal; // Set by SetNextItemOpen()
|
||||||
ImGuiID MultiSelectScopeId; // Set by SetNextItemMultiSelectData()
|
|
||||||
void* SelectionData; // Set by SetNextItemSelectionData() (note that NULL/0 is a valid value)
|
void* SelectionData; // Set by SetNextItemSelectionData() (note that NULL/0 is a valid value)
|
||||||
|
|
||||||
ImGuiNextItemData() { memset(this, 0, sizeof(*this)); }
|
ImGuiNextItemData() { memset(this, 0, sizeof(*this)); }
|
||||||
@ -1338,9 +1338,10 @@ struct ImGuiNavItemData
|
|||||||
float DistBox; // Move // Best candidate box distance to current NavId
|
float DistBox; // Move // Best candidate box distance to current NavId
|
||||||
float DistCenter; // Move // Best candidate center distance to current NavId
|
float DistCenter; // Move // Best candidate center distance to current NavId
|
||||||
float DistAxial; // Move // Best candidate axial distance to current NavId
|
float DistAxial; // Move // Best candidate axial distance to current NavId
|
||||||
|
bool HasSelectionData; // Move // Copy of (NextItemData.Flags & ImGuiNextItemDataFlags_HasSelection)
|
||||||
|
|
||||||
ImGuiNavItemData() { Clear(); }
|
ImGuiNavItemData() { Clear(); }
|
||||||
void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; DistBox = DistCenter = DistAxial = FLT_MAX; }
|
void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; DistBox = DistCenter = DistAxial = FLT_MAX; HasSelectionData = false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -1403,18 +1404,19 @@ struct ImGuiOldColumns
|
|||||||
// [SECTION] Multi-select support
|
// [SECTION] Multi-select support
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
//#define IMGUI_HAS_MULTI_SELECT 1
|
|
||||||
#ifdef IMGUI_HAS_MULTI_SELECT
|
#ifdef IMGUI_HAS_MULTI_SELECT
|
||||||
|
|
||||||
struct IMGUI_API ImGuiMultiSelectState
|
struct IMGUI_API ImGuiMultiSelectState
|
||||||
{
|
{
|
||||||
|
ImGuiID FocusScopeId; // Same as CurrentWindow->DC.FocusScopeIdCurrent (unless another selection scope was pushed manually)
|
||||||
|
ImGuiID BackupFocusScopeId;
|
||||||
ImGuiMultiSelectData In; // The In requests are set and returned by BeginMultiSelect()
|
ImGuiMultiSelectData In; // The In requests are set and returned by BeginMultiSelect()
|
||||||
ImGuiMultiSelectData Out; // The Out requests are finalized and returned by EndMultiSelect()
|
ImGuiMultiSelectData Out; // The Out requests are finalized and returned by EndMultiSelect()
|
||||||
bool InRangeDstPassedBy; // (Internal) set by the the item that match NavJustMovedToId when InRequestRangeSetNav is set.
|
bool InRangeDstPassedBy; // (Internal) set by the the item that match NavJustMovedToId when InRequestRangeSetNav is set.
|
||||||
bool InRequestSetRangeNav; // (Internal) set by BeginMultiSelect() when using Shift+Navigation. Because scrolling may be affected we can't afford a frame of lag with Shift+Navigation.
|
bool InRequestSetRangeNav; // (Internal) set by BeginMultiSelect() when using Shift+Navigation. Because scrolling may be affected we can't afford a frame of lag with Shift+Navigation.
|
||||||
|
|
||||||
ImGuiMultiSelectState() { Clear(); }
|
ImGuiMultiSelectState() { Clear(); }
|
||||||
void Clear() { In.Clear(); Out.Clear(); InRangeDstPassedBy = InRequestSetRangeNav = false; }
|
void Clear() { FocusScopeId = BackupFocusScopeId = 0; In.Clear(); Out.Clear(); InRangeDstPassedBy = InRequestSetRangeNav = false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // #ifdef IMGUI_HAS_MULTI_SELECT
|
#endif // #ifdef IMGUI_HAS_MULTI_SELECT
|
||||||
@ -1672,6 +1674,7 @@ struct ImGuiContext
|
|||||||
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
|
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
|
||||||
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
|
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
|
||||||
ImGuiKeyModFlags NavJustMovedToKeyMods;
|
ImGuiKeyModFlags NavJustMovedToKeyMods;
|
||||||
|
bool NavJustMovedToHasSelectionData; // " (FIXME-NAV: We should maybe just store ImGuiNavMoveResult)
|
||||||
ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame.
|
ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame.
|
||||||
ImGuiActivateFlags NavNextActivateFlags;
|
ImGuiActivateFlags NavNextActivateFlags;
|
||||||
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard.
|
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard.
|
||||||
@ -1715,10 +1718,9 @@ struct ImGuiContext
|
|||||||
bool NavWindowingToggleLayer;
|
bool NavWindowingToggleLayer;
|
||||||
|
|
||||||
// Range-Select/Multi-Select
|
// Range-Select/Multi-Select
|
||||||
ImGuiID MultiSelectScopeId;
|
bool MultiSelectEnabled;
|
||||||
ImGuiWindow* MultiSelectScopeWindow;
|
|
||||||
ImGuiMultiSelectFlags MultiSelectFlags;
|
ImGuiMultiSelectFlags MultiSelectFlags;
|
||||||
ImGuiMultiSelectState MultiSelectState;
|
ImGuiMultiSelectState MultiSelectState; // We currently don't support recursing/stacking multi-select
|
||||||
|
|
||||||
// Render
|
// Render
|
||||||
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
|
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
|
||||||
@ -1890,6 +1892,7 @@ struct ImGuiContext
|
|||||||
NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
|
NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
|
||||||
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
|
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
|
||||||
NavJustMovedToKeyMods = ImGuiKeyModFlags_None;
|
NavJustMovedToKeyMods = ImGuiKeyModFlags_None;
|
||||||
|
NavJustMovedToHasSelectionData = false;
|
||||||
NavInputSource = ImGuiInputSource_None;
|
NavInputSource = ImGuiInputSource_None;
|
||||||
NavLayer = ImGuiNavLayer_Main;
|
NavLayer = ImGuiNavLayer_Main;
|
||||||
NavIdIsAlive = false;
|
NavIdIsAlive = false;
|
||||||
@ -1915,9 +1918,8 @@ struct ImGuiContext
|
|||||||
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
|
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
|
||||||
NavWindowingToggleLayer = false;
|
NavWindowingToggleLayer = false;
|
||||||
|
|
||||||
MultiSelectScopeId = 0;
|
MultiSelectEnabled = false;
|
||||||
MultiSelectScopeWindow = NULL;
|
MultiSelectFlags = ImGuiMultiSelectFlags_None;
|
||||||
MultiSelectFlags = 0;
|
|
||||||
|
|
||||||
DimBgRatio = 0.0f;
|
DimBgRatio = 0.0f;
|
||||||
MouseCursor = ImGuiMouseCursor_Arrow;
|
MouseCursor = ImGuiMouseCursor_Arrow;
|
||||||
|
@ -5924,7 +5924,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
|||||||
const bool was_selected = selected;
|
const bool was_selected = selected;
|
||||||
|
|
||||||
// Multi-selection support (header)
|
// Multi-selection support (header)
|
||||||
const bool is_multi_select = (g.MultiSelectScopeWindow == window);
|
const bool is_multi_select = g.MultiSelectEnabled;
|
||||||
if (is_multi_select)
|
if (is_multi_select)
|
||||||
{
|
{
|
||||||
flags |= ImGuiTreeNodeFlags_OpenOnArrow;
|
flags |= ImGuiTreeNodeFlags_OpenOnArrow;
|
||||||
@ -6253,7 +6253,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
|||||||
if (flags & ImGuiSelectableFlags_AllowItemOverlap) { button_flags |= ImGuiButtonFlags_AllowItemOverlap; }
|
if (flags & ImGuiSelectableFlags_AllowItemOverlap) { button_flags |= ImGuiButtonFlags_AllowItemOverlap; }
|
||||||
|
|
||||||
// Multi-selection support (header)
|
// Multi-selection support (header)
|
||||||
const bool is_multi_select = (g.MultiSelectScopeWindow == window);
|
const bool is_multi_select = g.MultiSelectEnabled;
|
||||||
const bool was_selected = selected;
|
const bool was_selected = selected;
|
||||||
if (is_multi_select)
|
if (is_multi_select)
|
||||||
{
|
{
|
||||||
@ -6369,17 +6369,20 @@ bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags
|
|||||||
|
|
||||||
ImGuiMultiSelectData* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, void* range_ref, bool range_ref_is_selected)
|
ImGuiMultiSelectData* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, void* range_ref, bool range_ref_is_selected)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *ImGui::GetCurrentContext();
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiWindow* window = g.CurrentWindow;
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
|
|
||||||
IM_ASSERT(g.MultiSelectScopeId == 0); // No recursion allowed yet (we could allow it if we deem it useful)
|
IM_ASSERT(g.MultiSelectEnabled == false); // No recursion allowed yet (we could allow it if we deem it useful)
|
||||||
IM_ASSERT(g.MultiSelectFlags == 0);
|
IM_ASSERT(g.MultiSelectFlags == 0);
|
||||||
|
IM_ASSERT(g.MultiSelectState.FocusScopeId == 0);
|
||||||
|
|
||||||
|
// FIXME: BeginFocusScope()
|
||||||
ImGuiMultiSelectState* state = &g.MultiSelectState;
|
ImGuiMultiSelectState* state = &g.MultiSelectState;
|
||||||
g.MultiSelectScopeId = window->IDStack.back();
|
|
||||||
g.MultiSelectScopeWindow = window;
|
|
||||||
g.MultiSelectFlags = flags;
|
|
||||||
state->Clear();
|
state->Clear();
|
||||||
|
state->BackupFocusScopeId = window->DC.NavFocusScopeIdCurrent;
|
||||||
|
state->FocusScopeId = window->DC.NavFocusScopeIdCurrent = window->IDStack.back();
|
||||||
|
g.MultiSelectEnabled = true;
|
||||||
|
g.MultiSelectFlags = flags;
|
||||||
|
|
||||||
if ((flags & ImGuiMultiSelectFlags_NoMultiSelect) == 0)
|
if ((flags & ImGuiMultiSelectFlags_NoMultiSelect) == 0)
|
||||||
{
|
{
|
||||||
@ -6388,7 +6391,7 @@ ImGuiMultiSelectData* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, void*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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 SelectScopeId so it possible to use multiple lists inside a same window)
|
||||||
if (g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == g.MultiSelectScopeId)
|
if (g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == state->FocusScopeId && g.NavJustMovedToHasSelectionData)
|
||||||
{
|
{
|
||||||
if (g.IO.KeyShift)
|
if (g.IO.KeyShift)
|
||||||
state->InRequestSetRangeNav = true;
|
state->InRequestSetRangeNav = true;
|
||||||
@ -6411,14 +6414,19 @@ ImGuiMultiSelectData* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, void*
|
|||||||
|
|
||||||
ImGuiMultiSelectData* ImGui::EndMultiSelect()
|
ImGuiMultiSelectData* ImGui::EndMultiSelect()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *ImGui::GetCurrentContext();
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
ImGuiMultiSelectState* state = &g.MultiSelectState;
|
ImGuiMultiSelectState* state = &g.MultiSelectState;
|
||||||
IM_ASSERT(g.MultiSelectScopeId != 0);
|
|
||||||
|
IM_ASSERT(g.MultiSelectState.FocusScopeId != 0);
|
||||||
|
IM_ASSERT(g.MultiSelectState.FocusScopeId == window->DC.NavFocusScopeIdCurrent);
|
||||||
|
|
||||||
if (g.MultiSelectFlags & ImGuiMultiSelectFlags_NoUnselect)
|
if (g.MultiSelectFlags & ImGuiMultiSelectFlags_NoUnselect)
|
||||||
state->Out.RangeValue = true;
|
state->Out.RangeValue = true;
|
||||||
g.MultiSelectScopeId = 0;
|
g.MultiSelectState.FocusScopeId = 0;
|
||||||
g.MultiSelectScopeWindow = NULL;
|
window->DC.NavFocusScopeIdCurrent = g.MultiSelectState.BackupFocusScopeId;
|
||||||
g.MultiSelectFlags = 0;
|
g.MultiSelectEnabled = false;
|
||||||
|
g.MultiSelectFlags = ImGuiMultiSelectFlags_None;
|
||||||
|
|
||||||
#ifdef IMGUI_DEBUG_MULTISELECT
|
#ifdef IMGUI_DEBUG_MULTISELECT
|
||||||
if (state->Out.RequestClear) printf("[%05d] EndMultiSelect: RequestClear\n", g.FrameCount);
|
if (state->Out.RequestClear) printf("[%05d] EndMultiSelect: RequestClear\n", g.FrameCount);
|
||||||
@ -6432,17 +6440,24 @@ ImGuiMultiSelectData* ImGui::EndMultiSelect()
|
|||||||
void ImGui::SetNextItemSelectionData(void* item_data)
|
void ImGui::SetNextItemSelectionData(void* item_data)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
IM_ASSERT(g.MultiSelectScopeId != 0);
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
|
IM_ASSERT(window->DC.NavFocusScopeIdCurrent != 0);
|
||||||
g.NextItemData.SelectionData = item_data;
|
g.NextItemData.SelectionData = item_data;
|
||||||
g.NextItemData.MultiSelectScopeId = g.MultiSelectScopeId;
|
g.NextItemData.FocusScopeId = window->DC.NavFocusScopeIdCurrent;
|
||||||
|
|
||||||
|
// Note that the flag will be cleared by ItemAdd(), so it's only useful for Navigation code!
|
||||||
|
// This designed so widgets can also cheaply set this before calling ItemAdd(), so we are not tied to MultiSelect api.
|
||||||
|
g.NextItemData.Flags |= ImGuiNextItemDataFlags_HasSelectionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImGui::MultiSelectItemHeader(ImGuiID id, bool* p_selected)
|
void ImGui::MultiSelectItemHeader(ImGuiID id, bool* p_selected)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiWindow* window = g.CurrentWindow;
|
||||||
ImGuiMultiSelectState* state = &g.MultiSelectState;
|
ImGuiMultiSelectState* state = &g.MultiSelectState;
|
||||||
|
|
||||||
IM_ASSERT(g.NextItemData.MultiSelectScopeId == g.MultiSelectScopeId && "Forgot to call SetNextItemSelectionData() prior to item, required in BeginMultiSelect()/EndMultiSelect() scope");
|
IM_UNUSED(window);
|
||||||
|
IM_ASSERT(g.NextItemData.FocusScopeId == window->DC.NavFocusScopeIdCurrent && "Forgot to call SetNextItemSelectionData() prior to item, required in BeginMultiSelect()/EndMultiSelect() scope");
|
||||||
void* item_data = g.NextItemData.SelectionData;
|
void* item_data = g.NextItemData.SelectionData;
|
||||||
|
|
||||||
// Apply Clear/SelectAll requests requested by BeginMultiSelect().
|
// Apply Clear/SelectAll requests requested by BeginMultiSelect().
|
||||||
@ -6483,7 +6498,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
|||||||
ImGuiMultiSelectState* state = &g.MultiSelectState;
|
ImGuiMultiSelectState* state = &g.MultiSelectState;
|
||||||
|
|
||||||
void* item_data = g.NextItemData.SelectionData;
|
void* item_data = g.NextItemData.SelectionData;
|
||||||
g.NextItemData.MultiSelectScopeId = 0;
|
g.NextItemData.FocusScopeId = 0;
|
||||||
|
|
||||||
bool selected = *p_selected;
|
bool selected = *p_selected;
|
||||||
bool pressed = *p_pressed;
|
bool pressed = *p_pressed;
|
||||||
|
Loading…
Reference in New Issue
Block a user