mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-07 13:35:49 +02:00
Merge branch 'master' into docking
# Conflicts: # backends/imgui_impl_opengl3.cpp # imgui.cpp # imgui.h # imgui_demo.cpp
This commit is contained in:
@ -1450,6 +1450,8 @@ bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float
|
||||
ImRect bb_interact = bb;
|
||||
bb_interact.Expand(axis == ImGuiAxis_Y ? ImVec2(0.0f, hover_extend) : ImVec2(hover_extend, 0.0f));
|
||||
ButtonBehavior(bb_interact, id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap);
|
||||
if (hovered)
|
||||
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect; // for IsItemHovered(), because bb_interact is larger than bb
|
||||
if (g.ActiveId != id)
|
||||
SetItemAllowOverlap();
|
||||
|
||||
@ -1547,6 +1549,8 @@ void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_exc
|
||||
// - BeginCombo()
|
||||
// - BeginComboPopup() [Internal]
|
||||
// - EndCombo()
|
||||
// - BeginComboPreview() [Internal]
|
||||
// - EndComboPreview() [Internal]
|
||||
// - Combo()
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
@ -1608,6 +1612,14 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
|
||||
}
|
||||
RenderFrameBorder(bb.Min, bb.Max, style.FrameRounding);
|
||||
|
||||
// Custom preview
|
||||
if (flags & ImGuiComboFlags_CustomPreview)
|
||||
{
|
||||
g.ComboPreviewData.PreviewRect = ImRect(bb.Min.x, bb.Min.y, value_x2, bb.Max.y);
|
||||
IM_ASSERT(preview_value == NULL || preview_value[0] == 0);
|
||||
preview_value = NULL;
|
||||
}
|
||||
|
||||
// Render preview and label
|
||||
if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview))
|
||||
{
|
||||
@ -1689,6 +1701,57 @@ void ImGui::EndCombo()
|
||||
EndPopup();
|
||||
}
|
||||
|
||||
// Call directly after the BeginCombo/EndCombo block. The preview is designed to only host non-interactive elements
|
||||
// (Experimental, see GitHub issues: #1658, #4168)
|
||||
bool ImGui::BeginComboPreview()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiComboPreviewData* preview_data = &g.ComboPreviewData;
|
||||
|
||||
if (window->SkipItems || !window->ClipRect.Overlaps(window->DC.LastItemRect)) // FIXME: Because we don't have a ImGuiItemStatusFlags_Visible flag to test last ItemAdd() result
|
||||
return false;
|
||||
IM_ASSERT(window->DC.LastItemRect.Min.x == preview_data->PreviewRect.Min.x && window->DC.LastItemRect.Min.y == preview_data->PreviewRect.Min.y); // Didn't call after BeginCombo/EndCombo block or forgot to pass ImGuiComboFlags_CustomPreview flag?
|
||||
if (!window->ClipRect.Contains(preview_data->PreviewRect)) // Narrower test (optional)
|
||||
return false;
|
||||
|
||||
// FIXME: This could be contained in a PushWorkRect() api
|
||||
preview_data->BackupCursorPos = window->DC.CursorPos;
|
||||
preview_data->BackupCursorMaxPos = window->DC.CursorMaxPos;
|
||||
preview_data->BackupCursorPosPrevLine = window->DC.CursorPosPrevLine;
|
||||
preview_data->BackupPrevLineTextBaseOffset = window->DC.PrevLineTextBaseOffset;
|
||||
preview_data->BackupLayout = window->DC.LayoutType;
|
||||
window->DC.CursorPos = preview_data->PreviewRect.Min + g.Style.FramePadding;
|
||||
window->DC.CursorMaxPos = window->DC.CursorPos;
|
||||
window->DC.LayoutType = ImGuiLayoutType_Horizontal;
|
||||
PushClipRect(preview_data->PreviewRect.Min, preview_data->PreviewRect.Max, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui::EndComboPreview()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImGuiComboPreviewData* preview_data = &g.ComboPreviewData;
|
||||
|
||||
// FIXME: Using CursorMaxPos approximation instead of correct AABB which we will store in ImDrawCmd in the future
|
||||
ImDrawList* draw_list = window->DrawList;
|
||||
if (window->DC.CursorMaxPos.x < preview_data->PreviewRect.Max.x && window->DC.CursorMaxPos.y < preview_data->PreviewRect.Max.y)
|
||||
if (draw_list->CmdBuffer.Size > 1) // Unlikely case that the PushClipRect() didn't create a command
|
||||
{
|
||||
draw_list->_CmdHeader.ClipRect = draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 1].ClipRect = draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 2].ClipRect;
|
||||
draw_list->_TryMergeDrawCmds();
|
||||
}
|
||||
PopClipRect();
|
||||
window->DC.CursorPos = preview_data->BackupCursorPos;
|
||||
window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, preview_data->BackupCursorMaxPos);
|
||||
window->DC.CursorPosPrevLine = preview_data->BackupCursorPosPrevLine;
|
||||
window->DC.PrevLineTextBaseOffset = preview_data->BackupPrevLineTextBaseOffset;
|
||||
window->DC.LayoutType = preview_data->BackupLayout;
|
||||
preview_data->PreviewRect = ImRect();
|
||||
}
|
||||
|
||||
// Getter for the old Combo() API: const char*[]
|
||||
static bool Items_ArrayGetter(void* data, int idx, const char** out_text)
|
||||
{
|
||||
@ -5889,8 +5952,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
{
|
||||
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
||||
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);
|
||||
RenderNavHighlight(frame_bb, id, nav_highlight_flags);
|
||||
}
|
||||
RenderNavHighlight(frame_bb, id, nav_highlight_flags);
|
||||
if (flags & ImGuiTreeNodeFlags_Bullet)
|
||||
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize * 0.5f), text_col);
|
||||
else if (!is_leaf)
|
||||
@ -6127,6 +6190,17 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
|
||||
|
||||
// Auto-select when moved into
|
||||
// - This will be more fully fleshed in the range-select branch
|
||||
// - This is not exposed as it won't nicely work with some user side handling of shift/control
|
||||
// - We cannot do 'if (g.NavJustMovedToId != id) { selected = false; pressed = was_selected; }' for two reasons
|
||||
// - (1) it would require focus scope to be set, need exposing PushFocusScope() or equivalent (e.g. BeginSelection() calling PushFocusScope())
|
||||
// - (2) usage will fail with clipped items
|
||||
// The multi-select API aim to fix those issues, e.g. may be replaced with a BeginSelection() API.
|
||||
if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == window->DC.NavFocusScopeIdCurrent)
|
||||
if (g.NavJustMovedToId == id)
|
||||
selected = pressed = true;
|
||||
|
||||
// Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard
|
||||
if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover)))
|
||||
{
|
||||
@ -6153,8 +6227,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
{
|
||||
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
||||
RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
|
||||
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
|
||||
}
|
||||
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
|
||||
|
||||
if (span_all_columns && window->DC.CurrentColumns)
|
||||
PopColumnsBackground();
|
||||
@ -8138,14 +8212,7 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
|
||||
#endif
|
||||
|
||||
// Render text label (with clipping + alpha gradient) + unsaved marker
|
||||
const char* TAB_UNSAVED_MARKER = "*";
|
||||
ImRect text_pixel_clip_bb(bb.Min.x + frame_padding.x, bb.Min.y + frame_padding.y, bb.Max.x - frame_padding.x, bb.Max.y);
|
||||
if (flags & ImGuiTabItemFlags_UnsavedDocument)
|
||||
{
|
||||
text_pixel_clip_bb.Max.x -= CalcTextSize(TAB_UNSAVED_MARKER, NULL, false).x;
|
||||
ImVec2 unsaved_marker_pos(ImMin(bb.Min.x + frame_padding.x + label_size.x + 2, text_pixel_clip_bb.Max.x), bb.Min.y + frame_padding.y + IM_FLOOR(-g.FontSize * 0.25f));
|
||||
RenderTextClippedEx(draw_list, unsaved_marker_pos, bb.Max - frame_padding, TAB_UNSAVED_MARKER, NULL, NULL);
|
||||
}
|
||||
ImRect text_ellipsis_clip_bb = text_pixel_clip_bb;
|
||||
|
||||
// Return clipped state ignoring the close button
|
||||
@ -8155,7 +8222,10 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
|
||||
//draw_list->AddCircle(text_ellipsis_clip_bb.Min, 3.0f, *out_text_clipped ? IM_COL32(255, 0, 0, 255) : IM_COL32(0, 255, 0, 255));
|
||||
}
|
||||
|
||||
// Close Button
|
||||
const float button_sz = g.FontSize;
|
||||
const ImVec2 button_pos(ImMax(bb.Min.x, bb.Max.x - frame_padding.x * 2.0f - button_sz), bb.Min.y);
|
||||
|
||||
// Close Button & Unsaved Marker
|
||||
// We are relying on a subtle and confusing distinction between 'hovered' and 'g.HoveredId' which happens because we are using ImGuiButtonFlags_AllowOverlapMode + SetItemAllowOverlap()
|
||||
// 'hovered' will be true when hovering the Tab but NOT when hovering the close button
|
||||
// 'g.HoveredId==id' will be true when hovering the Tab including when hovering the close button
|
||||
@ -8163,15 +8233,16 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
|
||||
bool close_button_pressed = false;
|
||||
bool close_button_visible = false;
|
||||
if (close_button_id != 0)
|
||||
if (is_contents_visible || bb.GetWidth() >= g.Style.TabMinWidthForCloseButton)
|
||||
if (is_contents_visible || bb.GetWidth() >= ImMax(button_sz, g.Style.TabMinWidthForCloseButton))
|
||||
if (g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == tab_id || g.ActiveId == close_button_id)
|
||||
close_button_visible = true;
|
||||
bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x);
|
||||
|
||||
if (close_button_visible)
|
||||
{
|
||||
ImGuiLastItemDataBackup last_item_backup;
|
||||
const float close_button_sz = g.FontSize;
|
||||
PushStyleVar(ImGuiStyleVar_FramePadding, frame_padding);
|
||||
if (CloseButton(close_button_id, ImVec2(bb.Max.x - frame_padding.x * 2.0f - close_button_sz, bb.Min.y)))
|
||||
if (CloseButton(close_button_id, button_pos))
|
||||
close_button_pressed = true;
|
||||
PopStyleVar();
|
||||
last_item_backup.Restore();
|
||||
@ -8179,12 +8250,23 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
|
||||
// Close with middle mouse button
|
||||
if (!(flags & ImGuiTabItemFlags_NoCloseWithMiddleMouseButton) && IsMouseClicked(2))
|
||||
close_button_pressed = true;
|
||||
|
||||
text_pixel_clip_bb.Max.x -= close_button_sz;
|
||||
}
|
||||
else if (unsaved_marker_visible)
|
||||
{
|
||||
const ImRect bullet_bb(button_pos, button_pos + ImVec2(button_sz, button_sz) + g.Style.FramePadding * 2.0f);
|
||||
RenderBullet(draw_list, bullet_bb.GetCenter(), GetColorU32(ImGuiCol_Text));
|
||||
}
|
||||
|
||||
// This is all rather complicated
|
||||
// (the main idea is that because the close button only appears on hover, we don't want it to alter the ellipsis position)
|
||||
// FIXME: if FramePadding is noticeably large, ellipsis_max_x will be wrong here (e.g. #3497), maybe for consistency that parameter of RenderTextEllipsis() shouldn't exist..
|
||||
float ellipsis_max_x = close_button_visible ? text_pixel_clip_bb.Max.x : bb.Max.x - 1.0f;
|
||||
if (close_button_visible || unsaved_marker_visible)
|
||||
{
|
||||
text_pixel_clip_bb.Max.x -= close_button_visible ? (button_sz) : (button_sz * 0.80f);
|
||||
text_ellipsis_clip_bb.Max.x -= unsaved_marker_visible ? (button_sz * 0.80f) : 0.0f;
|
||||
ellipsis_max_x = text_pixel_clip_bb.Max.x;
|
||||
}
|
||||
RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, text_pixel_clip_bb.Max.x, ellipsis_max_x, label, NULL, &label_size);
|
||||
|
||||
#if 0
|
||||
|
Reference in New Issue
Block a user