Skip to content

Commit

Permalink
feat: Improve Wrap behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
enrique-lozano committed Jan 16, 2024
1 parent 6084c5d commit 6676a42
Show file tree
Hide file tree
Showing 5 changed files with 848 additions and 27 deletions.
29 changes: 14 additions & 15 deletions lib/app/categories/category_selector.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:monekin/core/models/category/category.dart';
import 'package:monekin/core/models/supported-icon/icon_displayer.dart';
import 'package:monekin/core/presentation/app_colors.dart';
import 'package:monekin/core/presentation/widgets/wrap/wrap_extended.dart';
import 'package:monekin/core/utils/color_utils.dart';
import 'package:monekin/i18n/translations.g.dart';

Expand Down Expand Up @@ -166,21 +167,19 @@ class _CategorySelectorState extends State<CategorySelector> {
}

if (widget.direction == Axis.vertical) {
return Align(
alignment: Alignment.topLeft,
child: Wrap(
runSpacing: 12,
spacing: 24,
crossAxisAlignment: WrapCrossAlignment.start,
alignment: WrapAlignment.start,
children: [
if (extraHeaderButtonsWithSameSize != null)
...extraHeaderButtonsWithSameSize,
...buildCategoriesOptions(
selectedCategories: selectedCategories,
)
],
),
return WrapSuper(
wrapType: WrapType.balanced,
wrapFit: WrapFit.min,
lineSpacing: 12,
spacing: 24,
alignment: WrapSuperAlignment.center,
children: [
if (extraHeaderButtonsWithSameSize != null)
...extraHeaderButtonsWithSameSize,
...buildCategoriesOptions(
selectedCategories: selectedCategories,
)
],
);
}

Expand Down
30 changes: 18 additions & 12 deletions lib/core/presentation/widgets/monekin_quick_actions_buttons.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:monekin/core/presentation/widgets/wrap/wrap_extended.dart';

import '../../utils/list_tile_action_item.dart';

Expand All @@ -12,14 +13,17 @@ class MonekinQuickActionsButton extends StatelessWidget {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
child: LayoutBuilder(builder: (context, constraints) {
return Wrap(
spacing: 14,
runSpacing: 16,
direction: Axis.horizontal,
alignment: WrapAlignment.start,
children: actions
.map((item) => SizedBox(
child: LayoutBuilder(
builder: (context, constraints) {
return WrapSuper(
spacing: 14,
wrapType: WrapType.balanced,
wrapFit: WrapFit.min,
lineSpacing: 16,
alignment: WrapSuperAlignment.left,
children: actions
.map(
(item) => SizedBox(
width: constraints.maxWidth > 600 ? 100 : 62,
child: Column(
mainAxisSize: MainAxisSize.min,
Expand Down Expand Up @@ -48,10 +52,12 @@ class MonekinQuickActionsButton extends StatelessWidget {
)
],
),
))
.toList(),
);
}),
),
)
.toList(),
);
},
),
);
}
}
2 changes: 2 additions & 0 deletions lib/core/presentation/widgets/wrap/credits.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Many thanks to Marcelo Glasberg for this awesome Widget!!
See the full package at: https://pub.dev/packages/assorted_layout_widgets
120 changes: 120 additions & 0 deletions lib/core/presentation/widgets/wrap/min_raggedness.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import 'dart:collection';
import 'dart:math';

// ignore: avoid_classes_with_only_static_members
class MinimumRaggedness {
/// Given some [boxWidths], break it into the smallest possible number
/// of lines such as each line has width not larger than [maxWidth].
/// It also minimizes the difference between width of each line,
/// achieving a "balanced" result.
/// Optionally accepts a [spacing] between boxes.
///
static List<List<int>> divide(List<num> boxWidths, num maxWidth,
{num spacing = 0.0}) {
int count = boxWidths.length;
List<num> offsets = [0];

for (num boxWidth in boxWidths) {
offsets.add(offsets.last + min(boxWidth, maxWidth));
}

List<num> minimum = [0, ...List<num>.filled(count, 9007199254740991)];
List<int> breaks = List<int>.filled(count + 1, 0);

num cost(int i, int j) {
num width = offsets[j] - offsets[i] + spacing * (j - i - 1);
if (width > maxWidth)
return 9007199254740991;
else
return minimum[i] + pow(maxWidth - width, 2);
}

void search(int i0, int j0, int i1, int j1) {
Queue<List<int>> stack = Queue()..add([i0, j0, i1, j1]);

while (stack.isNotEmpty) {
List<int> info = stack.removeLast();
i0 = info[0];
j0 = info[1];
i1 = info[2];
j1 = info[3];

if (j0 < j1) {
int j = (j0 + j1) ~/ 2;

for (int i = i0; i < i1; i++) {
num c = cost(i, j);
if (c <= minimum[j]) {
minimum[j] = c;
breaks[j] = i;
}
}

stack.add([breaks[j], j + 1, i1, j1]);
stack.add([i0, j0, breaks[j] + 1, j]);
}
}
}

int n = count + 1;
int i = 0;
int offset = 0;

while (true) {
int r = min(n, pow(2, i + 1) as int);
int edge = pow(2, i) + offset as int;
search(0 + offset, edge, edge, r + offset);
num x = minimum[r - 1 + offset];

bool flag = true;
for (int j = pow(2, i) as int; j < r - 1; j++) {
num y = cost(j + offset, r - 1 + offset);
if (y <= x) {
n -= j;
i = 0;
offset += j;
flag = false;
break;
}
}

if (flag) {
if (r == n) break;
i = i + 1;
}
}

int j = count;

List<List<int>> indexes = [];

while (j > 0) {
int i = breaks[j];
indexes.add(List<int>.generate(j - i, (index) => index + i));
j = i;
}

return indexes.reversed.toList();
}

/// Given some [text], breaks it into the smallest possible number of lines
/// such as each line has width not larger than [maxWidthInChars] chars.
/// It also minimizes the difference between width of each line,
/// achieving a "balanced" result.
///
static List<String> divideWords(String text, int maxWidthInChars) {
List<String> words = text.split(" ");
List<int> boxes = words.map((word) => word.length).toList();

List<List<num>> divided = divide(boxes, maxWidthInChars, spacing: 1.0);

List<String> result = [];

for (List<num> partList in divided) {
String text = partList.map((part) => words[part as int]).join(" ");
result.add(text);
}

return result;
}
}
Loading

0 comments on commit 6676a42

Please sign in to comment.