mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-04 12:08:47 +02:00
Drag and Drop: Added ImGuiDragDropFlags_SourceExtern to facilitate interfacing with WM_DROPFILES (#143)
This commit is contained in:
83
imgui.cpp
83
imgui.cpp
@ -11220,50 +11220,67 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
if (g.IO.MouseDown[mouse_button] == false)
|
||||
return false;
|
||||
|
||||
ImGuiID id = window->DC.LastItemId;
|
||||
if (id == 0)
|
||||
bool source_drag_active = false;
|
||||
ImGuiID source_id = 0;
|
||||
ImGuiID source_parent_id = 0;
|
||||
if (!(flags & ImGuiDragDropFlags_SourceExtern))
|
||||
{
|
||||
// If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to:
|
||||
// A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag, C) Swallow your programmer pride.
|
||||
if (!(flags & ImGuiDragDropFlags_SourceAllowNullID))
|
||||
{
|
||||
IM_ASSERT(0);
|
||||
source_id = window->DC.LastItemId;
|
||||
if (source_id != 0 && g.ActiveId != source_id) // Early out for most common case
|
||||
return false;
|
||||
if (g.IO.MouseDown[mouse_button] == false)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image()
|
||||
// We build a throwaway ID based on current ID stack + relative AABB of items in window.
|
||||
// THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled.
|
||||
// We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive.
|
||||
bool is_hovered = window->DC.LastItemRectHoveredRect;
|
||||
if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window))
|
||||
return false;
|
||||
id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect);
|
||||
if (is_hovered)
|
||||
SetHoveredID(id);
|
||||
if (is_hovered && g.IO.MouseClicked[mouse_button])
|
||||
if (source_id == 0)
|
||||
{
|
||||
SetActiveID(id, window);
|
||||
FocusWindow(window);
|
||||
// If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to:
|
||||
// A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag, C) Swallow your programmer pride.
|
||||
if (!(flags & ImGuiDragDropFlags_SourceAllowNullID))
|
||||
{
|
||||
IM_ASSERT(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image()
|
||||
// We build a throwaway ID based on current ID stack + relative AABB of items in window.
|
||||
// THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled.
|
||||
// We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive.
|
||||
bool is_hovered = window->DC.LastItemRectHoveredRect;
|
||||
if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window))
|
||||
return false;
|
||||
source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect);
|
||||
if (is_hovered)
|
||||
SetHoveredID(source_id);
|
||||
if (is_hovered && g.IO.MouseClicked[mouse_button])
|
||||
{
|
||||
SetActiveID(source_id, window);
|
||||
FocusWindow(window);
|
||||
}
|
||||
if (g.ActiveId == source_id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker.
|
||||
g.ActiveIdAllowOverlap = is_hovered;
|
||||
}
|
||||
if (g.ActiveId == id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker.
|
||||
g.ActiveIdAllowOverlap = is_hovered;
|
||||
if (g.ActiveId != source_id)
|
||||
return false;
|
||||
source_parent_id = window->IDStack.back();
|
||||
source_drag_active = IsMouseDragging(mouse_button);
|
||||
}
|
||||
else
|
||||
{
|
||||
window = NULL;
|
||||
source_id = ImHash("#SourceExtern", 0);
|
||||
source_drag_active = true;
|
||||
}
|
||||
if (g.ActiveId != id)
|
||||
return false;
|
||||
|
||||
if (IsMouseDragging(mouse_button))
|
||||
if (source_drag_active)
|
||||
{
|
||||
if (!g.DragDropActive)
|
||||
{
|
||||
IM_ASSERT(id != 0);
|
||||
IM_ASSERT(source_id != 0);
|
||||
ClearDragDrop();
|
||||
ImGuiPayload& payload = g.DragDropPayload;
|
||||
payload.SourceId = id;
|
||||
payload.SourceParentId = window->IDStack.back();
|
||||
payload.SourceId = source_id;
|
||||
payload.SourceParentId = source_parent_id;
|
||||
g.DragDropActive = true;
|
||||
g.DragDropSourceFlags = flags;
|
||||
g.DragDropMouseButton = mouse_button;
|
||||
@ -11279,7 +11296,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button)
|
||||
BeginTooltipEx(ImGuiWindowFlags_NoInputs);
|
||||
}
|
||||
|
||||
if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover))
|
||||
if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern))
|
||||
window->DC.LastItemRectHoveredRect = false;
|
||||
|
||||
return true;
|
||||
@ -11434,7 +11451,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop
|
||||
}
|
||||
|
||||
g.DragDropAcceptFrameCount = g.FrameCount;
|
||||
payload.Delivery = was_accepted_previously && IsMouseReleased(g.DragDropMouseButton);
|
||||
payload.Delivery = was_accepted_previously && !IsMouseDown(g.DragDropMouseButton); // For extern drag sources affecting os window focus, it's easier to just test !IsMouseDown() instead of IsMouseReleased()
|
||||
if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery))
|
||||
return NULL;
|
||||
|
||||
|
Reference in New Issue
Block a user