Skip to content

Commit 350717e

Browse files
authored
Merge pull request #13 from EXXETA/feature/box-padding-local
Feature/box padding local
2 parents b369ec1 + 5e48c80 commit 350717e

15 files changed

Lines changed: 250 additions & 56 deletions

File tree

.github/workflows/basic_dart_check.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ jobs:
1515

1616
- name: 🛠️ Set up Flutter
1717
uses: subosito/flutter-action@v2
18+
with:
19+
channel: stable
20+
flutter-version: 3.22.3
21+
- run: flutter --version
1822

1923
- name: ⚙️ Install dependencies
2024
run: flutter pub get

example/lib/screens/examples/box_example_screen.dart

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ class BoxExampleScreen extends StatelessWidget {
4646
TextDecorator.boxed(
4747
style: BoxStyle.bubble,
4848
text: const Text(
49-
'Bubble Text 2',
50-
style: TextStyle(fontSize: 32),
49+
'Franz jagt im komplett verwahrlosten Taxi quer durch Berlin',
50+
style: TextStyle(fontSize: 16),
5151
),
5252
strokeWidth: 2,
5353
borderRadius: 16,
@@ -63,14 +63,17 @@ class BoxExampleScreen extends StatelessWidget {
6363
borderRadius: 16,
6464
),
6565
const SizedBox(height: 32),
66-
TextDecorator.boxed(
67-
style: BoxStyle.curled,
68-
text: const Text(
69-
'Franz jagt im komplett verwahrlosten Taxi quer durch Berlin',
70-
style: TextStyle(fontSize: 16),
66+
Padding(
67+
padding: const EdgeInsets.all(16.0),
68+
child: TextDecorator.boxed(
69+
style: BoxStyle.curled,
70+
text: const Text(
71+
'Franz jagt im komplett verwahrlosten Taxi quer durch Berlin',
72+
style: TextStyle(fontSize: 16),
73+
),
74+
strokeWidth: 2,
75+
borderRadius: 16,
7176
),
72-
strokeWidth: 2,
73-
borderRadius: 16,
7477
),
7578
],
7679
),

lib/flutter_text_decorator.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
21
export 'src/modules/base/styles.dart';
3-
export 'src/widgets/text_draw_decorator.dart';
2+
export 'src/widgets/text_decorator.dart';

lib/src/modules/box/enums/box_style.dart

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,31 @@ enum BoxStyle {
2121
/// - `strokeWidth`: Intended for the thickness of the box outline.
2222
///
2323
/// See individual enum value documentation for notes on parameter usage for specific styles.
24-
CustomPainter getPainter(Text text, double borderRadius, double strokeWidth) {
24+
CustomPainter getPainter(Text text, double borderRadius, double strokeWidth, EdgeInsets padding) {
2525
switch (this) {
2626
case BoxStyle.rounded:
27-
return RoundedBoxPainter(text: text, borderRadius: borderRadius, strokeWidth: strokeWidth);
27+
return RoundedBoxPainter(
28+
text: text,
29+
borderRadius: borderRadius,
30+
strokeWidth: strokeWidth,
31+
padding: padding,
32+
);
2833
case BoxStyle.bubble:
2934
return BubbleBoxPainter(
3035
text: text,
31-
padding: 4,
3236
bubbleColor: Colors.orange,
3337
tip: const BubbleBoxTip(
3438
position: TipPosition.left,
3539
orientation: TipOrientation.left,
3640
),
41+
padding: padding,
3742
);
3843
case BoxStyle.curled:
39-
return WavyBoxPainter(text: text, borderColor: Colors.black);
44+
return WavyBoxPainter(
45+
text: text,
46+
borderColor: Colors.black,
47+
padding: padding,
48+
);
4049
}
4150
}
4251
}

lib/src/modules/box/painter/bubble_box_painter.dart

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:math';
2+
13
import 'package:flutter/material.dart';
24
import 'package:flutter_text_decorator/src/modules/box/decorations/bubble_box_tip.dart';
35

@@ -22,14 +24,14 @@ import 'package:flutter_text_decorator/src/modules/box/decorations/bubble_box_ti
2224
class BubbleBoxPainter extends CustomPainter {
2325
BubbleBoxPainter({
2426
required this.text,
25-
required this.padding,
2627
required this.bubbleColor,
28+
required this.padding,
2729
super.repaint,
2830
this.borderRadius = 8,
2931
this.tip = const BubbleBoxTip(),
3032
});
3133
final Text text;
32-
final double padding; //! TODO: fix text not being centered
34+
final EdgeInsets padding;
3335
final Color bubbleColor;
3436
final double borderRadius;
3537
final BubbleBoxTip tip;
@@ -48,29 +50,31 @@ class BubbleBoxPainter extends CustomPainter {
4850
)..layout();
4951

5052
final textWidth = textPainter.width;
53+
final availableWidth = min(textWidth, size.width);
5154
final textHeight = textPainter.height;
55+
final availableHeight = max(textHeight, size.height);
5256

5357
// Calculate bubble size
54-
final bubbleWidth = textWidth + padding * 2;
55-
final bubbleHeight = textHeight + padding * 2;
58+
final bubbleWidth = availableWidth + padding.horizontal;
59+
final bubbleHeight = availableHeight + padding.vertical;
5660

5761
// Calculate tail size
58-
//! TODO: extract
62+
// !TODO: extract
5963
final tailHeight = bubbleHeight * 0.25;
6064

6165
final path = Path()
6266

6367
// Top left corner
64-
..moveTo(0, borderRadius)
65-
..quadraticBezierTo(0, 0, borderRadius, 0)
68+
..moveTo(0 - padding.left, borderRadius - padding.top)
69+
..quadraticBezierTo(0 - padding.left, 0 - padding.top, borderRadius - padding.left, 0 - padding.top)
6670

6771
// Top right corner
68-
..lineTo(bubbleWidth - borderRadius, 0)
69-
..quadraticBezierTo(bubbleWidth, 0, bubbleWidth, borderRadius)
72+
..lineTo(bubbleWidth - borderRadius - padding.left, 0 - padding.top)
73+
..quadraticBezierTo(bubbleWidth - padding.left, 0 - padding.top, bubbleWidth - padding.left, borderRadius - padding.top)
7074

7175
// Bottom right corner
72-
..lineTo(bubbleWidth, bubbleHeight - borderRadius)
73-
..quadraticBezierTo(bubbleWidth, bubbleHeight, bubbleWidth - borderRadius, bubbleHeight);
76+
..lineTo(bubbleWidth - padding.left, bubbleHeight - borderRadius - padding.top)
77+
..quadraticBezierTo(bubbleWidth - padding.left, bubbleHeight - padding.top, bubbleWidth - borderRadius - padding.left, bubbleHeight - padding.top);
7478

7579
final tipOffset = bubbleWidth * 0.05;
7680

@@ -84,11 +88,11 @@ class BubbleBoxPainter extends CustomPainter {
8488

8589
// Bottom left corner with tail
8690
path
87-
..lineTo(tipStart, bubbleHeight)
88-
..lineTo(tipPeak, bubbleHeight + tailHeight)
89-
..lineTo(tipEnd, bubbleHeight)
90-
..lineTo(borderRadius, bubbleHeight)
91-
..quadraticBezierTo(0, bubbleHeight, 0, bubbleHeight - borderRadius)
91+
..lineTo(tipStart, bubbleHeight - padding.top)
92+
..lineTo(tipPeak, bubbleHeight + tailHeight - padding.top)
93+
..lineTo(tipEnd, bubbleHeight - padding.top)
94+
..lineTo(borderRadius - padding.left, bubbleHeight - padding.top)
95+
..quadraticBezierTo(0 - padding.left, bubbleHeight - padding.top, 0 - padding.left, bubbleHeight - borderRadius - padding.top)
9296
..close();
9397

9498
// Draw the bubble

lib/src/modules/box/painter/rounded_box_painter.dart

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,22 @@ class RoundedBoxPainter extends CustomPainter {
3030
required this.text,
3131
required this.borderRadius,
3232
required this.strokeWidth,
33+
required this.padding,
3334
super.repaint,
3435
});
3536
final Text text;
3637
final double borderRadius;
3738
final double strokeWidth;
39+
final EdgeInsets padding;
3840

3941
@override
4042
void paint(Canvas canvas, Size size) {
4143
final paint = Paint()
4244
..strokeWidth = strokeWidth
4345
..style = PaintingStyle.stroke;
4446

45-
// TODO(everyone): Extract and make generic
4647
final textSpan = TextSpan(text: text.data, style: text.style);
47-
final textPainter = TextPainter(
48-
text: textSpan,
49-
textDirection: TextDirection.ltr,
50-
)..layout();
48+
final textPainter = TextPainter(text: textSpan, textDirection: TextDirection.ltr)..layout();
5149

5250
final textWidth = textPainter.width;
5351
final boxWidth = min(textWidth, size.width);
@@ -60,18 +58,36 @@ class RoundedBoxPainter extends CustomPainter {
6058
boxHeight = nLines * textHeight;
6159

6260
final centerOffset = Offset(
63-
size.width / 2,
64-
size.height / 2,
61+
_getOffsetDx(size),
62+
_getOffsetDy(size),
6563
);
6664

6765
final rrect = RRect.fromRectAndRadius(
68-
Rect.fromCenter(center: centerOffset, width: boxWidth, height: boxHeight),
66+
Rect.fromCenter(center: centerOffset, width: boxWidth + padding.horizontal, height: boxHeight + padding.vertical),
6967
Radius.circular(borderRadius),
7068
);
7169

7270
canvas.drawRRect(rrect, paint);
7371
}
7472

73+
double _getOffsetDx(Size size) {
74+
var dx = size.width / 2;
75+
if (padding.left != padding.right) {
76+
final diff = (padding.left - padding.right).abs() / 2;
77+
dx = padding.left < padding.right ? dx + diff : dx - diff;
78+
}
79+
return dx;
80+
}
81+
82+
double _getOffsetDy(Size size) {
83+
var dy = size.height / 2;
84+
if (padding.top != padding.bottom) {
85+
final diff = (padding.top - padding.bottom).abs() / 2;
86+
dy = padding.top < padding.bottom ? dy + diff : dy - diff;
87+
}
88+
return dy;
89+
}
90+
7591
@override
7692
bool shouldRepaint(covariant CustomPainter oldDelegate) {
7793
return false;

lib/src/modules/box/painter/wavy_box_painter.dart

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,18 @@ class WavyBoxPainter extends CustomPainter {
3636
WavyBoxPainter({
3737
required this.text,
3838
required this.borderColor,
39+
required this.padding,
40+
this.nHorizontalSegments = 12,
41+
this.nVerticalSegments = 3,
3942
super.repaint,
4043
});
4144
// TODO(everyone): add padding?
4245
// TODO(everyone): add fill color?
4346
final Text text;
4447
final Color borderColor;
48+
final EdgeInsets padding;
49+
final int nHorizontalSegments;
50+
final int nVerticalSegments;
4551

4652
@override
4753
void paint(Canvas canvas, Size size) {
@@ -63,44 +69,44 @@ class WavyBoxPainter extends CustomPainter {
6369
final nLines = heightFactor.ceil();
6470
textHeight = nLines * textHeight;
6571

66-
const nHorizontalSegments = 10;
67-
final availableWidth = min(textWidth, size.width);
68-
final lengthSegment = (availableWidth / nHorizontalSegments).ceil();
69-
final nVerticalSegments = (textHeight / lengthSegment).ceil();
72+
final availableWidth = min(textWidth, size.width) + padding.horizontal;
73+
final availableHeight = max(textHeight, size.height) + padding.vertical;
74+
final widthHorizontalSegment = availableWidth / nHorizontalSegments;
75+
final heightVerticalSegment = availableHeight / nVerticalSegments;
7076

7177
const arcHeight = -10.0;
7278
const weight = 1.0;
73-
var lastX2 = 0.0;
79+
var lastX2 = 0.0 - padding.left;
7480

7581
// TODO(everyone): Fix corners, maybe with [arcTo]?
76-
final path = Path()..moveTo(0, 0);
82+
final path = Path()..moveTo(0 - padding.left, 0 - padding.top);
7783

7884
// Upper left to upper right
7985
for (var i = 1; i <= nHorizontalSegments; i++) {
80-
final x2 = i * lengthSegment / 1.0;
81-
path.conicTo(lastX2 + lengthSegment / 2, arcHeight, x2 / 1.0, 0, weight);
86+
final x2 = (i * widthHorizontalSegment / 1.0) - padding.left;
87+
path.conicTo(lastX2 + widthHorizontalSegment / 2, arcHeight - padding.top, x2 / 1.0, 0 - padding.top, weight);
8288
lastX2 = x2;
8389
}
8490

8591
// Upper right to lower right
86-
double lastY2 = 0;
92+
var lastY2 = 0 - padding.top;
8793
for (var i = 1; i <= nVerticalSegments; i++) {
88-
final y2 = i * lengthSegment / 1.0;
89-
path.conicTo(lastX2 - arcHeight, lastY2 + lengthSegment / 2, lastX2, y2, weight);
94+
final y2 = (i * heightVerticalSegment / 1.0) - padding.top;
95+
path.conicTo(lastX2 - arcHeight, lastY2 + heightVerticalSegment / 2, lastX2, y2, weight);
9096
lastY2 = y2;
9197
}
9298

9399
// Lower right to lower left
94100
for (var i = nHorizontalSegments - 1; i >= 0; i--) {
95-
final x2 = i * lengthSegment / 1.0;
96-
path.conicTo(lastX2 - lengthSegment / 2, lastY2 - arcHeight, x2 / 1.0, lastY2, weight);
101+
final x2 = (i * widthHorizontalSegment / 1.0) - padding.left;
102+
path.conicTo(lastX2 - widthHorizontalSegment / 2, lastY2 - arcHeight, x2 / 1.0, lastY2, weight);
97103
lastX2 = x2;
98104
}
99105

100106
// Lower left to upper right
101107
for (var i = nVerticalSegments - 1; i >= 0; i--) {
102-
final y2 = i * lengthSegment / 1.0;
103-
path.conicTo(arcHeight, y2 + lengthSegment / 2, lastX2, y2, weight);
108+
final y2 = (i * heightVerticalSegment / 1.0) - padding.top;
109+
path.conicTo(arcHeight - padding.left, y2 + heightVerticalSegment / 2, 0 - padding.left, y2, weight);
104110
lastY2 = y2;
105111
}
106112

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ import 'package:flutter_text_decorator/src/modules/underline/enums/underline_sty
4141
/// ```
4242
///
4343
class TextDecorator extends StatelessWidget {
44-
4544
const TextDecorator({
4645
required this.text,
4746
required this.painter,
@@ -131,10 +130,11 @@ class TextDecorator extends StatelessWidget {
131130
BoxStyle style = BoxStyle.bubble,
132131
double borderRadius = 1,
133132
double strokeWidth = 1,
133+
EdgeInsets padding = const EdgeInsets.all(8),
134134
}) {
135135
return TextDecorator(
136136
text: text,
137-
painter: style.getPainter(text, borderRadius, strokeWidth),
137+
painter: style.getPainter(text, borderRadius, strokeWidth, padding),
138138
);
139139
}
140140

test/flutter_test_config.dart

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import 'dart:async';
2+
3+
import 'package:flutter_test/flutter_test.dart';
4+
5+
import 'utils/local_file_comparer.dart';
6+
7+
const _kGoldenTestsThreshold = 0.5 / 100;
8+
9+
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
10+
if (goldenFileComparator is LocalFileComparator) {
11+
final testUrl = (goldenFileComparator as LocalFileComparator).basedir;
12+
13+
goldenFileComparator = LocalFileComparatorWithThreshold(
14+
Uri.parse('$testUrl/test.dart'),
15+
_kGoldenTestsThreshold,
16+
);
17+
} else {
18+
throw Exception(
19+
'Expected `goldenFileComparator` to be of type `LocalFileComparator`, '
20+
'but it is of type `${goldenFileComparator.runtimeType}`',
21+
);
22+
}
23+
24+
await testMain();
25+
}
5.55 KB
Loading

0 commit comments

Comments
 (0)