-
Notifications
You must be signed in to change notification settings - Fork 12
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
Panel minWidth mutability/shared minWidths #276
Comments
Brainstorming: what about SameWidthNode(others) which would be used for the content of the panels? You would still need to create contents first, but this could address margins and dynamic changes. Usage: var topPanelContents = ...;
var bottomPanelContents = ...;
var topPanel = new Panel(new SameWidthNode(topPanelContents,[bottomPanelContents]))
var bottomPanel = new Panel(new SameWidthNode(bottomPanelContents[topPanelContents])) |
Short term: Along the lines of @samreid's suggestion (SameWidthNode), there are 2 others that I would find to be immediately useful: SameHeightNode, SameCenterNode. Long term: I don't think that this type of layout responsibility belongs in Node subtypes. And putting these responsibilities in Node subtypes builds technical debt. A better solution would be something like Java's layout managers. GridBagLayout was generally the most useful. In other GUI toolkits (Motif,...) something like Java's SpringLayout was even more useful. Unfortunately Java's SpringLayout always seemed buggy, never really behaved as expected. |
LayoutManagers sound reasonable, but it's a large area of uncertainty (how would the API look? how would it be implemented?). Can we implement something unintrusive, so that our explicit layouts which we commonly use (like setting panel1.left = panel2.left) still work perfectly? |
I'll investigate options. |
What about an option for HBox that tells the children to fill to max width? |
You mean min width, no? |
"Set all of the children's width to be equal to the maximum width of the children." |
How would an HBox option help with the described Panel case? |
var panel1 = new Panel( content1, ... );
var panel2 = new Panel( content2, ... );
var panel3 = new Panel( content3, ... );
var panelBox = new VBox({sameWidth:true,children:[panel1,panel2,panel3]}) // or HBox
// Then VBox calls setters on the children to update their widths EDIT: added the |
Changing the width of the children (Panels) with localBounds wouldn't resize the panels? Ran into a case in ProportionPlayground where it would be ideal to have a same-sizing effect with alignment for each item (the ABSwitch needs to be logically centered, easy if we just say "left and right labels take up the same bounds size, but left is left-aligned and right is right-aligned". I'll plan to add a prototype that is capable of this behavior. |
I didn't think it would, but I'm not too certain. |
I've added AlignBox and AlignGroup as a proposal for how to handle these situations. AlignBox takes a single content node, and allows the content to be aligned within a specified bounding box, with controls for horizontal/vertical alignment and margins on each side. Its local bounds will be that of the specified bounding box. For example: // our content
var circle = new scenery.Circle( 20 );
var box = new scenery.AlignBox( circle, {
alignBounds: new dot.Bounds2( 0, 0, 100, 100 ), // specify the bounds inside which our content is aligned
xAlign: 'center', // 'center' is the default for both xAlign and yAlign
yAlign: 'top'
} );
box.bounds // Bounds2 {minX: 0, minY: 0, maxX: 100, maxY: 100}, equal to the alignBounds
circle.bounds // Bounds2 {minX: 30, minY: 0, maxX: 70, maxY: 40}, at the top-center of the alignBounds margins can also be specified: var box = new scenery.AlignBox( circle, {
alignBounds: new dot.Bounds2( 0, 0, 100, 100 ),
xAlign: 'center',
yAlign: 'top',
topMargin: 10
} );
circle.bounds // Bounds2 {minX: 30, minY: 10, maxX: 70, maxY: 50}, with the 10 offset at the top and can be used without alignBounds (if alignBounds is not specified, content will be aligned in a bounding box with the upper-left of (0,0) and with a width/height matching the content + margins): var box = new scenery.AlignBox( circle, {
margin: 10,
leftMargin: 20
} );
// fits the 40x40 circle with top/right/bottom margin of 10 and left margin of 20
box.bounds // Bounds2 {minX: 0, minY: 0, maxX: 70, maxY: 60}
// circle is inside the box's bounds with the specified margins
circle.bounds // Bounds2 {minX: 20, minY: 10, maxX: 60, maxY: 50} AlignGroup groups together AlignBoxes, synchronizing their alignBounds so that they all have the same width, height or both (the default): var circle = new scenery.Circle( 20 ); // 40x40
var rect = new scenery.Rectangle( 0, 0, 100, 20 ); // 100x20
var group = new scenery.AlignGroup();
var circleBox = new scenery.AlignBox( circle, {
group: group
} );
var rectBox = new scenery.AlignBox( rect, {
group: group
} );
// The bounds of both boxes fit both the circle and the rectangle
circleBox.bounds // Bounds2 {minX: 0, minY: 0, maxX: 100, maxY: 40}
rectBox.bounds // Bounds2 {minX: 0, minY: 0, maxX: 100, maxY: 40}
// The circle and rectangle are centered in their boxes (xAlign/yAlign default is 'center'):
circle.bounds // Bounds2 {minX: 30, minY: 0, maxX: 70, maxY: 40}
rect.bounds // Bounds2 {minX: 0, minY: 10, maxX: 100, maxY: 30} Each AlignBox can specify its own alignment and margins: var circleBox = new scenery.AlignBox( circle, {
group: group,
xAlign: 'right',
yAlign: 'bottom'
} );
var rectBox = new scenery.AlignBox( rect, {
group: group,
xMargin: 20,
yAlign: 'top'
} );
// Bounds for the boxes are larger to account for the rectangle's margin
circleBox.bounds // Bounds2 {minX: 0, minY: 0, maxX: 140, maxY: 40}
rectBox.bounds // Bounds2 {minX: 0, minY: 0, maxX: 140, maxY: 40}
circle.bounds // Bounds2 {minX: 100, minY: 0, maxX: 140, maxY: 40}, in the bottom-right (no margins)
rect.bounds // Bounds2 {minX: 20, minY: 0, maxX: 120, maxY: 20}, on the top, with horizontal margins and AlignGroup can control individually whether width and height are matched between all boxes, or can vary: var group = new scenery.AlignGroup( {
matchVertical: false
} );
circleBox.bounds // Bounds2 {minX: 0, minY: 0, maxX: 100, maxY: 40}, height of 40 fits the circle exactly
rectBox.bounds // Bounds2 {minX: 0, minY: 0, maxX: 100, maxY: 20}, height of 20 fits the rectangle exactly Potential usage examples:
A few of these are exhibited in the Sun demo currently (top row has varying-size 'icons', bottom shows panel alignment). It also avoids the need to know about all of the usages beforehand. For example, in Pendulum Lab, a supertype creates an AccordionBox with content, and one subtype creates a Panel that needs to be aligned. The supertype doesn't have to know about the subtype's panel contents BEFORE constructing the AccordionBox. I'm curious about people's thoughts, as I've already found it helpful for my own code (I'll refactor my sim code as this changes, and can revert if it needs to be removed). |
Retagging for developer meeting, as it would be good to get people's thoughts on the above comment (#276 (comment)) and currently-existing code (see Scenery's AlignBox/AlignGroup, they should be documented). |
Code review issue: AlignBox is calling private functions of AlignGroup: onAlignBoxResized, removeAlignBox |
12/8/16 dev meeting: Devs will test drive as they have time. I will try using this in unit-rates. |
I'm sufficiently satisfied with this solution for sizing the content and alignment, so I'm fine personally with closing it. (Tagging for developer meeting to see if people have used it). Sizing the container instead of the content is a whole other animal, and would be a separate issue. |
I've had good a experience with AlignGroup in CCK. |
Reviewed for developer meeting. I have had no experience with this yet, unlikely to be needed in the sim that I'm working on. |
Currently, it's a bit clunky to properly align Panels (so that vertically stacked panels have the same width, etc.)
Something like this seems required:
with the disadvantages:
I'd ideally like something like:
although to not have both a 'contentWidth' and 'minWidth' (which seems unclean), we'd presumably want a getter for "content width + margin" (which would potentially IGNORE any expansion from a previous minWidth), for example:
Thoughts about how to handle this issue?
The text was updated successfully, but these errors were encountered: