From 48e9a8b507f9e1c055a0e48c0c79b6fa842e9482 Mon Sep 17 00:00:00 2001 From: Maarten Bezemer Date: Tue, 18 Jun 2024 13:12:45 +0200 Subject: [PATCH 1/8] Document Scroll classes --- Yafc.UI/ImGui/ScrollArea.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Yafc.UI/ImGui/ScrollArea.cs b/Yafc.UI/ImGui/ScrollArea.cs index 40f327ad..d8a19115 100644 --- a/Yafc.UI/ImGui/ScrollArea.cs +++ b/Yafc.UI/ImGui/ScrollArea.cs @@ -4,8 +4,12 @@ using SDL2; namespace Yafc.UI { + /// Provide scrolling support for any component. + /// The component should use the property to get the offset of rendering the contents. public abstract class Scrollable(bool vertical, bool horizontal, bool collapsible) : IKeyboardFocus { + /// Required size to fit Scrollable (child) contents private Vector2 contentSize; + /// Maximum scroller offset, calculated with the and the available size private Vector2 maxScroll; private Vector2 _scroll; private float height; @@ -132,7 +136,10 @@ public float scrollX { set => scroll2d = new Vector2(value, _scroll.Y); } + ///This method is called when the required area of the is needed. + /// The required area of the contents of the . protected abstract Vector2 MeasureContent(Rect rect, ImGui gui); + public bool KeyDown(SDL.SDL_Keysym key) { switch (key.scancode) { case SDL.SDL_Scancode.SDL_SCANCODE_UP: @@ -171,6 +178,7 @@ public bool KeyDown(SDL.SDL_Keysym key) { public void FocusChanged(bool focused) { } } + /// Provides a builder to the Scrollable to render the contents. public abstract class ScrollAreaBase : Scrollable { protected ImGui contents; protected readonly float height; @@ -194,6 +202,7 @@ protected override void PositionContent(ImGui gui, Rect viewport) { protected override Vector2 MeasureContent(Rect rect, ImGui gui) => contents.CalculateState(rect.Width, gui.pixelsPerUnit); } + ///Area with scrollbars, which will be visible if it does not fit in the parent area in order to let the user fully view the content of the area. public class ScrollArea(float height, GuiBuilder builder, InputSystem inputSystem, Padding padding = default, bool collapsible = false, bool vertical = true, bool horizontal = false) : ScrollAreaBase(height, padding, inputSystem, collapsible, vertical, horizontal) { protected override void BuildContents(ImGui gui) => builder(gui); From 6d03467aaf6c55748f1be36af1c228aa49d75a88 Mon Sep 17 00:00:00 2001 From: Maarten Bezemer Date: Tue, 18 Jun 2024 13:14:11 +0200 Subject: [PATCH 2/8] Rename scrollX, scrollY and scroll properties Now they actually reflect what they are about --- Yafc.UI/ImGui/ScrollArea.cs | 41 +++++++++++++++++-------------- Yafc/Windows/FilesystemScreen.cs | 2 +- Yafc/Workspace/ProjectPageView.cs | 2 +- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/Yafc.UI/ImGui/ScrollArea.cs b/Yafc.UI/ImGui/ScrollArea.cs index d8a19115..234bf1e9 100644 --- a/Yafc.UI/ImGui/ScrollArea.cs +++ b/Yafc.UI/ImGui/ScrollArea.cs @@ -5,7 +5,7 @@ namespace Yafc.UI { /// Provide scrolling support for any component. - /// The component should use the property to get the offset of rendering the contents. + /// The component should use the property to get the offset of rendering the contents. public abstract class Scrollable(bool vertical, bool horizontal, bool collapsible) : IKeyboardFocus { /// Required size to fit Scrollable (child) contents private Vector2 contentSize; @@ -46,7 +46,7 @@ public void Build(ImGui gui, float height, bool useBottomPadding = false) { innerRect.Height = realHeight; } _ = gui.EncapsulateRect(rect); - scroll2d = Vector2.Clamp(scroll2d, Vector2.Zero, maxScroll); + scroll = Vector2.Clamp(scroll, Vector2.Zero, maxScroll); PositionContent(gui, innerRect); } else { @@ -69,7 +69,7 @@ public void Build(ImGui gui, float height, bool useBottomPadding = false) { if (gui.action == ImGuiAction.MouseScroll) { if (gui.ConsumeEvent(rect)) { if (vertical && (!horizontal || !gui.inputSystem.control)) { - scroll += gui.actionParameter * 3f; + scrollY += gui.actionParameter * 3f; } else { scrollX += gui.actionParameter * 3f; @@ -105,7 +105,7 @@ private void BuildScrollBar(ImGui gui, int axis, in Rect fullScrollRect, in Rect scrollX += gui.inputSystem.mouseDelta.X * contentSize.X / fullScrollRect.Width; } else { - scroll += gui.inputSystem.mouseDelta.Y * contentSize.Y / fullScrollRect.Height; + scrollY += gui.inputSystem.mouseDelta.Y * contentSize.Y / fullScrollRect.Height; } } break; @@ -115,7 +115,8 @@ private void BuildScrollBar(ImGui gui, int axis, in Rect fullScrollRect, in Rect } } - public virtual Vector2 scroll2d { + /// X and Y positions of the scrollers + public virtual Vector2 scroll { get => _scroll; set { value = Vector2.Clamp(value, Vector2.Zero, maxScroll); @@ -126,14 +127,16 @@ public virtual Vector2 scroll2d { } } - public float scroll { + /// Position of the Y scroller + public float scrollY { get => _scroll.Y; - set => scroll2d = new Vector2(_scroll.X, value); + set => scroll = new Vector2(_scroll.X, value); } + /// Position of the X scroller public float scrollX { get => _scroll.X; - set => scroll2d = new Vector2(value, _scroll.Y); + set => scroll = new Vector2(value, _scroll.Y); } ///This method is called when the required area of the is needed. @@ -143,10 +146,10 @@ public float scrollX { public bool KeyDown(SDL.SDL_Keysym key) { switch (key.scancode) { case SDL.SDL_Scancode.SDL_SCANCODE_UP: - scroll -= 3; + scrollY -= 3; return true; case SDL.SDL_Scancode.SDL_SCANCODE_DOWN: - scroll += 3; + scrollY += 3; return true; case SDL.SDL_Scancode.SDL_SCANCODE_LEFT: scrollX -= 3; @@ -155,16 +158,16 @@ public bool KeyDown(SDL.SDL_Keysym key) { scrollX += 3; return true; case SDL.SDL_Scancode.SDL_SCANCODE_PAGEDOWN: - scroll += height; + scrollY += height; return true; case SDL.SDL_Scancode.SDL_SCANCODE_PAGEUP: - scroll -= height; + scrollY -= height; return true; case SDL.SDL_Scancode.SDL_SCANCODE_HOME: - scroll = 0; + scrollY = 0; return true; case SDL.SDL_Scancode.SDL_SCANCODE_END: - scroll = maxScroll.Y; + scrollY = maxScroll.Y; return true; default: return false; @@ -190,7 +193,7 @@ public ScrollAreaBase(float height, Padding padding, InputSystem inputSystem, bo protected override void PositionContent(ImGui gui, Rect viewport) { gui.DrawPanel(viewport, contents); - contents.offset = -scroll2d; + contents.offset = -scroll; } public void Build(ImGui gui) => Build(gui, height); @@ -247,12 +250,12 @@ public VirtualScrollList(float height, Vector2 elementSize, Drawer drawer, Input this.reorder = reorder; } - private int CalcFirstBlock() => Math.Max(0, MathUtils.Floor((scroll - contents.initialPadding.top) / (elementSize.Y * bufferRows))); + private int CalcFirstBlock() => Math.Max(0, MathUtils.Floor((scrollY - contents.initialPadding.top) / (elementSize.Y * bufferRows))); - public override Vector2 scroll2d { - get => base.scroll2d; + public override Vector2 scroll { + get => base.scroll; set { - base.scroll2d = value; + base.scroll = value; int row = CalcFirstBlock(); if (row != firstVisibleBlock) { RebuildContents(); diff --git a/Yafc/Windows/FilesystemScreen.cs b/Yafc/Windows/FilesystemScreen.cs index 53f2d6c8..31828b95 100644 --- a/Yafc/Windows/FilesystemScreen.cs +++ b/Yafc/Windows/FilesystemScreen.cs @@ -99,7 +99,7 @@ private void SetLocation(string directory) { location = directory; UpdatePossibleResult(); - entries.scroll = 0; + entries.scrollY = 0; } public void UpdatePossibleResult() { diff --git a/Yafc/Workspace/ProjectPageView.cs b/Yafc/Workspace/ProjectPageView.cs index bad3afc1..2a45dec7 100644 --- a/Yafc/Workspace/ProjectPageView.cs +++ b/Yafc/Workspace/ProjectPageView.cs @@ -67,7 +67,7 @@ public void Build(ImGui gui, Vector2 visibleSize) { protected override void PositionContent(ImGui gui, Rect viewport) { headerContent.offset = new Vector2(-scrollX, 0); - bodyContent.offset = -scroll2d; + bodyContent.offset = -scroll; gui.DrawPanel(viewport, bodyContent); } From 491712c9300474ce4cd1c7dbcd1d4e516d233679 Mon Sep 17 00:00:00 2001 From: Maarten Bezemer Date: Tue, 18 Jun 2024 13:36:16 +0200 Subject: [PATCH 3/8] Cleanup Scrollable class * Get rid of misleading height property (a visible area height is needed instead) * MeasureContent only uses width, so replace Rect param * Rename Scrollbar Rects to make their purpose more clear * Document code blocks to clarify a little better what happens --- Yafc.UI/ImGui/ScrollArea.cs | 87 +++++++++++++++++-------------- Yafc/Workspace/ProjectPageView.cs | 2 +- 2 files changed, 48 insertions(+), 41 deletions(-) diff --git a/Yafc.UI/ImGui/ScrollArea.cs b/Yafc.UI/ImGui/ScrollArea.cs index 234bf1e9..86a05549 100644 --- a/Yafc.UI/ImGui/ScrollArea.cs +++ b/Yafc.UI/ImGui/ScrollArea.cs @@ -8,11 +8,10 @@ namespace Yafc.UI { /// The component should use the property to get the offset of rendering the contents. public abstract class Scrollable(bool vertical, bool horizontal, bool collapsible) : IKeyboardFocus { /// Required size to fit Scrollable (child) contents - private Vector2 contentSize; - /// Maximum scroller offset, calculated with the and the available size + private Vector2 requiredContentSize; + /// Maximum scroller offset, calculated with the and the available size private Vector2 maxScroll; private Vector2 _scroll; - private float height; private ImGui? gui; public const float ScrollbarSize = 1f; @@ -22,9 +21,9 @@ public abstract class Scrollable(bool vertical, bool horizontal, bool collapsibl protected abstract void PositionContent(ImGui gui, Rect viewport); - public void Build(ImGui gui, float height, bool useBottomPadding = false) { + /// Available height without in parent context for the Scrollable + public void Build(ImGui gui, float availableHeight, bool useBottomPadding = false) { this.gui = gui; - this.height = height; var rect = gui.statePosition; float width = rect.Width; if (vertical) { @@ -32,25 +31,30 @@ public void Build(ImGui gui, float height, bool useBottomPadding = false) { } if (gui.isBuilding) { - var innerRect = rect; - innerRect.Width = width; - contentSize = MeasureContent(innerRect, gui); - if (contentSize.Y > height && useBottomPadding) { - contentSize.Y += BottomPaddingInPixels / gui.pixelsPerUnit; + /// This rectangle contains the available size (and position) of the scrollable content + var contentRect = rect; + contentRect.Width = width; + + // Calculate required size, including padding if needed + requiredContentSize = MeasureContent(width, gui); + if (requiredContentSize.Y > availableHeight && useBottomPadding) { + requiredContentSize.Y += BottomPaddingInPixels / gui.pixelsPerUnit; } - maxScroll = Vector2.Max(contentSize - new Vector2(innerRect.Width, height), Vector2.Zero); - float realHeight = collapsible ? MathF.Min(contentSize.Y, height) : height; - innerRect.Height = rect.Height = realHeight; + + maxScroll = Vector2.Max(requiredContentSize - new Vector2(contentRect.Width, availableHeight), Vector2.Zero); + scroll = Vector2.Clamp(scroll, Vector2.Zero, maxScroll); + + float realHeight = collapsible ? MathF.Min(requiredContentSize.Y, availableHeight) : availableHeight; + contentRect.Height = rect.Height = realHeight; if (horizontal && maxScroll.X > 0) { - realHeight -= ScrollbarSize; - innerRect.Height = realHeight; + contentRect.Height -= ScrollbarSize; } + _ = gui.EncapsulateRect(rect); - scroll = Vector2.Clamp(scroll, Vector2.Zero, maxScroll); - PositionContent(gui, innerRect); + PositionContent(gui, contentRect); } else { - float realHeight = collapsible ? MathF.Min(contentSize.Y, height) : height; + float realHeight = collapsible ? MathF.Min(requiredContentSize.Y, availableHeight) : availableHeight; if (horizontal && maxScroll.X > 0) { realHeight -= ScrollbarSize; } @@ -58,10 +62,13 @@ public void Build(ImGui gui, float height, bool useBottomPadding = false) { rect.Height = realHeight; _ = gui.EncapsulateRect(rect); } - Vector2 size = new Vector2(width, height); - var scrollSize = size * size / (size + maxScroll); - scrollSize = Vector2.Max(scrollSize, Vector2.One); - var scrollStart = _scroll / maxScroll * (size - scrollSize); + + // Calculate scroller dimensions. + Vector2 size = new Vector2(width, availableHeight); + var scrollerSize = size * size / (size + maxScroll); + scrollerSize = Vector2.Max(scrollerSize, Vector2.One); + var scrollerStart = _scroll / maxScroll * (size - scrollerSize); + if ((gui.action == ImGuiAction.MouseDown || gui.action == ImGuiAction.MouseScroll) && rect.Contains(gui.mousePosition)) { gui.inputSystem.SetKeyboardFocus(this); } @@ -78,39 +85,39 @@ public void Build(ImGui gui, float height, bool useBottomPadding = false) { } else { if (horizontal && maxScroll.X > 0f) { - Rect fullScrollRect = new Rect(rect.X, rect.Bottom - ScrollbarSize, rect.Width, ScrollbarSize); - Rect scrollRect = new Rect(rect.X + scrollStart.X, fullScrollRect.Y, scrollSize.X, ScrollbarSize); - BuildScrollBar(gui, 0, in fullScrollRect, in scrollRect); + Rect scrollbarRect = new Rect(rect.X, rect.Bottom - ScrollbarSize, rect.Width, ScrollbarSize); + Rect scrollerRect = new Rect(rect.X + scrollerStart.X, scrollbarRect.Y, scrollerSize.X, ScrollbarSize); + BuildScrollBar(gui, 0, in scrollbarRect, in scrollerRect); } if (vertical && maxScroll.Y > 0f) { - Rect fullScrollRect = new Rect(rect.Right - ScrollbarSize, rect.Y, ScrollbarSize, rect.Height); - Rect scrollRect = new Rect(fullScrollRect.X, rect.Y + scrollStart.Y, ScrollbarSize, scrollSize.Y); - BuildScrollBar(gui, 1, in fullScrollRect, in scrollRect); + Rect scrollbarRect = new Rect(rect.Right - ScrollbarSize, rect.Y, ScrollbarSize, rect.Height); + Rect scrollerRect = new Rect(scrollbarRect.X, rect.Y + scrollerStart.Y, ScrollbarSize, scrollerSize.Y); + BuildScrollBar(gui, 1, in scrollbarRect, in scrollerRect); } } } - private void BuildScrollBar(ImGui gui, int axis, in Rect fullScrollRect, in Rect scrollRect) { + private void BuildScrollBar(ImGui gui, int axis, in Rect scrollbarRect, in Rect scrollerRect) { switch (gui.action) { case ImGuiAction.MouseDown: - if (scrollRect.Contains(gui.mousePosition)) { - _ = gui.ConsumeMouseDown(fullScrollRect); + if (scrollerRect.Contains(gui.mousePosition)) { + _ = gui.ConsumeMouseDown(scrollbarRect); } break; case ImGuiAction.MouseMove: - if (gui.IsMouseDown(fullScrollRect, SDL.SDL_BUTTON_LEFT)) { + if (gui.IsMouseDown(scrollbarRect, SDL.SDL_BUTTON_LEFT)) { if (axis == 0) { - scrollX += gui.inputSystem.mouseDelta.X * contentSize.X / fullScrollRect.Width; + scrollX += gui.inputSystem.mouseDelta.X * requiredContentSize.X / scrollbarRect.Width; } else { - scrollY += gui.inputSystem.mouseDelta.Y * contentSize.Y / fullScrollRect.Height; + scrollY += gui.inputSystem.mouseDelta.Y * requiredContentSize.Y / scrollbarRect.Height; } } break; case ImGuiAction.Build: - gui.DrawRectangle(scrollRect, gui.IsMouseDown(fullScrollRect, SDL.SDL_BUTTON_LEFT) ? SchemeColor.GreyAlt : SchemeColor.Grey); + gui.DrawRectangle(scrollerRect, gui.IsMouseDown(scrollbarRect, SDL.SDL_BUTTON_LEFT) ? SchemeColor.GreyAlt : SchemeColor.Grey); break; } } @@ -139,9 +146,9 @@ public float scrollX { set => scroll = new Vector2(value, _scroll.Y); } - ///This method is called when the required area of the is needed. + ///This method is called when the required area of the for the provided is needed. /// The required area of the contents of the . - protected abstract Vector2 MeasureContent(Rect rect, ImGui gui); + protected abstract Vector2 MeasureContent(float width, ImGui gui); public bool KeyDown(SDL.SDL_Keysym key) { switch (key.scancode) { @@ -158,10 +165,10 @@ public bool KeyDown(SDL.SDL_Keysym key) { scrollX += 3; return true; case SDL.SDL_Scancode.SDL_SCANCODE_PAGEDOWN: - scrollY += height; + // TODO Calculate page height return true; case SDL.SDL_Scancode.SDL_SCANCODE_PAGEUP: - scrollY -= height; + // TODO Calculate page height return true; case SDL.SDL_Scancode.SDL_SCANCODE_HOME: scrollY = 0; @@ -202,7 +209,7 @@ protected override void PositionContent(ImGui gui, Rect viewport) { public void RebuildContents() => contents.Rebuild(); - protected override Vector2 MeasureContent(Rect rect, ImGui gui) => contents.CalculateState(rect.Width, gui.pixelsPerUnit); + protected override Vector2 MeasureContent(float width, ImGui gui) => contents.CalculateState(width, gui.pixelsPerUnit); } ///Area with scrollbars, which will be visible if it does not fit in the parent area in order to let the user fully view the content of the area. diff --git a/Yafc/Workspace/ProjectPageView.cs b/Yafc/Workspace/ProjectPageView.cs index 2a45dec7..068c93f0 100644 --- a/Yafc/Workspace/ProjectPageView.cs +++ b/Yafc/Workspace/ProjectPageView.cs @@ -63,7 +63,7 @@ public void Build(ImGui gui, Vector2 visibleSize) { base.Build(gui, visibleSize.Y - headerHeight, true); } - protected override Vector2 MeasureContent(Rect rect, ImGui gui) => new Vector2(contentWidth, contentHeight); + protected override Vector2 MeasureContent(float _, ImGui gui) => new Vector2(contentWidth, contentHeight); protected override void PositionContent(ImGui gui, Rect viewport) { headerContent.offset = new Vector2(-scrollX, 0); From d9f815158b71bb8aaab387600220a8281709e821 Mon Sep 17 00:00:00 2001 From: Maarten Bezemer Date: Tue, 18 Jun 2024 23:37:34 +0200 Subject: [PATCH 4/8] Make horizontal scrollbar clickable/dragable rect.Heigth does not need the correction for the ScrollbarSize when not building. It does not have the correction when it is building. So with this fix both the building and not building states use the same rect.Height. --- Yafc.UI/ImGui/ScrollArea.cs | 3 --- changelog.txt | 1 + 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Yafc.UI/ImGui/ScrollArea.cs b/Yafc.UI/ImGui/ScrollArea.cs index 86a05549..f2632220 100644 --- a/Yafc.UI/ImGui/ScrollArea.cs +++ b/Yafc.UI/ImGui/ScrollArea.cs @@ -55,9 +55,6 @@ public void Build(ImGui gui, float availableHeight, bool useBottomPadding = fals } else { float realHeight = collapsible ? MathF.Min(requiredContentSize.Y, availableHeight) : availableHeight; - if (horizontal && maxScroll.X > 0) { - realHeight -= ScrollbarSize; - } rect.Height = realHeight; _ = gui.EncapsulateRect(rect); diff --git a/changelog.txt b/changelog.txt index f670d9b6..b333225e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -19,6 +19,7 @@ Date: soon Bugfixes: - Fix that some pages couldn't be deleted. - Fix that returning to the Welcome Screen could break the panels in the main window. + - Make horizontal scrollbar clickable/draggable. ---------------------------------------------------------------------------------------------------------------------- Version: 0.7.1 Date: June 12th 2024 From c0076c5cc954108d72d28248b85ad0f56d705621 Mon Sep 17 00:00:00 2001 From: Maarten Bezemer Date: Tue, 18 Jun 2024 23:53:23 +0200 Subject: [PATCH 5/8] Cleanup duplicate code Possible since last fix --- Yafc.UI/ImGui/ScrollArea.cs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/Yafc.UI/ImGui/ScrollArea.cs b/Yafc.UI/ImGui/ScrollArea.cs index f2632220..7a1f2735 100644 --- a/Yafc.UI/ImGui/ScrollArea.cs +++ b/Yafc.UI/ImGui/ScrollArea.cs @@ -31,34 +31,33 @@ public void Build(ImGui gui, float availableHeight, bool useBottomPadding = fals } if (gui.isBuilding) { - /// This rectangle contains the available size (and position) of the scrollable content - var contentRect = rect; - contentRect.Width = width; - // Calculate required size, including padding if needed requiredContentSize = MeasureContent(width, gui); if (requiredContentSize.Y > availableHeight && useBottomPadding) { requiredContentSize.Y += BottomPaddingInPixels / gui.pixelsPerUnit; } + } + + float realHeight = collapsible ? MathF.Min(requiredContentSize.Y, availableHeight) : availableHeight; + + if (gui.isBuilding) { + /// This rectangle contains the available size (and position) of the scrollable content + var contentRect = rect; + contentRect.Width = width; maxScroll = Vector2.Max(requiredContentSize - new Vector2(contentRect.Width, availableHeight), Vector2.Zero); scroll = Vector2.Clamp(scroll, Vector2.Zero, maxScroll); - float realHeight = collapsible ? MathF.Min(requiredContentSize.Y, availableHeight) : availableHeight; - contentRect.Height = rect.Height = realHeight; + contentRect.Height = realHeight; if (horizontal && maxScroll.X > 0) { contentRect.Height -= ScrollbarSize; } - _ = gui.EncapsulateRect(rect); PositionContent(gui, contentRect); } - else { - float realHeight = collapsible ? MathF.Min(requiredContentSize.Y, availableHeight) : availableHeight; - rect.Height = realHeight; - _ = gui.EncapsulateRect(rect); - } + rect.Height = realHeight; + _ = gui.EncapsulateRect(rect); // Calculate scroller dimensions. Vector2 size = new Vector2(width, availableHeight); From cf5518fcfca99d5c306a1c66f65f65f6a180b8e3 Mon Sep 17 00:00:00 2001 From: Maarten Bezemer Date: Tue, 18 Jun 2024 23:55:11 +0200 Subject: [PATCH 6/8] Fix height of ScrollArea The height of the horizontal scrollbar is already taken care of by Scrollable. So it sohuld not be part of the height calculation. The calculation got messed up, when ScrollbarSize != 1 indicating the old calculations were wrong already. --- Yafc/Workspace/SummaryView.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Yafc/Workspace/SummaryView.cs b/Yafc/Workspace/SummaryView.cs index 8c066b31..42276e49 100644 --- a/Yafc/Workspace/SummaryView.cs +++ b/Yafc/Workspace/SummaryView.cs @@ -11,8 +11,8 @@ private class SummaryScrollArea(GuiBuilder builder) : ScrollArea(DefaultHeight, private static readonly float DefaultHeight = 10; public new void Build(ImGui gui) => - // Maximize scroll area to fit parent area (minus header and 'show issues' heights, and some (2) padding probably) - Build(gui, gui.valid && gui.parent is not null ? gui.parent.contentSize.Y - Font.header.size - Font.text.size - ScrollbarSize - 2 : DefaultHeight); + // Maximize scroll area to fit parent area (minus header and 'show issues' heights, and some (3) padding probably) + Build(gui, gui.valid && gui.parent is not null ? gui.parent.contentSize.Y - Font.header.size - Font.text.size - 3 : DefaultHeight); } private class SummaryTabColumn : TextDataColumn { From e1cd68e3ab3c76864b99b85f018a9a39fe9d4f7b Mon Sep 17 00:00:00 2001 From: Maarten Bezemer Date: Tue, 18 Jun 2024 23:59:18 +0200 Subject: [PATCH 7/8] Remove the scrollbar highlighting when clicked It does not 'de-highlight' and it was only active for the Summary view (making it more consistent with the rest of YAFC) --- Yafc.UI/ImGui/ScrollArea.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Yafc.UI/ImGui/ScrollArea.cs b/Yafc.UI/ImGui/ScrollArea.cs index 7a1f2735..777bf569 100644 --- a/Yafc.UI/ImGui/ScrollArea.cs +++ b/Yafc.UI/ImGui/ScrollArea.cs @@ -113,7 +113,7 @@ private void BuildScrollBar(ImGui gui, int axis, in Rect scrollbarRect, in Rect } break; case ImGuiAction.Build: - gui.DrawRectangle(scrollerRect, gui.IsMouseDown(scrollbarRect, SDL.SDL_BUTTON_LEFT) ? SchemeColor.GreyAlt : SchemeColor.Grey); + gui.DrawRectangle(scrollerRect, SchemeColor.Grey); break; } } From 4a8c135169cbc2f8cce355d81d5c1733afd52764 Mon Sep 17 00:00:00 2001 From: Maarten Bezemer Date: Wed, 19 Jun 2024 00:04:18 +0200 Subject: [PATCH 8/8] Scroll down/up exactly one page with page down/up keys --- Yafc.UI/ImGui/ScrollArea.cs | 9 +++++---- changelog.txt | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Yafc.UI/ImGui/ScrollArea.cs b/Yafc.UI/ImGui/ScrollArea.cs index 777bf569..b5c93254 100644 --- a/Yafc.UI/ImGui/ScrollArea.cs +++ b/Yafc.UI/ImGui/ScrollArea.cs @@ -9,6 +9,8 @@ namespace Yafc.UI { public abstract class Scrollable(bool vertical, bool horizontal, bool collapsible) : IKeyboardFocus { /// Required size to fit Scrollable (child) contents private Vector2 requiredContentSize; + /// This rectangle contains the available size (and position) of the scrollable content + private Rect contentRect; /// Maximum scroller offset, calculated with the and the available size private Vector2 maxScroll; private Vector2 _scroll; @@ -41,8 +43,7 @@ public void Build(ImGui gui, float availableHeight, bool useBottomPadding = fals float realHeight = collapsible ? MathF.Min(requiredContentSize.Y, availableHeight) : availableHeight; if (gui.isBuilding) { - /// This rectangle contains the available size (and position) of the scrollable content - var contentRect = rect; + contentRect = rect; contentRect.Width = width; maxScroll = Vector2.Max(requiredContentSize - new Vector2(contentRect.Width, availableHeight), Vector2.Zero); @@ -161,10 +162,10 @@ public bool KeyDown(SDL.SDL_Keysym key) { scrollX += 3; return true; case SDL.SDL_Scancode.SDL_SCANCODE_PAGEDOWN: - // TODO Calculate page height + scrollY += contentRect.Height; return true; case SDL.SDL_Scancode.SDL_SCANCODE_PAGEUP: - // TODO Calculate page height + scrollY -= contentRect.Height; return true; case SDL.SDL_Scancode.SDL_SCANCODE_HOME: scrollY = 0; diff --git a/changelog.txt b/changelog.txt index b333225e..e2596ef5 100644 --- a/changelog.txt +++ b/changelog.txt @@ -20,6 +20,7 @@ Date: soon - Fix that some pages couldn't be deleted. - Fix that returning to the Welcome Screen could break the panels in the main window. - Make horizontal scrollbar clickable/draggable. + - Scroll down/up exactly one page with page down/up keys ---------------------------------------------------------------------------------------------------------------------- Version: 0.7.1 Date: June 12th 2024