mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-27 16:29:02 +08:00
MultiSelect: Added ImGuiMultiSelectFlags_SelectOnClickRelease to allow dragging an unselected item without altering selection + update drag and drop demo.
This commit is contained in:
parent
5628dda5a5
commit
82de6c470b
2
imgui.h
2
imgui.h
@ -2736,6 +2736,8 @@ enum ImGuiMultiSelectFlags_
|
||||
ImGuiMultiSelectFlags_ClearOnEscape = 1 << 2, // Clear selection when pressing Escape while scope is focused.
|
||||
ImGuiMultiSelectFlags_ClearOnClickWindowVoid= 1 << 3, // Clear selection when clicking on empty location within host window (use if BeginMultiSelect() covers a whole window)
|
||||
//ImGuiMultiSelectFlags_ClearOnClickRectVoid= 1 << 4, // Clear selection when clicking on empty location within rectangle covered by selection scope (use if multiple BeginMultiSelect() are used in the same host window)
|
||||
ImGuiMultiSelectFlags_SelectOnClick = 1 << 5, // Apply selection on mouse down when clicking on unselected item. (Default)
|
||||
ImGuiMultiSelectFlags_SelectOnClickRelease = 1 << 6, // Apply selection on mouse release when clicking an unselected item. Allow dragging an unselected item without altering selection.
|
||||
};
|
||||
|
||||
// Multi-selection system
|
||||
|
@ -3338,6 +3338,7 @@ static void ShowDemoWindowMultiSelect()
|
||||
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoSelectAll", &flags, ImGuiMultiSelectFlags_NoSelectAll);
|
||||
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnEscape", &flags, ImGuiMultiSelectFlags_ClearOnEscape);
|
||||
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnClickWindowVoid", &flags, ImGuiMultiSelectFlags_ClearOnClickWindowVoid);
|
||||
ImGui::CheckboxFlags("ImGuiMultiSelectFlags_SelectOnClickRelease", &flags, ImGuiMultiSelectFlags_SelectOnClickRelease); ImGui::SameLine(); HelpMarker("Allow dragging an unselected item without altering selection.");
|
||||
|
||||
// Initialize default list with 1000 items.
|
||||
static ImVector<int> items;
|
||||
@ -3403,11 +3404,11 @@ static void ShowDemoWindowMultiSelect()
|
||||
// IMPORTANT: for deletion refocus to work we need object ID to be stable,
|
||||
// aka not depend on their index in the list. Here we use our persistent item_id
|
||||
// instead of index to build a unique ID that will persist.
|
||||
// (If we used PushID(n) instead, focus wouldn't be restored correctly after deletion).
|
||||
// (If we used PushID(index) instead, focus wouldn't be restored correctly after deletion).
|
||||
ImGui::PushID(item_id);
|
||||
|
||||
// Emit a color button, to test that Shift+LeftArrow landing on an item that is not part
|
||||
// of the selection scope doesn't erroneously alter our selection (FIXME-TESTS: Add a test for that!).
|
||||
// of the selection scope doesn't erroneously alter our selection.
|
||||
if (show_color_button)
|
||||
{
|
||||
ImU32 dummy_col = (ImU32)((unsigned int)n * 0xC250B74B) | IM_COL32_A_MASK;
|
||||
@ -3415,39 +3416,57 @@ static void ShowDemoWindowMultiSelect()
|
||||
ImGui::SameLine();
|
||||
}
|
||||
|
||||
// Submit item
|
||||
bool item_is_selected = selection.Contains((ImGuiID)n);
|
||||
bool item_is_open = false;
|
||||
ImGui::SetNextItemSelectionUserData(n);
|
||||
if (widget_type == WidgetType_Selectable)
|
||||
{
|
||||
ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_None;
|
||||
ImGui::Selectable(label, item_is_selected, selectable_flags);
|
||||
if (item_curr_idx_to_focus == n)
|
||||
ImGui::SetKeyboardFocusHere(-1);
|
||||
|
||||
if (use_drag_drop && ImGui::BeginDragDropSource())
|
||||
{
|
||||
ImGui::Text("(Dragging %d items)", selection.GetSize());
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
ImGui::Selectable(label, item_is_selected, ImGuiSelectableFlags_None);
|
||||
}
|
||||
else if (widget_type == WidgetType_TreeNode)
|
||||
{
|
||||
ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAvailWidth;
|
||||
tree_node_flags |= ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
|
||||
ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
|
||||
if (item_is_selected)
|
||||
tree_node_flags |= ImGuiTreeNodeFlags_Selected;
|
||||
bool open = ImGui::TreeNodeEx(label, tree_node_flags);
|
||||
if (item_curr_idx_to_focus == n)
|
||||
ImGui::SetKeyboardFocusHere(-1);
|
||||
if (use_drag_drop && ImGui::BeginDragDropSource())
|
||||
{
|
||||
ImGui::Text("(Dragging %d items)", selection.GetSize());
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
if (open)
|
||||
ImGui::TreePop();
|
||||
item_is_open = ImGui::TreeNodeEx(label, tree_node_flags);
|
||||
}
|
||||
|
||||
// Focus (for after deletion)
|
||||
if (item_curr_idx_to_focus == n)
|
||||
ImGui::SetKeyboardFocusHere(-1);
|
||||
|
||||
// Drag and Drop
|
||||
if (use_drag_drop && ImGui::BeginDragDropSource())
|
||||
{
|
||||
// Write payload with full selection OR single unselected item (only possible with ImGuiMultiSelectFlags_SelectOnClickRelease)
|
||||
if (ImGui::GetDragDropPayload() == NULL)
|
||||
{
|
||||
ImVector<int> payload_items;
|
||||
if (!item_is_selected)
|
||||
payload_items.push_back(item_id);
|
||||
else
|
||||
for (const ImGuiStoragePair& pair : selection.Storage.Data)
|
||||
if (pair.val_i)
|
||||
payload_items.push_back((int)pair.key);
|
||||
ImGui::SetDragDropPayload("MULTISELECT_DEMO_ITEMS", payload_items.Data, (size_t)payload_items.size_in_bytes());
|
||||
}
|
||||
|
||||
// Display payload content in tooltip
|
||||
const ImGuiPayload* payload = ImGui::GetDragDropPayload();
|
||||
const int* payload_items = (int*)payload->Data;
|
||||
const int payload_count = (int)payload->DataSize / (int)sizeof(payload_items[0]);
|
||||
if (payload_count == 1)
|
||||
ImGui::Text("Object %05d: %s", payload_items[0], ExampleNames[payload_items[0] % IM_ARRAYSIZE(ExampleNames)]);
|
||||
else
|
||||
ImGui::Text("Dragging %d objects", payload_count);
|
||||
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
if (widget_type == WidgetType_TreeNode && item_is_open)
|
||||
ImGui::TreePop();
|
||||
|
||||
// Right-click: context menu
|
||||
if (ImGui::BeginPopupContextItem())
|
||||
{
|
||||
|
@ -7306,10 +7306,9 @@ void ImGui::MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags
|
||||
// Alter button behavior flags
|
||||
// To handle drag and drop of multiple items we need to avoid clearing selection on click.
|
||||
// Enabling this test makes actions using CTRL+SHIFT delay their effect on MouseUp which is annoying, but it allows drag and drop of multiple items.
|
||||
// FIXME-MULTISELECT: Consider opt-in for drag and drop behavior in ImGuiMultiSelectFlags?
|
||||
ImGuiButtonFlags button_flags = *p_button_flags;
|
||||
button_flags |= ImGuiButtonFlags_NoHoveredOnFocus;
|
||||
if (!selected || (g.ActiveId == id && g.ActiveIdHasBeenPressedBefore))
|
||||
if ((!selected || (g.ActiveId == id && g.ActiveIdHasBeenPressedBefore)) && !(ms->Flags & ImGuiMultiSelectFlags_SelectOnClickRelease))
|
||||
button_flags = (button_flags | ImGuiButtonFlags_PressedOnClick) & ~ImGuiButtonFlags_PressedOnClickRelease;
|
||||
else
|
||||
button_flags |= ImGuiButtonFlags_PressedOnClickRelease;
|
||||
|
Loading…
Reference in New Issue
Block a user