Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lib/src/resizable_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ class ResizableWidget extends StatefulWidget {
/// If this value is [null], [children] will be split into the same size.
final List<double>? percentages;

/// Applies a Maximum Percent of the screen each widget can occupy
/// At least one element must be set to double.infinity
final List<double?>? maxPercentages;
/// Applies a Minimum Percent of the screen each widget can occupy
/// At least one element must be set to 0.0
final List<double?>? minPercentages;

/// When set to true, creates horizontal separators.
@Deprecated('Use [isHorizontalSeparator] instead')
final bool isColumnChildren;
Expand Down Expand Up @@ -53,6 +60,8 @@ class ResizableWidget extends StatefulWidget {
Key? key,
required this.children,
this.percentages,
this.maxPercentages,
this.minPercentages,
@Deprecated('Use [isHorizontalSeparator] instead')
this.isColumnChildren = false,
this.isHorizontalSeparator = false,
Expand All @@ -65,6 +74,8 @@ class ResizableWidget extends StatefulWidget {
assert(percentages == null || percentages!.length == children.length);
assert(percentages == null ||
percentages!.reduce((value, element) => value + element) == 1);
assert(maxPercentages == null || maxPercentages!.contains(double.infinity));
assert(minPercentages == null || minPercentages!.reduce((value, element) => value! + element!)! < 1);
}

@override
Expand Down
4 changes: 4 additions & 0 deletions lib/src/resizable_widget_args_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import 'resizable_widget.dart';
class ResizableWidgetArgsInfo {
final List<Widget> children;
final List<double>? percentages;
final List<double?>? maxPercentages;
final List<double?>? minPercentages;
final bool isHorizontalSeparator;
final bool isDisabledSmartHide;
final double separatorSize;
Expand All @@ -13,6 +15,8 @@ class ResizableWidgetArgsInfo {
ResizableWidgetArgsInfo(ResizableWidget widget)
: children = widget.children,
percentages = widget.percentages,
maxPercentages = widget.maxPercentages,
minPercentages = widget.minPercentages,
isHorizontalSeparator =
// TODO: delete the deprecated member on the next minor update.
// ignore: deprecated_member_use_from_same_package
Expand Down
4 changes: 3 additions & 1 deletion lib/src/resizable_widget_child_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ class ResizableWidgetChildData {
double? percentage;
double? defaultPercentage;
double? hidingPercentage;
ResizableWidgetChildData(this.widget, this.percentage);
double? maxPercentage;
double? minPercentage;
ResizableWidgetChildData(this.widget, this.percentage, this.maxPercentage, this.minPercentage);
}
117 changes: 95 additions & 22 deletions lib/src/resizable_widget_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ import 'widget_size_info.dart';

typedef SeparatorFactory = Widget Function(SeparatorArgsBasicInfo basicInfo);

enum ResizableWidgetResizeImplReturnState {
VALID,
INVALID
}

class ResizableWidgetResizeImplReturn {
ResizableWidgetResizeImplReturnState state;
double size;
double percent;
ResizableWidgetResizeImplReturn({required this.size, required this.percent, required this.state});
}

class ResizableWidgetModel {
final ResizableWidgetArgsInfo _info;
final children = <ResizableWidgetChildData>[];
Expand All @@ -22,9 +34,14 @@ class ResizableWidgetModel {
final size = originalChildren.length;
final originalPercentages =
_info.percentages ?? List.filled(size, 1 / size);
final maxPercentages = _info.maxPercentages;
final minPercentages = _info.minPercentages;
for (var i = 0; i < size - 1; i++) {
children.add(ResizableWidgetChildData(
originalChildren[i], originalPercentages[i]));
originalChildren[i], originalPercentages[i],
(maxPercentages != null ? maxPercentages[i] : null),
(minPercentages != null ? minPercentages[i] : null)
));
children.add(ResizableWidgetChildData(
separatorFactory.call(SeparatorArgsBasicInfo(
2 * i + 1,
Expand All @@ -33,10 +50,16 @@ class ResizableWidgetModel {
_info.separatorSize,
_info.separatorColor,
)),
null));
null,
null,
null,
));
}
children.add(ResizableWidgetChildData(
originalChildren[size - 1], originalPercentages[size - 1]));
originalChildren[size - 1], originalPercentages[size - 1],
(maxPercentages != null ? maxPercentages[size - 1] : null),
(minPercentages != null ? minPercentages[size - 1] : null)
));
}

void setSizeIfNeeded(BoxConstraints constraints) {
Expand All @@ -63,35 +86,46 @@ class ResizableWidgetModel {
}

void resize(int separatorIndex, Offset offset) {
final leftSize = _resizeImpl(separatorIndex - 1, offset);
final rightSize = _resizeImpl(separatorIndex + 1, offset * (-1));
ResizableWidgetResizeImplReturn leftReturn = _resizeImpl(separatorIndex - 1, offset, apply: false);
if(leftReturn.state != ResizableWidgetResizeImplReturnState.VALID) {
return;
}

ResizableWidgetResizeImplReturn rightReturn = _resizeImpl(separatorIndex + 1, offset * (-1), apply: false);
if(rightReturn.state != ResizableWidgetResizeImplReturnState.VALID) {
return;
}
__applyResizeImpl(separatorIndex - 1, leftReturn);
__applyResizeImpl(separatorIndex + 1, rightReturn);

if (leftSize < 0) {

if (leftReturn.size < 0) {
_resizeImpl(
separatorIndex - 1,
_info.isHorizontalSeparator
? Offset(0, -leftSize)
: Offset(-leftSize, 0));
? Offset(0, -leftReturn.size)
: Offset(-leftReturn.size, 0));
_resizeImpl(
separatorIndex + 1,
_info.isHorizontalSeparator
? Offset(0, leftSize)
: Offset(leftSize, 0));
? Offset(0, leftReturn.size)
: Offset(leftReturn.size, 0));
}
if (rightSize < 0) {
if (rightReturn.size < 0) {
_resizeImpl(
separatorIndex - 1,
_info.isHorizontalSeparator
? Offset(0, rightSize)
: Offset(rightSize, 0));
? Offset(0, rightReturn.size)
: Offset(rightReturn.size, 0));
_resizeImpl(
separatorIndex + 1,
_info.isHorizontalSeparator
? Offset(0, -rightSize)
: Offset(-rightSize, 0));
? Offset(0, -rightReturn.size)
: Offset(-rightReturn.size, 0));
}
}


void callOnResized() {
_info.onResized?.call(children
.where((x) => x.widget is! Separator)
Expand Down Expand Up @@ -136,13 +170,52 @@ class ResizableWidgetModel {
return true;
}

double _resizeImpl(int widgetIndex, Offset offset) {
final size = children[widgetIndex].size ?? 0;
children[widgetIndex].size =
size + (_info.isHorizontalSeparator ? offset.dy : offset.dx);
children[widgetIndex].percentage =
children[widgetIndex].size! / maxSizeWithoutSeparators!;
return children[widgetIndex].size!;

ResizableWidgetResizeImplReturn _resizeImpl(int widgetIndex, Offset offset, {bool apply = true}) {
final size = children[widgetIndex].size ?? 0;
final appliedSize = size + (_info.isHorizontalSeparator ? offset.dy : offset.dx);
final appliedPercentage = size / maxSizeWithoutSeparators!;


/// Check if transformation will exceed the requested Min / Max value for the specific row / column
if(
(
(children[widgetIndex].minPercentage != null) &&
(children[widgetIndex].minPercentage! > appliedPercentage) &&
(
((_info.isHorizontalSeparator == false) && (offset.dx < 0)) ||
((_info.isHorizontalSeparator == true) && (offset.dy < 0))
)
) ||
(
(children[widgetIndex].maxPercentage != null) &&
(children[widgetIndex].maxPercentage! < appliedPercentage) &&
(
((_info.isHorizontalSeparator == false) && (offset.dx > 0)) ||
((_info.isHorizontalSeparator == true) && (offset.dy > 0))
)
)
) {
return ResizableWidgetResizeImplReturn(
size: children[widgetIndex].size!,
percent: children[widgetIndex].percentage!,
state: ResizableWidgetResizeImplReturnState.INVALID
);
}

ResizableWidgetResizeImplReturn _data = ResizableWidgetResizeImplReturn(
size: appliedSize,
percent: appliedPercentage,
state: ResizableWidgetResizeImplReturnState.VALID
);
if(apply) { __applyResizeImpl(widgetIndex, _data); }
return _data;
}


void __applyResizeImpl(int widgetIndex, ResizableWidgetResizeImplReturn data){
children[widgetIndex].size = data.size;
children[widgetIndex].percentage = data.percent;
}

bool _isNearlyZero(double size) {
Expand Down