using Annulus; using Azimuth; using System; namespace Glass.Testbed { /// /// ScrollViews sized from their own items by BoundsSizeFor: capped and scrolling on one axis or both, fitting /// so the bar hides but its strip stays, and with the bars on different edges. Clicking an item scrolls it /// fully into view, and the mouse wheel scrolls the view under the pointer. /// public class ScrollViewTestCase : TestCase { public ScrollViewTestCase(string name) : base(name) { } private ScrollView BuildView(bool scrollsHorizontally, bool scrollsVertically, Anchor horizontalAnchor, Anchor verticalAnchor, int columns, int rows, Vector maximumSize) { var view = NewChild($"{columns}x{rows} scroll view"); view.ScrollsHorizontally = scrollsHorizontally; view.ScrollsVertically = scrollsVertically; view.HorizontalScrollBarAnchor = horizontalAnchor; view.VerticalScrollBarAnchor = verticalAnchor; view.ScrollViewMaterial = new ScrollViewMaterial { Background = Material.Invisible, Canvas = UiPacksheetMaterials.GreenFlatPanel, HorizontalScrollBar = UiPacksheetMaterials.HorizontalScrollBar, VerticalScrollBar = UiPacksheetMaterials.VerticalScrollBar, }; Vector labelSize = Widgets.ButtonLabel("00, 00").PreferredSize(Constraints.Unbounded); Vector itemSize = UiPacksheetMaterials.YellowButton.BoundsSizeFor(labelSize); RectDivider grid = RectAggregator.NewGrid( Vector.Zero, itemSize, rows, columns, margin: new Vector(Margin, Margin)); for (int row = 0; row < rows; ++row) { for (int column = 0; column < columns; ++column) { Button item = Widgets.ButtonLabel($"{row}, {column}") .BuildControl(Constraints.Tight(labelSize)) .WrapIn(UiPacksheetMaterials.YellowButton); item.Bounds = grid[row, column]; item.OnClick += (in MouseState _, MouseButtonFlags __) => view.ScrollIntoView(item.Bounds); view.CanvasChildren.Add(item); } } Vector contentSize = grid.Bounds.Size; Vector boundsSize = view.ScrollViewMaterial.BoundsSizeFor(contentSize, view.ScrollAxes); view.Bounds = Rect.FromPositionAndSize(Vector.Zero, Vector.Min(boundsSize, maximumSize)); view.ContentSize = contentSize; return view; } private void PlaceInRow(ScrollView[] views) { Scalar rowHeight = 0; foreach (ScrollView view in views) { rowHeight = Math.Max(rowHeight, view.Bounds.Height); } Rect row = ContentAggregator.NewRow(rowHeight); foreach (ScrollView view in views) { Rect slot = row.NewCol(view.Bounds.Width, margin: Margin); view.Bounds = view.Bounds.WithPosition(slot.TopLeft); } } protected override void Populate() { Scalar uncapped = Scalar.PositiveInfinity; AddCaption("Items go straight onto each view's CanvasChildren; click one to scroll it fully into view"); AddCaption("The mouse wheel scrolls the view under the pointer; a horizontal-only view scrolls sideways"); AddCaption("Left to right: vertical only and capped; vertical only and short enough to fit, so the bar"); AddCaption("hides but its strip stays; both axes with bars bottom right; both axes with bars top left"); PlaceInRow(new[] { BuildView(scrollsHorizontally: false, scrollsVertically: true, Anchor.Bottom, Anchor.Right, columns: 1, rows: 16, new Vector(uncapped, 190)), BuildView(scrollsHorizontally: false, scrollsVertically: true, Anchor.Bottom, Anchor.Right, columns: 1, rows: 3, new Vector(uncapped, 190)), BuildView(scrollsHorizontally: true, scrollsVertically: true, Anchor.Bottom, Anchor.Right, columns: 6, rows: 12, new Vector(300, 190)), BuildView(scrollsHorizontally: true, scrollsVertically: true, Anchor.Top, Anchor.Left, columns: 5, rows: 8, new Vector(240, 160)), }); AddCaption("Horizontal only, bar along the top"); PlaceInRow(new[] { BuildView(scrollsHorizontally: true, scrollsVertically: false, Anchor.Top, Anchor.Right, columns: 12, rows: 1, new Vector(300, uncapped)), }); } } }