mirror of
https://github.com/Drezil/imgui.git
synced 2024-12-19 14:36:34 +00:00
Docking: Making it possible to undock a node by clicking on the tab bar / title bar for the node. (#2645, #2109)
This commit is contained in:
parent
56e10f1c35
commit
bb2aa5e770
43
imgui.cpp
43
imgui.cpp
@ -3403,6 +3403,32 @@ void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
|
|||||||
g.MovingWindow = window;
|
g.MovingWindow = window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImGui::StartMouseDragFromTitleBar(ImGuiWindow* window, ImGuiDockNode* node, bool from_collapse_button)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
bool can_extract_dock_node = false;
|
||||||
|
if (node != NULL && node->VisibleWindow && (node->VisibleWindow->Flags & ImGuiWindowFlags_NoMove) == 0)
|
||||||
|
{
|
||||||
|
ImGuiDockNode* root_node = DockNodeGetRootNode(node);
|
||||||
|
if (root_node->OnlyNodeWithWindows != node || (root_node->CentralNode != NULL))
|
||||||
|
if (from_collapse_button || root_node->IsDockSpace())
|
||||||
|
can_extract_dock_node = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool clicked = IsMouseClicked(0);
|
||||||
|
const bool dragging = IsMouseDragging(0, g.IO.MouseDragThreshold * 1.70f);
|
||||||
|
if (can_extract_dock_node && dragging)
|
||||||
|
{
|
||||||
|
DockContextQueueUndockNode(&g, node);
|
||||||
|
g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - node->Pos;
|
||||||
|
}
|
||||||
|
else if (!can_extract_dock_node && (clicked || dragging) && g.MovingWindow != window)
|
||||||
|
{
|
||||||
|
StartMouseMovingWindow(window);
|
||||||
|
g.ActiveIdClickOffset = g.IO.MouseClickedPos[0] - window->RootWindow->Pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Handle mouse moving window
|
// Handle mouse moving window
|
||||||
// Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing()
|
// Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing()
|
||||||
void ImGui::UpdateMouseMovingWindowNewFrame()
|
void ImGui::UpdateMouseMovingWindowNewFrame()
|
||||||
@ -12802,15 +12828,20 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
|
|||||||
}
|
}
|
||||||
|
|
||||||
// When clicking on the title bar outside of tabs, we still focus the selected tab for that node
|
// When clicking on the title bar outside of tabs, we still focus the selected tab for that node
|
||||||
if (g.HoveredWindow == host_window && g.HoveredId == 0 && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max))
|
// FIXME: TabItem use AllowItemOverlap so we manually perform a more specific test for now (hovered || held)
|
||||||
|
ImGuiID title_bar_id = host_window->GetID("#TITLEBAR");
|
||||||
|
if (g.HoveredId == 0 || g.HoveredId == title_bar_id || g.ActiveId == title_bar_id)
|
||||||
|
{
|
||||||
|
bool held;
|
||||||
|
ButtonBehavior(title_bar_rect, title_bar_id, NULL, &held);
|
||||||
|
if (held)
|
||||||
{
|
{
|
||||||
if (IsMouseClicked(0))
|
if (IsMouseClicked(0))
|
||||||
{
|
|
||||||
focus_tab_id = tab_bar->SelectedTabId;
|
focus_tab_id = tab_bar->SelectedTabId;
|
||||||
|
|
||||||
// Forward moving request to selected window
|
// Forward moving request to selected window
|
||||||
if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, focus_tab_id))
|
if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
|
||||||
StartMouseMovingWindow(tab->Window);
|
StartMouseDragFromTitleBar(tab->Window, node, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13418,7 +13449,7 @@ void ImGui::DockNodeTreeUpdateSplitter(ImGuiDockNode* node)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
// [DEBUG] Render limits
|
// [DEBUG] Render limits
|
||||||
ImDrawList* draw_list = node->HostWindow ? GetOverlayDrawList(node->HostWindow) : GetOverlayDrawList((ImGuiViewportP*)GetMainViewport());
|
ImDrawList* draw_list = node->HostWindow ? GetForegroundDrawList(node->HostWindow) : GetForegroundDrawList((ImGuiViewportP*)GetMainViewport());
|
||||||
for (int n = 0; n < 2; n++)
|
for (int n = 0; n < 2; n++)
|
||||||
if (axis == ImGuiAxis_X)
|
if (axis == ImGuiAxis_X)
|
||||||
draw_list->AddLine(ImVec2(resize_limits[n], node->ChildNodes[n]->Pos.y), ImVec2(resize_limits[n], node->ChildNodes[n]->Pos.y + node->ChildNodes[n]->Size.y), IM_COL32(255, 0, 255, 255), 3.0f);
|
draw_list->AddLine(ImVec2(resize_limits[n], node->ChildNodes[n]->Pos.y), ImVec2(resize_limits[n], node->ChildNodes[n]->Pos.y + node->ChildNodes[n]->Size.y), IM_COL32(255, 0, 255, 255), 3.0f);
|
||||||
@ -13446,7 +13477,7 @@ void ImGui::DockNodeTreeUpdateSplitter(ImGuiDockNode* node)
|
|||||||
for (int touching_node_n = 0; touching_node_n < touching_nodes[side_n].Size; touching_node_n++)
|
for (int touching_node_n = 0; touching_node_n < touching_nodes[side_n].Size; touching_node_n++)
|
||||||
{
|
{
|
||||||
ImGuiDockNode* touching_node = touching_nodes[side_n][touching_node_n];
|
ImGuiDockNode* touching_node = touching_nodes[side_n][touching_node_n];
|
||||||
//ImDrawList* draw_list = node->HostWindow ? GetOverlayDrawList(node->HostWindow) : GetOverlayDrawList((ImGuiViewportP*)GetMainViewport());
|
//ImDrawList* draw_list = node->HostWindow ? GetForegroundDrawList(node->HostWindow) : GetForegroundDrawList((ImGuiViewportP*)GetMainViewport());
|
||||||
//draw_list->AddRect(touching_node->Pos, touching_node->Pos + touching_node->Size, IM_COL32(255, 128, 0, 255));
|
//draw_list->AddRect(touching_node->Pos, touching_node->Pos + touching_node->Size, IM_COL32(255, 128, 0, 255));
|
||||||
while (touching_node->ParentNode != node)
|
while (touching_node->ParentNode != node)
|
||||||
{
|
{
|
||||||
|
@ -1661,6 +1661,7 @@ namespace ImGui
|
|||||||
// NewFrame
|
// NewFrame
|
||||||
IMGUI_API void UpdateHoveredWindowAndCaptureFlags();
|
IMGUI_API void UpdateHoveredWindowAndCaptureFlags();
|
||||||
IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window);
|
IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window);
|
||||||
|
IMGUI_API void StartMouseDragFromTitleBar(ImGuiWindow* window, ImGuiDockNode* node, bool from_collapse_button);
|
||||||
IMGUI_API void UpdateMouseMovingWindowNewFrame();
|
IMGUI_API void UpdateMouseMovingWindowNewFrame();
|
||||||
IMGUI_API void UpdateMouseMovingWindowEndFrame();
|
IMGUI_API void UpdateMouseMovingWindowEndFrame();
|
||||||
|
|
||||||
|
@ -776,30 +776,7 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_no
|
|||||||
|
|
||||||
// Switch to moving the window after mouse is moved beyond the initial drag threshold
|
// Switch to moving the window after mouse is moved beyond the initial drag threshold
|
||||||
if (IsItemActive() && IsMouseDragging(0))
|
if (IsItemActive() && IsMouseDragging(0))
|
||||||
{
|
StartMouseDragFromTitleBar(window, dock_node, true);
|
||||||
bool can_extract_dock_node = false;
|
|
||||||
if (dock_node != NULL && dock_node->VisibleWindow && !(dock_node->VisibleWindow->Flags & ImGuiWindowFlags_NoMove))
|
|
||||||
{
|
|
||||||
ImGuiDockNode* root_node = DockNodeGetRootNode(dock_node);
|
|
||||||
if (root_node->OnlyNodeWithWindows != dock_node || (root_node->CentralNode != NULL))
|
|
||||||
can_extract_dock_node = true;
|
|
||||||
}
|
|
||||||
if (can_extract_dock_node)
|
|
||||||
{
|
|
||||||
float threshold_base = g.FontSize;
|
|
||||||
float threshold_x = (threshold_base * 2.2f);
|
|
||||||
float threshold_y = (threshold_base * 1.5f);
|
|
||||||
IM_ASSERT(window->DockNodeAsHost != NULL);
|
|
||||||
if (g.IO.MouseDragMaxDistanceAbs[0].x > threshold_x || g.IO.MouseDragMaxDistanceAbs[0].y > threshold_y)
|
|
||||||
DockContextQueueUndockNode(&g, dock_node);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ImVec2 backup_active_click_offset = g.ActiveIdClickOffset + (pos - window->Pos);
|
|
||||||
StartMouseMovingWindow(window);
|
|
||||||
g.ActiveIdClickOffset = backup_active_click_offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pressed;
|
return pressed;
|
||||||
}
|
}
|
||||||
@ -7048,7 +7025,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
|||||||
//float threshold_base = g.IO.ConfigDockingWithShift ? g.FontSize * 0.5f : g.FontSize;
|
//float threshold_base = g.IO.ConfigDockingWithShift ? g.FontSize * 0.5f : g.FontSize;
|
||||||
float threshold_x = (threshold_base * 2.2f);
|
float threshold_x = (threshold_base * 2.2f);
|
||||||
float threshold_y = (threshold_base * 1.5f) + ImClamp((ImFabs(g.IO.MouseDragMaxDistanceAbs[0].x) - threshold_base * 2.0f) * 0.20f, 0.0f, threshold_base * 4.0f);
|
float threshold_y = (threshold_base * 1.5f) + ImClamp((ImFabs(g.IO.MouseDragMaxDistanceAbs[0].x) - threshold_base * 2.0f) * 0.20f, 0.0f, threshold_base * 4.0f);
|
||||||
//GetOverlayDrawList(window)->AddRect(ImVec2(bb.Min.x - threshold_x, bb.Min.y - threshold_y), ImVec2(bb.Max.x + threshold_x, bb.Max.y + threshold_y), IM_COL32_WHITE); // [DEBUG]
|
//GetForegroundDrawList()->AddRect(ImVec2(bb.Min.x - threshold_x, bb.Min.y - threshold_y), ImVec2(bb.Max.x + threshold_x, bb.Max.y + threshold_y), IM_COL32_WHITE); // [DEBUG]
|
||||||
|
|
||||||
float distance_from_edge_y = ImMax(bb.Min.y - g.IO.MousePos.y, g.IO.MousePos.y - bb.Max.y);
|
float distance_from_edge_y = ImMax(bb.Min.y - g.IO.MousePos.y, g.IO.MousePos.y - bb.Max.y);
|
||||||
if (distance_from_edge_y >= threshold_y)
|
if (distance_from_edge_y >= threshold_y)
|
||||||
|
Loading…
Reference in New Issue
Block a user