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
Introduce a vertical/horizontal split layout #1261
Conversation
@@ -113,3 +116,163 @@ class DefaultTaggedText extends StatelessWidget { | |||
); | |||
} | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe move this widget over to its own file under src/flutter. It is complex enough to be worth its own file. I would propose keeping comm_widgets.dart for widgets that don't really have complex business logic but are good to share.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM, moved.
@@ -113,3 +116,163 @@ class DefaultTaggedText extends StatelessWidget { | |||
); | |||
} | |||
} | |||
|
|||
/// A widget that takes two children and lays them out along one axis. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This summary is missing the key bit that the user resize the widgets along that axis.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, done.
/// [firstChild] will be placed before [secondChild] in a [Row]. | ||
const Split.horizontal({ | ||
Key key, | ||
@required Widget firstChild, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of firstChild and second child, why not use children:
If you only support two children you can always assert that there are exactly two children.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
firstChild
and secondChild
explain exactly what the code does without a need for asserts.
It's simpler, and this pattern has prior art.
Unless we plan on supporting n != 2 children, I'd like to leave this as-is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my guess is at some point we will want to support n > 2 children.
Key key, | ||
@required Widget firstChild, | ||
@required Widget secondChild, | ||
double initialFirstFraction, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you also need to track the minimum size allowed for each split component. that is critical to ensure that users don't accidentally get the UI in a weird state by collapsing one side of the split too much.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've left a TODO to follow up on this.
height: isHorizontal ? height : Split.dividerMainAxisSize, | ||
child: const Center( | ||
child: Text( | ||
':::::::', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use the existing png for this instead of using text.
Alternately, find a more material design appropriate splitter icon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naturally we aren't going to land that :D
Do you know the name of the png file for the splitter grip?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The splitter icons are currently stored as data urls in the app as that is the typical way they are included as the images are tiny.
You can also find the pngs here.
https://github.com/nathancahill/split/tree/master/packages/splitjs/grips
.gutter.gutter-horizontal {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
cursor: col-resize;
height: 100%;
}
.gutter.gutter-vertical {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAFAQMAAABo7865AAAABlBMVEVHcEzMzMzyAv2sAAAAAXRSTlMAQObYZgAAABBJREFUeF5jOAMEEAIEEFwAn3kMwcB6I2AAAAAASUVORK5CYII=');
cursor: row-resize;
width: 100%;
}
child: widget.secondChild, | ||
), | ||
]; | ||
if (widget.axis == Axis.horizontal) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be replaced with
Flex(direction: widget.axis, children: children)
Column and Row are just sugar around Flex with a fixed direction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestion, done.
}); | ||
}); | ||
|
||
group('drags properly', () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great to see a test of this!
}); | ||
} | ||
|
||
Widget _w1, _w2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: instead of making _w1, _w2, and _split
surprise side effects of
buildSplitAndChildren why not use keys and lookup the widgets bsed on keys instead of using
find.byWidget?
final fractionalDelta = delta / axisSize; | ||
setState(() { | ||
// Update the fraction of space consumed by the children, | ||
// being sure not to allocate any of them negative space. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here is where we need to instead clamp so no children violate their minSize constraint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
feel free to apply the feature request to specify a minWidth for each column as a followup cl.
this.firstChild, | ||
this.secondChild, | ||
double initialFirstFraction, | ||
) : initialFirstFraction = initialFirstFraction ?? 0.5, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does ??= work for this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. This is equivalent to:
this.initialFirstFraction = initialFirstFraction ?? 0.5
The two variables are different, even though they have the same name.
const halfDivider = Split.dividerMainAxisSize / 2.0; | ||
// The fraction of the layout the divider needs to take up from each child. | ||
final halfDividerFraction = halfDivider / axisSize; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we using fractions instead of just subtracting Split.dividerMainAxisSize / 2.0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestion, I've removed this field.
final halfDividerFraction = halfDivider / axisSize; | ||
|
||
final sanitizedFirstFraction = | ||
firstFraction.clamp(halfDividerFraction, 1.0 - halfDividerFraction); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't the lower bound of the clamp be 0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to make sure there is enough space to take halfDivider from each child, no matter how far we have slid the divider.
To do that, we have to clamp the available space to at least halfDivider for both children, then we can remove the halfDivider space.
I've updated the comments to explain, let me know if you have more questions. The geometry took a while to explain even explaining it to myself, so feedback here is appreciated.
One other high level comment. It would be nice to change the cursor matching how the cursor is changed by the existing UI when interacting with the spiller on desktop and web. If you want to do it with a follow up cl, feel free to add a tracking bug. |
|
Fixes #1183.
TODO: