Docking: Added SetNextWindowUserType() + user type filtering in dockspace and window merging. Added DockSpace() flag ImGuiDockFlags_NoSplit. Renaming. Reworked the DockNodeUpdateFindOnlyNodeWithWindows code so DockNodeUpdate can access the first window.

This commit is contained in:
omar 2018-09-10 12:07:29 +02:00
parent b872aa5c8e
commit a68c98bb67
3 changed files with 65 additions and 26 deletions

View File

@ -2371,6 +2371,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name)
HiddenFramesRegular = HiddenFramesForResize = 0;
SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = SetWindowDockAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing;
SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX);
UserTypeId = 0;
LastFrameActive = -1;
ItemWidthDefault = 0.0f;
@ -3350,7 +3351,7 @@ void ImGui::NewFrame()
// Undocking
// (needs to be before UpdateMovingWindow so the window is already offset and following the mouse on the detaching frame)
DockContextUpdateUndocking(g.DockContext);
DockContextNewFrameUpdateUndocking(g.DockContext);
// Find hovered window
// (needs to be before UpdateMovingWindow so we fill HoveredWindowUnderMovingWindow on the mouse release frame)
@ -3404,7 +3405,7 @@ void ImGui::NewFrame()
ClosePopupsOverWindow(g.NavWindow);
// Docking
DockContextUpdateDocking(g.DockContext);
DockContextNewFrameUpdateDocking(g.DockContext);
// Create implicit window - we will only render it if the user has added something to it.
// We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
@ -4954,6 +4955,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
{
window->SizeContentsExplicit = ImVec2(0.0f, 0.0f);
}
window->UserTypeId = g.NextWindowData.UserTypeId;
if (g.NextWindowData.CollapsedCond)
SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond);
if (g.NextWindowData.FocusCond)
@ -6320,6 +6322,12 @@ void ImGui::SetNextWindowDock(ImGuiID id, ImGuiCond cond)
g.NextWindowData.DockId = id;
}
void ImGui::SetNextWindowUserType(ImGuiID user_type)
{
ImGuiContext& g = *GImGui;
g.NextWindowData.UserTypeId = user_type;
}
// In window space (not screen space!)
ImVec2 ImGui::GetContentRegionMax()
{
@ -9580,7 +9588,6 @@ namespace ImGui
static void DockNodeRemoveWindow(ImGuiDockNode* node, ImGuiWindow* window, ImGuiID save_dock_id);
static void DockNodeHideHostWindow(ImGuiDockNode* node);
static void DockNodeUpdate(ImGuiDockNode* node);
static ImGuiDockNode* DockNodeUpdateFindOnlyNodeWithWindows(ImGuiDockNode* node);
static void DockNodeUpdateVisibleFlagAndInactiveChilds(ImGuiDockNode* node);
static void DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_window);
static void DockNodeUpdateVisibleFlag(ImGuiDockNode* node);
@ -9656,7 +9663,7 @@ void ImGui::DockContextRebuild(ImGuiDockContext* ctx)
DockContextBuildAddWindowsToNodes(ctx);
}
void ImGui::DockContextUpdateUndocking(ImGuiDockContext* ctx)
void ImGui::DockContextNewFrameUpdateUndocking(ImGuiDockContext* ctx)
{
ImGuiContext& g = *GImGui;
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
@ -9682,7 +9689,7 @@ void ImGui::DockContextUpdateUndocking(ImGuiDockContext* ctx)
DockContextProcessUndock(ctx, ctx->Requests[n].WindowUndock);
}
void ImGui::DockContextUpdateDocking(ImGuiDockContext* ctx)
void ImGui::DockContextNewFrameUpdateDocking(ImGuiDockContext* ctx)
{
ImGuiContext& g = *GImGui;
if (!(g.IO.ConfigFlags & ImGuiConfigFlags_DockingEnable))
@ -10000,6 +10007,8 @@ void ImGui::DockContextProcessUndock(ImGuiDockContext* ctx, ImGuiWindow* window)
ImGuiDockNode::ImGuiDockNode(ImGuiID id)
{
ID = id;
UserTypeIdFilter = 0;
Flags = 0;
ParentNode = ChildNodes[0] = ChildNodes[1] = NULL;
TabBar = NULL;
SplitAxis = ImGuiAxis_None;
@ -10197,28 +10206,20 @@ static void ImGui::DockNodeHideHostWindow(ImGuiDockNode* node)
}
}
static void DockNodeUpdateFindOnlyNodeWithWindowsRec(ImGuiDockNode* node, int* p_count, ImGuiDockNode** p_only_node_with_windows)
static void DockNodeUpdateFindOnlyNodeWithWindowsRec(ImGuiDockNode* node, int* p_count, ImGuiDockNode** p_first_node_with_windows)
{
if (node->Windows.Size > 0)
{
if (*p_only_node_with_windows == NULL)
*p_only_node_with_windows = node;
if (*p_first_node_with_windows == NULL)
*p_first_node_with_windows = node;
(*p_count)++;
}
if (*p_count > 1)
return;
if (node->ChildNodes[0])
DockNodeUpdateFindOnlyNodeWithWindowsRec(node->ChildNodes[0], p_count, p_only_node_with_windows);
DockNodeUpdateFindOnlyNodeWithWindowsRec(node->ChildNodes[0], p_count, p_first_node_with_windows);
if (node->ChildNodes[1])
DockNodeUpdateFindOnlyNodeWithWindowsRec(node->ChildNodes[1], p_count, p_only_node_with_windows);
}
static ImGuiDockNode* ImGui::DockNodeUpdateFindOnlyNodeWithWindows(ImGuiDockNode* node)
{
int count = 0;
ImGuiDockNode* only_node_with_windows = NULL;
DockNodeUpdateFindOnlyNodeWithWindowsRec(node, &count, &only_node_with_windows);
return (count == 1 ? only_node_with_windows : NULL);
DockNodeUpdateFindOnlyNodeWithWindowsRec(node->ChildNodes[1], p_count, p_first_node_with_windows);
}
static void ImGui::DockNodeUpdateVisibleFlagAndInactiveChilds(ImGuiDockNode* node)
@ -10280,8 +10281,19 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node)
if (node->IsRootNode())
{
DockNodeUpdateVisibleFlagAndInactiveChilds(node);
ImGuiDockNode* only_node_with_windows = node->IsExplicitRoot ? NULL : DockNodeUpdateFindOnlyNodeWithWindows(node);
node->OnlyNodeWithWindows = only_node_with_windows;
// Find if there's only a single visible window in the hierarchy (in which case we need to display a regular title bar, FIXME-DOCK: Not done yet!)
if (!node->IsExplicitRoot)
{
int count = 0;
ImGuiDockNode* first_node_with_windows = NULL;
DockNodeUpdateFindOnlyNodeWithWindowsRec(node, &count, &first_node_with_windows);
node->OnlyNodeWithWindows = (count == 1 ? first_node_with_windows : NULL);
// Copy the user type from _any_ of our window so it can be used for proper dock filtering.
if (first_node_with_windows)
node->UserTypeIdFilter = first_node_with_windows->Windows[0]->UserTypeId;
}
}
// Early out for standalone floating window that are holding on a DockId (with an invisible dock node)
@ -10640,6 +10652,11 @@ static bool ImGui::DockNodeIsDropAllowed(ImGuiWindow* host_window, ImGuiWindow*
ImGuiWindow* payload = root_payload->DockNodeAsHost ? root_payload->DockNodeAsHost->Windows[payload_n] : root_payload;
if ((host_window->Flags & ImGuiWindowFlags_DockNodeHost) && payload->BeginOrderWithinContext < host_window->BeginOrderWithinContext)
continue;
ImGuiID host_user_type_id = host_window->DockNodeAsHost ? host_window->DockNodeAsHost->UserTypeIdFilter : host_window->UserTypeId;
if (payload->UserTypeId != host_user_type_id)
return false;
return true;
}
return false;
@ -10756,6 +10773,8 @@ static bool ImGui::DockNodePreviewDockCalc(ImGuiWindow* host_window, ImGuiDockNo
data->IsCenterAvailable = false;
data->IsSidesAvailable = true;
if (host_node && (host_node->Flags & ImGuiDockFlags_NoSplit))
data->IsSidesAvailable = false;
if (!is_outer_docking && host_node && host_node->ParentNode == NULL && host_node->IsDocumentRoot)
data->IsSidesAvailable = false;
@ -10871,6 +10890,9 @@ static void ImGui::DockNodePreviewDockRender(ImGuiWindow* host_window, ImGuiDock
}
}
if (host_node && (host_node->Flags & ImGuiDockFlags_NoSplit))
return;
// Display drop boxes
const float overlay_rounding = ImMax(3.0f, g.Style.FrameRounding);
for (int dir = ImGuiDir_None; dir < ImGuiDir_COUNT; dir++)
@ -11189,7 +11211,7 @@ void ImGui::SetWindowDock(ImGuiWindow* window, ImGuiID dock_id, ImGuiCond cond)
window->DockId = dock_id;
}
void ImGui::DockSpace(const char* str_id, const ImVec2& size_arg)
void ImGui::DockSpace(const char* str_id, const ImVec2& size_arg, ImGuiDockFlags dock_flags, ImGuiID user_type_filter)
{
ImGuiContext& g = *GImGui;
ImGuiDockContext* ctx = g.DockContext;
@ -11204,6 +11226,8 @@ void ImGui::DockSpace(const char* str_id, const ImVec2& size_arg)
node = DockContextAddNode(ctx, id);
node->IsDocumentRoot = true;
}
node->Flags = dock_flags;
node->UserTypeIdFilter = user_type_filter;
node->IsExplicitRoot = true;
const ImVec2 content_avail = GetContentRegionAvail();
@ -11235,6 +11259,7 @@ void ImGui::DockSpace(const char* str_id, const ImVec2& size_arg)
host_window->DockNodeAsHost = node;
host_window->ChildId = window->GetID(title);
node->HostWindow = host_window;
node->OnlyNodeWithWindows = NULL;
IM_ASSERT(node->IsRootNode());
DockNodeUpdate(node);
@ -11320,7 +11345,7 @@ void ImGui::BeginDocked(ImGuiWindow* window, bool* p_open)
window->Flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_NoResize;
window->Flags &= ~ImGuiWindowFlags_NoTitleBar; // Clear the NoTitleBar flag in case the user set it: confusingly enough we need a title bar height so we are correctly offset, but it won't be displayed!
// Position window
// Position window
SetNextWindowPos(dock_node->Pos);
SetNextWindowSize(dock_node->Size);
g.NextWindowData.PosUndock = false;

11
imgui.h
View File

@ -111,6 +111,7 @@ typedef int ImGuiColorEditFlags; // -> enum ImGuiColorEditFlags_ // Flags: f
typedef int ImGuiColumnsFlags; // -> enum ImGuiColumnsFlags_ // Flags: for Columns(), BeginColumns()
typedef int ImGuiConfigFlags; // -> enum ImGuiConfigFlags_ // Flags: for io.ConfigFlags
typedef int ImGuiComboFlags; // -> enum ImGuiComboFlags_ // Flags: for BeginCombo()
typedef int ImGuiDockFlags; // -> enum ImGuiDockFlags_ // Flags: for DockSpace()
typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: for *DragDrop*()
typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: for IsWindowFocused()
typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc.
@ -519,7 +520,8 @@ namespace ImGui
// Docking
// [BETA API] Enable with io.ConfigFlags |= ImGuiConfigFlags_DockingEnable.
// Note: you DO NOT need to call DockSpace() to use most Docking facilities! You can hold SHIFT anywhere while moving windows. Use DockSpace() if you need to create an explicit docking space _within_ an existing window. See Docking demo for details)
IMGUI_API void DockSpace(const char* str_id, const ImVec2& size = ImVec2(0, 0));
IMGUI_API void DockSpace(const char* str_id, const ImVec2& size = ImVec2(0, 0), ImGuiDockFlags flags = 0, ImGuiID user_type_filter = 0);
IMGUI_API void SetNextWindowUserType(ImGuiID user_type); // FIXME-DOCK: set next window user type (docking filters by same user_type)
// Logging/Capture: all text output from interface is captured to tty/file/clipboard. By default, tree nodes are automatically opened during logging.
IMGUI_API void LogToTTY(int max_depth = -1); // start logging to tty
@ -779,6 +781,13 @@ enum ImGuiTabItemFlags_
ImGuiTabItemFlags_NoPushId = 1 << 3 // Don't call PushID(tab->ID)/PopID() on BeginTabItem()/EndTabItem()
};
// Flags for ImGui::DockSpace()
enum ImGuiDockFlags_
{
ImGuiDockFlags_None = 0,
ImGuiDockFlags_NoSplit = 1 << 0
};
// Flags for ImGui::IsWindowFocused()
enum ImGuiFocusedFlags_
{

View File

@ -704,6 +704,7 @@ struct ImGuiNextWindowData
float BgAlphaVal;
ImGuiID ViewportId;
ImGuiID DockId;
ImGuiID UserTypeId;
ImVec2 MenuBarOffsetMinVal; // This is not exposed publicly, so we don't clear it.
ImGuiNextWindowData()
@ -716,13 +717,14 @@ struct ImGuiNextWindowData
SizeCallback = NULL;
SizeCallbackUserData = NULL;
BgAlphaVal = FLT_MAX;
ViewportId = DockId = 0;
ViewportId = DockId = UserTypeId = 0;
MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f);
}
void Clear()
{
PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = BgAlphaCond = ViewportCond = DockCond = 0;
UserTypeId = 0;
}
};
@ -740,6 +742,8 @@ struct ImGuiTabBarSortItem
struct ImGuiDockNode
{
ImGuiID ID;
ImGuiID UserTypeIdFilter;
ImGuiDockFlags Flags;
ImGuiDockNode* ParentNode;
ImGuiDockNode* ChildNodes[2];
ImVector<ImGuiWindow*> Windows; // Note: unordered list! Iterate TabBar->Tabs for user-order.
@ -1200,6 +1204,7 @@ struct IMGUI_API ImGuiWindow
ImGuiCond SetWindowDockAllowFlags; // store acceptable condition flags for SetNextWindowDock() use.
ImVec2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size)
ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0,0) when positioning from top-left corner; ImVec2(0.5f,0.5f) for centering; ImVec2(1,1) for bottom right.
ImGuiID UserTypeId; // user value set with SetNextWindowUserType(const char*)
ImGuiWindowTempData DC; // Temporary per-window data, reset at the beginning of the frame. This used to be called ImGuiDrawContext, hence the "DC" variable name.
ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack
@ -1457,8 +1462,8 @@ namespace ImGui
IMGUI_API void DockContextShutdown(ImGuiContext* imgui_context);
IMGUI_API void DockContextOnLoadSettings();
IMGUI_API void DockContextRebuild(ImGuiDockContext* ctx);
IMGUI_API void DockContextUpdateUndocking(ImGuiDockContext* ctx);
IMGUI_API void DockContextUpdateDocking(ImGuiDockContext* ctx);
IMGUI_API void DockContextNewFrameUpdateUndocking(ImGuiDockContext* ctx);
IMGUI_API void DockContextNewFrameUpdateDocking(ImGuiDockContext* ctx);
IMGUI_API void DockContextQueueUndock(ImGuiDockContext* ctx, ImGuiWindow* window);
IMGUI_API void BeginDocked(ImGuiWindow* window, bool* p_open);
IMGUI_API void BeginAsDockableDragDropSource(ImGuiWindow* window);