Updated ImGui.
This commit is contained in:
parent
7fce7273af
commit
23b92ce879
8
3rdparty/dear-imgui/imgui.cpp
vendored
8
3rdparty/dear-imgui/imgui.cpp
vendored
@ -7093,7 +7093,7 @@ static void ImGui::ErrorCheckNewFrameSanityChecks()
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
// Check user IM_ASSERT macro
|
||||
// (IF YOU GET A WARNING OR COMPILE ERROR HERE: it means you assert macro is incorrectly defined!
|
||||
// (IF YOU GET A WARNING OR COMPILE ERROR HERE: it means your assert macro is incorrectly defined!
|
||||
// If your macro uses multiple statements, it NEEDS to be surrounded by a 'do { ... } while (0)' block.
|
||||
// This is a common C/C++ idiom to allow multiple statements macros to be used in control flow blocks.)
|
||||
// #define IM_ASSERT(EXPR) if (SomeCode(EXPR)) SomeMoreCode(); // Wrong!
|
||||
@ -10568,9 +10568,9 @@ static void ImGui::UpdateViewportsNewFrame()
|
||||
ImGuiViewportP* viewport = g.Viewports[n];
|
||||
|
||||
// Lock down space taken by menu bars and status bars, reset the offset for fucntions like BeginMainMenuBar() to alter them again.
|
||||
viewport->WorkOffsetMin = viewport->CurrWorkOffsetMin;
|
||||
viewport->WorkOffsetMax = viewport->CurrWorkOffsetMax;
|
||||
viewport->CurrWorkOffsetMin = viewport->CurrWorkOffsetMax = ImVec2(0.0f, 0.0f);
|
||||
viewport->WorkOffsetMin = viewport->BuildWorkOffsetMin;
|
||||
viewport->WorkOffsetMax = viewport->BuildWorkOffsetMax;
|
||||
viewport->BuildWorkOffsetMin = viewport->BuildWorkOffsetMax = ImVec2(0.0f, 0.0f);
|
||||
viewport->UpdateWorkRect();
|
||||
}
|
||||
}
|
||||
|
1
3rdparty/dear-imgui/imgui.h
vendored
1
3rdparty/dear-imgui/imgui.h
vendored
@ -723,6 +723,7 @@ namespace ImGui
|
||||
IMGUI_API int TableGetRowIndex(); // return current row index.
|
||||
IMGUI_API const char* TableGetColumnName(int column_n = -1); // return "" if column didn't have a name declared by TableSetupColumn(). Pass -1 to use current column.
|
||||
IMGUI_API ImGuiTableColumnFlags TableGetColumnFlags(int column_n = -1); // return column flags so you can query their Enabled/Visible/Sorted/Hovered status flags. Pass -1 to use current column.
|
||||
IMGUI_API void TableSetColumnEnabled(int column_n, bool v);// change enabled/disabled state of a column, set to false to hide the column. Note that end-user can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody)
|
||||
IMGUI_API void TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n = -1); // change the color of a cell, row, or column. See ImGuiTableBgTarget_ flags for details.
|
||||
|
||||
// Legacy Columns API (2020: prefer using Tables!)
|
||||
|
29
3rdparty/dear-imgui/imgui_internal.h
vendored
29
3rdparty/dear-imgui/imgui_internal.h
vendored
@ -1180,14 +1180,21 @@ struct ImGuiViewportP : public ImGuiViewport
|
||||
|
||||
ImVec2 WorkOffsetMin; // Work Area: Offset from Pos to top-left corner of Work Area. Generally (0,0) or (0,+main_menu_bar_height). Work Area is Full Area but without menu-bars/status-bars (so WorkArea always fit inside Pos/Size!)
|
||||
ImVec2 WorkOffsetMax; // Work Area: Offset from Pos+Size to bottom-right corner of Work Area. Generally (0,0) or (0,-status_bar_height).
|
||||
ImVec2 CurrWorkOffsetMin; // Work Area: Offset being built/increased during current frame
|
||||
ImVec2 CurrWorkOffsetMax; // Work Area: Offset being built/decreased during current frame
|
||||
ImVec2 BuildWorkOffsetMin; // Work Area: Offset being built during current frame. Generally >= 0.0f.
|
||||
ImVec2 BuildWorkOffsetMax; // Work Area: Offset being built during current frame. Generally <= 0.0f.
|
||||
|
||||
ImGuiViewportP() { DrawListsLastFrame[0] = DrawListsLastFrame[1] = -1; DrawLists[0] = DrawLists[1] = NULL; }
|
||||
~ImGuiViewportP() { if (DrawLists[0]) IM_DELETE(DrawLists[0]); if (DrawLists[1]) IM_DELETE(DrawLists[1]); }
|
||||
ImRect GetMainRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
|
||||
ImRect GetWorkRect() const { return ImRect(WorkPos.x, WorkPos.y, WorkPos.x + WorkSize.x, WorkPos.y + WorkSize.y); }
|
||||
void UpdateWorkRect() { WorkPos = ImVec2(Pos.x + WorkOffsetMin.x, Pos.y + WorkOffsetMin.y); WorkSize = ImVec2(ImMax(0.0f, Size.x - WorkOffsetMin.x + WorkOffsetMax.x), ImMax(0.0f, Size.y - WorkOffsetMin.y + WorkOffsetMax.y)); }
|
||||
ImGuiViewportP() { DrawListsLastFrame[0] = DrawListsLastFrame[1] = -1; DrawLists[0] = DrawLists[1] = NULL; }
|
||||
~ImGuiViewportP() { if (DrawLists[0]) IM_DELETE(DrawLists[0]); if (DrawLists[1]) IM_DELETE(DrawLists[1]); }
|
||||
|
||||
// Calculate work rect pos/size given a set of offset (we have 1 pair of offset for rect locked from last frame data, and 1 pair for currently building rect)
|
||||
ImVec2 CalcWorkRectPos(const ImVec2& off_min) const { return ImVec2(Pos.x + off_min.x, Pos.y + off_min.y); }
|
||||
ImVec2 CalcWorkRectSize(const ImVec2& off_min, const ImVec2& off_max) const { return ImVec2(ImMax(0.0f, Size.x - off_min.x + off_max.x), ImMax(0.0f, Size.y - off_min.y + off_max.y)); }
|
||||
void UpdateWorkRect() { WorkPos = CalcWorkRectPos(WorkOffsetMin); WorkSize = CalcWorkRectSize(WorkOffsetMin, WorkOffsetMax); } // Update public fields
|
||||
|
||||
// Helpers to retrieve ImRect (we don't need to store BuildWorkRect as every access tend to change it, hence the code asymmetry)
|
||||
ImRect GetMainRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
|
||||
ImRect GetWorkRect() const { return ImRect(WorkPos.x, WorkPos.y, WorkPos.x + WorkSize.x, WorkPos.y + WorkSize.y); }
|
||||
ImRect GetBuildWorkRect() const { ImVec2 pos = CalcWorkRectPos(BuildWorkOffsetMin); ImVec2 size = CalcWorkRectSize(BuildWorkOffsetMin, BuildWorkOffsetMax); return ImRect(pos.x, pos.y, pos.x + size.x, pos.y + size.y); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1878,6 +1885,7 @@ enum ImGuiTabBarFlagsPrivate_
|
||||
// Extend ImGuiTabItemFlags_
|
||||
enum ImGuiTabItemFlagsPrivate_
|
||||
{
|
||||
ImGuiTabItemFlags_SectionMask_ = ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing,
|
||||
ImGuiTabItemFlags_NoCloseButton = 1 << 20, // Track whether p_open was set or not (we'll need this info on the next frame to recompute ContentWidth during layout)
|
||||
ImGuiTabItemFlags_Button = 1 << 21 // Used by TabItemButton, change the tab item behavior to mimic a button
|
||||
};
|
||||
@ -1923,7 +1931,7 @@ struct ImGuiTabBar
|
||||
float ScrollingRectMinX;
|
||||
float ScrollingRectMaxX;
|
||||
ImGuiID ReorderRequestTabId;
|
||||
ImS8 ReorderRequestDir;
|
||||
ImS16 ReorderRequestOffset;
|
||||
ImS8 BeginCount;
|
||||
bool WantLayout;
|
||||
bool VisibleTabWasSubmitted;
|
||||
@ -2309,6 +2317,7 @@ namespace ImGui
|
||||
IMGUI_API ImGuiWindow* GetTopMostPopupModal();
|
||||
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
|
||||
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
|
||||
IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags);
|
||||
|
||||
// Gamepad/Keyboard Navigation
|
||||
IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit);
|
||||
@ -2361,7 +2370,6 @@ namespace ImGui
|
||||
|
||||
// Tables: Candidates for public API
|
||||
IMGUI_API void TableOpenContextMenu(int column_n = -1);
|
||||
IMGUI_API void TableSetColumnEnabled(int column_n, bool enabled);
|
||||
IMGUI_API void TableSetColumnWidth(int column_n, float width);
|
||||
IMGUI_API void TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs);
|
||||
IMGUI_API int TableGetHoveredColumn(); // May use (TableGetColumnFlags() & ImGuiTableColumnFlags_IsHovered) instead. Return hovered column. return -1 when table is not hovered. return columns_count if the unused space at the right of visible columns is hovered.
|
||||
@ -2415,7 +2423,8 @@ namespace ImGui
|
||||
IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id);
|
||||
IMGUI_API void TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id);
|
||||
IMGUI_API void TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
|
||||
IMGUI_API void TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir);
|
||||
IMGUI_API void TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int offset);
|
||||
IMGUI_API void TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, ImVec2 mouse_pos);
|
||||
IMGUI_API bool TabBarProcessReorder(ImGuiTabBar* tab_bar);
|
||||
IMGUI_API bool TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags);
|
||||
IMGUI_API ImVec2 TabItemCalcSize(const char* label, bool has_close_button);
|
||||
|
3
3rdparty/dear-imgui/imgui_tables.cpp
vendored
3
3rdparty/dear-imgui/imgui_tables.cpp
vendored
@ -1491,6 +1491,9 @@ const char* ImGui::TableGetColumnName(const ImGuiTable* table, int column_n)
|
||||
return &table->ColumnsNames.Buf[column->NameOffset];
|
||||
}
|
||||
|
||||
// Request enabling/disabling a column (often perceived as "showing/hiding" from users point of view)
|
||||
// Note that end-user can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody)
|
||||
// Request will be applied during next layout, which happens on the first call to TableNextRow() after BeginTable()
|
||||
// For the getter you can use (TableGetColumnFlags() & ImGuiTableColumnFlags_IsEnabled)
|
||||
void ImGui::TableSetColumnEnabled(int column_n, bool enabled)
|
||||
{
|
||||
|
164
3rdparty/dear-imgui/imgui_widgets.cpp
vendored
164
3rdparty/dear-imgui/imgui_widgets.cpp
vendored
@ -2082,6 +2082,7 @@ static const char* ImAtoi(const char* src, TYPE* output)
|
||||
// - stb_sprintf.h supports several new modifiers which format numbers in a way that also makes them incompatible atof/atoi.
|
||||
static void SanitizeFormatString(const char* fmt, char* fmt_out, size_t fmt_out_size)
|
||||
{
|
||||
IM_UNUSED(fmt_out_size);
|
||||
const char* fmt_end = ImParseFormatFindEnd(fmt);
|
||||
IM_ASSERT((size_t)(fmt_end - fmt + 1) < fmt_out_size); // Format is too long, let us know if this happens to you!
|
||||
while (fmt < fmt_end)
|
||||
@ -4819,7 +4820,8 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
|
||||
char* p = buf;
|
||||
while (*p == '#' || ImCharIsBlankA(*p))
|
||||
p++;
|
||||
i[0] = i[1] = i[2] = i[3] = 0;
|
||||
i[0] = i[1] = i[2] = 0;
|
||||
i[3] = 0xFF; // alpha default to 255 is not parsed by scanf (e.g. inputting #FFFFFF omitting alpha)
|
||||
if (alpha)
|
||||
sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned)
|
||||
else
|
||||
@ -6617,46 +6619,63 @@ void ImGui::EndMenuBar()
|
||||
window->DC.MenuBarAppending = false;
|
||||
}
|
||||
|
||||
// Important: calling order matters!
|
||||
// FIXME: Somehow overlapping with docking tech.
|
||||
// FIXME: The "rect-cut" aspect of this could be formalized into a lower-level helper (rect-cut: https://halt.software/dead-simple-layouts)
|
||||
bool ImGui::BeginViewportSideBar(const char* name, ImGuiViewport* viewport_p, ImGuiDir dir, float axis_size, ImGuiWindowFlags window_flags)
|
||||
{
|
||||
IM_ASSERT(dir != ImGuiDir_None);
|
||||
|
||||
ImGuiWindow* bar_window = FindWindowByName(name);
|
||||
if (bar_window == NULL || bar_window->BeginCount == 0)
|
||||
{
|
||||
// Calculate and set window size/position
|
||||
ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)(viewport_p ? viewport_p : GetMainViewport());
|
||||
ImRect avail_rect = viewport->GetBuildWorkRect();
|
||||
ImGuiAxis axis = (dir == ImGuiDir_Up || dir == ImGuiDir_Down) ? ImGuiAxis_Y : ImGuiAxis_X;
|
||||
ImVec2 pos = avail_rect.Min;
|
||||
if (dir == ImGuiDir_Right || dir == ImGuiDir_Down)
|
||||
pos[axis] = avail_rect.Max[axis] - axis_size;
|
||||
ImVec2 size = avail_rect.GetSize();
|
||||
size[axis] = axis_size;
|
||||
SetNextWindowPos(pos);
|
||||
SetNextWindowSize(size);
|
||||
|
||||
// Report our size into work area (for next frame) using actual window size
|
||||
if (dir == ImGuiDir_Up || dir == ImGuiDir_Left)
|
||||
viewport->BuildWorkOffsetMin[axis] += axis_size;
|
||||
else if (dir == ImGuiDir_Down || dir == ImGuiDir_Right)
|
||||
viewport->BuildWorkOffsetMax[axis] -= axis_size;
|
||||
}
|
||||
|
||||
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
|
||||
PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0, 0)); // Lift normal size constraint
|
||||
bool is_open = Begin(name, NULL, window_flags);
|
||||
PopStyleVar(2);
|
||||
|
||||
return is_open;
|
||||
}
|
||||
|
||||
bool ImGui::BeginMainMenuBar()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)GetMainViewport();
|
||||
ImGuiWindow* menu_bar_window = FindWindowByName("##MainMenuBar");
|
||||
|
||||
// For the main menu bar, which cannot be moved, we honor g.Style.DisplaySafeAreaPadding to ensure text can be visible on a TV set.
|
||||
// FIXME: This could be generalized as an opt-in way to clamp window->DC.CursorStartPos to avoid SafeArea?
|
||||
// FIXME: Consider removing support for safe area down the line... it's messy. Nowadays consoles have support for TV calibration in OS settings.
|
||||
g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f));
|
||||
|
||||
// Get our rectangle at the top of the work area
|
||||
if (menu_bar_window == NULL || menu_bar_window->BeginCount == 0)
|
||||
{
|
||||
// Set window position
|
||||
// We don't attempt to calculate our height ahead, as it depends on the per-viewport font size.
|
||||
// However menu-bar will affect the minimum window size so we'll get the right height.
|
||||
ImVec2 menu_bar_pos = viewport->Pos + viewport->CurrWorkOffsetMin;
|
||||
ImVec2 menu_bar_size = ImVec2(viewport->Size.x - viewport->CurrWorkOffsetMin.x + viewport->CurrWorkOffsetMax.x, 1.0f);
|
||||
SetNextWindowPos(menu_bar_pos);
|
||||
SetNextWindowSize(menu_bar_size);
|
||||
}
|
||||
|
||||
// Create window
|
||||
PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0, 0)); // Lift normal size constraint, however the presence of a menu-bar will give us the minimum height we want.
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar;
|
||||
bool is_open = Begin("##MainMenuBar", NULL, window_flags) && BeginMenuBar();
|
||||
PopStyleVar(2);
|
||||
|
||||
// Report our size into work area (for next frame) using actual window size
|
||||
menu_bar_window = GetCurrentWindow();
|
||||
if (menu_bar_window->BeginCount == 1)
|
||||
viewport->CurrWorkOffsetMin.y += menu_bar_window->Size.y;
|
||||
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar;
|
||||
float height = GetFrameHeight();
|
||||
bool is_open = BeginViewportSideBar("##MainMenuBar", viewport, ImGuiDir_Up, height, window_flags);
|
||||
g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f);
|
||||
if (!is_open)
|
||||
{
|
||||
|
||||
if (is_open)
|
||||
BeginMenuBar();
|
||||
else
|
||||
End();
|
||||
return false;
|
||||
}
|
||||
return true; //-V1020
|
||||
return is_open;
|
||||
}
|
||||
|
||||
void ImGui::EndMainMenuBar()
|
||||
@ -6958,12 +6977,17 @@ ImGuiTabBar::ImGuiTabBar()
|
||||
LastTabItemIdx = -1;
|
||||
}
|
||||
|
||||
static inline int TabItemGetSectionIdx(const ImGuiTabItem* tab)
|
||||
{
|
||||
return (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
|
||||
}
|
||||
|
||||
static int IMGUI_CDECL TabItemComparerBySection(const void* lhs, const void* rhs)
|
||||
{
|
||||
const ImGuiTabItem* a = (const ImGuiTabItem*)lhs;
|
||||
const ImGuiTabItem* b = (const ImGuiTabItem*)rhs;
|
||||
const int a_section = (a->Flags & ImGuiTabItemFlags_Leading) ? 0 : (a->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
|
||||
const int b_section = (b->Flags & ImGuiTabItemFlags_Leading) ? 0 : (b->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
|
||||
const int a_section = TabItemGetSectionIdx(a);
|
||||
const int b_section = TabItemGetSectionIdx(b);
|
||||
if (a_section != b_section)
|
||||
return a_section - b_section;
|
||||
return (int)(a->IndexDuringLayout - b->IndexDuringLayout);
|
||||
@ -7132,11 +7156,11 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
tab->IndexDuringLayout = (ImS16)tab_dst_n;
|
||||
|
||||
// We will need sorting if tabs have changed section (e.g. moved from one of Leading/Central/Trailing to another)
|
||||
int curr_tab_section_n = (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
|
||||
int curr_tab_section_n = TabItemGetSectionIdx(tab);
|
||||
if (tab_dst_n > 0)
|
||||
{
|
||||
ImGuiTabItem* prev_tab = &tab_bar->Tabs[tab_dst_n - 1];
|
||||
int prev_tab_section_n = (prev_tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (prev_tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
|
||||
int prev_tab_section_n = TabItemGetSectionIdx(prev_tab);
|
||||
if (curr_tab_section_n == 0 && prev_tab_section_n != 0)
|
||||
need_sort_by_section = true;
|
||||
if (prev_tab_section_n == 2 && curr_tab_section_n != 2)
|
||||
@ -7208,7 +7232,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
const bool has_close_button = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) ? false : true;
|
||||
tab->ContentWidth = TabItemCalcSize(tab_name, has_close_button).x;
|
||||
|
||||
int section_n = (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
|
||||
int section_n = TabItemGetSectionIdx(tab);
|
||||
ImGuiTabBarSection* section = §ions[section_n];
|
||||
section->Width += tab->ContentWidth + (section_n == curr_section_n ? g.Style.ItemInnerSpacing.x : 0.0f);
|
||||
curr_section_n = section_n;
|
||||
@ -7263,7 +7287,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
if (shrinked_width < 0.0f)
|
||||
continue;
|
||||
|
||||
int section_n = (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
|
||||
int section_n = TabItemGetSectionIdx(tab);
|
||||
sections[section_n].Width -= (tab->Width - shrinked_width);
|
||||
tab->Width = shrinked_width;
|
||||
}
|
||||
@ -7408,7 +7432,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
|
||||
ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id);
|
||||
if (tab == NULL)
|
||||
return;
|
||||
if (tab->Flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing))
|
||||
if (tab->Flags & ImGuiTabItemFlags_SectionMask_)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
@ -7437,12 +7461,48 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir)
|
||||
void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int offset)
|
||||
{
|
||||
IM_ASSERT(dir == -1 || dir == +1);
|
||||
IM_ASSERT(offset != 0);
|
||||
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
|
||||
tab_bar->ReorderRequestTabId = tab->ID;
|
||||
tab_bar->ReorderRequestDir = (ImS8)dir;
|
||||
tab_bar->ReorderRequestOffset = (ImS16)offset;
|
||||
}
|
||||
|
||||
void ImGui::TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, const ImGuiTabItem* src_tab, ImVec2 mouse_pos)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
|
||||
if ((tab_bar->Flags & ImGuiTabBarFlags_Reorderable) == 0)
|
||||
return;
|
||||
|
||||
const bool is_central_section = (src_tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0;
|
||||
const float bar_offset = tab_bar->BarRect.Min.x - (is_central_section ? tab_bar->ScrollingTarget : 0);
|
||||
|
||||
// Count number of contiguous tabs we are crossing over
|
||||
const int dir = (bar_offset + src_tab->Offset) > mouse_pos.x ? -1 : +1;
|
||||
const int src_idx = tab_bar->Tabs.index_from_ptr(src_tab);
|
||||
int dst_idx = src_idx;
|
||||
for (int i = src_idx; i >= 0 && i < tab_bar->Tabs.Size; i += dir)
|
||||
{
|
||||
// Reordered tabs must share the same section
|
||||
const ImGuiTabItem* dst_tab = &tab_bar->Tabs[i];
|
||||
if (dst_tab->Flags & ImGuiTabItemFlags_NoReorder)
|
||||
break;
|
||||
if ((dst_tab->Flags & ImGuiTabItemFlags_SectionMask_) != (src_tab->Flags & ImGuiTabItemFlags_SectionMask_))
|
||||
break;
|
||||
dst_idx = i;
|
||||
|
||||
// Include spacing after tab, so when mouse cursor is between tabs we would not continue checking further tabs that are not hovered.
|
||||
const float x1 = bar_offset + dst_tab->Offset - g.Style.ItemInnerSpacing.x;
|
||||
const float x2 = bar_offset + dst_tab->Offset + dst_tab->Width + g.Style.ItemInnerSpacing.x;
|
||||
//GetForegroundDrawList()->AddRect(ImVec2(x1, tab_bar->BarRect.Min.y), ImVec2(x2, tab_bar->BarRect.Max.y), IM_COL32(255, 0, 0, 255));
|
||||
if ((dir < 0 && mouse_pos.x > x1) || (dir > 0 && mouse_pos.x < x2))
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst_idx != src_idx)
|
||||
TabBarQueueReorder(tab_bar, src_tab, dst_idx - src_idx);
|
||||
}
|
||||
|
||||
bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar)
|
||||
@ -7452,19 +7512,23 @@ bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar)
|
||||
return false;
|
||||
|
||||
//IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
|
||||
int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestDir;
|
||||
int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestOffset;
|
||||
if (tab2_order < 0 || tab2_order >= tab_bar->Tabs.Size)
|
||||
return false;
|
||||
|
||||
// Reordered TabItem must share the same position flags than target
|
||||
// Reordered tabs must share the same section
|
||||
// (Note: TabBarQueueReorderFromMousePos() also has a similar test but since we allow direct calls to TabBarQueueReorder() we do it here too)
|
||||
ImGuiTabItem* tab2 = &tab_bar->Tabs[tab2_order];
|
||||
if (tab2->Flags & ImGuiTabItemFlags_NoReorder)
|
||||
return false;
|
||||
if ((tab1->Flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)) != (tab2->Flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)))
|
||||
if ((tab1->Flags & ImGuiTabItemFlags_SectionMask_) != (tab2->Flags & ImGuiTabItemFlags_SectionMask_))
|
||||
return false;
|
||||
|
||||
ImGuiTabItem item_tmp = *tab1;
|
||||
*tab1 = *tab2;
|
||||
ImGuiTabItem* src_tab = (tab_bar->ReorderRequestOffset > 0) ? tab1 + 1 : tab2;
|
||||
ImGuiTabItem* dst_tab = (tab_bar->ReorderRequestOffset > 0) ? tab1 : tab2 + 1;
|
||||
const int move_count = (tab_bar->ReorderRequestOffset > 0) ? tab_bar->ReorderRequestOffset : -tab_bar->ReorderRequestOffset;
|
||||
memmove(dst_tab, src_tab, move_count * sizeof(ImGuiTabItem));
|
||||
*tab2 = item_tmp;
|
||||
|
||||
if (tab_bar->Flags & ImGuiTabBarFlags_SaveSettings)
|
||||
@ -7746,7 +7810,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
const ImVec2 backup_main_cursor_pos = window->DC.CursorPos;
|
||||
|
||||
// Layout
|
||||
const bool is_central_section = (tab->Flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)) == 0;
|
||||
const bool is_central_section = (tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0;
|
||||
size.x = tab->Width;
|
||||
if (is_central_section)
|
||||
window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(IM_FLOOR(tab->Offset - tab_bar->ScrollingAnim), 0.0f);
|
||||
@ -7794,13 +7858,11 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
// While moving a tab it will jump on the other side of the mouse, so we also test for MouseDelta.x
|
||||
if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < bb.Min.x)
|
||||
{
|
||||
if (tab_bar->Flags & ImGuiTabBarFlags_Reorderable)
|
||||
TabBarQueueReorder(tab_bar, tab, -1);
|
||||
TabBarQueueReorderFromMousePos(tab_bar, tab, g.IO.MousePos);
|
||||
}
|
||||
else if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > bb.Max.x)
|
||||
{
|
||||
if (tab_bar->Flags & ImGuiTabBarFlags_Reorderable)
|
||||
TabBarQueueReorder(tab_bar, tab, +1);
|
||||
TabBarQueueReorderFromMousePos(tab_bar, tab, g.IO.MousePos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user