|
|
@@ -575,17 +575,17 @@ CODE
|
|
|
Q: Where is the documentation?
|
|
|
A: This library is poorly documented at the moment and expects of the user to be acquainted with C/C++.
|
|
|
- Run the examples/ and explore them.
|
|
|
- - See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function.
|
|
|
- - The demo covers most features of Dear ImGui, so you can read the code and see its output.
|
|
|
+ - See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function.
|
|
|
+ - The demo covers most features of Dear ImGui, so you can read the code and see its output.
|
|
|
- See documentation and comments at the top of imgui.cpp + effectively imgui.h.
|
|
|
- - Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/
|
|
|
+ - Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/
|
|
|
folder to explain how to integrate Dear ImGui with your own engine/application.
|
|
|
- - Your programming IDE is your friend, find the type or function declaration to find comments
|
|
|
+ - Your programming IDE is your friend, find the type or function declaration to find comments
|
|
|
associated to it.
|
|
|
|
|
|
Q: Which version should I get?
|
|
|
- A: I occasionally tag Releases (https://github.com/ocornut/imgui/releases) but it is generally safe
|
|
|
- and recommended to sync to master/latest. The library is fairly stable and regressions tend to be
|
|
|
+ A: I occasionally tag Releases (https://github.com/ocornut/imgui/releases) but it is generally safe
|
|
|
+ and recommended to sync to master/latest. The library is fairly stable and regressions tend to be
|
|
|
fixed fast when reported. You may also peak at the 'docking' branch which includes:
|
|
|
- Docking/Merging features (https://github.com/ocornut/imgui/issues/2109)
|
|
|
- Multi-viewport features (https://github.com/ocornut/imgui/issues/1542)
|
|
|
@@ -597,11 +597,11 @@ CODE
|
|
|
for a list of games/software which are publicly known to use dear imgui. Please add yours if you can!
|
|
|
|
|
|
Q: Why the odd dual naming, "Dear ImGui" vs "ImGui"?
|
|
|
- A: The library started its life as "ImGui" due to the fact that I didn't give it a proper name when
|
|
|
- when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI
|
|
|
- (immediate-mode graphical user interface) was coined before and is being used in variety of other
|
|
|
- situations (e.g. Unity uses it own implementation of the IMGUI paradigm).
|
|
|
- To reduce the ambiguity without affecting existing code bases, I have decided on an alternate,
|
|
|
+ A: The library started its life as "ImGui" due to the fact that I didn't give it a proper name when
|
|
|
+ when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI
|
|
|
+ (immediate-mode graphical user interface) was coined before and is being used in variety of other
|
|
|
+ situations (e.g. Unity uses it own implementation of the IMGUI paradigm).
|
|
|
+ To reduce the ambiguity without affecting existing code bases, I have decided on an alternate,
|
|
|
longer name "Dear ImGui" that people can use to refer to this specific library.
|
|
|
Please try to refer to this library as "Dear ImGui".
|
|
|
|
|
|
@@ -1080,7 +1080,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2&
|
|
|
// Navigation
|
|
|
static void NavUpdate();
|
|
|
static void NavUpdateWindowing();
|
|
|
-static void NavUpdateWindowingList();
|
|
|
+static void NavUpdateWindowingOverlay();
|
|
|
static void NavUpdateMoveResult();
|
|
|
static float NavUpdatePageUpPageDown(int allowed_dir_flags);
|
|
|
static inline void NavUpdateAnyRequestFlag();
|
|
|
@@ -2490,14 +2490,18 @@ void ImGui::RenderTextClipped(const ImVec2& pos_min, const ImVec2& pos_max, cons
|
|
|
|
|
|
// Another overly complex function until we reorganize everything into a nice all-in-one helper.
|
|
|
// This is made more complex because we have dissociated the layout rectangle (pos_min..pos_max) which define _where_ the ellipsis is, from actual clipping of text and limit of the ellipsis display.
|
|
|
-// This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move.
|
|
|
-void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known)
|
|
|
+// This is because in the context of tabs we selectively hide part of the text when the Close Button appears, but we don't want the ellipsis to move.
|
|
|
+void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, const ImVec2& pos_max, float clip_max_x, float ellipsis_max_x, const char* text, const char* text_end_full, const ImVec2* text_size_if_known)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
if (text_end_full == NULL)
|
|
|
text_end_full = FindRenderedTextEnd(text);
|
|
|
const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full, false, 0.0f);
|
|
|
|
|
|
+ //draw_list->AddLine(ImVec2(pos_max.x, pos_min.y - 4), ImVec2(pos_max.x, pos_max.y + 4), IM_COL32(0, 0, 255, 255));
|
|
|
+ //draw_list->AddLine(ImVec2(ellipsis_max_x, pos_min.y-2), ImVec2(ellipsis_max_x, pos_max.y+2), IM_COL32(0, 255, 0, 255));
|
|
|
+ //draw_list->AddLine(ImVec2(clip_max_x, pos_min.y), ImVec2(clip_max_x, pos_max.y), IM_COL32(255, 0, 0, 255));
|
|
|
+ // FIXME: We could technically remove (last_glyph->AdvanceX - last_glyph->X1) from text_size.x here and save a few pixels.
|
|
|
if (text_size.x > pos_max.x - pos_min.x)
|
|
|
{
|
|
|
// Hello wo...
|
|
|
@@ -2505,15 +2509,33 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min,
|
|
|
// min max ellipsis_max
|
|
|
// <-> this is generally some padding value
|
|
|
|
|
|
- // FIXME-STYLE: RenderPixelEllipsis() style should use actual font data.
|
|
|
const ImFont* font = draw_list->_Data->Font;
|
|
|
const float font_size = draw_list->_Data->FontSize;
|
|
|
- const int ellipsis_dot_count = 3;
|
|
|
- const float ellipsis_width = (1.0f + 1.0f) * ellipsis_dot_count - 1.0f;
|
|
|
const char* text_end_ellipsis = NULL;
|
|
|
|
|
|
- float text_width = ImMax((pos_max.x - ellipsis_width) - pos_min.x, 1.0f);
|
|
|
- float text_size_clipped_x = font->CalcTextSizeA(font_size, text_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
|
|
|
+ ImWchar ellipsis_char = font->EllipsisChar;
|
|
|
+ int ellipsis_char_count = 1;
|
|
|
+ if (ellipsis_char == (ImWchar)-1)
|
|
|
+ {
|
|
|
+ ellipsis_char = (ImWchar)'.';
|
|
|
+ ellipsis_char_count = 3;
|
|
|
+ }
|
|
|
+ const ImFontGlyph* glyph = font->FindGlyph(ellipsis_char);
|
|
|
+
|
|
|
+ float ellipsis_glyph_width = glyph->X1; // Width of the glyph with no padding on either side
|
|
|
+ float ellipsis_total_width = ellipsis_glyph_width; // Full width of entire ellipsis
|
|
|
+
|
|
|
+ if (ellipsis_char_count > 1)
|
|
|
+ {
|
|
|
+ // Full ellipsis size without free spacing after it.
|
|
|
+ const float spacing_between_dots = 1.0f * (draw_list->_Data->FontSize / font->FontSize);
|
|
|
+ ellipsis_glyph_width = glyph->X1 - glyph->X0 + spacing_between_dots;
|
|
|
+ ellipsis_total_width = ellipsis_glyph_width * (float)ellipsis_char_count - spacing_between_dots;
|
|
|
+ }
|
|
|
+
|
|
|
+ // We can now claim the space between pos_max.x and ellipsis_max.x
|
|
|
+ const float text_avail_width = ImMax((ImMax(pos_max.x, ellipsis_max_x) - ellipsis_total_width) - pos_min.x, 1.0f);
|
|
|
+ float text_size_clipped_x = font->CalcTextSizeA(font_size, text_avail_width, 0.0f, text, text_end_full, &text_end_ellipsis).x;
|
|
|
if (text == text_end_ellipsis && text_end_ellipsis < text_end_full)
|
|
|
{
|
|
|
// Always display at least 1 character if there's no room for character + ellipsis
|
|
|
@@ -2522,15 +2544,20 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min,
|
|
|
}
|
|
|
while (text_end_ellipsis > text && ImCharIsBlankA(text_end_ellipsis[-1]))
|
|
|
{
|
|
|
- // Trim trailing space before ellipsis
|
|
|
+ // Trim trailing space before ellipsis (FIXME: Supporting non-ascii blanks would be nice, for this we need a function to backtrack in UTF-8 text)
|
|
|
text_end_ellipsis--;
|
|
|
text_size_clipped_x -= font->CalcTextSizeA(font_size, FLT_MAX, 0.0f, text_end_ellipsis, text_end_ellipsis + 1).x; // Ascii blanks are always 1 byte
|
|
|
}
|
|
|
- RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f));
|
|
|
|
|
|
- const float ellipsis_x = pos_min.x + text_size_clipped_x + 1.0f;
|
|
|
- if (ellipsis_x + ellipsis_width - 1.0f <= ellipsis_max_x)
|
|
|
- RenderPixelEllipsis(draw_list, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_dot_count);
|
|
|
+ // Render text, render ellipsis
|
|
|
+ RenderTextClippedEx(draw_list, pos_min, ImVec2(clip_max_x, pos_max.y), text, text_end_ellipsis, &text_size, ImVec2(0.0f, 0.0f));
|
|
|
+ float ellipsis_x = pos_min.x + text_size_clipped_x;
|
|
|
+ if (ellipsis_x + ellipsis_total_width <= ellipsis_max_x)
|
|
|
+ for (int i = 0; i < ellipsis_char_count; i++)
|
|
|
+ {
|
|
|
+ font->RenderChar(draw_list, font_size, ImVec2(ellipsis_x, pos_min.y), GetColorU32(ImGuiCol_Text), ellipsis_char);
|
|
|
+ ellipsis_x += ellipsis_glyph_width;
|
|
|
+ }
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
@@ -2998,8 +3025,8 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
|
|
|
{
|
|
|
// Navigation processing runs prior to clipping early-out
|
|
|
// (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget
|
|
|
- // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests
|
|
|
- // unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of
|
|
|
+ // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests
|
|
|
+ // unfortunately, but it is still limited to one window. It may not scale very well for windows with ten of
|
|
|
// thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame.
|
|
|
// We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able
|
|
|
// to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick).
|
|
|
@@ -4046,7 +4073,7 @@ static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
|
|
|
+ // Draw list sanity check. Detect mismatch between PrimReserve() calls and incrementing _VtxCurrentIdx, _VtxWritePtr etc.
|
|
|
// May trigger for you if you are using PrimXXX functions incorrectly.
|
|
|
IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_list->VtxBuffer.Data + draw_list->VtxBuffer.Size);
|
|
|
IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size);
|
|
|
@@ -4055,7 +4082,7 @@ static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d
|
|
|
|
|
|
// Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window)
|
|
|
// If this assert triggers because you are drawing lots of stuff manually:
|
|
|
- // - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds.
|
|
|
+ // - First, make sure you are coarse clipping yourself and not trying to draw many things outside visible bounds.
|
|
|
// Be mindful that the ImDrawList API doesn't filter vertices. Use the Metrics window to inspect draw list contents.
|
|
|
// - If you want large meshes with more than 64K vertices, you can either:
|
|
|
// (A) Handle the ImDrawCmd::VtxOffset value in your renderer back-end, and set 'io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset'.
|
|
|
@@ -4064,9 +4091,9 @@ static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d
|
|
|
// (B) Or handle 32-bits indices in your renderer back-end, and uncomment '#define ImDrawIdx unsigned int' line in imconfig.h.
|
|
|
// Most example back-ends already support this. For example, the OpenGL example code detect index size at compile-time:
|
|
|
// glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);
|
|
|
- // Your own engine or render API may use different parameters or function calls to specify index sizes.
|
|
|
+ // Your own engine or render API may use different parameters or function calls to specify index sizes.
|
|
|
// 2 and 4 bytes indices are generally supported by most graphics API.
|
|
|
- // - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching
|
|
|
+ // - If for some reason neither of those solutions works for you, a workaround is to call BeginChild()/EndChild() before reaching
|
|
|
// the 64K limit to split your draw commands in multiple draw lists.
|
|
|
if (sizeof(ImDrawIdx) == 2)
|
|
|
IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above");
|
|
|
@@ -4186,8 +4213,8 @@ void ImGui::EndFrame()
|
|
|
End();
|
|
|
|
|
|
// Show CTRL+TAB list window
|
|
|
- if (g.NavWindowingTarget)
|
|
|
- NavUpdateWindowingList();
|
|
|
+ if (g.NavWindowingTarget != NULL)
|
|
|
+ NavUpdateWindowingOverlay();
|
|
|
|
|
|
// Drag and Drop: Elapse payload (if delivered, or if source stops being submitted)
|
|
|
if (g.DragDropActive)
|
|
|
@@ -4383,7 +4410,7 @@ int ImGui::GetKeyIndex(ImGuiKey imgui_key)
|
|
|
// Note that imgui doesn't know the semantic of each entry of io.KeysDown[]. Use your own indices/enums according to how your back-end/engine stored them into io.KeysDown[]!
|
|
|
bool ImGui::IsKeyDown(int user_key_index)
|
|
|
{
|
|
|
- if (user_key_index < 0)
|
|
|
+ if (user_key_index < 0)
|
|
|
return false;
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown));
|
|
|
@@ -5743,7 +5770,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
window->OuterRectClipped.ClipWith(host_rect);
|
|
|
|
|
|
// Inner rectangle
|
|
|
- // Not affected by window border size. Used by:
|
|
|
+ // Not affected by window border size. Used by:
|
|
|
// - InnerClipRect
|
|
|
// - ScrollToBringRectIntoView()
|
|
|
// - NavUpdatePageUpPageDown()
|
|
|
@@ -5821,7 +5848,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
render_decorations_in_parent = true;
|
|
|
if (render_decorations_in_parent)
|
|
|
window->DrawList = parent_window->DrawList;
|
|
|
-
|
|
|
+
|
|
|
// Handle title bar, scrollbar, resize grips and resize borders
|
|
|
const ImGuiWindow* window_to_highlight = g.NavWindowingTarget ? g.NavWindowingTarget : g.NavWindow;
|
|
|
const bool title_bar_is_highlight = want_focus || (window_to_highlight && window->RootWindowForTitleBarHighlight == window_to_highlight->RootWindowForTitleBarHighlight);
|
|
|
@@ -8076,7 +8103,7 @@ void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, const Im
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_None);
|
|
|
- ImGui::NavMoveRequestCancel();
|
|
|
+ NavMoveRequestCancel();
|
|
|
g.NavMoveDir = move_dir;
|
|
|
g.NavMoveClipDir = clip_dir;
|
|
|
g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued;
|
|
|
@@ -8412,10 +8439,10 @@ static void ImGui::NavUpdate()
|
|
|
g.NavMoveRequestFlags = ImGuiNavMoveFlags_None;
|
|
|
if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
|
|
|
{
|
|
|
- if ((allowed_dir_flags & (1<<ImGuiDir_Left)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadLeft, ImGuiNavInput_KeyLeft_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Left;
|
|
|
- if ((allowed_dir_flags & (1<<ImGuiDir_Right)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadRight,ImGuiNavInput_KeyRight_,ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Right;
|
|
|
- if ((allowed_dir_flags & (1<<ImGuiDir_Up)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadUp, ImGuiNavInput_KeyUp_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Up;
|
|
|
- if ((allowed_dir_flags & (1<<ImGuiDir_Down)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadDown, ImGuiNavInput_KeyDown_, ImGuiInputReadMode_Repeat)) g.NavMoveDir = ImGuiDir_Down;
|
|
|
+ if ((allowed_dir_flags & (1 << ImGuiDir_Left)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadLeft, ImGuiNavInput_KeyLeft_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Left; }
|
|
|
+ if ((allowed_dir_flags & (1 << ImGuiDir_Right)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadRight,ImGuiNavInput_KeyRight_,ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Right; }
|
|
|
+ if ((allowed_dir_flags & (1 << ImGuiDir_Up)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadUp, ImGuiNavInput_KeyUp_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Up; }
|
|
|
+ if ((allowed_dir_flags & (1 << ImGuiDir_Down)) && IsNavInputPressedAnyOfTwo(ImGuiNavInput_DpadDown, ImGuiNavInput_KeyDown_, ImGuiInputReadMode_Repeat)) { g.NavMoveDir = ImGuiDir_Down; }
|
|
|
}
|
|
|
g.NavMoveClipDir = g.NavMoveDir;
|
|
|
}
|
|
|
@@ -8428,7 +8455,8 @@ static void ImGui::NavUpdate()
|
|
|
g.NavMoveRequestForward = ImGuiNavForward_ForwardActive;
|
|
|
}
|
|
|
|
|
|
- // Update PageUp/PageDown scroll
|
|
|
+ // Update PageUp/PageDown/Home/End scroll
|
|
|
+ // FIXME-NAV: Consider enabling those keys even without the master ImGuiConfigFlags_NavEnableKeyboard flag?
|
|
|
float nav_scoring_rect_offset_y = 0.0f;
|
|
|
if (nav_keyboard_active)
|
|
|
nav_scoring_rect_offset_y = NavUpdatePageUpPageDown(allowed_dir_flags);
|
|
|
@@ -8547,8 +8575,18 @@ static void ImGui::NavUpdateMoveResult()
|
|
|
// Scroll to keep newly navigated item fully into view.
|
|
|
if (g.NavLayer == 0)
|
|
|
{
|
|
|
- ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos);
|
|
|
- ImVec2 delta_scroll = ScrollToBringRectIntoView(result->Window, rect_abs);
|
|
|
+ ImVec2 delta_scroll;
|
|
|
+ if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_ScrollToEdge)
|
|
|
+ {
|
|
|
+ float scroll_target = (g.NavMoveDir == ImGuiDir_Up) ? result->Window->ScrollMax.y : 0.0f;
|
|
|
+ delta_scroll.y = result->Window->Scroll.y - scroll_target;
|
|
|
+ SetScrollY(result->Window, scroll_target);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos);
|
|
|
+ delta_scroll = ScrollToBringRectIntoView(result->Window, rect_abs);
|
|
|
+ }
|
|
|
|
|
|
// Offset our result position so mouse position can be applied immediately after in NavUpdate()
|
|
|
result->RectRel.TranslateX(-delta_scroll.x);
|
|
|
@@ -8567,6 +8605,7 @@ static void ImGui::NavUpdateMoveResult()
|
|
|
g.NavMoveFromClampedRefRect = false;
|
|
|
}
|
|
|
|
|
|
+// Handle PageUp/PageDown/Home/End keys
|
|
|
static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
@@ -8576,9 +8615,11 @@ static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
|
|
|
return 0.0f;
|
|
|
|
|
|
ImGuiWindow* window = g.NavWindow;
|
|
|
- bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up));
|
|
|
- bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down));
|
|
|
- if (page_up_held != page_down_held) // If either (not both) are pressed
|
|
|
+ const bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up));
|
|
|
+ const bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down));
|
|
|
+ const bool home_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_Home]) && (allowed_dir_flags & (1 << ImGuiDir_Up));
|
|
|
+ const bool end_pressed = IsKeyPressed(g.IO.KeyMap[ImGuiKey_End]) && (allowed_dir_flags & (1 << ImGuiDir_Down));
|
|
|
+ if (page_up_held != page_down_held || home_pressed != end_pressed) // If either (not both) are pressed
|
|
|
{
|
|
|
if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll)
|
|
|
{
|
|
|
@@ -8587,26 +8628,49 @@ static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
|
|
|
SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight());
|
|
|
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
|
|
|
SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight());
|
|
|
+ else if (home_pressed)
|
|
|
+ SetScrollY(window, 0.0f);
|
|
|
+ else if (end_pressed)
|
|
|
+ SetScrollY(window, window->ScrollMax.y);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
|
|
|
+ ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
|
|
|
const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
|
|
|
float nav_scoring_rect_offset_y = 0.0f;
|
|
|
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
|
|
|
{
|
|
|
nav_scoring_rect_offset_y = -page_offset_y;
|
|
|
- g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
|
|
|
+ g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset up, we request the down direction (so we can always land on the last item)
|
|
|
g.NavMoveClipDir = ImGuiDir_Up;
|
|
|
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
|
|
|
}
|
|
|
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
|
|
|
{
|
|
|
nav_scoring_rect_offset_y = +page_offset_y;
|
|
|
- g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
|
|
|
+ g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset down, we request the up direction (so we can always land on the last item)
|
|
|
g.NavMoveClipDir = ImGuiDir_Down;
|
|
|
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
|
|
|
}
|
|
|
+ else if (home_pressed)
|
|
|
+ {
|
|
|
+ // FIXME-NAV: handling of Home/End is assuming that the top/bottom most item will be visible with Scroll.y == 0/ScrollMax.y
|
|
|
+ // Scrolling will be handled via the ImGuiNavMoveFlags_ScrollToEdge flag, we don't scroll immediately to avoid scrolling happening before nav result.
|
|
|
+ // Preserve current horizontal position if we have any.
|
|
|
+ nav_rect_rel.Min.y = nav_rect_rel.Max.y = -window->Scroll.y;
|
|
|
+ if (nav_rect_rel.IsInverted())
|
|
|
+ nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
|
|
|
+ g.NavMoveDir = ImGuiDir_Down;
|
|
|
+ g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge;
|
|
|
+ }
|
|
|
+ else if (end_pressed)
|
|
|
+ {
|
|
|
+ nav_rect_rel.Min.y = nav_rect_rel.Max.y = window->ScrollMax.y + window->SizeFull.y - window->Scroll.y;
|
|
|
+ if (nav_rect_rel.IsInverted())
|
|
|
+ nav_rect_rel.Min.x = nav_rect_rel.Max.x = 0.0f;
|
|
|
+ g.NavMoveDir = ImGuiDir_Up;
|
|
|
+ g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_ScrollToEdge;
|
|
|
+ }
|
|
|
return nav_scoring_rect_offset_y;
|
|
|
}
|
|
|
}
|
|
|
@@ -8802,7 +8866,7 @@ static const char* GetFallbackWindowNameForWindowingList(ImGuiWindow* window)
|
|
|
}
|
|
|
|
|
|
// Overlay displayed when using CTRL+TAB. Called by EndFrame().
|
|
|
-void ImGui::NavUpdateWindowingList()
|
|
|
+void ImGui::NavUpdateWindowingOverlay()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
IM_ASSERT(g.NavWindowingTarget != NULL);
|
|
|
@@ -9654,7 +9718,7 @@ static const char* GetClipboardTextFn_DefaultImpl(void*)
|
|
|
|
|
|
ItemCount item_count = 0;
|
|
|
PasteboardGetItemCount(main_clipboard, &item_count);
|
|
|
- for (int i = 0; i < item_count; i++)
|
|
|
+ for (ItemCount i = 0; i < item_count; i++)
|
|
|
{
|
|
|
PasteboardItemID item_id = 0;
|
|
|
PasteboardGetItemIdentifier(main_clipboard, i + 1, &item_id);
|