Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create new ScrollBar based on a new Scroll and remove ScrollBarView/ScrollView #2489

Open
tig opened this issue Apr 4, 2023 · 24 comments
Open
Assignees
Labels
v2 For discussions, issues, etc... relavant for v2
Milestone

Comments

@tig
Copy link
Collaborator

tig commented Apr 4, 2023

This is a sub-issue of:

Requires

Design

Scroll bar support will be based on three views: ScrollBar which is a composite of two buttons supporting continuous button press and a Scroll, which is just the "middle" part of a scroll bar.

These views are described below.

Scroll

A new View that represents the "inside part" of a scroll bar, minus the arrow buttons

It should look like the existing ScrollBarView (but better).

image

and

image

It should have the following fields/methods/events (roughly):

  • public Orientation Orientation {get ;set;} - Determines the Orientation of the scroll.
  • public int Size { get;set;} - The size of content the scroll represents.
  • public int Position { get; set;} - The position, relative to Size`, to set the scrollbar at.
  • public event PositionChanging
  • public event PositionChanged
  • public event SizeChanged

It'd be cool (but not required) for all the glyphs and styling to be configurable; similar to how Slider.SliderStyle works.

The names/types of these should match Slider as much as is reasonable for consistency.

It must not have any internal knowledge of ScrollBar or the other views ScrollBar contains.

ScrollBar

A new View that is a composition of 3 subviews

  • public Button Decrease { get; set; } - Has WantContinousButtonPressed set to true
  • public Button Increase { get; set; } - Has WantContinousButtonPressed set to true
  • public Scroll Scroll { get; set; }

Exposes public Orientation Orientation { get; set; }. This is used to layout the 3 views correctly depending on orientation. Obvioulsy it also needs to change the glyph each of the two buttons have to be correct for orientation too.

This will be just a regular View that can be added as a subview to another view. It will not need any of the Host complexity that ScrollBarView has.

Exposes:

  • public Orientation Orientation {get ;set;} - Determines the Orientation of the scroll. A passthrough to scrollBar.Scroll.Orientation.
  • public int Size { get;set;} - The size of content the scrollbar represents. Just a passthrough to scrollBar.Scroll.Size.
  • public int Position { get; set;} - The position, relative to Size`, to set the scrollbar at.
  • public event PositionChanging
  • public event PositionChanged
  • public event SizeChanged

Keyboard bindings for the most common operations should be included:

  • Key.UpArrow, Key.DownArrow, Key.LeftArrow, Key.RightArrow, Key.PageUp/Down

Specialized mouse code should not be needed because the 2 Buttons and the Scroll should "just work".

View changes required

Once ScrollBar is ready, View can be modified to have two built-in scroll bars that can be enabled by the developer. These will wire in to the content scrolling support enabled in #3323.

The two ScrollBar views will be added to Padding using computed layout.

Exposes:

  • public ScrollBar HoriztonalScrollBar { get; set ;}; // Actually created inside of Padding`
  • public ScrollBar VerticalScrollBar { get; set ;}; // Actually created inside of Padding`

We will expand ViewportSettings with more flags that control the behavior of the scroll bars:

  • AutoHoriztonalScrollBar, AutoVerticalScrollBar, and AutoBothScrollBars - when set auto show/hide

We should be able to use Pos.Function() to automatically ensure the bottom-right-corner is handled correctly depending on Viewport and ContentSize and the above settings.

For a scroll bar to be visible the Padding.Thickness needs to be adjusted and ScrollBar.Visible needs to be set. Using ScrollBar.VisibleChanged, we should be able to automatically adjust Padding.Thickness when a developer sets HorizontalScrollBar.Visible = true/false, etc...

Delete ScrollBarView and ScrollView

Once ScrollBar is ready, we will delete ScrollBarView and ScrollView from the project, updating any built-in Views and Scenarios that use them.

@tig
Copy link
Collaborator Author

tig commented Apr 16, 2023

Also:

  • In addition, I'd like to revisit the pattern used. The new Frames concept should allow any View to have scrolling without having to add and manage a bunch of scroll objects as is needed today. The idea being the Adornments Frame (temporarily called BorderFrame) can host scroll bars and the work I've done to decouple Bounds from Frame such that Bounds could have a non-zero Location should make scrolling much easier on devs.

@BDisp
Copy link
Collaborator

BDisp commented Feb 1, 2024

We need to decide whether the scrollbars will be inside the Border or inside the Padding adornment. Regardless of where it resides, the adornment can only be designed after executing the layout of the content subviews. Border already calls OnRenderLineCanvas after the content has finished being drawn, but Padding does not.

@BDisp
Copy link
Collaborator

BDisp commented Feb 1, 2024

I started developing the scroll bar added to Padding. The problem is that FindDeepestView does not search for sub-views within Padding. Any news on this?

image

@BDisp
Copy link
Collaborator

BDisp commented Feb 1, 2024

ahah I already can capture the mouse click in the Padding but see the first effect I get 😄

VsDebugConsole_FIypdNdwhp.mp4

@BDisp
Copy link
Collaborator

BDisp commented Feb 1, 2024

With negative bounds is working but I have to avoid drawing.

VsDebugConsole_C5EmSaeNrU.mp4

@BDisp
Copy link
Collaborator

BDisp commented Feb 3, 2024

Using the Margin location as (0,0) whatever is the View.Frame will invalidade any way of using the LayoutSubViews on the Adornments. I think the Margin.Frame should always equal to the View.Frame. The only doubt is if the Margin thickness isn't empty the View.Frame should be equal to the Margin.Frame. I think it should.

@dodexahedron
Copy link
Collaborator

dodexahedron commented Feb 3, 2024 via email

@BDisp
Copy link
Collaborator

BDisp commented Feb 3, 2024

It isn't so simples like that. Layout sub-views will be still needed because we are draw others views and they aren't totally always be accommodate in the padding area. If both scroll vertical and horizontal are visible then the width and the height are Dim.Fill(1). To deal with layout calculations then the frame must be the screen relative values. Deal with absolutes values won't be a problem like it's on the video above, but with computed values then the layout sub-views is important.

@BDisp
Copy link
Collaborator

BDisp commented Feb 3, 2024

  • We will figure out how to enable Bounds.Location to be negative (or introduce a ContentArea)

I need to decide what of the both properties could allow to have negative location. I started with the Bounds and it's working as expected and I created the ContentArea property with only a getter. Personally I would prefer to use the Bounds to use negative location and use the ContentArea with a empty location. This will implies that I change all the call to the ClipToBounds to ClipToContentArea. Do you all agree with this?

@BDisp
Copy link
Collaborator

BDisp commented Feb 3, 2024

I already having it working on Padding.

VsDebugConsole_uE0h67RM9F.mp4

@BDisp
Copy link
Collaborator

BDisp commented Feb 3, 2024

See the difference if TextFormatter.Draw fillRemaining parameter is true. All the ContentArea is filled with whitespaces showing a perfect rectangle. I think I'll create a FillRemaining property to be configurable by the views. I think the default should be true in the View.Draw method. The _contentBottomRightCorner is already fixed here.

VsDebugConsole_a2BDBfZXLB.mp4

@BDisp
Copy link
Collaborator

BDisp commented Feb 14, 2024

I need to decide what of the both properties could allow to have negative location. I started with the Bounds and it's working as expected and I created the ContentArea property with only a getter. Personally I would prefer to use the Bounds to use negative location and use the ContentArea with a empty location. This will implies that I change all the call to the ClipToBounds to ClipToContentArea. Do you all agree with this?

@tig, @tznind , @dodexahedron I need a final decision on which of both should using negative location. I'm using the Bounds for negative location and if the majority decide other way that will imply more difficult to me to fix, because when location has X, Y or both negative we need to compensate the Width and Height by increasing and decreasing their length.
If anybody say nothing until today I'll consider that you want using Bounds to deal with negative location and I won't revert that behavior. Thanks.

Edit:
I'm also using the Padding because is the most near of the ContentArea and much more easy to deal.

@tig
Copy link
Collaborator Author

tig commented Feb 14, 2024

I need to decide what of the both properties could allow to have negative location. I started with the Bounds and it's working as expected and I created the ContentArea property with only a getter. Personally I would prefer to use the Bounds to use negative location and use the ContentArea with a empty location. This will implies that I change all the call to the ClipToBounds to ClipToContentArea. Do you all agree with this?

@tig, @tznind , @dodexahedron I need a final decision on which of both should using negative location. I'm using the Bounds for negative location and if the majority decide other way that will imply more difficult to me to fix, because when location has X, Y or both negative we need to compensate the Width and Height by increasing and decreasing their length. If anybody say nothing until today I'll consider that you want using Bounds to deal with negative location and I won't revert that behavior. Thanks.

I think using Bounds (which WILL be renamed to ContentArea per #3169) is the right way to go.

Question: How far are you going in changing existing sample code to use the built-in View scrolling with your PR? Similarly, what are you doing to light up new use-cases. For example, making it so that CategoryList.EnableVerticalScrollBar = true (or equivalent) in UICatalog.cs is all that's needed to have the scroll bar just work?

I ask because, until we do 3 or four use-cases like that I don't think we'll really know the answer to your question

Edit: I'm also using the Padding because is the most near of the ContentArea and much more easy to deal.

I like this. It was how I envisioned it working.

@BDisp
Copy link
Collaborator

BDisp commented Feb 14, 2024

I think using Bounds (which WILL be renamed to ContentArea per #3169) is the right way to go.

I wouldn't recommended rename it because when Bounds have negative location the Width/Height will be different than it's actually we know. So, they may really have different values from each other.

Question: How far are you going in changing existing sample code to use the built-in View scrolling with your PR? Similarly, what are you doing to light up new use-cases. For example, making it so that CategoryList.EnableVerticalScrollBar = true (or equivalent) in UICatalog.cs is all that's needed to have the scroll bar just work?

I have a lot of work of this and I'll open a PR asap, maybe today for you see what I'm doing. I'm not using a bool to show/hide the scroll bars but a enum of scroll bar type (None, Both, Vertical, Horizontal).

I ask because, until we do 3 or four use-cases like that I don't think we'll really know the answer to your question

Yes I know, I'll try to submit a PR today if possible.

Edit: I'm also using the Padding because is the most near of the ContentArea and much more easy to deal.

I like this. It was how I envisioned it working.

Good, we are in syntony.

@BDisp
Copy link
Collaborator

BDisp commented Feb 15, 2024

@tig I'll get rid of this constructor. Do you have any objection?

public ScrollBarView (View host, bool isVertical, bool showBothScrollIndicator = true)

It will only have a default constructor and a internal constructor that will only used by the View class.

internal ScrollBarView (View host, ScrollBarType scrollBarType)

@tig
Copy link
Collaborator Author

tig commented Feb 16, 2024

@tig I'll get rid of this constructor. Do you have any objection?

public ScrollBarView (View host, bool isVertical, bool showBothScrollIndicator = true)

It will only have a default constructor and a internal constructor that will only used by the View class.

internal ScrollBarView (View host, ScrollBarType scrollBarType)

I don't understand why you are asking about this. I have no problem removing that constructor.

However, to me, if View supports scrolling natively, then there's no need for ScrollBarView to exist at all.

But until I see your code, I have no idea how you're approaching this.

@BDisp
Copy link
Collaborator

BDisp commented Feb 16, 2024

I don't understand why you are asking about this. I have no problem removing that constructor.

Great.

However, to me, if View supports scrolling natively, then there's no need for ScrollBarView to exist at all.

I'm still using it to draw the bars. Have you other idea for that?

But until I see your code, I have no idea how you're approaching this.

I'm struggling with some issues after I've merged from v2_developer, but I'm doing my best as possible.

@tig
Copy link
Collaborator Author

tig commented Feb 16, 2024

I see. That makes sense. I always ScrollBarView and ScrollView mixed up.

@tig
Copy link
Collaborator Author

tig commented Feb 16, 2024

Why would ScrollBarView need a "host"? Why isn't that just its SuperView?

@BDisp
Copy link
Collaborator

BDisp commented Feb 16, 2024

Why would ScrollBarView need a "host"? Why isn't that just its SuperView?

The SuperView is the Padding but the data is from the Parent. With the default constructor I want allow that any view can add it where the user want. I can remove the View parameter and in this case it will always added to the Padding but that will prevent it can be added into the Border. The host field will be only internal to identify the SuperView.

@tig
Copy link
Collaborator Author

tig commented Feb 16, 2024

I definately agree ScrollBarView should be usable as just a subview in any View. I want to us it in the new ColorPicker as a slider for truecolor (24 bits of sliding). So yeah.

I'll wait to comment further until I see the code. But I do have one other suggestion: Feel free to clone ScrollBarView into ScrollBar (better name) and make it incompatible with the old way of doing things if you can make the new model simpler.

@BDisp
Copy link
Collaborator

BDisp commented Feb 16, 2024

I'll wait to comment further until I see the code. But I do have one other suggestion: Feel free to clone ScrollBarView into ScrollBar (better name) and make it incompatible with the old way of doing things if you can make the new model simpler.

I already created a ViewScrollBar file as Partial View, but kept the ScrollBarView file as is. But that can be changed of course.

@BDisp
Copy link
Collaborator

BDisp commented Apr 1, 2024

I'm reopen this because I'm convinced that the SetRelativeLayout should handled the location offset, although until now it wasn't never used. This is only to proof that and not for be merged, of course.

WindowsTerminal_ECSMSxAgT4.mp4

@tig tig changed the title Build scrolling into View Create new ScrollBar based on a new Scroll and remove ScrollBarView/ScrollView Apr 15, 2024
@tig
Copy link
Collaborator Author

tig commented Apr 15, 2024

I've renamed this issue, and updated the proposed design in the first comment. Most of the other comments in this Issue are out-of-date, but useful historical context.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
v2 For discussions, issues, etc... relavant for v2
Projects
Status: No status
Status: 📋 Approved - Need Owner
Development

No branches or pull requests

3 participants