|
@@ -6403,10 +6403,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags
|
|
frame_bb.Max.y = window->DC.CursorPos.y + frame_height;
|
|
frame_bb.Max.y = window->DC.CursorPos.y + frame_height;
|
|
if (display_frame)
|
|
if (display_frame)
|
|
{
|
|
{
|
|
- // Framed header expand a little outside the default padding, to the edge of InnerClipRect
|
|
|
|
- // (FIXME: May remove this at some point and make InnerClipRect align with WindowPadding.x instead of WindowPadding.x*0.5f)
|
|
|
|
- frame_bb.Min.x -= IM_TRUNC(window->WindowPadding.x * 0.5f - 1.0f);
|
|
|
|
- frame_bb.Max.x += IM_TRUNC(window->WindowPadding.x * 0.5f);
|
|
|
|
|
|
+ const float outer_extend = IM_TRUNC(window->WindowPadding.x * 0.5f); // Framed header expand a little outside of current limits
|
|
|
|
+ frame_bb.Min.x -= outer_extend;
|
|
|
|
+ frame_bb.Max.x += outer_extend;
|
|
}
|
|
}
|
|
|
|
|
|
ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y);
|
|
ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y);
|
|
@@ -6417,26 +6416,27 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags
|
|
if ((flags & (ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_SpanTextWidth | ImGuiTreeNodeFlags_SpanAllColumns)) == 0)
|
|
if ((flags & (ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_SpanTextWidth | ImGuiTreeNodeFlags_SpanAllColumns)) == 0)
|
|
interact_bb.Max.x = frame_bb.Min.x + text_width + (label_size.x > 0.0f ? style.ItemSpacing.x * 2.0f : 0.0f);
|
|
interact_bb.Max.x = frame_bb.Min.x + text_width + (label_size.x > 0.0f ? style.ItemSpacing.x * 2.0f : 0.0f);
|
|
|
|
|
|
- // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable..
|
|
|
|
- const float backup_clip_rect_min_x = window->ClipRect.Min.x;
|
|
|
|
- const float backup_clip_rect_max_x = window->ClipRect.Max.x;
|
|
|
|
- if (span_all_columns)
|
|
|
|
- {
|
|
|
|
- window->ClipRect.Min.x = window->ParentWorkRect.Min.x;
|
|
|
|
- window->ClipRect.Max.x = window->ParentWorkRect.Max.x;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
// Compute open and multi-select states before ItemAdd() as it clear NextItem data.
|
|
// Compute open and multi-select states before ItemAdd() as it clear NextItem data.
|
|
bool is_open = TreeNodeUpdateNextOpen(storage_id, flags);
|
|
bool is_open = TreeNodeUpdateNextOpen(storage_id, flags);
|
|
- bool item_add = ItemAdd(interact_bb, id);
|
|
|
|
- g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect;
|
|
|
|
- g.LastItemData.DisplayRect = frame_bb;
|
|
|
|
|
|
|
|
|
|
+ bool is_visible;
|
|
if (span_all_columns)
|
|
if (span_all_columns)
|
|
{
|
|
{
|
|
|
|
+ // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable..
|
|
|
|
+ const float backup_clip_rect_min_x = window->ClipRect.Min.x;
|
|
|
|
+ const float backup_clip_rect_max_x = window->ClipRect.Max.x;
|
|
|
|
+ window->ClipRect.Min.x = window->ParentWorkRect.Min.x;
|
|
|
|
+ window->ClipRect.Max.x = window->ParentWorkRect.Max.x;
|
|
|
|
+ is_visible = ItemAdd(interact_bb, id);
|
|
window->ClipRect.Min.x = backup_clip_rect_min_x;
|
|
window->ClipRect.Min.x = backup_clip_rect_min_x;
|
|
window->ClipRect.Max.x = backup_clip_rect_max_x;
|
|
window->ClipRect.Max.x = backup_clip_rect_max_x;
|
|
}
|
|
}
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ is_visible = ItemAdd(interact_bb, id);
|
|
|
|
+ }
|
|
|
|
+ g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HasDisplayRect;
|
|
|
|
+ g.LastItemData.DisplayRect = frame_bb;
|
|
|
|
|
|
// If a NavLeft request is happening and ImGuiTreeNodeFlags_NavLeftJumpsBackHere enabled:
|
|
// If a NavLeft request is happening and ImGuiTreeNodeFlags_NavLeftJumpsBackHere enabled:
|
|
// Store data for the current depth to allow returning to this node from any child item.
|
|
// Store data for the current depth to allow returning to this node from any child item.
|
|
@@ -6451,7 +6451,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags
|
|
}
|
|
}
|
|
|
|
|
|
const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
|
|
const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
|
|
- if (!item_add)
|
|
|
|
|
|
+ if (!is_visible)
|
|
{
|
|
{
|
|
if (store_tree_node_stack_data && is_open)
|
|
if (store_tree_node_stack_data && is_open)
|
|
TreeNodeStoreStackData(flags); // Call before TreePushOverrideID()
|
|
TreeNodeStoreStackData(flags); // Call before TreePushOverrideID()
|
|
@@ -6573,52 +6573,54 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiID storage_id, ImGuiTreeNodeFlags
|
|
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
|
|
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
|
|
|
|
|
|
// Render
|
|
// Render
|
|
- const ImU32 text_col = GetColorU32(ImGuiCol_Text);
|
|
|
|
- ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_Compact;
|
|
|
|
- if (is_multi_select)
|
|
|
|
- nav_highlight_flags |= ImGuiNavHighlightFlags_AlwaysDraw; // Always show the nav rectangle
|
|
|
|
- if (display_frame)
|
|
|
|
- {
|
|
|
|
- // Framed type
|
|
|
|
- const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
|
|
|
- RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding);
|
|
|
|
- RenderNavHighlight(frame_bb, id, nav_highlight_flags);
|
|
|
|
- if (flags & ImGuiTreeNodeFlags_Bullet)
|
|
|
|
- RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col);
|
|
|
|
- else if (!is_leaf)
|
|
|
|
- RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 1.0f);
|
|
|
|
- else // Leaf without bullet, left-adjusted text
|
|
|
|
- text_pos.x -= text_offset_x -padding.x;
|
|
|
|
- if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton)
|
|
|
|
- frame_bb.Max.x -= g.FontSize + style.FramePadding.x;
|
|
|
|
- if (g.LogEnabled)
|
|
|
|
- LogSetNextTextDecoration("###", "###");
|
|
|
|
- }
|
|
|
|
- else
|
|
|
|
{
|
|
{
|
|
- // Unframed typed for tree nodes
|
|
|
|
- if (hovered || selected)
|
|
|
|
|
|
+ const ImU32 text_col = GetColorU32(ImGuiCol_Text);
|
|
|
|
+ ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_Compact;
|
|
|
|
+ if (is_multi_select)
|
|
|
|
+ nav_highlight_flags |= ImGuiNavHighlightFlags_AlwaysDraw; // Always show the nav rectangle
|
|
|
|
+ if (display_frame)
|
|
{
|
|
{
|
|
|
|
+ // Framed type
|
|
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
|
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
|
- RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);
|
|
|
|
|
|
+ RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding);
|
|
|
|
+ RenderNavHighlight(frame_bb, id, nav_highlight_flags);
|
|
|
|
+ if (flags & ImGuiTreeNodeFlags_Bullet)
|
|
|
|
+ RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.60f, text_pos.y + g.FontSize * 0.5f), text_col);
|
|
|
|
+ else if (!is_leaf)
|
|
|
|
+ RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 1.0f);
|
|
|
|
+ else // Leaf without bullet, left-adjusted text
|
|
|
|
+ text_pos.x -= text_offset_x - padding.x;
|
|
|
|
+ if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton)
|
|
|
|
+ frame_bb.Max.x -= g.FontSize + style.FramePadding.x;
|
|
|
|
+ if (g.LogEnabled)
|
|
|
|
+ LogSetNextTextDecoration("###", "###");
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ // Unframed typed for tree nodes
|
|
|
|
+ if (hovered || selected)
|
|
|
|
+ {
|
|
|
|
+ const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
|
|
|
+ RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);
|
|
|
|
+ }
|
|
|
|
+ RenderNavHighlight(frame_bb, id, nav_highlight_flags);
|
|
|
|
+ if (flags & ImGuiTreeNodeFlags_Bullet)
|
|
|
|
+ RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col);
|
|
|
|
+ else if (!is_leaf)
|
|
|
|
+ RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 0.70f);
|
|
|
|
+ if (g.LogEnabled)
|
|
|
|
+ LogSetNextTextDecoration(">", NULL);
|
|
}
|
|
}
|
|
- RenderNavHighlight(frame_bb, id, nav_highlight_flags);
|
|
|
|
- if (flags & ImGuiTreeNodeFlags_Bullet)
|
|
|
|
- RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col);
|
|
|
|
- else if (!is_leaf)
|
|
|
|
- RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize * 0.15f), text_col, is_open ? ((flags & ImGuiTreeNodeFlags_UpsideDownArrow) ? ImGuiDir_Up : ImGuiDir_Down) : ImGuiDir_Right, 0.70f);
|
|
|
|
- if (g.LogEnabled)
|
|
|
|
- LogSetNextTextDecoration(">", NULL);
|
|
|
|
- }
|
|
|
|
|
|
|
|
- if (span_all_columns)
|
|
|
|
- TablePopBackgroundChannel();
|
|
|
|
|
|
+ if (span_all_columns)
|
|
|
|
+ TablePopBackgroundChannel();
|
|
|
|
|
|
- // Label
|
|
|
|
- if (display_frame)
|
|
|
|
- RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size);
|
|
|
|
- else
|
|
|
|
- RenderText(text_pos, label, label_end, false);
|
|
|
|
|
|
+ // Label
|
|
|
|
+ if (display_frame)
|
|
|
|
+ RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size);
|
|
|
|
+ else
|
|
|
|
+ RenderText(text_pos, label, label_end, false);
|
|
|
|
+ }
|
|
|
|
|
|
if (store_tree_node_stack_data && is_open)
|
|
if (store_tree_node_stack_data && is_open)
|
|
TreeNodeStoreStackData(flags); // Call before TreePushOverrideID()
|
|
TreeNodeStoreStackData(flags); // Call before TreePushOverrideID()
|
|
@@ -6787,7 +6789,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
|
const ImVec2 text_max(min_x + size.x, pos.y + size.y);
|
|
const ImVec2 text_max(min_x + size.x, pos.y + size.y);
|
|
|
|
|
|
// Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable.
|
|
// Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable.
|
|
- // FIXME: Not part of layout so not included in clipper calculation, but ItemSize currenty doesn't allow offsetting CursorPos.
|
|
|
|
|
|
+ // FIXME: Not part of layout so not included in clipper calculation, but ItemSize currently doesn't allow offsetting CursorPos.
|
|
ImRect bb(min_x, pos.y, text_max.x, text_max.y);
|
|
ImRect bb(min_x, pos.y, text_max.x, text_max.y);
|
|
if ((flags & ImGuiSelectableFlags_NoPadWithHalfSpacing) == 0)
|
|
if ((flags & ImGuiSelectableFlags_NoPadWithHalfSpacing) == 0)
|
|
{
|
|
{
|
|
@@ -6802,23 +6804,24 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
|
}
|
|
}
|
|
//if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(0, 255, 0, 255)); }
|
|
//if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(0, 255, 0, 255)); }
|
|
|
|
|
|
- // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable..
|
|
|
|
- const float backup_clip_rect_min_x = window->ClipRect.Min.x;
|
|
|
|
- const float backup_clip_rect_max_x = window->ClipRect.Max.x;
|
|
|
|
|
|
+ const bool disabled_item = (flags & ImGuiSelectableFlags_Disabled) != 0;
|
|
|
|
+ const ImGuiItemFlags extra_item_flags = disabled_item ? (ImGuiItemFlags)ImGuiItemFlags_Disabled : ImGuiItemFlags_None;
|
|
|
|
+ bool is_visible;
|
|
if (span_all_columns)
|
|
if (span_all_columns)
|
|
{
|
|
{
|
|
|
|
+ // Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackgroundChannel for every Selectable..
|
|
|
|
+ const float backup_clip_rect_min_x = window->ClipRect.Min.x;
|
|
|
|
+ const float backup_clip_rect_max_x = window->ClipRect.Max.x;
|
|
window->ClipRect.Min.x = window->ParentWorkRect.Min.x;
|
|
window->ClipRect.Min.x = window->ParentWorkRect.Min.x;
|
|
window->ClipRect.Max.x = window->ParentWorkRect.Max.x;
|
|
window->ClipRect.Max.x = window->ParentWorkRect.Max.x;
|
|
- }
|
|
|
|
-
|
|
|
|
- const bool disabled_item = (flags & ImGuiSelectableFlags_Disabled) != 0;
|
|
|
|
- const bool is_visible = ItemAdd(bb, id, NULL, disabled_item ? (ImGuiItemFlags)ImGuiItemFlags_Disabled : ImGuiItemFlags_None);
|
|
|
|
-
|
|
|
|
- if (span_all_columns)
|
|
|
|
- {
|
|
|
|
|
|
+ is_visible = ItemAdd(bb, id, NULL, extra_item_flags);
|
|
window->ClipRect.Min.x = backup_clip_rect_min_x;
|
|
window->ClipRect.Min.x = backup_clip_rect_min_x;
|
|
window->ClipRect.Max.x = backup_clip_rect_max_x;
|
|
window->ClipRect.Max.x = backup_clip_rect_max_x;
|
|
}
|
|
}
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ is_visible = ItemAdd(bb, id, NULL, extra_item_flags);
|
|
|
|
+ }
|
|
|
|
|
|
const bool is_multi_select = (g.LastItemData.InFlags & ImGuiItemFlags_IsMultiSelect) != 0;
|
|
const bool is_multi_select = (g.LastItemData.InFlags & ImGuiItemFlags_IsMultiSelect) != 0;
|
|
if (!is_visible)
|
|
if (!is_visible)
|
|
@@ -7073,7 +7076,7 @@ static int ImStrimatchlen(const char* s1, const char* s1_end, const char* s2)
|
|
// When SingleCharMode is set:
|
|
// When SingleCharMode is set:
|
|
// - it is better to NOT display a tooltip of other on-screen display indicator.
|
|
// - it is better to NOT display a tooltip of other on-screen display indicator.
|
|
// - the index of the currently focused item is required.
|
|
// - the index of the currently focused item is required.
|
|
-// if your SetNextItemSelectionData() values are indices, you can obtain it from ImGuiMultiSelectIO::NavIdItem, otherwise from g.NavLastValidSelectionUserData.
|
|
|
|
|
|
+// if your SetNextItemSelectionUserData() values are indices, you can obtain it from ImGuiMultiSelectIO::NavIdItem, otherwise from g.NavLastValidSelectionUserData.
|
|
int ImGui::TypingSelectFindMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx)
|
|
int ImGui::TypingSelectFindMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx)
|
|
{
|
|
{
|
|
if (req == NULL || req->SelectRequest == false) // Support NULL parameter so both calls can be done from same spot.
|
|
if (req == NULL || req->SelectRequest == false) // Support NULL parameter so both calls can be done from same spot.
|
|
@@ -7165,6 +7168,7 @@ static void BoxSelectPreStartDrag(ImGuiID id, ImGuiSelectionUserData clicked_ite
|
|
bs->ID = id;
|
|
bs->ID = id;
|
|
bs->IsStarting = true; // Consider starting box-select.
|
|
bs->IsStarting = true; // Consider starting box-select.
|
|
bs->IsStartedFromVoid = (clicked_item == ImGuiSelectionUserData_Invalid);
|
|
bs->IsStartedFromVoid = (clicked_item == ImGuiSelectionUserData_Invalid);
|
|
|
|
+ bs->IsStartedSetNavIdOnce = bs->IsStartedFromVoid;
|
|
bs->KeyMods = g.IO.KeyMods;
|
|
bs->KeyMods = g.IO.KeyMods;
|
|
bs->StartPosRel = bs->EndPosRel = ImGui::WindowPosAbsToRel(g.CurrentWindow, g.IO.MousePos);
|
|
bs->StartPosRel = bs->EndPosRel = ImGui::WindowPosAbsToRel(g.CurrentWindow, g.IO.MousePos);
|
|
bs->ScrollAccum = ImVec2(0.0f, 0.0f);
|
|
bs->ScrollAccum = ImVec2(0.0f, 0.0f);
|
|
@@ -7401,7 +7405,6 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel
|
|
if (flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d))
|
|
if (flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d))
|
|
{
|
|
{
|
|
ms->BoxSelectId = GetID("##BoxSelect");
|
|
ms->BoxSelectId = GetID("##BoxSelect");
|
|
- ms->BoxSelectLastitem = ImGuiSelectionUserData_Invalid;
|
|
|
|
if (BeginBoxSelect(window, ms->BoxSelectId, flags))
|
|
if (BeginBoxSelect(window, ms->BoxSelectId, flags))
|
|
request_clear |= bs->RequestClear;
|
|
request_clear |= bs->RequestClear;
|
|
}
|
|
}
|
|
@@ -7430,12 +7433,12 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel
|
|
|
|
|
|
if (request_clear || request_select_all)
|
|
if (request_clear || request_select_all)
|
|
{
|
|
{
|
|
- ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetAll, request_select_all, 0, ImGuiSelectionUserData_Invalid, ImGuiSelectionUserData_Invalid };
|
|
|
|
|
|
+ MultiSelectAddSetAll(ms, request_select_all);
|
|
if (!request_select_all)
|
|
if (!request_select_all)
|
|
storage->LastSelectionSize = 0;
|
|
storage->LastSelectionSize = 0;
|
|
- ms->IO.Requests.push_back(req);
|
|
|
|
}
|
|
}
|
|
ms->LoopRequestSetAll = request_select_all ? 1 : request_clear ? 0 : -1;
|
|
ms->LoopRequestSetAll = request_select_all ? 1 : request_clear ? 0 : -1;
|
|
|
|
+ ms->LastSubmittedItem = ImGuiSelectionUserData_Invalid;
|
|
|
|
|
|
if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)
|
|
if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)
|
|
DebugLogMultiSelectRequests("BeginMultiSelect", &ms->IO);
|
|
DebugLogMultiSelectRequests("BeginMultiSelect", &ms->IO);
|
|
@@ -7500,11 +7503,7 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect()
|
|
|
|
|
|
if (ms->Flags & ImGuiMultiSelectFlags_ClearOnClickVoid)
|
|
if (ms->Flags & ImGuiMultiSelectFlags_ClearOnClickVoid)
|
|
if (IsMouseReleased(0) && IsMouseDragPastThreshold(0) == false && g.IO.KeyMods == ImGuiMod_None)
|
|
if (IsMouseReleased(0) && IsMouseDragPastThreshold(0) == false && g.IO.KeyMods == ImGuiMod_None)
|
|
- {
|
|
|
|
- ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetAll, false, 0, ImGuiSelectionUserData_Invalid, ImGuiSelectionUserData_Invalid };
|
|
|
|
- ms->IO.Requests.resize(0);
|
|
|
|
- ms->IO.Requests.push_back(req);
|
|
|
|
- }
|
|
|
|
|
|
+ MultiSelectAddSetAll(ms, false);
|
|
}
|
|
}
|
|
|
|
|
|
// Courtesy nav wrapping helper flag
|
|
// Courtesy nav wrapping helper flag
|
|
@@ -7691,24 +7690,18 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
|
const bool rect_overlap_prev = bs->BoxSelectRectPrev.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 ((rect_overlap_curr && !rect_overlap_prev && !selected) || (rect_overlap_prev && !rect_overlap_curr))
|
|
{
|
|
{
|
|
- if (storage->LastSelectionSize <= 0 && bs->IsStartedFromVoid)
|
|
|
|
|
|
+ if (storage->LastSelectionSize <= 0 && bs->IsStartedSetNavIdOnce)
|
|
{
|
|
{
|
|
pressed = true; // First item act as a pressed: code below will emit selection request and set NavId (whatever we emit here will be overridden anyway)
|
|
pressed = true; // First item act as a pressed: code below will emit selection request and set NavId (whatever we emit here will be overridden anyway)
|
|
|
|
+ bs->IsStartedSetNavIdOnce = false;
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
selected = !selected;
|
|
selected = !selected;
|
|
- ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetRange, selected, +1, item_data, item_data };
|
|
|
|
- // Merge continuous ranges (unless NoRangeSelect is set)
|
|
|
|
- ImGuiSelectionRequest* prev = ms->IO.Requests.Size > 0 ? &ms->IO.Requests.Data[ms->IO.Requests.Size - 1] : NULL;
|
|
|
|
- if (prev && prev->Type == ImGuiSelectionRequestType_SetRange && prev->RangeLastItem == ms->BoxSelectLastitem && prev->Selected == selected && (ms->Flags & ImGuiMultiSelectFlags_NoRangeSelect) == 0)
|
|
|
|
- prev->RangeLastItem = item_data; // Merge span into same request
|
|
|
|
- else
|
|
|
|
- ms->IO.Requests.push_back(req);
|
|
|
|
|
|
+ MultiSelectAddSetRange(ms, selected, +1, item_data, item_data);
|
|
}
|
|
}
|
|
storage->LastSelectionSize = ImMax(storage->LastSelectionSize + 1, 1);
|
|
storage->LastSelectionSize = ImMax(storage->LastSelectionSize + 1, 1);
|
|
}
|
|
}
|
|
- ms->BoxSelectLastitem = item_data;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
// Right-click handling.
|
|
// Right-click handling.
|
|
@@ -7766,11 +7759,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
|
else if ((input_source == ImGuiInputSource_Keyboard || input_source == ImGuiInputSource_Gamepad) && is_shift && !is_ctrl)
|
|
else if ((input_source == ImGuiInputSource_Keyboard || input_source == ImGuiInputSource_Gamepad) && is_shift && !is_ctrl)
|
|
request_clear = true; // With is_shift==false the RequestClear was done in BeginIO, not necessary to do again.
|
|
request_clear = true; // With is_shift==false the RequestClear was done in BeginIO, not necessary to do again.
|
|
if (request_clear)
|
|
if (request_clear)
|
|
- {
|
|
|
|
- ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetAll, false, 0, ImGuiSelectionUserData_Invalid, ImGuiSelectionUserData_Invalid };
|
|
|
|
- ms->IO.Requests.resize(0);
|
|
|
|
- ms->IO.Requests.push_back(req);
|
|
|
|
- }
|
|
|
|
|
|
+ MultiSelectAddSetAll(ms, false);
|
|
}
|
|
}
|
|
|
|
|
|
int range_direction;
|
|
int range_direction;
|
|
@@ -7808,9 +7797,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
|
range_selected = selected;
|
|
range_selected = selected;
|
|
range_direction = +1;
|
|
range_direction = +1;
|
|
}
|
|
}
|
|
- ImGuiSelectionUserData range_dst_item = item_data;
|
|
|
|
- ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetRange, range_selected, (ImS8)range_direction, (range_direction > 0) ? storage->RangeSrcItem : range_dst_item, (range_direction > 0) ? range_dst_item : storage->RangeSrcItem };
|
|
|
|
- ms->IO.Requests.push_back(req);
|
|
|
|
|
|
+ MultiSelectAddSetRange(ms, range_selected, range_direction, storage->RangeSrcItem, item_data);
|
|
}
|
|
}
|
|
|
|
|
|
// Update/store the selection state of the Source item (used by CTRL+SHIFT, when Source is unselected we perform a range unselect)
|
|
// Update/store the selection state of the Source item (used by CTRL+SHIFT, when Source is unselected we perform a range unselect)
|
|
@@ -7825,11 +7812,36 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
|
}
|
|
}
|
|
if (storage->NavIdItem == item_data)
|
|
if (storage->NavIdItem == item_data)
|
|
ms->NavIdPassedBy = true;
|
|
ms->NavIdPassedBy = true;
|
|
|
|
+ ms->LastSubmittedItem = item_data;
|
|
|
|
|
|
*p_selected = selected;
|
|
*p_selected = selected;
|
|
*p_pressed = pressed;
|
|
*p_pressed = pressed;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void ImGui::MultiSelectAddSetAll(ImGuiMultiSelectTempData* ms, bool selected)
|
|
|
|
+{
|
|
|
|
+ ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetAll, selected, 0, ImGuiSelectionUserData_Invalid, ImGuiSelectionUserData_Invalid };
|
|
|
|
+ ms->IO.Requests.resize(0); // Can always clear previous requests
|
|
|
|
+ ms->IO.Requests.push_back(req); // Add new request
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ImGui::MultiSelectAddSetRange(ImGuiMultiSelectTempData* ms, bool selected, int range_dir, ImGuiSelectionUserData first_item, ImGuiSelectionUserData last_item)
|
|
|
|
+{
|
|
|
|
+ // Merge contiguous spans into same request (unless NoRangeSelect is set which guarantees single-item ranges)
|
|
|
|
+ if (ms->IO.Requests.Size > 0 && first_item == last_item && (ms->Flags & ImGuiMultiSelectFlags_NoRangeSelect) == 0)
|
|
|
|
+ {
|
|
|
|
+ ImGuiSelectionRequest* prev = &ms->IO.Requests.Data[ms->IO.Requests.Size - 1];
|
|
|
|
+ if (prev->Type == ImGuiSelectionRequestType_SetRange && prev->RangeLastItem == ms->LastSubmittedItem && prev->Selected == selected)
|
|
|
|
+ {
|
|
|
|
+ prev->RangeLastItem = last_item;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetRange, selected, (ImS8)range_dir, (range_dir > 0) ? first_item : last_item, (range_dir > 0) ? last_item : first_item };
|
|
|
|
+ ms->IO.Requests.push_back(req); // Add new request
|
|
|
|
+}
|
|
|
|
+
|
|
void ImGui::DebugNodeMultiSelectState(ImGuiMultiSelectState* storage)
|
|
void ImGui::DebugNodeMultiSelectState(ImGuiMultiSelectState* storage)
|
|
{
|
|
{
|
|
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|
|
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
|