1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
|
import 'package:flutter/material.dart';
import 'dart:math' as math;
/// Your code should go into the DrawFractal class.
/// The fractal is drawn as an extension of the CustomPainter.
class DrawFractal extends CustomPainter {
var level = 10; // max level of fractal
// Constructor that initializes the level of the fractal
DrawFractal(value) {
level = value;
}
// Recursively draw the fractal
void fractal(Canvas canvas, int level) {
if (level >= this.level) {
return;
}
final paint = Paint()
..color = Colors.black
..strokeWidth = 1;
// Recursively draw the left branch
canvas.save();
canvas.rotate(math.pi / 6);
canvas.drawLine(Offset.zero, Offset(50 / level, 50 / level), paint);
canvas.translate(50 / level, 50 / level);
fractal(canvas, level + 1);
canvas.restore();
// As we go up the call stack, draw the right branch
canvas.rotate(-math.pi / 6);
canvas.drawLine(Offset.zero, Offset(50 / level, 50 / level), paint);
canvas.translate(50 / level, 50 / level);
fractal(canvas, level + 1);
}
/// Called when the canvas is (re)painted, perform the initial moving of the
/// fractal to the center and other actions here such as the initial call to fractal.
@override
void paint(Canvas canvas, Size size) {
fractal(canvas, 1);
}
/// Always repaint
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
// The code before here is to set up the flutter app and run it. You may not have to
// change this code.
/// Run the application
void main() => runApp(MyApp());
/// The application runs a streambuilder widget
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// The title of my application
title: 'My flutter application',
home: StreamBuilderSetup(),
debugShowCheckedModeBanner: false,
);
}
}
/// Stream to generate numbers from 1 to 10
Stream<int> generateNumbers = (() async* {
await Future<void>.delayed(const Duration(seconds: 2));
for (int i = 1; i <= 10; i++) {
await Future<void>.delayed(const Duration(seconds: 1));
yield i;
}
})();
/// Setup a streambuild widget
class StreamBuilderSetup extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _StreamBuilderSetupState();
}
}
/// The innards of the streambuilder widget
class _StreamBuilderSetupState extends State<StreamBuilderSetup> {
/// Boilerplate for initializing the state of the widget
@override
initState() {
super.initState();
}
/// Build the widget, it consists of a title and a SizedBox where the
/// drawing of the fractal (but could be anything takes place)
/// Most of this is boilerplate code.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Title bar for the widget
title: const Text('Draw a Fractal in Flutter'),
),
// Box in which to draw the fractal
body: SizedBox(
width: double.infinity,
child: Center(
child: StreamBuilder<int>(
stream: generateNumbers,
initialData: 0,
builder: (
BuildContext context,
AsyncSnapshot<int> snapshot,
) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircularProgressIndicator(),
Visibility(
visible: snapshot.hasData,
child: Text(
snapshot.data.toString(),
style:
const TextStyle(color: Colors.black, fontSize: 24),
),
),
],
);
} else if (snapshot.connectionState == ConnectionState.active ||
snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return const Text('Error');
} else if (snapshot.hasData) {
return Center(
child: CustomPaint(
// Set up a canvas of size 500 by 5000
size: const Size(500, 500),
// Draw the fractal passing the level from the stream
painter: DrawFractal(snapshot.data)),
);
} else {
return const Text('Empty data');
}
} else {
return Text('State: ${snapshot.connectionState}');
}
},
),
),
),
);
}
}
|