@@ -2,8 +2,10 @@ import 'package:flutter/material.dart';
2
2
import 'package:multi_window_ref_app/app/window_controller_render.dart' ;
3
3
import 'package:multi_window_ref_app/app/window_manager_model.dart' ;
4
4
import 'package:multi_window_ref_app/app/window_settings.dart' ;
5
+ import 'dart:math' ;
6
+ import 'package:vector_math/vector_math_64.dart' ;
5
7
6
- class RegularWindowContent extends StatelessWidget {
8
+ class RegularWindowContent extends StatefulWidget {
7
9
const RegularWindowContent (
8
10
{super .key,
9
11
required this .window,
@@ -14,54 +16,111 @@ class RegularWindowContent extends StatelessWidget {
14
16
final WindowSettings windowSettings;
15
17
final WindowManagerModel windowManagerModel;
16
18
19
+ @override
20
+ State <StatefulWidget > createState () => _RegularWindowContentState ();
21
+ }
22
+
23
+ class _RegularWindowContentState extends State <RegularWindowContent >
24
+ with SingleTickerProviderStateMixin {
25
+ late final AnimationController _animation;
26
+ late final Color cubeColor;
27
+
28
+ @override
29
+ void initState () {
30
+ super .initState ();
31
+ _animation = AnimationController (
32
+ vsync: this ,
33
+ lowerBound: 0 ,
34
+ upperBound: 2 * pi,
35
+ duration: const Duration (seconds: 15 ),
36
+ )..repeat ();
37
+ cubeColor = _generateRandomDarkColor ();
38
+ }
39
+
40
+ @override
41
+ void dispose () {
42
+ _animation.dispose ();
43
+ super .dispose ();
44
+ }
45
+
46
+ Color _generateRandomDarkColor () {
47
+ final random = Random ();
48
+ const int lowerBound = 32 ;
49
+ const int span = 160 ;
50
+ int red = lowerBound + random.nextInt (span);
51
+ int green = lowerBound + random.nextInt (span);
52
+ int blue = lowerBound + random.nextInt (span);
53
+ return Color .fromARGB (255 , red, green, blue);
54
+ }
55
+
17
56
@override
18
57
Widget build (BuildContext context) {
19
58
final child = Scaffold (
20
- appBar: AppBar (title: Text ('${window .type }' )),
59
+ appBar: AppBar (title: Text ('${widget . window .type }' )),
21
60
body: Center (
22
- child: Column (
23
- mainAxisAlignment: MainAxisAlignment .center,
24
- crossAxisAlignment: CrossAxisAlignment .center,
25
- children: [
26
- ElevatedButton (
27
- onPressed: () {
28
- windowManagerModel.add (KeyedWindowController (
29
- controller: RegularWindowController ()));
30
- },
31
- child: const Text ('Create Regular Window' ),
32
- ),
33
- const SizedBox (height: 20 ),
34
- ListenableBuilder (
35
- listenable: window,
36
- builder: (BuildContext context, Widget ? _) {
37
- return Text (
38
- 'View #${window .view ?.viewId ?? "Unknown" }\n '
39
- 'Parent View: ${window .parentViewId }\n '
40
- 'Logical Size: ${window .size ?.width ?? "?" }\u 00D7${window .size ?.height ?? "?" }\n '
41
- 'DPR: ${MediaQuery .of (context ).devicePixelRatio }' ,
42
- textAlign: TextAlign .center,
61
+ child: Row (
62
+ mainAxisAlignment: MainAxisAlignment .center,
63
+ children: [
64
+ Column (
65
+ mainAxisAlignment: MainAxisAlignment .center,
66
+ children: [
67
+ AnimatedBuilder (
68
+ animation: _animation,
69
+ builder: (context, child) {
70
+ return CustomPaint (
71
+ size: const Size (200 , 200 ),
72
+ painter: _RotatedWireCube (
73
+ angle: _animation.value, color: cubeColor),
43
74
);
44
- })
45
- ],
46
- ),
47
- ),
75
+ },
76
+ ),
77
+ ],
78
+ ),
79
+ Column (
80
+ mainAxisAlignment: MainAxisAlignment .center,
81
+ crossAxisAlignment: CrossAxisAlignment .center,
82
+ children: [
83
+ ElevatedButton (
84
+ onPressed: () {
85
+ widget.windowManagerModel.add (KeyedWindowController (
86
+ controller: RegularWindowController ()));
87
+ },
88
+ child: const Text ('Create Regular Window' ),
89
+ ),
90
+ const SizedBox (height: 20 ),
91
+ ListenableBuilder (
92
+ listenable: widget.window,
93
+ builder: (BuildContext context, Widget ? _) {
94
+ return Text (
95
+ 'View #${widget .window .view ?.viewId ?? "Unknown" }\n '
96
+ 'Parent View: ${widget .window .parentViewId }\n '
97
+ 'Logical Size: ${widget .window .size ?.width ?? "?" }\u 00D7${widget .window .size ?.height ?? "?" }\n '
98
+ 'DPR: ${MediaQuery .of (context ).devicePixelRatio }' ,
99
+ textAlign: TextAlign .center,
100
+ );
101
+ })
102
+ ],
103
+ ),
104
+ ],
105
+ )),
48
106
);
49
107
50
108
return ViewAnchor (
51
109
view: ListenableBuilder (
52
- listenable: windowManagerModel,
110
+ listenable: widget. windowManagerModel,
53
111
builder: (BuildContext context, Widget ? _) {
54
112
final List <Widget > childViews = < Widget > [];
55
113
for (final KeyedWindowController controller
56
- in windowManagerModel.windows) {
57
- if (controller.parent == window) {
114
+ in widget. windowManagerModel.windows) {
115
+ if (controller.parent == widget. window) {
58
116
childViews.add (WindowControllerRender (
59
117
controller: controller.controller,
60
118
key: controller.key,
61
- windowSettings: windowSettings,
62
- windowManagerModel: windowManagerModel,
63
- onDestroyed: () => windowManagerModel.remove (controller),
64
- onError: () => windowManagerModel.remove (controller),
119
+ windowSettings: widget.windowSettings,
120
+ windowManagerModel: widget.windowManagerModel,
121
+ onDestroyed: () =>
122
+ widget.windowManagerModel.remove (controller),
123
+ onError: () => widget.windowManagerModel.remove (controller),
65
124
));
66
125
}
67
126
}
@@ -71,3 +130,57 @@ class RegularWindowContent extends StatelessWidget {
71
130
child: child);
72
131
}
73
132
}
133
+
134
+ class _RotatedWireCube extends CustomPainter {
135
+ static List <Vector3 > vertices = [
136
+ Vector3 (- 0.5 , - 0.5 , - 0.5 ),
137
+ Vector3 (0.5 , - 0.5 , - 0.5 ),
138
+ Vector3 (0.5 , 0.5 , - 0.5 ),
139
+ Vector3 (- 0.5 , 0.5 , - 0.5 ),
140
+ Vector3 (- 0.5 , - 0.5 , 0.5 ),
141
+ Vector3 (0.5 , - 0.5 , 0.5 ),
142
+ Vector3 (0.5 , 0.5 , 0.5 ),
143
+ Vector3 (- 0.5 , 0.5 , 0.5 ),
144
+ ];
145
+
146
+ static const List <List <int >> edges = [
147
+ [0 , 1 ], [1 , 2 ], [2 , 3 ], [3 , 0 ], // Front face
148
+ [4 , 5 ], [5 , 6 ], [6 , 7 ], [7 , 4 ], // Back face
149
+ [0 , 4 ], [1 , 5 ], [2 , 6 ], [3 , 7 ], // Connecting front and back
150
+ ];
151
+
152
+ final double angle;
153
+ final Color color;
154
+
155
+ _RotatedWireCube ({required this .angle, required this .color});
156
+
157
+ Offset scaleAndCenter (Vector3 point, double size, Offset center) {
158
+ final scale = size / 2 ;
159
+ return Offset (center.dx + point.x * scale, center.dy - point.y * scale);
160
+ }
161
+
162
+ @override
163
+ void paint (Canvas canvas, Size size) {
164
+ final rotatedVertices = vertices
165
+ .map ((vertex) => Matrix4 .rotationX (angle).transformed3 (vertex))
166
+ .map ((vertex) => Matrix4 .rotationY (angle).transformed3 (vertex))
167
+ .map ((vertex) => Matrix4 .rotationZ (angle).transformed3 (vertex))
168
+ .toList ();
169
+
170
+ final center = Offset (size.width / 2 , size.height / 2 );
171
+
172
+ final paint = Paint ()
173
+ ..color = color
174
+ ..style = PaintingStyle .stroke
175
+ ..strokeWidth = 2 ;
176
+
177
+ for (var edge in edges) {
178
+ final p1 = scaleAndCenter (rotatedVertices[edge[0 ]], size.width, center);
179
+ final p2 = scaleAndCenter (rotatedVertices[edge[1 ]], size.width, center);
180
+ canvas.drawLine (p1, p2, paint);
181
+ }
182
+ }
183
+
184
+ @override
185
+ bool shouldRepaint (_RotatedWireCube oldDelegate) => true ;
186
+ }
0 commit comments