Skip to content

Commit c4d069f

Browse files
committed
No children shrink-wrapping #3
- Refactor and improve constraining. - Implement shrink-wrapping for Checkbox.
1 parent f3dfe13 commit c4d069f

File tree

2 files changed

+91
-154
lines changed

2 files changed

+91
-154
lines changed

lib/src/api/nodes/base_node.dart

Lines changed: 90 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -480,43 +480,35 @@ abstract class BaseNode
480480
List<String> get childrenOrEmpty =>
481481
(this is ChildrenMixin) ? (this as ChildrenMixin).children : <String>[];
482482

483-
/// A convenience getter.
483+
/// Whether this node has reached both its minimum height and width.
484484
bool get isAtMinimumSize => isAtMinWidth && isAtMinHeight;
485485

486-
/// A convenience getter.
486+
/// Whether this node has reached both its maximum height and width.
487487
bool get isAtMaximumSize => isAtMaxWidth && isAtMaxHeight;
488488

489489
/// Whether the height of this node is at the maximum height it can be.
490490
/// This is always false if no maxHeight constraint is set.
491-
bool get isAtMaxHeight {
492-
return resolvedConstraints.maxHeight != null &&
493-
outerBoxLocal.height >=
494-
(resolvedConstraints.maxHeight! + outerBoxLocal.verticalEdgeSpace);
495-
}
491+
bool get isAtMaxHeight =>
492+
resolvedConstraints.maxHeight != null &&
493+
middleBoxLocal.height >= resolvedConstraints.maxHeight!;
496494

497495
/// Whether the width of this node is at the maximum width it can be.
498496
/// This is always false if no maxHeight constraint is set.
499-
bool get isAtMaxWidth {
500-
return resolvedConstraints.maxWidth != null &&
501-
outerBoxLocal.width >=
502-
(resolvedConstraints.maxWidth! + outerBoxLocal.horizontalEdgeSpace);
503-
}
497+
bool get isAtMaxWidth =>
498+
resolvedConstraints.maxWidth != null &&
499+
middleBoxLocal.width >= resolvedConstraints.maxWidth!;
504500

505501
/// Whether the height of this node is at the minimum height it can be.
506502
/// This is always false if no maxHeight constraint is set.
507-
bool get isAtMinHeight {
508-
return resolvedConstraints.minHeight != null &&
509-
outerBoxLocal.height <=
510-
(resolvedConstraints.minHeight! + outerBoxLocal.verticalEdgeSpace);
511-
}
503+
bool get isAtMinHeight =>
504+
resolvedConstraints.minHeight != null &&
505+
middleBoxLocal.height <= resolvedConstraints.minHeight!;
512506

513507
/// Whether the width of this node is at the minimum width it can be.
514508
/// This is always false if no maxHeight constraint is set.
515-
bool get isAtMinWidth {
516-
return resolvedConstraints.minWidth != null &&
517-
outerBoxLocal.width <=
518-
(resolvedConstraints.minWidth! + outerBoxLocal.horizontalEdgeSpace);
519-
}
509+
bool get isAtMinWidth =>
510+
resolvedConstraints.minWidth != null &&
511+
middleBoxLocal.width <= resolvedConstraints.minWidth!;
520512

521513
/// Determines whether this node relegates internal constraints to its
522514
/// children.
@@ -530,13 +522,43 @@ abstract class BaseNode
530522
/// its own constraints onto its child.
531523
BoxConstraintsModel? relegatedConstraintsToChildren(BaseNode child) => null;
532524

525+
/// Returns the relevant [NodeBox] given the [NodeBoundaryType] and the
526+
/// [PositioningSpace] desired.
527+
///
528+
/// This is a convenience function meant for programmatic use.
529+
NodeBox getBox({
530+
required NodeBoundaryType type,
531+
required PositioningSpace space,
532+
}) =>
533+
switch (space) {
534+
PositioningSpace.local => switch (type) {
535+
NodeBoundaryType.outerBox => outerBoxLocal,
536+
NodeBoundaryType.innerBox ||
537+
NodeBoundaryType.innerRotatedBox =>
538+
innerBoxLocal,
539+
NodeBoundaryType.middleBox => basicBoxLocal,
540+
NodeBoundaryType.outerRotatedBox => outerRotatedBoxGlobal,
541+
NodeBoundaryType.middleRotatedBox => middleRotatedBoxLocal,
542+
},
543+
PositioningSpace.global => switch (type) {
544+
NodeBoundaryType.outerBox => outerBoxGlobal,
545+
NodeBoundaryType.innerBox ||
546+
NodeBoundaryType.innerRotatedBox =>
547+
innerBoxGlobal,
548+
NodeBoundaryType.middleBox => basicBoxGlobal,
549+
NodeBoundaryType.outerRotatedBox => outerRotatedBoxGlobal,
550+
NodeBoundaryType.middleRotatedBox => middleRotatedBoxGlobal,
551+
}
552+
};
553+
533554
/// A convenience function that will take a [value] and constraint it
534555
/// using the [resolvedConstraints] function.
535556
///
536-
/// It takes an additional [nodeBoundaryType] to indicate which [NodeBox]
537-
/// to use to constrain the desired [value].
538-
SizeC constrainSize(SizeC value,
539-
{required NodeBoundaryType nodeBoundaryType}) =>
557+
/// The value is going to be constrained according to the node's [middleBox]
558+
SizeC constrainSize(
559+
SizeC value, {
560+
required NodeBoundaryType nodeBoundaryType,
561+
}) =>
540562
SizeC(
541563
constrainValue(
542564
value.width,
@@ -550,59 +572,24 @@ abstract class BaseNode
550572
),
551573
);
552574

553-
/// A convenience function that is exactly the same as [constrainSize]
554-
/// except it takes a [Vec] instead.
555-
Vec constrainVec(Vec value, {required NodeBoundaryType nodeBoundaryType}) =>
556-
Vec(
557-
constrainValue(
558-
value.x,
559-
AxisC.horizontal,
560-
nodeBoundaryType: nodeBoundaryType,
561-
),
562-
constrainValue(
563-
value.y,
564-
AxisC.vertical,
565-
nodeBoundaryType: nodeBoundaryType,
566-
),
567-
);
568-
569-
/// Returns the relevant [NodeBox] given the [NodeBoundaryType] and the
570-
/// [PositioningSpace] desired.
571-
///
572-
/// This is a convenience function meant for programmatic use.
573-
NodeBox getBox(
574-
{required NodeBoundaryType type, required PositioningSpace space}) {
575-
switch (space) {
576-
case PositioningSpace.local:
577-
switch (type) {
578-
case NodeBoundaryType.outerBox:
579-
return outerBoxLocal;
580-
case NodeBoundaryType.innerBox:
581-
case NodeBoundaryType.innerRotatedBox:
582-
return innerBoxLocal;
583-
case NodeBoundaryType.middleBox:
584-
return basicBoxLocal;
585-
case NodeBoundaryType.outerRotatedBox:
586-
return outerRotatedBoxGlobal;
587-
case NodeBoundaryType.middleRotatedBox:
588-
return middleRotatedBoxLocal;
589-
}
590-
case PositioningSpace.global:
591-
switch (type) {
592-
case NodeBoundaryType.outerBox:
593-
return outerBoxGlobal;
594-
case NodeBoundaryType.innerBox:
595-
case NodeBoundaryType.innerRotatedBox:
596-
return innerBoxGlobal;
597-
case NodeBoundaryType.middleBox:
598-
return basicBoxGlobal;
599-
case NodeBoundaryType.outerRotatedBox:
600-
return outerRotatedBoxGlobal;
601-
case NodeBoundaryType.middleRotatedBox:
602-
return middleRotatedBoxGlobal;
603-
}
604-
}
605-
}
575+
double _convertMiddleSizeToBoundary(
576+
double value,
577+
AxisC axis, {
578+
required NodeBoundaryType nodeBoundaryType,
579+
}) =>
580+
switch (nodeBoundaryType) {
581+
NodeBoundaryType.middleBox ||
582+
NodeBoundaryType.middleRotatedBox =>
583+
value,
584+
NodeBoundaryType.innerBox || NodeBoundaryType.innerRotatedBox => value -
585+
(axis.isHorizontal
586+
? innerBoxLocal.horizontalEdgeSpace
587+
: innerBoxLocal.verticalEdgeSpace),
588+
NodeBoundaryType.outerBox || NodeBoundaryType.outerRotatedBox => value +
589+
(axis.isHorizontal
590+
? outerBoxLocal.horizontalEdgeSpace
591+
: outerBoxLocal.verticalEdgeSpace)
592+
};
606593

607594
/// A convenience function that will take a [value] and constrain it
608595
/// using the [resolvedConstraints] of this node.
@@ -623,90 +610,40 @@ abstract class BaseNode
623610
///
624611
/// Returns the constrained value that cannot exceed the total constraints of
625612
/// this node.
613+
///
614+
/// The [resolvedConstraints] are relative to the node's [middleBox]
626615
double constrainValue(
627616
double value,
628617
AxisC axis, {
629618
required NodeBoundaryType nodeBoundaryType,
630619
}) {
631620
switch (axis) {
632621
case AxisC.horizontal:
633-
double minValue = resolvedConstraints.minWidth ?? 0.0;
634-
switch (nodeBoundaryType) {
635-
case NodeBoundaryType.middleBox:
636-
case NodeBoundaryType.middleRotatedBox:
637-
minValue += innerBoxLocal.horizontalEdgeSpace;
638-
break;
639-
case NodeBoundaryType.outerBox:
640-
case NodeBoundaryType.outerRotatedBox:
641-
minValue += outerBoxLocal.horizontalEdgeSpace +
642-
innerBoxLocal.horizontalEdgeSpace;
643-
break;
644-
case NodeBoundaryType.innerBox:
645-
case NodeBoundaryType.innerRotatedBox:
646-
minValue -= innerBoxLocal.horizontalEdgeSpace;
647-
break;
648-
}
649-
650-
double output = max(value, minValue);
651-
652-
if (resolvedConstraints.maxWidth != null) {
653-
double maxValue = resolvedConstraints.maxWidth!;
654-
switch (nodeBoundaryType) {
655-
case NodeBoundaryType.middleBox:
656-
case NodeBoundaryType.middleRotatedBox:
657-
break;
658-
case NodeBoundaryType.outerBox:
659-
case NodeBoundaryType.outerRotatedBox:
660-
maxValue += outerBoxLocal.horizontalEdgeSpace;
661-
break;
662-
case NodeBoundaryType.innerBox:
663-
case NodeBoundaryType.innerRotatedBox:
664-
maxValue -= innerBoxLocal.horizontalEdgeSpace;
665-
break;
666-
}
667-
output = min(output, maxValue);
668-
}
622+
final double minWidth = _convertMiddleSizeToBoundary(
623+
resolvedConstraints.minWidth ?? 0,
624+
axis,
625+
nodeBoundaryType: nodeBoundaryType,
626+
);
627+
final double maxWidth = _convertMiddleSizeToBoundary(
628+
resolvedConstraints.maxWidth ?? double.infinity,
629+
axis,
630+
nodeBoundaryType: nodeBoundaryType,
631+
);
669632

670-
return output;
633+
return value.clamp(minWidth, maxWidth);
671634
case AxisC.vertical:
672-
double minValue = resolvedConstraints.minHeight ?? 0.0;
673-
switch (nodeBoundaryType) {
674-
case NodeBoundaryType.middleBox:
675-
case NodeBoundaryType.middleRotatedBox:
676-
minValue += innerBoxLocal.verticalEdgeSpace;
677-
break;
678-
case NodeBoundaryType.outerBox:
679-
case NodeBoundaryType.outerRotatedBox:
680-
minValue += outerBoxLocal.verticalEdgeSpace +
681-
innerBoxLocal.verticalEdgeSpace;
682-
break;
683-
case NodeBoundaryType.innerBox:
684-
case NodeBoundaryType.innerRotatedBox:
685-
minValue -= innerBoxLocal.verticalEdgeSpace;
686-
break;
687-
}
688-
689-
double output = max(value, minValue);
690-
691-
if (resolvedConstraints.maxHeight != null) {
692-
double maxValue = resolvedConstraints.maxHeight!;
693-
switch (nodeBoundaryType) {
694-
case NodeBoundaryType.middleBox:
695-
case NodeBoundaryType.middleRotatedBox:
696-
break;
697-
case NodeBoundaryType.outerBox:
698-
case NodeBoundaryType.outerRotatedBox:
699-
maxValue += outerBoxLocal.verticalEdgeSpace;
700-
break;
701-
case NodeBoundaryType.innerBox:
702-
case NodeBoundaryType.innerRotatedBox:
703-
maxValue -= innerBoxLocal.verticalEdgeSpace;
704-
break;
705-
}
706-
output = min(output, maxValue);
707-
}
635+
final double minHeight = _convertMiddleSizeToBoundary(
636+
resolvedConstraints.minHeight ?? 0,
637+
axis,
638+
nodeBoundaryType: nodeBoundaryType,
639+
);
640+
final double maxHeight = _convertMiddleSizeToBoundary(
641+
resolvedConstraints.maxHeight ?? double.infinity,
642+
axis,
643+
nodeBoundaryType: nodeBoundaryType,
644+
);
708645

709-
return output;
646+
return value.clamp(minHeight, maxHeight);
710647
}
711648
}
712649

lib/src/api/nodes/checkbox_node.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ part 'checkbox_node.g.dart';
1616
const double kRadialReactionRadius = 20.0;
1717

1818
/// Default size of the checkbox.
19-
const double kCheckboxDefaultSize = 32;
19+
const double kCheckboxDefaultSize = 40;
2020

2121
/// A checkbox is a widget that permits the user to make a binary
2222
/// choice, i.e. a choice between one of two possible mutually exclusive

0 commit comments

Comments
 (0)