mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-04 12:08:47 +02:00
Merge branch 'master' into viewport
# Conflicts: # examples/imgui_impl_opengl2.cpp # examples/imgui_impl_opengl2.h # examples/imgui_impl_opengl3.cpp # examples/imgui_impl_opengl3.h # imgui.cpp # imgui.h
This commit is contained in:
152
imgui.cpp
152
imgui.cpp
@ -2200,6 +2200,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
|
||||
if (g.ActiveIdIsJustActivated)
|
||||
{
|
||||
g.ActiveIdTimer = 0.0f;
|
||||
g.ActiveIdValueChanged = false;
|
||||
if (id != 0)
|
||||
{
|
||||
g.LastActiveId = id;
|
||||
@ -2217,12 +2218,6 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiID ImGui::GetActiveID()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
return g.ActiveId;
|
||||
}
|
||||
|
||||
void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@ -2269,6 +2264,17 @@ void ImGui::KeepAliveID(ImGuiID id)
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.ActiveId == id)
|
||||
g.ActiveIdIsAlive = true;
|
||||
if (g.ActiveIdPreviousFrame == id)
|
||||
g.ActiveIdPreviousFrameIsAlive = true;
|
||||
}
|
||||
|
||||
void ImGui::MarkItemValueChanged(ImGuiID id)
|
||||
{
|
||||
// This marking is solely to be able to provide info for IsItemDeactivatedAfterChange().
|
||||
// ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need need to fill the data.
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(g.ActiveId == id || g.ActiveId == 0);
|
||||
g.ActiveIdValueChanged = true;
|
||||
}
|
||||
|
||||
static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
|
||||
@ -2700,7 +2706,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
|
||||
return false;
|
||||
if (!IsMouseHoveringRect(bb.Min, bb.Max))
|
||||
return false;
|
||||
if (g.NavDisableMouseHover || !IsWindowContentHoverable(window, ImGuiHoveredFlags_Default))
|
||||
if (g.NavDisableMouseHover || !IsWindowContentHoverable(window, ImGuiHoveredFlags_None))
|
||||
return false;
|
||||
if (window->DC.ItemFlags & ImGuiItemFlags_Disabled)
|
||||
return false;
|
||||
@ -4196,7 +4202,9 @@ void ImGui::NewFrame()
|
||||
g.ActiveIdTimer += g.IO.DeltaTime;
|
||||
g.LastActiveIdTimer += g.IO.DeltaTime;
|
||||
g.ActiveIdPreviousFrame = g.ActiveId;
|
||||
g.ActiveIdIsAlive = false;
|
||||
g.ActiveIdPreviousFrameWindow = g.ActiveIdWindow;
|
||||
g.ActiveIdPreviousFrameValueChanged = g.ActiveIdValueChanged;
|
||||
g.ActiveIdIsAlive = g.ActiveIdPreviousFrameIsAlive = false;
|
||||
g.ActiveIdIsJustActivated = false;
|
||||
if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId)
|
||||
g.ScalarAsInputTextId = 0;
|
||||
@ -4456,7 +4464,7 @@ void ImGui::Shutdown(ImGuiContext* context)
|
||||
g.NavWindow = NULL;
|
||||
g.HoveredWindow = NULL;
|
||||
g.HoveredRootWindow = NULL;
|
||||
g.ActiveIdWindow = NULL;
|
||||
g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL;
|
||||
g.MovingWindow = NULL;
|
||||
g.ColorModifiers.clear();
|
||||
g.StyleModifiers.clear();
|
||||
@ -5617,6 +5625,19 @@ bool ImGui::IsItemActive()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ImGui::IsItemDeactivated()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
return (g.ActiveIdPreviousFrame == window->DC.LastItemId && g.ActiveIdPreviousFrame != 0 && g.ActiveId != window->DC.LastItemId);
|
||||
}
|
||||
|
||||
bool ImGui::IsItemDeactivatedAfterChange()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
return IsItemDeactivated() && (g.ActiveIdPreviousFrameValueChanged || (g.ActiveId == 0 && g.ActiveIdValueChanged));
|
||||
}
|
||||
|
||||
bool ImGui::IsItemFocused()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@ -5625,7 +5646,7 @@ bool ImGui::IsItemFocused()
|
||||
|
||||
bool ImGui::IsItemClicked(int mouse_button)
|
||||
{
|
||||
return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_Default);
|
||||
return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None);
|
||||
}
|
||||
|
||||
bool ImGui::IsAnyItemHovered()
|
||||
@ -8963,6 +8984,8 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags
|
||||
flags |= ImGuiButtonFlags_Repeat;
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
||||
if (pressed)
|
||||
MarkItemValueChanged(id);
|
||||
|
||||
// Render
|
||||
const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
|
||||
@ -9245,7 +9268,7 @@ void ImGui::LogButtons()
|
||||
bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags)
|
||||
{
|
||||
if (flags & ImGuiTreeNodeFlags_Leaf)
|
||||
return false;
|
||||
return true;
|
||||
|
||||
// We only write to the tree storage if the user clicks (or explicitly use SetNextTreeNode*** functions)
|
||||
ImGuiContext& g = *GImGui;
|
||||
@ -10268,6 +10291,8 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co
|
||||
// Actual slider behavior + render grab
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
const bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power);
|
||||
if (value_changed)
|
||||
MarkItemValueChanged(id);
|
||||
|
||||
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
|
||||
char value_buf[64];
|
||||
@ -10321,7 +10346,9 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
|
||||
}
|
||||
|
||||
// Actual slider behavior + render grab
|
||||
bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power, ImGuiSliderFlags_Vertical);
|
||||
const bool value_changed = SliderBehavior(frame_bb, id, data_type, v, v_min, v_max, format, power, ImGuiSliderFlags_Vertical);
|
||||
if (value_changed)
|
||||
MarkItemValueChanged(id);
|
||||
|
||||
// Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
|
||||
// For the vertical slider we allow centered text to overlap the frame padding
|
||||
@ -10598,6 +10625,8 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* v, floa
|
||||
// Actual drag behavior
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
const bool value_changed = DragBehavior(id, data_type, v, v_speed, v_min, v_max, format, power);
|
||||
if (value_changed)
|
||||
MarkItemValueChanged(id);
|
||||
|
||||
// Draw frame
|
||||
const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
|
||||
@ -10684,7 +10713,6 @@ bool ImGui::DragFloatRange2(const char* label, float* v_current_min, float* v_cu
|
||||
TextUnformatted(label, FindRenderedTextEnd(label));
|
||||
EndGroup();
|
||||
PopID();
|
||||
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@ -10947,7 +10975,10 @@ bool ImGui::Checkbox(const char* label, bool* v)
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
|
||||
if (pressed)
|
||||
{
|
||||
*v = !(*v);
|
||||
MarkItemValueChanged(id);
|
||||
}
|
||||
|
||||
RenderNavHighlight(total_bb, id);
|
||||
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
|
||||
@ -11015,6 +11046,8 @@ bool ImGui::RadioButton(const char* label, bool active)
|
||||
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
|
||||
if (pressed)
|
||||
MarkItemValueChanged(id);
|
||||
|
||||
RenderNavHighlight(total_bb, id);
|
||||
window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16);
|
||||
@ -11043,9 +11076,7 @@ bool ImGui::RadioButton(const char* label, int* v, int v_button)
|
||||
{
|
||||
const bool pressed = RadioButton(label, *v == v_button);
|
||||
if (pressed)
|
||||
{
|
||||
*v = v_button;
|
||||
}
|
||||
return pressed;
|
||||
}
|
||||
|
||||
@ -11326,7 +11357,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
||||
const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0;
|
||||
const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0;
|
||||
|
||||
if (is_multiline) // Open group before calling GetID() because groups tracks id created during their spawn
|
||||
if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope,
|
||||
BeginGroup();
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
@ -11916,6 +11947,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
|
||||
if (label_size.x > 0)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
||||
|
||||
if (value_changed)
|
||||
MarkItemValueChanged(id);
|
||||
|
||||
if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0)
|
||||
return enter_pressed;
|
||||
else
|
||||
@ -12038,7 +12072,6 @@ bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, in
|
||||
|
||||
TextUnformatted(label, FindRenderedTextEnd(label));
|
||||
EndGroup();
|
||||
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@ -12381,6 +12414,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
g.NavDisableHighlight = true;
|
||||
SetNavID(id, window->DC.NavLayerCurrent);
|
||||
}
|
||||
if (pressed)
|
||||
MarkItemValueChanged(id);
|
||||
|
||||
// Render
|
||||
if (hovered || selected)
|
||||
@ -12416,6 +12451,7 @@ bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: Rename to BeginListBox()
|
||||
// Helper to calculate the size of a listbox and display a label on the right.
|
||||
// Tip: To have a list filling the entire window width, PushItemWidth(-1) and pass an empty label "##empty"
|
||||
bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg)
|
||||
@ -12443,6 +12479,7 @@ bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg)
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: Rename to BeginListBox()
|
||||
bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_items)
|
||||
{
|
||||
// Size default to hold ~7 items. Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.
|
||||
@ -12459,6 +12496,7 @@ bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_item
|
||||
return ListBoxHeader(label, size);
|
||||
}
|
||||
|
||||
// FIXME: Rename to EndListBox()
|
||||
void ImGui::ListBoxFooter()
|
||||
{
|
||||
ImGuiWindow* parent_window = GetCurrentWindow()->ParentWindow;
|
||||
@ -12606,7 +12644,7 @@ bool ImGui::BeginMenuBar()
|
||||
return false;
|
||||
|
||||
IM_ASSERT(!window->DC.MenuBarAppending);
|
||||
BeginGroup(); // Save position
|
||||
BeginGroup(); // Backup position on layer 0
|
||||
PushID("##menubar");
|
||||
|
||||
// We don't clip with current window clipping rectangle as it is already set to the area below. However we clip with window full rect.
|
||||
@ -12658,7 +12696,7 @@ void ImGui::EndMenuBar()
|
||||
PopID();
|
||||
window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->MenuBarRect().Min.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos.
|
||||
window->DC.GroupStack.back().AdvanceCursor = false;
|
||||
EndGroup();
|
||||
EndGroup(); // Restore position on layer 0
|
||||
window->DC.LayoutType = ImGuiLayoutType_Vertical;
|
||||
window->DC.NavLayerCurrent--;
|
||||
window->DC.NavLayerCurrentMask >>= 1;
|
||||
@ -12970,6 +13008,9 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
|
||||
if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered)
|
||||
ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf));
|
||||
|
||||
if (pressed)
|
||||
MarkItemValueChanged(id);
|
||||
|
||||
return pressed;
|
||||
}
|
||||
|
||||
@ -13264,6 +13305,9 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
|
||||
if (picker_active_window && g.ActiveId != 0 && g.ActiveIdWindow == picker_active_window)
|
||||
window->DC.LastItemId = g.ActiveId;
|
||||
|
||||
if (value_changed)
|
||||
MarkItemValueChanged(window->DC.LastItemId);
|
||||
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@ -13587,12 +13631,18 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
}
|
||||
|
||||
EndGroup();
|
||||
|
||||
if (value_changed && memcmp(backup_initial_col, col, components * sizeof(float)) == 0)
|
||||
value_changed = false;
|
||||
if (value_changed)
|
||||
MarkItemValueChanged(window->DC.LastItemId);
|
||||
|
||||
PopID();
|
||||
|
||||
return value_changed && memcmp(backup_initial_col, col, components * sizeof(float));
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
// Horizontal separating line.
|
||||
// Horizontal/vertical separating line
|
||||
void ImGui::Separator()
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
@ -13600,9 +13650,8 @@ void ImGui::Separator()
|
||||
return;
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
ImGuiSeparatorFlags flags = 0;
|
||||
if ((flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)) == 0)
|
||||
flags |= (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
|
||||
// Those flags should eventually be overridable by the user
|
||||
ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
|
||||
IM_ASSERT(ImIsPowerOfTwo((int)(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)))); // Check that only 1 option is selected
|
||||
if (flags & ImGuiSeparatorFlags_Vertical)
|
||||
{
|
||||
@ -13697,6 +13746,8 @@ bool ImGui::SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float
|
||||
*size1 += mouse_delta;
|
||||
*size2 -= mouse_delta;
|
||||
bb_render.Translate((axis == ImGuiAxis_X) ? ImVec2(mouse_delta, 0.0f) : ImVec2(0.0f, mouse_delta));
|
||||
|
||||
MarkItemValueChanged(id);
|
||||
}
|
||||
|
||||
// Render
|
||||
@ -13740,6 +13791,7 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max)
|
||||
// Lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.)
|
||||
void ImGui::BeginGroup()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
|
||||
window->DC.GroupStack.resize(window->DC.GroupStack.Size + 1);
|
||||
@ -13751,21 +13803,21 @@ void ImGui::BeginGroup()
|
||||
group_data.BackupCurrentLineHeight = window->DC.CurrentLineHeight;
|
||||
group_data.BackupCurrentLineTextBaseOffset = window->DC.CurrentLineTextBaseOffset;
|
||||
group_data.BackupLogLinePosY = window->DC.LogLinePosY;
|
||||
group_data.BackupActiveIdIsAlive = GImGui->ActiveIdIsAlive;
|
||||
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
|
||||
group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
|
||||
group_data.AdvanceCursor = true;
|
||||
|
||||
window->DC.GroupOffsetX = window->DC.CursorPos.x - window->Pos.x - window->DC.ColumnsOffsetX;
|
||||
window->DC.IndentX = window->DC.GroupOffsetX;
|
||||
window->DC.CursorMaxPos = window->DC.CursorPos;
|
||||
window->DC.CurrentLineHeight = 0.0f;
|
||||
window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f;
|
||||
window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return
|
||||
}
|
||||
|
||||
void ImGui::EndGroup()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
|
||||
IM_ASSERT(!window->DC.GroupStack.empty()); // Mismatched BeginGroup()/EndGroup() calls
|
||||
|
||||
ImGuiGroupData& group_data = window->DC.GroupStack.back();
|
||||
@ -13775,11 +13827,11 @@ void ImGui::EndGroup()
|
||||
|
||||
window->DC.CursorPos = group_data.BackupCursorPos;
|
||||
window->DC.CursorMaxPos = ImMax(group_data.BackupCursorMaxPos, window->DC.CursorMaxPos);
|
||||
window->DC.CurrentLineHeight = group_data.BackupCurrentLineHeight;
|
||||
window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset;
|
||||
window->DC.IndentX = group_data.BackupIndentX;
|
||||
window->DC.GroupOffsetX = group_data.BackupGroupOffsetX;
|
||||
window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f;
|
||||
window->DC.CurrentLineHeight = group_data.BackupCurrentLineHeight;
|
||||
window->DC.CurrentLineTextBaseOffset = group_data.BackupCurrentLineTextBaseOffset;
|
||||
window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; // To enforce Log carriage return
|
||||
|
||||
if (group_data.AdvanceCursor)
|
||||
{
|
||||
@ -13788,11 +13840,13 @@ void ImGui::EndGroup()
|
||||
ItemAdd(group_bb, 0);
|
||||
}
|
||||
|
||||
// If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive() will be functional on the entire group.
|
||||
// It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but if you search for LastItemId you'll notice it is only used in that context.
|
||||
const bool active_id_within_group = (!group_data.BackupActiveIdIsAlive && g.ActiveIdIsAlive && g.ActiveId && g.ActiveIdWindow->RootWindow == window->RootWindow);
|
||||
if (active_id_within_group)
|
||||
// If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group.
|
||||
// It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but put a little more burden on individual widgets.
|
||||
// (and if you grep for LastItemId you'll notice it is only used in that context.
|
||||
if (!group_data.BackupActiveIdIsAlive && g.ActiveIdIsAlive && g.ActiveId) // && g.ActiveIdWindow->RootWindow == window->RootWindow)
|
||||
window->DC.LastItemId = g.ActiveId;
|
||||
else if (!group_data.BackupActiveIdPreviousFrameIsAlive && g.ActiveIdPreviousFrameIsAlive) // && g.ActiveIdPreviousFrameWindow->RootWindow == window->RootWindow)
|
||||
window->DC.LastItemId = g.ActiveIdPreviousFrame;
|
||||
window->DC.LastItemRect = group_bb;
|
||||
|
||||
window->DC.GroupStack.pop_back();
|
||||
@ -14217,6 +14271,7 @@ void ImGui::TreePop()
|
||||
}
|
||||
window->DC.TreeDepthMayJumpToParentOnPop &= (1 << window->DC.TreeDepth) - 1;
|
||||
|
||||
IM_ASSERT(window->IDStack.Size > 1); // There should always be 1 element in the IDStack (pushed during window creation). If this triggers you called TreePop/PopID too much.
|
||||
PopID();
|
||||
}
|
||||
|
||||
@ -14565,42 +14620,43 @@ static const char* GetClipboardTextFn_DefaultImpl(void*)
|
||||
{
|
||||
static ImVector<char> buf_local;
|
||||
buf_local.clear();
|
||||
if (!OpenClipboard(NULL))
|
||||
if (!::OpenClipboard(NULL))
|
||||
return NULL;
|
||||
HANDLE wbuf_handle = GetClipboardData(CF_UNICODETEXT);
|
||||
HANDLE wbuf_handle = ::GetClipboardData(CF_UNICODETEXT);
|
||||
if (wbuf_handle == NULL)
|
||||
{
|
||||
CloseClipboard();
|
||||
::CloseClipboard();
|
||||
return NULL;
|
||||
}
|
||||
if (ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle))
|
||||
if (ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle))
|
||||
{
|
||||
int buf_len = ImTextCountUtf8BytesFromStr(wbuf_global, NULL) + 1;
|
||||
buf_local.resize(buf_len);
|
||||
ImTextStrToUtf8(buf_local.Data, buf_len, wbuf_global, NULL);
|
||||
}
|
||||
GlobalUnlock(wbuf_handle);
|
||||
CloseClipboard();
|
||||
::GlobalUnlock(wbuf_handle);
|
||||
::CloseClipboard();
|
||||
return buf_local.Data;
|
||||
}
|
||||
|
||||
static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
|
||||
{
|
||||
if (!OpenClipboard(NULL))
|
||||
if (!::OpenClipboard(NULL))
|
||||
return;
|
||||
const int wbuf_length = ImTextCountCharsFromUtf8(text, NULL) + 1;
|
||||
HGLOBAL wbuf_handle = GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar));
|
||||
HGLOBAL wbuf_handle = ::GlobalAlloc(GMEM_MOVEABLE, (SIZE_T)wbuf_length * sizeof(ImWchar));
|
||||
if (wbuf_handle == NULL)
|
||||
{
|
||||
CloseClipboard();
|
||||
::CloseClipboard();
|
||||
return;
|
||||
}
|
||||
ImWchar* wbuf_global = (ImWchar*)GlobalLock(wbuf_handle);
|
||||
ImWchar* wbuf_global = (ImWchar*)::GlobalLock(wbuf_handle);
|
||||
ImTextStrFromUtf8(wbuf_global, wbuf_length, text, NULL);
|
||||
GlobalUnlock(wbuf_handle);
|
||||
EmptyClipboard();
|
||||
SetClipboardData(CF_UNICODETEXT, wbuf_handle);
|
||||
CloseClipboard();
|
||||
::GlobalUnlock(wbuf_handle);
|
||||
::EmptyClipboard();
|
||||
if (::SetClipboardData(CF_UNICODETEXT, wbuf_handle) == NULL)
|
||||
::GlobalFree(wbuf_handle);
|
||||
::CloseClipboard();
|
||||
}
|
||||
|
||||
#else
|
||||
|
Reference in New Issue
Block a user