Skip to content

Commit d79edc2

Browse files
authored
Merge pull request #10 from EXXETA/improvement/FTD-9-documentation
[ADD] class and function documentations
2 parents fd10bfc + 020e62f commit d79edc2

20 files changed

+581
-104
lines changed
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
import 'package:flutter/material.dart';
22

3+
/// An abstract base class for defining common styling properties for text decorations.
4+
///
5+
/// This class serves as a contract for specific decoration types (e.g.,
6+
/// [CircleDecoration]), ensuring they provide essential visual attributes
7+
/// like [color] and [strokeWidth].
8+
///
39
abstract class DecorationBase {
410
final Color color;
511
final double strokeWidth;
612

7-
const DecorationBase({required this.color, required this.strokeWidth});
13+
const DecorationBase({
14+
required this.color,
15+
required this.strokeWidth,
16+
});
817
}
Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,30 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_text_decorator/src/modules/base/decoration_base.dart';
33

4+
/// An abstract base class for [CustomPainter] implementations that draw
5+
/// decorations around or on text, utilizing a [DecorationBase] object
6+
/// for common styling properties like color and stroke width.
7+
///
8+
/// This class provides a common structure for painters that need access to
9+
/// the text content, its [TextStyle], and a [DecorationBase] instance
10+
/// to define the visual characteristics of the decoration.
11+
///
12+
/// Subclasses are expected to implement the `paint` method to define the
13+
/// actual drawing logic for their specific decoration style.
14+
///
15+
/// Properties:
16+
/// - `text`: The [String] content to be decorated.
17+
/// - `textStyle`: The [TextStyle] applied to the `text`.
18+
/// - `decoration`: A [DecorationBase] instance providing base styling
419
abstract class TextDecoratorPainter extends CustomPainter {
520
final String text;
621
final TextStyle textStyle;
722
final DecorationBase decoration;
823

9-
TextDecoratorPainter({required this.text, required this.textStyle, required this.decoration, super.repaint});
24+
TextDecoratorPainter({
25+
required this.text,
26+
required this.textStyle,
27+
required this.decoration,
28+
super.repaint,
29+
});
1030
}
Lines changed: 3 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import 'package:flutter/material.dart';
2-
31
enum TipPosition {
42
left(0.3),
53
right(0.9),
@@ -18,88 +16,8 @@ class BubbleBoxTip {
1816
final TipPosition position;
1917
final TipOrientation orientation;
2018

21-
const BubbleBoxTip({this.position = TipPosition.center, this.orientation = TipOrientation.right});
22-
}
23-
24-
class BubbleBoxPainter extends CustomPainter {
25-
final Text text;
26-
final double padding; //! TODO: fix text not being centered
27-
final Color bubbleColor;
28-
final double borderRadius;
29-
final BubbleBoxTip tip;
30-
31-
BubbleBoxPainter({
32-
required this.text,
33-
required this.padding,
34-
required this.bubbleColor,
35-
super.repaint,
36-
this.borderRadius = 8,
37-
this.tip = const BubbleBoxTip(),
19+
const BubbleBoxTip({
20+
this.position = TipPosition.center,
21+
this.orientation = TipOrientation.right,
3822
});
39-
40-
@override
41-
void paint(Canvas canvas, Size size) {
42-
final Paint paint = Paint()
43-
..color = bubbleColor
44-
..strokeWidth = 2 // TODO: add as param?
45-
..style = PaintingStyle.stroke;
46-
47-
// Calculate text size
48-
final textPainter = TextPainter(
49-
text: TextSpan(text: text.data, style: text.style),
50-
textDirection: TextDirection.ltr,
51-
)..layout();
52-
53-
final textWidth = textPainter.width;
54-
final textHeight = textPainter.height;
55-
56-
// Calculate bubble size
57-
final bubbleWidth = textWidth + padding * 2;
58-
final bubbleHeight = textHeight + padding * 2;
59-
60-
// Calculate tail size
61-
//! TODO: extract
62-
final tailHeight = bubbleHeight * 0.25;
63-
64-
final path = Path()
65-
66-
// Top left corner
67-
..moveTo(0, borderRadius)
68-
..quadraticBezierTo(0, 0, borderRadius, 0)
69-
70-
// Top right corner
71-
..lineTo(bubbleWidth - borderRadius, 0)
72-
..quadraticBezierTo(bubbleWidth, 0, bubbleWidth, borderRadius)
73-
74-
// Bottom right corner
75-
..lineTo(bubbleWidth, bubbleHeight - borderRadius)
76-
..quadraticBezierTo(bubbleWidth, bubbleHeight, bubbleWidth - borderRadius, bubbleHeight);
77-
78-
final double tipOffset = bubbleWidth * 0.05;
79-
80-
final double tipStart = bubbleWidth * tip.position.percentage;
81-
final double tipBaseWidth = bubbleWidth * 0.2;
82-
final double tipEnd = tipStart - tipBaseWidth;
83-
double tipPeak = tipEnd - tipOffset;
84-
if (tip.orientation == TipOrientation.right) {
85-
tipPeak = tipStart + tipOffset;
86-
}
87-
88-
// Bottom left corner with tail
89-
path
90-
..lineTo(tipStart, bubbleHeight)
91-
..lineTo(tipPeak, bubbleHeight + tailHeight)
92-
..lineTo(tipEnd, bubbleHeight)
93-
..lineTo(borderRadius, bubbleHeight)
94-
..quadraticBezierTo(0, bubbleHeight, 0, bubbleHeight - borderRadius)
95-
..close();
96-
97-
// Draw the bubble
98-
canvas.drawPath(path, paint);
99-
}
100-
101-
@override
102-
bool shouldRepaint(covariant CustomPainter oldDelegate) {
103-
return false;
104-
}
10523
}

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,26 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_text_decorator/src/modules/box/decorations/bubble_box_tip.dart';
3+
import 'package:flutter_text_decorator/src/modules/box/painter/bubble_box_painter.dart';
34
import 'package:flutter_text_decorator/src/modules/box/painter/rounded_box_painter.dart';
45
import 'package:flutter_text_decorator/src/modules/box/painter/wavy_box_painter.dart';
56

7+
/// Defines the different styles available for box decorations around text.
8+
///
9+
/// Each style corresponds to a specific [CustomPainter] that will be used
10+
/// to render the box. The [getPainter] method is used to retrieve the
11+
/// appropriate painter instance based on the enum value.
612
enum BoxStyle {
713
rounded,
814
bubble,
915
curled;
1016

17+
/// Returns the [CustomPainter] corresponding to the box style.
18+
///
19+
/// - `text`: The [Text] widget to be decorated.
20+
/// - `borderRadius`: Intended for the radius of corners.
21+
/// - `strokeWidth`: Intended for the thickness of the box outline.
22+
///
23+
/// See individual enum value documentation for notes on parameter usage for specific styles.
1124
CustomPainter getPainter(Text text, double borderRadius, double strokeWidth) {
1225
switch (this) {
1326
case BoxStyle.rounded:
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_text_decorator/src/modules/box/decorations/bubble_box_tip.dart';
3+
4+
/// A [CustomPainter] that draws a speech bubble-like box around a given [Text] widget.
5+
///
6+
/// This painter creates a rounded rectangle with a "tip" or "tail" pointing outwards,
7+
/// commonly used to represent speech or thoughts in UI design. The appearance of
8+
/// the bubble, including its color, corner roundness, padding around the text,
9+
/// and the characteristics of the tip (its position and orientation), can be customized.
10+
///
11+
/// The painter calculates the size of the provided text to determine the overall
12+
/// dimensions of the bubble. The tip's geometry is then calculated based on the
13+
/// bubble's width and the properties defined in the [BubbleBoxTip] object.
14+
///
15+
/// Key properties:
16+
/// - `text`: The [Text] widget to be enclosed by the bubble.
17+
/// - `padding`: The space between the text and the bubble's edges.
18+
/// - `bubbleColor`: The color of the bubble's outline.
19+
/// - `borderRadius`: The radius for the rounded corners of the bubble.
20+
/// - `tip`: A [BubbleBoxTip] object defining the tip's position, orientation, and size.
21+
/// ```
22+
class BubbleBoxPainter extends CustomPainter {
23+
final Text text;
24+
final double padding; //! TODO: fix text not being centered
25+
final Color bubbleColor;
26+
final double borderRadius;
27+
final BubbleBoxTip tip;
28+
29+
BubbleBoxPainter({
30+
required this.text,
31+
required this.padding,
32+
required this.bubbleColor,
33+
super.repaint,
34+
this.borderRadius = 8,
35+
this.tip = const BubbleBoxTip(),
36+
});
37+
38+
@override
39+
void paint(Canvas canvas, Size size) {
40+
final Paint paint = Paint()
41+
..color = bubbleColor
42+
..strokeWidth = 2 // TODO: add as param?
43+
..style = PaintingStyle.stroke;
44+
45+
// Calculate text size
46+
final textPainter = TextPainter(
47+
text: TextSpan(text: text.data, style: text.style),
48+
textDirection: TextDirection.ltr,
49+
)..layout();
50+
51+
final textWidth = textPainter.width;
52+
final textHeight = textPainter.height;
53+
54+
// Calculate bubble size
55+
final bubbleWidth = textWidth + padding * 2;
56+
final bubbleHeight = textHeight + padding * 2;
57+
58+
// Calculate tail size
59+
//! TODO: extract
60+
final tailHeight = bubbleHeight * 0.25;
61+
62+
final path = Path()
63+
64+
// Top left corner
65+
..moveTo(0, borderRadius)
66+
..quadraticBezierTo(0, 0, borderRadius, 0)
67+
68+
// Top right corner
69+
..lineTo(bubbleWidth - borderRadius, 0)
70+
..quadraticBezierTo(bubbleWidth, 0, bubbleWidth, borderRadius)
71+
72+
// Bottom right corner
73+
..lineTo(bubbleWidth, bubbleHeight - borderRadius)
74+
..quadraticBezierTo(bubbleWidth, bubbleHeight, bubbleWidth - borderRadius, bubbleHeight);
75+
76+
final double tipOffset = bubbleWidth * 0.05;
77+
78+
final double tipStart = bubbleWidth * tip.position.percentage;
79+
final double tipBaseWidth = bubbleWidth * 0.2;
80+
final double tipEnd = tipStart - tipBaseWidth;
81+
double tipPeak = tipEnd - tipOffset;
82+
if (tip.orientation == TipOrientation.right) {
83+
tipPeak = tipStart + tipOffset;
84+
}
85+
86+
// Bottom left corner with tail
87+
path
88+
..lineTo(tipStart, bubbleHeight)
89+
..lineTo(tipPeak, bubbleHeight + tailHeight)
90+
..lineTo(tipEnd, bubbleHeight)
91+
..lineTo(borderRadius, bubbleHeight)
92+
..quadraticBezierTo(0, bubbleHeight, 0, bubbleHeight - borderRadius)
93+
..close();
94+
95+
// Draw the bubble
96+
canvas.drawPath(path, paint);
97+
}
98+
99+
@override
100+
bool shouldRepaint(covariant CustomPainter oldDelegate) {
101+
return false;
102+
}
103+
}

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

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,37 @@ import 'package:flutter/material.dart';
33
import 'package:flutter_text_decorator/src/modules/base/text_decoration_painter.dart';
44
import 'package:flutter_text_decorator/src/modules/circle/mixins/circle_mixin.dart';
55

6+
/// A [CustomPainter] that draws an "open circle" decoration around text.
7+
///
8+
/// This painter renders two distinct arcs, one above and one below the text,
9+
/// creating the visual effect of an incomplete or stylized circle. It extends
10+
/// [TextDecoratorPainter], taking text content, style, and a [DecorationBase]
11+
/// object (which provides color and stroke width) to define its appearance.
12+
///
13+
/// The sizing and positioning of the arcs are calculated based on the dimensions
14+
/// of the text (obtained via the [CircleConstraints] mixin using `getCircleSizes`)
15+
/// and internal scaling factors and offsets to achieve the specific "open circle" look.
16+
/// These scaling factors and angles are currently hardcoded to produce a specific
17+
/// aesthetic.
18+
///
19+
/// This painter asserts that the provided [text] is not empty and that
20+
/// `decoration.strokeWidth` is greater than 0.
21+
///
22+
/// Example (conceptual, as direct usage might be part of a larger framework):
23+
/// ```dart
24+
/// CustomPaint(
25+
/// painter: OpenCirclePainter(
26+
/// text: "Open Circle Text",
27+
/// textStyle: TextStyle(fontSize: 16, color: Colors.black),
28+
/// decoration: CircleDecoration(color: Colors.blue, strokeWidth: 2.0),
29+
/// ),
30+
/// child: Text(
31+
/// "Open Circle Text",
32+
/// style: TextStyle(fontSize: 16, color: Colors.black),
33+
/// ),
34+
/// )
35+
/// ```
36+
637
class OpenCirclePainter extends TextDecoratorPainter with CircleConstraints {
738
OpenCirclePainter({
839
required super.text,
@@ -23,15 +54,13 @@ class OpenCirclePainter extends TextDecoratorPainter with CircleConstraints {
2354
final scaledVerticalRadiusBottomCircle = circleSize.verticalRadius * 2.9;
2455
final scaledVerticalRadiusTopCircle = circleSize.verticalRadius * 3.5;
2556
const verticalOffset = 1.8;
26-
const startAngleBottomCircle = -1.5;
27-
const sweepAngleBottomCircle = pi + 1.5;
28-
const startAngleTopCircle = pi + 6.2;
29-
const sweepAngleTopCircle = pi - 1;
3057

31-
final centerOffset = Offset(
32-
size.width / 2,
33-
(size.height / verticalOffset) + verticalOffset,
34-
);
58+
const startAngleBottomArc = -1.5;
59+
const sweepAngleBottomArc = pi + 1.5;
60+
const startAngleTopArc = pi + 6.2;
61+
const sweepAngleTopArc = pi - 1;
62+
63+
final centerOffset = Offset(size.width / 2, (size.height / verticalOffset) + verticalOffset);
3564

3665
canvas
3766
..drawArc(
@@ -40,8 +69,8 @@ class OpenCirclePainter extends TextDecoratorPainter with CircleConstraints {
4069
width: scaledHorizontalRadius,
4170
height: scaledVerticalRadiusBottomCircle,
4271
),
43-
startAngleBottomCircle,
44-
sweepAngleBottomCircle,
72+
startAngleBottomArc,
73+
sweepAngleBottomArc,
4574
false,
4675
paint,
4776
)
@@ -51,8 +80,8 @@ class OpenCirclePainter extends TextDecoratorPainter with CircleConstraints {
5180
width: scaledHorizontalRadius,
5281
height: scaledVerticalRadiusTopCircle,
5382
),
54-
startAngleTopCircle,
55-
sweepAngleTopCircle,
83+
startAngleTopArc,
84+
sweepAngleTopArc,
5685
false,
5786
paint,
5887
);

0 commit comments

Comments
 (0)