Terminal.Gui
Terminal.Gui copied to clipboard
Adornments - Views in `Margin`, `Border`, and `Padding`
- Adornments - Adornments is the term used to describe
Views that are added toMargin,Border, andPadding.- Adornments are not part of the View's content and are not clipped by the View's
ClipArea. - Why?
- Changing the API such that
myview.Addis ONLY for subviews and adding aView.<Frame>.AddAPI for menu, StatusBar, scroll bar... will enable us to simplify the codebase. - Simplfiies the programming model for mainstream use-cases: Developers know that
Views.SubviewsONLY contains views they explicitly added withView.Add.
- Changing the API such that
- Examples of Adornments:
- A
TitleBarrenders the View'sTitleand a horizontal line defining the top of the View. Added toBorder. - One or more
LineViews that render the View's 'Border` - A
Vertical Scrollbaradds thickness toPadding.Right(or.Leftwhen right-to-left language support is added). - A
Horizontal Scrollbaradds thickness toPadding.Bottomwhen enabled. - A
MenuBaradds thickness toPadding.Top(NOTE: This is a change from v1 wheresubview.Y = 1is required). - A
StatusBaradds thickness otPadding.Bottomand is rendered at the bottom ofPadding. - In
Dialog(and derived classes), the buttons can be added toPadding(Y = Pos.AnchorEnd(1)).
- A
- Adornments are not part of the View's content and are not clipped by the View's
I've just built an experiment in modifying Dialog such that the buttons are placed in Padding. This raised some questions:
- Should expanding of, e.g.
Padding.Thicknessbe automatic whenPadding.Addis called? IfDim.Fitis implemented, it might be possible for this to happen. For now: I suggest devs adding adornments manually expand thickness as appropriate. In my Dialog prototype, I did this:
public void AddButton (Button button)
{
if (button == null) {
return;
}
_buttons.Add (button);
Padding.Thickness = new Thickness (Padding.Thickness.Top, Padding.Thickness.Left, Padding.Thickness.Right, 1);
Padding.Add (button);
LayoutButtons ();
}
-
How should
Focuswork? BecausePaddingis in a different view hierarchy from the dialog,Tabetc... doesn't tab into the buttons. I knew this would be an issue, but hadn't thought it all the way through.- Proposal:
Padding- Any views added toPaddingare included inPadding.Parent's focus chain. IfView.Subviews[^1].HasFocusand the user pressesTabPadding.SubViews[0]will get focus. Etc...Border-Ctrl-F10is used to set focus onBorder.Subviews[0]. SubsequentTabpresses cycle throughBorder.Subviews.Ctrl-F10again returns focus toBorder.Parent.Margin- No default behavior. If someone adds views toMarginthey are on their own to figure out a focus model (I can't think of any use case where it makes sense to add a subview toMargin.
- Proposal:
-
How should
MouseEvents work? In the currentv2_developMargin,Border, &Paddingare not getting mouse events (or there's a bug where they are but the coords are wrong. I think this just needs to be fixed. I don't think there's anything special that needs to happen other than ensuring these views and their subviews get the right mouse events.
Am I missing anything else here?
What do @bidisp & @tznind (and others) think of this proposal?
How you think on handling the StatusBar and a ScrollBar on Padding? If a StatusBar exists then the ScrollBar should be above, right?
The MouseEvent should be handled in the same way as the KeyEvent by using the the Parent property. The FindDeepestView must be changed to look in the parent too if a null is returned.
How you think on handling the
StatusBarand aScrollBaronPadding? If aStatusBarexists then theScrollBarshould be above, right?
Yes, I think that's right.
This reminds me of something else I was thinking about:
Thickness needs rules around which edges have precedence, by default.
E.g. which is more true, given view.Padding.Thickness = new Thickness(1); view.Width = 10; view.Height = 10;:
Padding.Top.Width == 10andPadding.Left.Height == 10ORPadding.Top.Width == 10andPadding.Left.Height == 8
Note, I do NOT mean Padding.Left.Height should be different if Padding.Top/Bottom > 0 literally; just to illustrate something that could be very confusing.
Regardless, here's how I think we'd lay out a View with all four adornments:
Padding.Thickness = new Thickness (
_menuBar.Visible ? 1 : 0, // Top
0, // Left
_verticalScrollBar.Visible ? 1: 0, // Right
(_statusBar.Visible ? 1 : 0) + (_horizontalScrollBar.Visible ? 1 :0)); // Bottom
// These have all been `Padding.Add()`ed
_menuBar.X = 0;
_menuBar.Y = 0;
_menuBar.Width = Dim.Fill();
_menuBar.Height = 1;
_statusBar.X = 0;
_statusBar.Y = Pos.AnchorEnd (1);
_statusBar.Width = Dim.Fill();
_statusBar.Height = 1;
_verticalScrollbar.X = Pos.AnchorEnd(1);
_verticalScrollbar.Y = _menuBar.Visible ? Pos.Bottom (_menuBar) : 0;
_verticalScrollbar.Width = 1;
_verticalScrollbar.Height = Dim.Fill ((_menuBar.Visible ? 1 : 0) + (_statusBar.Visible ? 1 : 0) + (_horizontalScrollBar.Visible ? 1 : 0));
_horizontalScrollbar.X = 0;
_horizontalcrollbar.Y = Pos.AnchorEnd (_statusBar.Visible ? 2 : 1);
_horizontalScrollbar.Width = Dim.Fill ();
_horizontalScrollbar.Height = 1;
- In
Dialog(and derived classes), the buttons can be added toPadding(Y = Pos.AnchorEnd(1)).
And in the cases where we want buttons arbitrary on others locations, that possible, right? Added to Padding you only mean the ones that are passed by the params, right?
- In
Dialog(and derived classes), the buttons can be added toPadding(Y = Pos.AnchorEnd(1)).And in the cases where we want buttons arbitrary on others locations, that possible, right? Added to
Paddingyou only mean the ones that are passed by theparams, right?
Correct.
On the same note, for Wizard I plan on putting the HelpText view (a TextView that is set to readonly) in Padding:
Padding.Thickness = new Thickness (Padding.Thickness.Top, Padding.Thickness.Left, Padding.Thickness.Right, 1);
_helpText.X = Pos.AnchorEnd (1);
_helpText.Y = 0;
_helpText.Width = 15;
_helpText.Height = Dim.Fill (2); // +1 for buttons on Bottom
Padding.Add (_helpText);
A key part of addressing this issue will be:
- enable
Margin,Border,Paddingto be overridden/replaced by aViewderivative
Less important (and highly debatlve), but interesting. Including this just to make sure we are intentional:
- enable
Margin,Border,Paddingto be overriden/replaced by a user of aView.
A key part of addressing this issue will be:
- enable
Margin,Border,Paddingto be overridden/replaced by aViewderivativeLess important (and highly debatlve), but interesting. Including this just to make sure we are intentional:
- enable
Margin,Border,Paddingto be overriden/replaced by a user of aView.
Just to remember that you may want to join LineCanvas through a View (Margin, Border, Padding) but not with others views.
A key part of addressing this issue will be:
- enable
Margin,Border,Paddingto be overridden/replaced by aViewderivativeLess important (and highly debatlve), but interesting. Including this just to make sure we are intentional:
- enable
Margin,Border,Paddingto be overriden/replaced by a user of aView.Just to remember that you may want to join
LineCanvasthrough a View (Margin,Border,Padding) but not with others views.
If I understand you correctly, this is what SuperViewRendersLineCanvas is for.