|
@@ -274,7 +274,6 @@ void ImGui::TextV(const char* fmt, va_list args)
|
|
if (window->SkipItems)
|
|
if (window->SkipItems)
|
|
return;
|
|
return;
|
|
|
|
|
|
- // FIXME-OPT: Handle the %s shortcut?
|
|
|
|
const char* text, *text_end;
|
|
const char* text, *text_end;
|
|
ImFormatStringToTempBufferV(&text, &text_end, fmt, args);
|
|
ImFormatStringToTempBufferV(&text, &text_end, fmt, args);
|
|
TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
|
|
TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
|
|
@@ -291,10 +290,7 @@ void ImGui::TextColored(const ImVec4& col, const char* fmt, ...)
|
|
void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
|
|
void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
|
|
{
|
|
{
|
|
PushStyleColor(ImGuiCol_Text, col);
|
|
PushStyleColor(ImGuiCol_Text, col);
|
|
- if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0)
|
|
|
|
- TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
|
|
|
|
- else
|
|
|
|
- TextV(fmt, args);
|
|
|
|
|
|
+ TextV(fmt, args);
|
|
PopStyleColor();
|
|
PopStyleColor();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -310,10 +306,7 @@ void ImGui::TextDisabledV(const char* fmt, va_list args)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);
|
|
PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);
|
|
- if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0)
|
|
|
|
- TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
|
|
|
|
- else
|
|
|
|
- TextV(fmt, args);
|
|
|
|
|
|
+ TextV(fmt, args);
|
|
PopStyleColor();
|
|
PopStyleColor();
|
|
}
|
|
}
|
|
|
|
|
|
@@ -328,13 +321,10 @@ void ImGui::TextWrapped(const char* fmt, ...)
|
|
void ImGui::TextWrappedV(const char* fmt, va_list args)
|
|
void ImGui::TextWrappedV(const char* fmt, va_list args)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
- bool need_backup = (g.CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position if one is already set
|
|
|
|
|
|
+ const bool need_backup = (g.CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position if one is already set
|
|
if (need_backup)
|
|
if (need_backup)
|
|
PushTextWrapPos(0.0f);
|
|
PushTextWrapPos(0.0f);
|
|
- if (fmt[0] == '%' && fmt[1] == 's' && fmt[2] == 0)
|
|
|
|
- TextEx(va_arg(args, const char*), NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
|
|
|
|
- else
|
|
|
|
- TextV(fmt, args);
|
|
|
|
|
|
+ TextV(fmt, args);
|
|
if (need_backup)
|
|
if (need_backup)
|
|
PopTextWrapPos();
|
|
PopTextWrapPos();
|
|
}
|
|
}
|
|
@@ -1048,7 +1038,7 @@ void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2&
|
|
|
|
|
|
// ImageButton() is flawed as 'id' is always derived from 'texture_id' (see #2464 #1390)
|
|
// ImageButton() is flawed as 'id' is always derived from 'texture_id' (see #2464 #1390)
|
|
// We provide this internal helper to write your own variant while we figure out how to redesign the public ImageButton() API.
|
|
// We provide this internal helper to write your own variant while we figure out how to redesign the public ImageButton() API.
|
|
-bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col)
|
|
|
|
|
|
+bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& bg_col, const ImVec4& tint_col, ImGuiButtonFlags flags)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
@@ -1062,7 +1052,7 @@ bool ImGui::ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size
|
|
return false;
|
|
return false;
|
|
|
|
|
|
bool hovered, held;
|
|
bool hovered, held;
|
|
- bool pressed = ButtonBehavior(bb, id, &hovered, &held);
|
|
|
|
|
|
+ bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
|
|
|
|
|
// Render
|
|
// Render
|
|
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
|
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
|
@@ -1711,7 +1701,12 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags
|
|
if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8;
|
|
if (flags & ImGuiComboFlags_HeightRegular) popup_max_height_in_items = 8;
|
|
else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4;
|
|
else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4;
|
|
else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20;
|
|
else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20;
|
|
- SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
|
|
|
|
|
|
+ ImVec2 constraint_min(0.0f, 0.0f), constraint_max(FLT_MAX, FLT_MAX);
|
|
|
|
+ if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.x <= 0.0f) // Don't apply constraints if user specified a size
|
|
|
|
+ constraint_min.x = w;
|
|
|
|
+ if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.y <= 0.0f)
|
|
|
|
+ constraint_max.y = CalcMaxPopupHeightFromItemCount(popup_max_height_in_items);
|
|
|
|
+ SetNextWindowSizeConstraints(constraint_min, constraint_max);
|
|
}
|
|
}
|
|
|
|
|
|
// This is essentially a specialized version of BeginPopupEx()
|
|
// This is essentially a specialized version of BeginPopupEx()
|
|
@@ -4102,6 +4097,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|
state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863)
|
|
state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ const bool is_osx = io.ConfigMacOSXBehaviors;
|
|
if (g.ActiveId != id && init_make_active)
|
|
if (g.ActiveId != id && init_make_active)
|
|
{
|
|
{
|
|
IM_ASSERT(state && state->ID == id);
|
|
IM_ASSERT(state && state->ID == id);
|
|
@@ -4124,6 +4120,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|
SetKeyOwner(ImGuiKey_PageUp, id);
|
|
SetKeyOwner(ImGuiKey_PageUp, id);
|
|
SetKeyOwner(ImGuiKey_PageDown, id);
|
|
SetKeyOwner(ImGuiKey_PageDown, id);
|
|
}
|
|
}
|
|
|
|
+ if (is_osx)
|
|
|
|
+ SetKeyOwner(ImGuiMod_Alt, id);
|
|
if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out as we will use the \t character.
|
|
if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out as we will use the \t character.
|
|
SetKeyOwner(ImGuiKey_Tab, id);
|
|
SetKeyOwner(ImGuiKey_Tab, id);
|
|
}
|
|
}
|
|
@@ -4193,7 +4191,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|
const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX;
|
|
const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + state->ScrollX;
|
|
const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f));
|
|
const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f));
|
|
|
|
|
|
- const bool is_osx = io.ConfigMacOSXBehaviors;
|
|
|
|
if (select_all)
|
|
if (select_all)
|
|
{
|
|
{
|
|
state->SelectAll();
|
|
state->SelectAll();
|
|
@@ -4294,7 +4291,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|
state->Stb.row_count_per_page = row_count_per_page;
|
|
state->Stb.row_count_per_page = row_count_per_page;
|
|
|
|
|
|
const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0);
|
|
const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0);
|
|
- const bool is_osx = io.ConfigMacOSXBehaviors;
|
|
|
|
const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl
|
|
const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl
|
|
const bool is_startend_key_down = is_osx && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End
|
|
const bool is_startend_key_down = is_osx && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End
|
|
|
|
|
|
@@ -4323,7 +4319,16 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|
else if (IsKeyPressed(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; }
|
|
else if (IsKeyPressed(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; }
|
|
else if (IsKeyPressed(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
|
|
else if (IsKeyPressed(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
|
|
else if (IsKeyPressed(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
|
|
else if (IsKeyPressed(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
|
|
- else if (IsKeyPressed(ImGuiKey_Delete) && !is_readonly && !is_cut) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
|
|
|
|
|
|
+ else if (IsKeyPressed(ImGuiKey_Delete) && !is_readonly && !is_cut)
|
|
|
|
+ {
|
|
|
|
+ if (!state->HasSelection())
|
|
|
|
+ {
|
|
|
|
+ // OSX doesn't seem to have Super+Delete to delete until end-of-line, so we don't emulate that (as opposed to Super+Backspace)
|
|
|
|
+ if (is_wordmove_key_down)
|
|
|
|
+ state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
|
|
|
|
+ }
|
|
|
|
+ state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask);
|
|
|
|
+ }
|
|
else if (IsKeyPressed(ImGuiKey_Backspace) && !is_readonly)
|
|
else if (IsKeyPressed(ImGuiKey_Backspace) && !is_readonly)
|
|
{
|
|
{
|
|
if (!state->HasSelection())
|
|
if (!state->HasSelection())
|
|
@@ -7033,7 +7038,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
|
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
|
|
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
|
|
float w = label_size.x;
|
|
float w = label_size.x;
|
|
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
|
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
|
- pressed = Selectable("", menu_is_open, selectable_flags, ImVec2(w, 0.0f));
|
|
|
|
|
|
+ pressed = Selectable("", menu_is_open, selectable_flags, ImVec2(w, label_size.y));
|
|
RenderText(text_pos, label);
|
|
RenderText(text_pos, label);
|
|
PopStyleVar();
|
|
PopStyleVar();
|
|
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
|
|
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
|
|
@@ -7049,7 +7054,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
|
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame
|
|
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, 0.0f, checkmark_w); // Feedback to next frame
|
|
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
|
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
|
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
|
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
|
- pressed = Selectable("", menu_is_open, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
|
|
|
|
|
|
+ pressed = Selectable("", menu_is_open, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
|
|
RenderText(text_pos, label);
|
|
RenderText(text_pos, label);
|
|
if (icon_w > 0.0f)
|
|
if (icon_w > 0.0f)
|
|
RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
|
|
RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
|
|
@@ -7241,7 +7246,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
|
float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);
|
|
float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);
|
|
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
|
|
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
|
|
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
|
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
|
- pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
|
|
|
|
|
|
+ pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
|
|
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)
|
|
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)
|
|
{
|
|
{
|
|
RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label);
|
|
RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label);
|
|
@@ -7293,12 +7298,19 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected,
|
|
// - TabBarCalcTabID() [Internal]
|
|
// - TabBarCalcTabID() [Internal]
|
|
// - TabBarCalcMaxTabWidth() [Internal]
|
|
// - TabBarCalcMaxTabWidth() [Internal]
|
|
// - TabBarFindTabById() [Internal]
|
|
// - TabBarFindTabById() [Internal]
|
|
|
|
+// - TabBarFindTabByOrder() [Internal]
|
|
|
|
+// - TabBarFindMostRecentlySelectedTabForActiveWindow() [Internal]
|
|
|
|
+// - TabBarGetCurrentTab() [Internal]
|
|
|
|
+// - TabBarGetTabName() [Internal]
|
|
// - TabBarAddTab() [Internal]
|
|
// - TabBarAddTab() [Internal]
|
|
// - TabBarRemoveTab() [Internal]
|
|
// - TabBarRemoveTab() [Internal]
|
|
// - TabBarCloseTab() [Internal]
|
|
// - TabBarCloseTab() [Internal]
|
|
// - TabBarScrollClamp() [Internal]
|
|
// - TabBarScrollClamp() [Internal]
|
|
// - TabBarScrollToTab() [Internal]
|
|
// - TabBarScrollToTab() [Internal]
|
|
-// - TabBarQueueChangeTabOrder() [Internal]
|
|
|
|
|
|
+// - TabBarQueueFocus() [Internal]
|
|
|
|
+// - TabBarQueueReorder() [Internal]
|
|
|
|
+// - TabBarProcessReorderFromMousePos() [Internal]
|
|
|
|
+// - TabBarProcessReorder() [Internal]
|
|
// - TabBarScrollingButtons() [Internal]
|
|
// - TabBarScrollingButtons() [Internal]
|
|
// - TabBarTabListPopupButton() [Internal]
|
|
// - TabBarTabListPopupButton() [Internal]
|
|
//-------------------------------------------------------------------------
|
|
//-------------------------------------------------------------------------
|
|
@@ -7424,6 +7436,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
|
|
tab_bar->ItemSpacingY = g.Style.ItemSpacing.y;
|
|
tab_bar->ItemSpacingY = g.Style.ItemSpacing.y;
|
|
tab_bar->FramePadding = g.Style.FramePadding;
|
|
tab_bar->FramePadding = g.Style.FramePadding;
|
|
tab_bar->TabsActiveCount = 0;
|
|
tab_bar->TabsActiveCount = 0;
|
|
|
|
+ tab_bar->LastTabItemIdx = -1;
|
|
tab_bar->BeginCount = 1;
|
|
tab_bar->BeginCount = 1;
|
|
|
|
|
|
// Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap
|
|
// Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap
|
|
@@ -7479,6 +7492,7 @@ void ImGui::EndTabBar()
|
|
if (tab_bar->BeginCount > 1)
|
|
if (tab_bar->BeginCount > 1)
|
|
window->DC.CursorPos = tab_bar->BackupCursorPos;
|
|
window->DC.CursorPos = tab_bar->BackupCursorPos;
|
|
|
|
|
|
|
|
+ tab_bar->LastTabItemIdx = -1;
|
|
if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
|
|
if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
|
|
PopID();
|
|
PopID();
|
|
|
|
|
|
@@ -7588,7 +7602,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
|
// Refresh tab width immediately, otherwise changes of style e.g. style.FramePadding.x would noticeably lag in the tab bar.
|
|
// Refresh tab width immediately, otherwise changes of style e.g. style.FramePadding.x would noticeably lag in the tab bar.
|
|
// Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet,
|
|
// Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet,
|
|
// and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window.
|
|
// and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window.
|
|
- const char* tab_name = tab_bar->GetTabName(tab);
|
|
|
|
|
|
+ const char* tab_name = TabBarGetTabName(tab_bar, tab);
|
|
const bool has_close_button_or_unsaved_marker = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) == 0 || (tab->Flags & ImGuiTabItemFlags_UnsavedDocument);
|
|
const bool has_close_button_or_unsaved_marker = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) == 0 || (tab->Flags & ImGuiTabItemFlags_UnsavedDocument);
|
|
tab->ContentWidth = (tab->RequestedWidth >= 0.0f) ? tab->RequestedWidth : TabItemCalcSize(tab_name, has_close_button_or_unsaved_marker).x;
|
|
tab->ContentWidth = (tab->RequestedWidth >= 0.0f) ? tab->RequestedWidth : TabItemCalcSize(tab_name, has_close_button_or_unsaved_marker).x;
|
|
|
|
|
|
@@ -7753,6 +7767,14 @@ ImGuiTabItem* ImGui::TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id)
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Order = visible order, not submission order! (which is tab->BeginOrder)
|
|
|
|
+ImGuiTabItem* ImGui::TabBarFindTabByOrder(ImGuiTabBar* tab_bar, int order)
|
|
|
|
+{
|
|
|
|
+ if (order < 0 || order >= tab_bar->Tabs.Size)
|
|
|
|
+ return NULL;
|
|
|
|
+ return &tab_bar->Tabs[order];
|
|
|
|
+}
|
|
|
|
+
|
|
// FIXME: See references to #2304 in TODO.txt
|
|
// FIXME: See references to #2304 in TODO.txt
|
|
ImGuiTabItem* ImGui::TabBarFindMostRecentlySelectedTabForActiveWindow(ImGuiTabBar* tab_bar)
|
|
ImGuiTabItem* ImGui::TabBarFindMostRecentlySelectedTabForActiveWindow(ImGuiTabBar* tab_bar)
|
|
{
|
|
{
|
|
@@ -7767,6 +7789,21 @@ ImGuiTabItem* ImGui::TabBarFindMostRecentlySelectedTabForActiveWindow(ImGuiTabBa
|
|
return most_recently_selected_tab;
|
|
return most_recently_selected_tab;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ImGuiTabItem* ImGui::TabBarGetCurrentTab(ImGuiTabBar* tab_bar)
|
|
|
|
+{
|
|
|
|
+ if (tab_bar->LastTabItemIdx <= 0 || tab_bar->LastTabItemIdx >= tab_bar->Tabs.Size)
|
|
|
|
+ return NULL;
|
|
|
|
+ return &tab_bar->Tabs[tab_bar->LastTabItemIdx];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const char* ImGui::TabBarGetTabName(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
|
|
|
|
+{
|
|
|
|
+ if (tab->Window)
|
|
|
|
+ return tab->Window->Name;
|
|
|
|
+ IM_ASSERT(tab->NameOffset != -1 && tab->NameOffset < tab_bar->TabsNames.Buf.Size);
|
|
|
|
+ return tab_bar->TabsNames.Buf.Data + tab->NameOffset;
|
|
|
|
+}
|
|
|
|
+
|
|
// The purpose of this call is to register tab in advance so we can control their order at the time they appear.
|
|
// The purpose of this call is to register tab in advance so we can control their order at the time they appear.
|
|
// Otherwise calling this is unnecessary as tabs are appending as needed by the BeginTabItem() function.
|
|
// Otherwise calling this is unnecessary as tabs are appending as needed by the BeginTabItem() function.
|
|
void ImGui::TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiTabItemFlags tab_flags, ImGuiWindow* window)
|
|
void ImGui::TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiTabItemFlags tab_flags, ImGuiWindow* window)
|
|
@@ -7788,7 +7825,7 @@ void ImGui::TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiTabItemFlags tab_flags, ImGu
|
|
tab_bar->Tabs.push_back(new_tab);
|
|
tab_bar->Tabs.push_back(new_tab);
|
|
}
|
|
}
|
|
|
|
|
|
-// The *TabId fields be already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
|
|
|
|
|
|
+// The *TabId fields are already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
|
|
void ImGui::TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id)
|
|
void ImGui::TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id)
|
|
{
|
|
{
|
|
if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id))
|
|
if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id))
|
|
@@ -7819,7 +7856,7 @@ void ImGui::TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
|
|
{
|
|
{
|
|
// Actually select before expecting closure attempt (on an UnsavedDocument tab user is expect to e.g. show a popup)
|
|
// Actually select before expecting closure attempt (on an UnsavedDocument tab user is expect to e.g. show a popup)
|
|
if (tab_bar->VisibleTabId != tab->ID)
|
|
if (tab_bar->VisibleTabId != tab->ID)
|
|
- tab_bar->NextSelectedTabId = tab->ID;
|
|
|
|
|
|
+ TabBarQueueFocus(tab_bar, tab);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -7840,7 +7877,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
|
|
|
|
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
float margin = g.FontSize * 1.0f; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar)
|
|
float margin = g.FontSize * 1.0f; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar)
|
|
- int order = tab_bar->GetTabOrder(tab);
|
|
|
|
|
|
+ int order = TabBarGetTabOrder(tab_bar, tab);
|
|
|
|
|
|
// Scrolling happens only in the central section (leading/trailing sections are not scrolling)
|
|
// Scrolling happens only in the central section (leading/trailing sections are not scrolling)
|
|
// FIXME: This is all confusing.
|
|
// FIXME: This is all confusing.
|
|
@@ -7864,7 +7901,12 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int offset)
|
|
|
|
|
|
+void ImGui::TabBarQueueFocus(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
|
|
|
|
+{
|
|
|
|
+ tab_bar->NextSelectedTabId = tab->ID;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, int offset)
|
|
{
|
|
{
|
|
IM_ASSERT(offset != 0);
|
|
IM_ASSERT(offset != 0);
|
|
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
|
|
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
|
|
@@ -7872,7 +7914,7 @@ void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, in
|
|
tab_bar->ReorderRequestOffset = (ImS16)offset;
|
|
tab_bar->ReorderRequestOffset = (ImS16)offset;
|
|
}
|
|
}
|
|
|
|
|
|
-void ImGui::TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, const ImGuiTabItem* src_tab, ImVec2 mouse_pos)
|
|
|
|
|
|
+void ImGui::TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, ImGuiTabItem* src_tab, ImVec2 mouse_pos)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
|
|
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
|
|
@@ -7915,7 +7957,7 @@ bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar)
|
|
return false;
|
|
return false;
|
|
|
|
|
|
//IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
|
|
//IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
|
|
- int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestOffset;
|
|
|
|
|
|
+ int tab2_order = TabBarGetTabOrder(tab_bar, tab1) + tab_bar->ReorderRequestOffset;
|
|
if (tab2_order < 0 || tab2_order >= tab_bar->Tabs.Size)
|
|
if (tab2_order < 0 || tab2_order >= tab_bar->Tabs.Size)
|
|
return false;
|
|
return false;
|
|
|
|
|
|
@@ -7975,7 +8017,7 @@ static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar)
|
|
if (select_dir != 0)
|
|
if (select_dir != 0)
|
|
if (ImGuiTabItem* tab_item = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
|
|
if (ImGuiTabItem* tab_item = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
|
|
{
|
|
{
|
|
- int selected_order = tab_bar->GetTabOrder(tab_item);
|
|
|
|
|
|
+ int selected_order = TabBarGetTabOrder(tab_bar, tab_item);
|
|
int target_order = selected_order + select_dir;
|
|
int target_order = selected_order + select_dir;
|
|
|
|
|
|
// Skip tab item buttons until another tab item is found or end is reached
|
|
// Skip tab item buttons until another tab item is found or end is reached
|
|
@@ -8027,7 +8069,7 @@ static ImGuiTabItem* ImGui::TabBarTabListPopupButton(ImGuiTabBar* tab_bar)
|
|
if (tab->Flags & ImGuiTabItemFlags_Button)
|
|
if (tab->Flags & ImGuiTabItemFlags_Button)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- const char* tab_name = tab_bar->GetTabName(tab);
|
|
|
|
|
|
+ const char* tab_name = TabBarGetTabName(tab_bar, tab);
|
|
if (Selectable(tab_name, tab_bar->SelectedTabId == tab->ID))
|
|
if (Selectable(tab_name, tab_bar->SelectedTabId == tab->ID))
|
|
tab_to_select = tab;
|
|
tab_to_select = tab;
|
|
}
|
|
}
|
|
@@ -8194,9 +8236,9 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
|
{
|
|
{
|
|
if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0)
|
|
if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0)
|
|
if (!tab_bar_appearing || tab_bar->SelectedTabId == 0)
|
|
if (!tab_bar_appearing || tab_bar->SelectedTabId == 0)
|
|
- tab_bar->NextSelectedTabId = id; // New tabs gets activated
|
|
|
|
|
|
+ TabBarQueueFocus(tab_bar, tab); // New tabs gets activated
|
|
if ((flags & ImGuiTabItemFlags_SetSelected) && (tab_bar->SelectedTabId != id)) // _SetSelected can only be passed on explicit tab bar
|
|
if ((flags & ImGuiTabItemFlags_SetSelected) && (tab_bar->SelectedTabId != id)) // _SetSelected can only be passed on explicit tab bar
|
|
- tab_bar->NextSelectedTabId = id;
|
|
|
|
|
|
+ TabBarQueueFocus(tab_bar, tab);
|
|
}
|
|
}
|
|
|
|
|
|
// Lock visibility
|
|
// Lock visibility
|
|
@@ -8260,7 +8302,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
|
bool hovered, held;
|
|
bool hovered, held;
|
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
|
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
|
|
if (pressed && !is_tab_button)
|
|
if (pressed && !is_tab_button)
|
|
- tab_bar->NextSelectedTabId = id;
|
|
|
|
|
|
+ TabBarQueueFocus(tab_bar, tab);
|
|
|
|
|
|
// Transfer active id window so the active id is not owned by the dock host (as StartMouseMovingWindow()
|
|
// Transfer active id window so the active id is not owned by the dock host (as StartMouseMovingWindow()
|
|
// will only do it on the drag). This allows FocusWindow() to be more conservative in how it clears active id.
|
|
// will only do it on the drag). This allows FocusWindow() to be more conservative in how it clears active id.
|
|
@@ -8317,7 +8359,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
|
if (distance_from_edge_y >= threshold_y)
|
|
if (distance_from_edge_y >= threshold_y)
|
|
undocking_tab = true;
|
|
undocking_tab = true;
|
|
if (drag_distance_from_edge_x > threshold_x)
|
|
if (drag_distance_from_edge_x > threshold_x)
|
|
- if ((drag_dir < 0 && tab_bar->GetTabOrder(tab) == 0) || (drag_dir > 0 && tab_bar->GetTabOrder(tab) == tab_bar->Tabs.Size - 1))
|
|
|
|
|
|
+ if ((drag_dir < 0 && TabBarGetTabOrder(tab_bar, tab) == 0) || (drag_dir > 0 && TabBarGetTabOrder(tab_bar, tab) == tab_bar->Tabs.Size - 1))
|
|
undocking_tab = true;
|
|
undocking_tab = true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -8353,9 +8395,8 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
|
|
|
|
|
// Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget.
|
|
// Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget.
|
|
const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
|
|
const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
|
|
- if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)))
|
|
|
|
- if (!is_tab_button)
|
|
|
|
- tab_bar->NextSelectedTabId = id;
|
|
|
|
|
|
+ if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)) && !is_tab_button)
|
|
|
|
+ TabBarQueueFocus(tab_bar, tab);
|
|
|
|
|
|
if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
|
|
if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
|
|
flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
|
|
flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
|