mirror of
https://github.com/ocornut/imgui.git
synced 2026-05-13 11:57:59 +08:00
Added BETA api for Tab Bar/Tabs widgets. (#261, #351) (merged this feature from the from Docking branch so it can be used earlier as as standalone feature)
- Added BeginTabBar(), EndTabBar(), BeginTabItem(), EndTabItem(), SetTabItemClosed() API. - Added ImGuiTabBarFlags flags for BeginTabBar(). - Added ImGuiTabItemFlags flags for BeginTabItem(). - Style: Added ImGuiCol_Tab, ImGuiCol_TabHovered, ImGuiCol_TabActive, ImGuiCol_TabUnfocused, ImGuiCol_TabUnfocusedActive colors. - Demo: Added Layout->Tabs demo code. - Demo: Added "Documents" example app showcasing possible use for tabs.
This commit is contained in:
@@ -39,6 +39,15 @@ Breaking Changes:
|
||||
The addition of new configuration options in the Docking branch is pushing for a little reorganization of those names.
|
||||
|
||||
Other Changes:
|
||||
- Added BETA api for Tab Bar/Tabs widgets: (#261, #351)
|
||||
- Added BeginTabBar(), EndTabBar(), BeginTabItem(), EndTabItem(), SetTabItemClosed() API.
|
||||
- Added ImGuiTabBarFlags flags for BeginTabBar().
|
||||
- Added ImGuiTabItemFlags flags for BeginTabItem().
|
||||
- Style: Added ImGuiCol_Tab, ImGuiCol_TabHovered, ImGuiCol_TabActive, ImGuiCol_TabUnfocused, ImGuiCol_TabUnfocusedActive colors.
|
||||
- Demo: Added Layout->Tabs demo code.
|
||||
- Demo: Added "Documents" example app showcasing possible use for tabs.
|
||||
This feature was merged from the Docking branch in order to allow the use of regular tabs in your code.
|
||||
(It does not provide the docking/splitting/merging of windows available in the Docking branch)
|
||||
- Added ImGuiWindowFlags_UnsavedDocument window flag to append '*' to title without altering
|
||||
the ID, as a convenience to avoid using the ### operator.
|
||||
- Resizing windows from edge is now enabled by default (io.ConfigWindowsResizeFromEdges=true). Note that
|
||||
|
||||
+2
-1
@@ -127,7 +127,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- dock: docking extension
|
||||
- dock: dock out from a collapsing header? would work nicely but need emitting window to keep submitting the code.
|
||||
|
||||
- tabs: re-ordering, close buttons, context menu, persistent order (#261, #351)
|
||||
- tabs: make EndTabBar fail if users doesn't respect BeginTabBar return value, for consistency/future-proofing.
|
||||
- tabs: persistent order/focus in BeginTabBar() api (#261, #351)
|
||||
|
||||
- ext: stl-ish friendly extension (imgui_stl.h) that has wrapper for std::string, std::vector etc.
|
||||
|
||||
|
||||
@@ -1015,6 +1015,8 @@ ImGuiStyle::ImGuiStyle()
|
||||
ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar
|
||||
GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar
|
||||
GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
|
||||
TabRounding = 4.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
|
||||
TabBorderSize = 0.0f; // Thickness of border around tabs.
|
||||
ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text.
|
||||
DisplayWindowPadding = ImVec2(19,19); // Window position are clamped to be visible within the display area by at least this amount. Only applies to regular windows.
|
||||
DisplaySafeAreaPadding = ImVec2(3,3); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows.
|
||||
@@ -1038,6 +1040,7 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor)
|
||||
PopupRounding = ImFloor(PopupRounding * scale_factor);
|
||||
FramePadding = ImFloor(FramePadding * scale_factor);
|
||||
FrameRounding = ImFloor(FrameRounding * scale_factor);
|
||||
TabRounding = ImFloor(TabRounding * scale_factor);
|
||||
ItemSpacing = ImFloor(ItemSpacing * scale_factor);
|
||||
ItemInnerSpacing = ImFloor(ItemInnerSpacing * scale_factor);
|
||||
TouchExtraPadding = ImFloor(TouchExtraPadding * scale_factor);
|
||||
@@ -2160,17 +2163,8 @@ void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end
|
||||
|
||||
// Default clip_rect uses (pos_min,pos_max)
|
||||
// Handle clipping on CPU immediately (vs typically let the GPU clip the triangles that are overlapping the clipping rectangle edges)
|
||||
void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
|
||||
void ImGui::RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_display_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
|
||||
{
|
||||
// Hide anything after a '##' string
|
||||
const char* text_display_end = FindRenderedTextEnd(text, text_end);
|
||||
const int text_len = (int)(text_display_end - text);
|
||||
if (text_len == 0)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
// Perform CPU side clipping for single clipped element to avoid using scissor state
|
||||
ImVec2 pos = pos_min;
|
||||
const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_display_end, false, 0.0f);
|
||||
@@ -2189,14 +2183,27 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons
|
||||
if (need_clipping)
|
||||
{
|
||||
ImVec4 fine_clip_rect(clip_min->x, clip_min->y, clip_max->x, clip_max->y);
|
||||
window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect);
|
||||
draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, &fine_clip_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
window->DrawList->AddText(g.Font, g.FontSize, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL);
|
||||
draw_list->AddText(NULL, 0.0f, pos, GetColorU32(ImGuiCol_Text), text, text_display_end, 0.0f, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align, const ImRect* clip_rect)
|
||||
{
|
||||
// Hide anything after a '##' string
|
||||
const char* text_display_end = FindRenderedTextEnd(text, text_end);
|
||||
const int text_len = (int)(text_display_end - text);
|
||||
if (text_len == 0)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
RenderTextClippedEx(window->DrawList, pos_min, pos_max, text, text_display_end, text_size_if_known, align, clip_rect);
|
||||
if (g.LogEnabled)
|
||||
LogRenderedText(&pos, text, text_display_end);
|
||||
LogRenderedText(&pos_min, text, text_display_end);
|
||||
}
|
||||
|
||||
// Render a rectangle shaped with optional rounding and borders
|
||||
@@ -5511,6 +5518,7 @@ static const ImGuiStyleVarInfo GStyleVarInfo[] =
|
||||
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding
|
||||
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize
|
||||
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding
|
||||
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, TabRounding) }, // ImGuiStyleVar_TabRounding
|
||||
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
|
||||
};
|
||||
|
||||
@@ -5603,6 +5611,11 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
|
||||
case ImGuiCol_ResizeGrip: return "ResizeGrip";
|
||||
case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered";
|
||||
case ImGuiCol_ResizeGripActive: return "ResizeGripActive";
|
||||
case ImGuiCol_Tab: return "Tab";
|
||||
case ImGuiCol_TabHovered: return "TabHovered";
|
||||
case ImGuiCol_TabActive: return "TabActive";
|
||||
case ImGuiCol_TabUnfocused: return "TabUnfocused";
|
||||
case ImGuiCol_TabUnfocusedActive: return "TabUnfocusedActive";
|
||||
case ImGuiCol_PlotLines: return "PlotLines";
|
||||
case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered";
|
||||
case ImGuiCol_PlotHistogram: return "PlotHistogram";
|
||||
@@ -9056,6 +9069,29 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair));
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
static void NodeTabBar(ImGuiTabBar* tab_bar)
|
||||
{
|
||||
// Standalone tab bars (not associated to docking/windows functionality) currently hold no discernable strings.
|
||||
char buf[256];
|
||||
char* p = buf;
|
||||
const char* buf_end = buf + IM_ARRAYSIZE(buf);
|
||||
p += ImFormatString(p, buf_end - p, "TabBar (%d tabs)%s",
|
||||
tab_bar->Tabs.Size, (tab_bar->PrevFrameVisible < ImGui::GetFrameCount() - 2) ? " *Inactive*" : "");
|
||||
if (ImGui::TreeNode(tab_bar, "%s", buf))
|
||||
{
|
||||
for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
|
||||
{
|
||||
const ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
|
||||
ImGui::PushID(tab);
|
||||
if (ImGui::SmallButton("<")) { TabBarQueueChangeTabOrder(tab_bar, tab, -1); } ImGui::SameLine(0, 2);
|
||||
if (ImGui::SmallButton(">")) { TabBarQueueChangeTabOrder(tab_bar, tab, +1); } ImGui::SameLine();
|
||||
ImGui::Text("%02d%c Tab 0x%08X", tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID);
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Access private state, we are going to display the draw lists from last frame
|
||||
@@ -9076,6 +9112,12 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNode("TabBars", "Tab Bars (%d)", g.TabBars.Data.Size))
|
||||
{
|
||||
for (int n = 0; n < g.TabBars.Data.Size; n++)
|
||||
Funcs::NodeTabBar(g.TabBars.GetByIndex(n));
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNode("Internal state"))
|
||||
{
|
||||
const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT);
|
||||
|
||||
@@ -135,6 +135,8 @@ typedef int ImGuiFocusedFlags; // -> enum ImGuiFocusedFlags_ // Flags: f
|
||||
typedef int ImGuiHoveredFlags; // -> enum ImGuiHoveredFlags_ // Flags: for IsItemHovered(), IsWindowHovered() etc.
|
||||
typedef int ImGuiInputTextFlags; // -> enum ImGuiInputTextFlags_ // Flags: for InputText*()
|
||||
typedef int ImGuiSelectableFlags; // -> enum ImGuiSelectableFlags_ // Flags: for Selectable()
|
||||
typedef int ImGuiTabBarFlags; // -> enum ImGuiTabBarFlags_ // Flags: for BeginTabBar()
|
||||
typedef int ImGuiTabItemFlags; // -> enum ImGuiTabItemFlags_ // Flags: for BeginTabItem()
|
||||
typedef int ImGuiTreeNodeFlags; // -> enum ImGuiTreeNodeFlags_ // Flags: for TreeNode*(),CollapsingHeader()
|
||||
typedef int ImGuiWindowFlags; // -> enum ImGuiWindowFlags_ // Flags: for Begin*()
|
||||
typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData *data);
|
||||
@@ -528,6 +530,14 @@ namespace ImGui
|
||||
IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column
|
||||
IMGUI_API int GetColumnsCount();
|
||||
|
||||
// Tab Bars, Tabs
|
||||
// [BETA API] API may evolve!
|
||||
IMGUI_API bool BeginTabBar(const char* str_id, ImGuiTabBarFlags flags = 0); // create and append into a TabBar
|
||||
IMGUI_API void EndTabBar();
|
||||
IMGUI_API bool BeginTabItem(const char* label, bool* p_open = NULL, ImGuiTabItemFlags flags = 0);// create a Tab. Returns true if the Tab is selected.
|
||||
IMGUI_API void EndTabItem(); // only call EndTabItem() if BeginTabItem() returns true!
|
||||
IMGUI_API void SetTabItemClosed(const char* tab_or_docked_window_label); // notify TabBar or Docking system of a closed tab/window ahead (useful to reduce visual flicker on reorderable tab bars). For tab-bar: call after BeginTabBar() and before Tab submissions. Otherwise call with a window name.
|
||||
|
||||
// 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
|
||||
IMGUI_API void LogToFile(int max_depth = -1, const char* filename = NULL); // start logging to file
|
||||
@@ -760,6 +770,31 @@ enum ImGuiComboFlags_
|
||||
ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest
|
||||
};
|
||||
|
||||
// Flags for ImGui::BeginTabBar()
|
||||
enum ImGuiTabBarFlags_
|
||||
{
|
||||
ImGuiTabBarFlags_None = 0,
|
||||
ImGuiTabBarFlags_Reorderable = 1 << 0, // Allow manually dragging tabs to re-order them + New tabs are appended at the end of list
|
||||
ImGuiTabBarFlags_AutoSelectNewTabs = 1 << 1, // Automatically select new tabs when they appear
|
||||
ImGuiTabBarFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false.
|
||||
ImGuiTabBarFlags_NoTabListPopupButton = 1 << 3,
|
||||
ImGuiTabBarFlags_NoTabListScrollingButtons = 1 << 4,
|
||||
ImGuiTabBarFlags_FittingPolicyResizeDown = 1 << 5, // Resize tabs when they don't fit
|
||||
ImGuiTabBarFlags_FittingPolicyScroll = 1 << 6, // Add scroll buttons when tabs don't fit
|
||||
ImGuiTabBarFlags_FittingPolicyMask_ = ImGuiTabBarFlags_FittingPolicyResizeDown | ImGuiTabBarFlags_FittingPolicyScroll,
|
||||
ImGuiTabBarFlags_FittingPolicyDefault_ = ImGuiTabBarFlags_FittingPolicyResizeDown
|
||||
};
|
||||
|
||||
// Flags for ImGui::BeginTabItem()
|
||||
enum ImGuiTabItemFlags_
|
||||
{
|
||||
ImGuiTabItemFlags_None = 0,
|
||||
ImGuiTabItemFlags_UnsavedDocument = 1 << 0, // Append '*' to title without affecting the ID, as a convenience to avoid using the ### operator. Also: tab is selected on closure and closure is deferred by one frame to allow code to undo it without flicker.
|
||||
ImGuiTabItemFlags_SetSelected = 1 << 1, // Trigger flag to programatically make the tab selected when calling BeginTabItem()
|
||||
ImGuiTabItemFlags_NoCloseWithMiddleMouseButton = 1 << 2, // Disable behavior of closing tabs (that are submitted with p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if (IsItemHovered() && IsMouseClicked(2)) *p_open = false.
|
||||
ImGuiTabItemFlags_NoPushId = 1 << 3 // Don't call PushID(tab->ID)/PopID() on BeginTabItem()/EndTabItem()
|
||||
};
|
||||
|
||||
// Flags for ImGui::IsWindowFocused()
|
||||
enum ImGuiFocusedFlags_
|
||||
{
|
||||
@@ -956,6 +991,11 @@ enum ImGuiCol_
|
||||
ImGuiCol_ResizeGrip,
|
||||
ImGuiCol_ResizeGripHovered,
|
||||
ImGuiCol_ResizeGripActive,
|
||||
ImGuiCol_Tab,
|
||||
ImGuiCol_TabHovered,
|
||||
ImGuiCol_TabActive,
|
||||
ImGuiCol_TabUnfocused,
|
||||
ImGuiCol_TabUnfocusedActive,
|
||||
ImGuiCol_PlotLines,
|
||||
ImGuiCol_PlotLinesHovered,
|
||||
ImGuiCol_PlotHistogram,
|
||||
@@ -1003,6 +1043,7 @@ enum ImGuiStyleVar_
|
||||
ImGuiStyleVar_ScrollbarRounding, // float ScrollbarRounding
|
||||
ImGuiStyleVar_GrabMinSize, // float GrabMinSize
|
||||
ImGuiStyleVar_GrabRounding, // float GrabRounding
|
||||
ImGuiStyleVar_TabRounding, // float TabRounding
|
||||
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
|
||||
ImGuiStyleVar_COUNT
|
||||
|
||||
@@ -1114,6 +1155,8 @@ struct ImGuiStyle
|
||||
float ScrollbarRounding; // Radius of grab corners for scrollbar.
|
||||
float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar.
|
||||
float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs.
|
||||
float TabRounding; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
|
||||
float TabBorderSize; // Thickness of border around tabs.
|
||||
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f,0.5f) for horizontally+vertically centered.
|
||||
ImVec2 DisplayWindowPadding; // Window position are clamped to be visible within the display area by at least this amount. Only applies to regular windows.
|
||||
ImVec2 DisplaySafeAreaPadding; // If you cannot see the edges of your screen (e.g. on a TV) increase the safe area padding. Apply to popups/tooltips as well regular windows. NB: Prefer configuring your TV sets correctly!
|
||||
|
||||
+342
@@ -40,6 +40,7 @@ Index of this file:
|
||||
// [SECTION] Example App: Simple Overlay / ShowExampleAppSimpleOverlay()
|
||||
// [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
|
||||
// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
|
||||
// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
|
||||
|
||||
*/
|
||||
|
||||
@@ -102,6 +103,7 @@ Index of this file:
|
||||
#if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
|
||||
|
||||
// Forward Declarations
|
||||
static void ShowExampleAppDocuments(bool* p_open);
|
||||
static void ShowExampleAppMainMenuBar();
|
||||
static void ShowExampleAppConsole(bool* p_open);
|
||||
static void ShowExampleAppLog(bool* p_open);
|
||||
@@ -168,6 +170,7 @@ static void ShowDemoWindowMisc();
|
||||
void ImGui::ShowDemoWindow(bool* p_open)
|
||||
{
|
||||
// Examples Apps (accessible from the "Examples" menu)
|
||||
static bool show_app_documents = false;
|
||||
static bool show_app_main_menu_bar = false;
|
||||
static bool show_app_console = false;
|
||||
static bool show_app_log = false;
|
||||
@@ -180,6 +183,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
|
||||
static bool show_app_window_titles = false;
|
||||
static bool show_app_custom_rendering = false;
|
||||
|
||||
if (show_app_documents) ShowExampleAppDocuments(&show_app_documents); // Process the Document app next, as it may also use a DockSpace()
|
||||
if (show_app_main_menu_bar) ShowExampleAppMainMenuBar();
|
||||
if (show_app_console) ShowExampleAppConsole(&show_app_console);
|
||||
if (show_app_log) ShowExampleAppLog(&show_app_log);
|
||||
@@ -263,6 +267,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
|
||||
ImGui::MenuItem("Simple overlay", NULL, &show_app_simple_overlay);
|
||||
ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles);
|
||||
ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
|
||||
ImGui::MenuItem("Documents", NULL, &show_app_documents);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Help"))
|
||||
@@ -1698,6 +1703,76 @@ static void ShowDemoWindowLayout()
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (ImGui::TreeNode("Tabs"))
|
||||
{
|
||||
if (ImGui::TreeNode("Basic"))
|
||||
{
|
||||
ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
|
||||
if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
|
||||
{
|
||||
if (ImGui::BeginTabItem("Avocado"))
|
||||
{
|
||||
ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah");
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Broccoli"))
|
||||
{
|
||||
ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah");
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Cucumber"))
|
||||
{
|
||||
ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah");
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
ImGui::Separator();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (ImGui::TreeNode("Advanced & Close Button"))
|
||||
{
|
||||
// Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0).
|
||||
static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable;
|
||||
ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_Reorderable);
|
||||
ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs);
|
||||
ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton);
|
||||
if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
|
||||
tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_;
|
||||
if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
|
||||
tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
|
||||
if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
|
||||
tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
|
||||
|
||||
// Tab Bar
|
||||
const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" };
|
||||
static bool opened[4] = { true, true, true, true }; // Persistent user state
|
||||
for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
|
||||
{
|
||||
if (n > 0) { ImGui::SameLine(); }
|
||||
ImGui::Checkbox(names[n], &opened[n]);
|
||||
}
|
||||
|
||||
// Passing a bool* to BeginTabItem() is similar to passing one to Begin(): the underlying bool will be set to false when the tab is closed.
|
||||
if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
|
||||
{
|
||||
for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
|
||||
if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n]))
|
||||
{
|
||||
ImGui::Text("This is the %s tab!", names[n]);
|
||||
if (n & 1)
|
||||
ImGui::Text("I am an odd tab.");
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
ImGui::Separator();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
if (ImGui::TreeNode("Groups"))
|
||||
{
|
||||
ImGui::TextWrapped("(Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundles the whole group so that you can use functions such as IsItemHovered() on it.)");
|
||||
@@ -2679,12 +2754,14 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
|
||||
ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
|
||||
ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
|
||||
ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
|
||||
ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f");
|
||||
ImGui::Text("Rounding");
|
||||
ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 14.0f, "%.0f");
|
||||
ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 16.0f, "%.0f");
|
||||
ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
|
||||
ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
|
||||
ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
|
||||
ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f");
|
||||
ImGui::Text("Alignment");
|
||||
ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
|
||||
ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a button is larger than its text content.");
|
||||
@@ -3758,6 +3835,271 @@ static void ShowExampleAppCustomRendering(bool* p_open)
|
||||
if (adding_preview)
|
||||
points.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Simplified structure to mimic a Document model
|
||||
struct MyDocument
|
||||
{
|
||||
const char* Name; // Document title
|
||||
bool Open; // Set when the document is open (in this demo, we keep an array of all available documents to simplify the demo)
|
||||
bool OpenPrev; // Copy of Open from last update.
|
||||
bool Dirty; // Set when the document has been modified
|
||||
bool WantClose; // Set when the document
|
||||
ImVec4 Color; // An arbitrary variable associated to the document
|
||||
|
||||
MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f,1.0f,1.0f,1.0f))
|
||||
{
|
||||
Name = name;
|
||||
Open = OpenPrev = open;
|
||||
Dirty = false;
|
||||
WantClose = false;
|
||||
Color = color;
|
||||
}
|
||||
void DoOpen() { Open = true; }
|
||||
void DoQueueClose() { WantClose = true; }
|
||||
void DoForceClose() { Open = false; Dirty = false; }
|
||||
void DoSave() { Dirty = false; }
|
||||
|
||||
// Display dummy contents for the Document
|
||||
static void DisplayContents(MyDocument* doc)
|
||||
{
|
||||
ImGui::PushID(doc);
|
||||
ImGui::Text("Document \"%s\"", doc->Name);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, doc->Color);
|
||||
ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
|
||||
ImGui::PopStyleColor();
|
||||
if (ImGui::Button("Modify", ImVec2(100, 0)))
|
||||
doc->Dirty = true;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Save", ImVec2(100, 0)))
|
||||
doc->DoSave();
|
||||
ImGui::ColorEdit3("color", &doc->Color.x); // Useful to test drag and drop and hold-dragged-to-open-tab behavior.
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
// Display context menu for the Document
|
||||
static void DisplayContextMenu(MyDocument* doc)
|
||||
{
|
||||
if (!ImGui::BeginPopupContextItem())
|
||||
return;
|
||||
|
||||
char buf[256];
|
||||
sprintf(buf, "Save %s", doc->Name);
|
||||
if (ImGui::MenuItem(buf, "CTRL+S", false, doc->Open))
|
||||
doc->DoSave();
|
||||
if (ImGui::MenuItem("Close", "CTRL+W", false, doc->Open))
|
||||
doc->DoQueueClose();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
};
|
||||
|
||||
struct ExampleAppDocuments
|
||||
{
|
||||
ImVector<MyDocument> Documents;
|
||||
|
||||
ExampleAppDocuments()
|
||||
{
|
||||
Documents.push_back(MyDocument("Lettuce", true, ImVec4(0.4f, 0.8f, 0.4f, 1.0f)));
|
||||
Documents.push_back(MyDocument("Eggplant", true, ImVec4(0.8f, 0.5f, 1.0f, 1.0f)));
|
||||
Documents.push_back(MyDocument("Carrot", true, ImVec4(1.0f, 0.8f, 0.5f, 1.0f)));
|
||||
Documents.push_back(MyDocument("Tomato", false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f)));
|
||||
Documents.push_back(MyDocument("A Rather Long Title", false));
|
||||
Documents.push_back(MyDocument("Some Document", false));
|
||||
}
|
||||
};
|
||||
|
||||
// [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface.
|
||||
// If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo, as opposed
|
||||
// to clicking on the regular tab closing button) and stops being submitted, it will take a frame for the tab bar to notice its absence.
|
||||
// During this frame there will be a gap in the tab bar, and if the tab that has disappeared was the selected one, the tab bar
|
||||
// will report no selected tab during the frame. This will effectively give the impression of a flicker for one frame.
|
||||
// We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch.
|
||||
// Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
|
||||
static void NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments& app)
|
||||
{
|
||||
for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
|
||||
{
|
||||
MyDocument* doc = &app.Documents[doc_n];
|
||||
if (!doc->Open && doc->OpenPrev)
|
||||
ImGui::SetTabItemClosed(doc->Name);
|
||||
doc->OpenPrev = doc->Open;
|
||||
}
|
||||
}
|
||||
|
||||
void ShowExampleAppDocuments(bool* p_open)
|
||||
{
|
||||
static ExampleAppDocuments app;
|
||||
|
||||
ImGui::Begin("Examples: Documents", p_open, ImGuiWindowFlags_MenuBar);
|
||||
|
||||
// Options
|
||||
static bool opt_reorderable = true;
|
||||
static ImGuiTabBarFlags opt_fitting_flags = ImGuiTabBarFlags_FittingPolicyDefault_;
|
||||
|
||||
// Menu
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::BeginMenu("File"))
|
||||
{
|
||||
int open_count = 0;
|
||||
for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
|
||||
open_count += app.Documents[doc_n].Open ? 1 : 0;
|
||||
|
||||
if (ImGui::BeginMenu("Open", open_count < app.Documents.Size))
|
||||
{
|
||||
for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
|
||||
{
|
||||
MyDocument* doc = &app.Documents[doc_n];
|
||||
if (!doc->Open)
|
||||
if (ImGui::MenuItem(doc->Name))
|
||||
doc->DoOpen();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0))
|
||||
for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
|
||||
app.Documents[doc_n].DoQueueClose();
|
||||
if (ImGui::MenuItem("Exit", "Alt+F4")) {}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
// [Debug] List documents with one checkbox for each
|
||||
for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
|
||||
{
|
||||
MyDocument* doc = &app.Documents[doc_n];
|
||||
if (doc_n > 0)
|
||||
ImGui::SameLine();
|
||||
ImGui::PushID(doc);
|
||||
if (ImGui::Checkbox(doc->Name, &doc->Open))
|
||||
if (!doc->Open)
|
||||
doc->DoForceClose();
|
||||
ImGui::PopID();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
// Submit Tab Bar and Tabs
|
||||
{
|
||||
ImGuiTabBarFlags tab_bar_flags = (opt_fitting_flags) | (opt_reorderable ? ImGuiTabBarFlags_Reorderable : 0);
|
||||
if (ImGui::BeginTabBar("##tabs", tab_bar_flags))
|
||||
{
|
||||
if (opt_reorderable)
|
||||
NotifyOfDocumentsClosedElsewhere(app);
|
||||
|
||||
// [DEBUG] Stress tests
|
||||
//if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1; // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on.
|
||||
//if (ImGui::GetIO().KeyCtrl) ImGui::SetTabItemSelected(docs[1].Name); // [DEBUG] Test SetTabItemSelected(), probably not very useful as-is anyway..
|
||||
|
||||
// Submit Tabs
|
||||
for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
|
||||
{
|
||||
MyDocument* doc = &app.Documents[doc_n];
|
||||
if (!doc->Open)
|
||||
continue;
|
||||
|
||||
ImGuiTabItemFlags tab_flags = (doc->Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0);
|
||||
bool visible = ImGui::BeginTabItem(doc->Name, &doc->Open, tab_flags);
|
||||
|
||||
// Cancel attempt to close when unsaved add to save queue so we can display a popup.
|
||||
if (!doc->Open && doc->Dirty)
|
||||
{
|
||||
doc->Open = true;
|
||||
doc->DoQueueClose();
|
||||
}
|
||||
|
||||
MyDocument::DisplayContextMenu(doc);
|
||||
if (visible)
|
||||
{
|
||||
MyDocument::DisplayContents(doc);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
|
||||
// Update closing queue
|
||||
static ImVector<MyDocument*> close_queue;
|
||||
if (close_queue.empty())
|
||||
{
|
||||
// Close queue is locked once we started a popup
|
||||
for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
|
||||
{
|
||||
MyDocument* doc = &app.Documents[doc_n];
|
||||
if (doc->WantClose)
|
||||
{
|
||||
doc->WantClose = false;
|
||||
close_queue.push_back(doc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Display closing confirmation UI
|
||||
if (!close_queue.empty())
|
||||
{
|
||||
int close_queue_unsaved_documents = 0;
|
||||
for (int n = 0; n < close_queue.Size; n++)
|
||||
if (close_queue[n]->Dirty)
|
||||
close_queue_unsaved_documents++;
|
||||
|
||||
if (close_queue_unsaved_documents == 0)
|
||||
{
|
||||
// Close documents when all are unsaved
|
||||
for (int n = 0; n < close_queue.Size; n++)
|
||||
close_queue[n]->DoForceClose();
|
||||
close_queue.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ImGui::IsPopupOpen("Save?"))
|
||||
ImGui::OpenPopup("Save?");
|
||||
if (ImGui::BeginPopupModal("Save?"))
|
||||
{
|
||||
ImGui::Text("Save change to the following items?");
|
||||
ImGui::PushItemWidth(-1.0f);
|
||||
ImGui::ListBoxHeader("##", close_queue_unsaved_documents, 6);
|
||||
for (int n = 0; n < close_queue.Size; n++)
|
||||
if (close_queue[n]->Dirty)
|
||||
ImGui::Text("%s", close_queue[n]->Name);
|
||||
ImGui::ListBoxFooter();
|
||||
|
||||
if (ImGui::Button("Yes", ImVec2(80, 0)))
|
||||
{
|
||||
for (int n = 0; n < close_queue.Size; n++)
|
||||
{
|
||||
if (close_queue[n]->Dirty)
|
||||
close_queue[n]->DoSave();
|
||||
close_queue[n]->DoForceClose();
|
||||
}
|
||||
close_queue.clear();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("No", ImVec2(80, 0)))
|
||||
{
|
||||
for (int n = 0; n < close_queue.Size; n++)
|
||||
close_queue[n]->DoForceClose();
|
||||
close_queue.clear();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel", ImVec2(80, 0)))
|
||||
{
|
||||
close_queue.clear();
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
||||
@@ -205,6 +205,11 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
|
||||
colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f);
|
||||
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
|
||||
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
|
||||
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
|
||||
colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
|
||||
colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
|
||||
colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
|
||||
colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
|
||||
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
|
||||
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||
@@ -255,6 +260,11 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
|
||||
colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.16f);
|
||||
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f);
|
||||
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f);
|
||||
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
|
||||
colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
|
||||
colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
|
||||
colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
|
||||
colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
|
||||
colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||
@@ -306,6 +316,11 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
|
||||
colors[ImGuiCol_ResizeGrip] = ImVec4(0.80f, 0.80f, 0.80f, 0.56f);
|
||||
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
|
||||
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
|
||||
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.90f);
|
||||
colors[ImGuiCol_TabHovered] = colors[ImGuiCol_HeaderHovered];
|
||||
colors[ImGuiCol_TabActive] = ImLerp(colors[ImGuiCol_HeaderActive], colors[ImGuiCol_TitleBgActive], 0.60f);
|
||||
colors[ImGuiCol_TabUnfocused] = ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
|
||||
colors[ImGuiCol_TabUnfocusedActive] = ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
|
||||
colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
|
||||
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
|
||||
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||
@@ -2821,6 +2836,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
|
||||
// - RenderMouseCursor()
|
||||
// - RenderArrowPointingAt()
|
||||
// - RenderRectFilledRangeH()
|
||||
// - RenderPixelEllipsis()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor)
|
||||
@@ -2929,6 +2945,15 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im
|
||||
draw_list->PathFillConvex(col);
|
||||
}
|
||||
|
||||
// FIXME: Rendering an ellipsis "..." is a surprisingly tricky problem for us... we cannot rely on font glyph having it,
|
||||
// and regular dot are typically too wide. If we render a dot/shape ourselves it comes with the risk that it wouldn't match
|
||||
// the boldness or positioning of what the font uses...
|
||||
void ImGui::RenderPixelEllipsis(ImDrawList* draw_list, ImFont* font, ImVec2 pos, int count, ImU32 col)
|
||||
{
|
||||
pos.y += (float)(int)(font->DisplayOffset.y + font->Ascent + 0.5f - 1.0f);
|
||||
for (int dot_n = 0; dot_n < count; dot_n++)
|
||||
draw_list->AddRectFilled(ImVec2(pos.x + dot_n * 2.0f, pos.y), ImVec2(pos.x + dot_n * 2.0f + 1.0f, pos.y + 1.0f), col);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Decompression code
|
||||
|
||||
@@ -49,6 +49,8 @@ struct ImGuiNextWindowData; // Storage for SetNexWindow** functions
|
||||
struct ImGuiPopupRef; // Storage for current popup stack
|
||||
struct ImGuiSettingsHandler; // Storage for one type registered in the .ini file
|
||||
struct ImGuiStyleMod; // Stacked style modifier, backup of modified data so we can restore it
|
||||
struct ImGuiTabBar; // Storage for a tab bar
|
||||
struct ImGuiTabItem; // Storage for a tab item (within a tab bar)
|
||||
struct ImGuiWindow; // Storage for one window
|
||||
struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame)
|
||||
struct ImGuiWindowSettings; // Storage for window settings stored in .ini file (we keep one of those even if the actual window wasn't instanced during this session)
|
||||
@@ -679,6 +681,12 @@ struct ImGuiNextWindowData
|
||||
}
|
||||
};
|
||||
|
||||
struct ImGuiTabBarSortItem
|
||||
{
|
||||
int Index;
|
||||
float Width;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main imgui context
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -804,6 +812,11 @@ struct ImGuiContext
|
||||
ImVector<unsigned char> DragDropPayloadBufHeap; // We don't expose the ImVector<> directly
|
||||
unsigned char DragDropPayloadBufLocal[8]; // Local buffer for small payloads
|
||||
|
||||
// Tab bars
|
||||
ImPool<ImGuiTabBar> TabBars;
|
||||
ImVector<ImGuiTabBar*> CurrentTabBar;
|
||||
ImVector<ImGuiTabBarSortItem> TabSortByWidthBuffer;
|
||||
|
||||
// Widget state
|
||||
ImGuiInputTextState InputTextState;
|
||||
ImFont InputTextPasswordFont;
|
||||
@@ -1154,6 +1167,59 @@ struct ImGuiItemHoveredDataBackup
|
||||
void Restore() const { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemStatusFlags = LastItemStatusFlags; window->DC.LastItemRect = LastItemRect; window->DC.LastItemDisplayRect = LastItemDisplayRect; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Tab Bar, Tab Item
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
enum ImGuiTabBarFlagsPrivate_
|
||||
{
|
||||
ImGuiTabBarFlags_DockNode = 1 << 20, // [Docking: Unused in Master Branch] Part of a dock node
|
||||
ImGuiTabBarFlags_DockNodeIsDockSpace = 1 << 21, // [Docking: Unused in Master Branch] Part of an explicit dockspace node node
|
||||
ImGuiTabBarFlags_IsFocused = 1 << 22,
|
||||
ImGuiTabBarFlags_SaveSettings = 1 << 23 // FIXME: Settings are handled by the docking system, this only request the tab bar to mark settings dirty when reordering tabs
|
||||
};
|
||||
|
||||
// Storage for one active tab item (sizeof() 26~32 bytes)
|
||||
struct ImGuiTabItem
|
||||
{
|
||||
ImGuiID ID;
|
||||
ImGuiTabItemFlags Flags;
|
||||
int LastFrameVisible;
|
||||
int LastFrameSelected; // This allows us to infer an ordered list of the last activated tabs with little maintenance
|
||||
float Offset; // Position relative to beginning of tab
|
||||
float Width; // Width currently displayed
|
||||
float WidthContents; // Width of actual contents, stored during BeginTabItem() call
|
||||
|
||||
ImGuiTabItem() { ID = Flags = 0; LastFrameVisible = LastFrameSelected = -1; Offset = Width = WidthContents = 0.0f; }
|
||||
};
|
||||
|
||||
// Storage for a tab bar (sizeof() 92~96 bytes)
|
||||
struct ImGuiTabBar
|
||||
{
|
||||
ImVector<ImGuiTabItem> Tabs;
|
||||
ImGuiID ID; // Zero for tab-bars used by docking
|
||||
ImGuiID SelectedTabId; // Selected tab
|
||||
ImGuiID NextSelectedTabId;
|
||||
ImGuiID VisibleTabId; // Can occasionally be != SelectedTabId (e.g. when previewing contents for CTRL+TAB preview)
|
||||
int CurrFrameVisible;
|
||||
int PrevFrameVisible;
|
||||
ImRect BarRect;
|
||||
float ContentsHeight;
|
||||
float OffsetMax; // Distance from BarRect.Min.x, locked during layout
|
||||
float OffsetNextTab; // Distance from BarRect.Min.x, incremented with each BeginTabItem() call, not used if ImGuiTabBarFlags_Reorderable if set.
|
||||
float ScrollingAnim;
|
||||
float ScrollingTarget;
|
||||
ImGuiTabBarFlags Flags;
|
||||
ImGuiID ReorderRequestTabId;
|
||||
int ReorderRequestDir;
|
||||
bool WantLayout;
|
||||
bool VisibleTabWasSubmitted;
|
||||
short LastTabItemIdx; // For BeginTabItem()/EndTabItem()
|
||||
|
||||
ImGuiTabBar();
|
||||
int GetTabOrder(const ImGuiTabItem* tab) const { return Tabs.index_from_pointer(tab); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Internal API
|
||||
// No guarantee of forward compatibility here.
|
||||
@@ -1270,12 +1336,24 @@ namespace ImGui
|
||||
IMGUI_API void EndColumns(); // close columns
|
||||
IMGUI_API void PushColumnClipRect(int column_index = -1);
|
||||
|
||||
// Tab Bars
|
||||
IMGUI_API bool BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags);
|
||||
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 TabBarQueueChangeTabOrder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir);
|
||||
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);
|
||||
IMGUI_API void TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col);
|
||||
IMGUI_API bool TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, const char* label, ImGuiID tab_id, ImGuiID close_button_id);
|
||||
|
||||
// Render helpers
|
||||
// AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT.
|
||||
// NB: All position are in absolute pixels coordinates (we are never using window coordinates internally)
|
||||
IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true);
|
||||
IMGUI_API void RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end, float wrap_width);
|
||||
IMGUI_API void RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0,0), const ImRect* clip_rect = NULL);
|
||||
IMGUI_API void RenderTextClippedEx(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, const char* text, const char* text_end, const ImVec2* text_size_if_known, const ImVec2& align = ImVec2(0, 0), const ImRect* clip_rect = NULL);
|
||||
IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f);
|
||||
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
|
||||
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, int rounding_corners_flags = ~0);
|
||||
@@ -1290,6 +1368,7 @@ namespace ImGui
|
||||
IMGUI_API void RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, ImGuiMouseCursor mouse_cursor = ImGuiMouseCursor_Arrow);
|
||||
IMGUI_API void RenderArrowPointingAt(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGuiDir direction, ImU32 col);
|
||||
IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding);
|
||||
IMGUI_API void RenderPixelEllipsis(ImDrawList* draw_list, ImFont* font, ImVec2 pos, int count, ImU32 col);
|
||||
|
||||
// Widgets
|
||||
IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user