Skip to content

Commit 3baaa80

Browse files
committed
Сreate property widget factories to apply pattern to flutter fidgets.
1 parent 506b40c commit 3baaa80

File tree

10 files changed

+265
-165
lines changed

10 files changed

+265
-165
lines changed

patterns/abstract_factory/tool_panel_factory/main.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import 'factories/triangle_factory.dart';
1010
import 'factories/text_factory.dart';
1111
import 'widgets/drawing_board.dart';
1212
import 'widgets/property_bar.dart';
13+
import 'widgets/property_widgets/bool_property_widget.dart';
14+
import 'widgets/property_widgets/double_property_widget.dart';
15+
import 'widgets/property_widgets/factories/property_widget_factories.dart';
16+
import 'widgets/property_widgets/string_property_widget.dart';
1317
import 'widgets/tool_panel.dart';
1418

1519
class ToolPanelFactoryApp extends StatefulWidget {
@@ -39,6 +43,14 @@ class _ToolPanelFactoryAppState extends State<ToolPanelFactoryApp> {
3943
),
4044
);
4145

46+
final propertyWidgetFactories = PropertyWidgetFactories(
47+
factories: [
48+
StringPropertyWidgetFactory(),
49+
DoublePropertyWidgetFactory(),
50+
BoolPropertyWidgetFactory(),
51+
],
52+
);
53+
4254
@override
4355
Widget build(BuildContext context) {
4456
return Stack(
@@ -52,6 +64,7 @@ class _ToolPanelFactoryAppState extends State<ToolPanelFactoryApp> {
5264
),
5365
PropertyPanel(
5466
tools: app.tools,
67+
propertyWidgetFactories: propertyWidgetFactories,
5568
),
5669
],
5770
);

patterns/abstract_factory/tool_panel_factory/widgets/factories_tool_bar.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ class FactoriesToolBar extends StatelessWidget {
2020
? _buildToolButtons()
2121
: Padding(
2222
padding: EdgeInsets.all(10),
23-
child: CircularProgressIndicator());
23+
child: CircularProgressIndicator(),
24+
);
2425
},
2526
),
2627
);
Lines changed: 9 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -1,196 +1,41 @@
11
import 'package:flutter/material.dart';
22

33
import '../app/tools.dart';
4-
import '../pattern/property.dart';
54
import '../pattern/tool_factory.dart';
65
import 'independent/panel.dart';
6+
import 'property_widgets/factories/property_widget_factories.dart';
7+
import 'property_widgets/primitive/theme_property.dart';
78

89
class PropertyPanel extends StatelessWidget {
910
final Tools tools;
11+
final PropertyWidgetFactories propertyWidgetFactories;
1012

1113
const PropertyPanel({
1214
Key? key,
1315
required this.tools,
16+
required this.propertyWidgetFactories,
1417
}) : super(key: key);
1518

1619
@override
1720
Widget build(BuildContext context) {
1821
return Positioned(
1922
top: 12,
2023
left: 12 + 64 + 8 + 12,
21-
child: _buildTheme(
24+
child: ThemeProperty(
2225
child: Panel(
2326
direction: Axis.horizontal,
2427
child: ValueListenableBuilder<ToolFactory>(
2528
valueListenable: tools.activeFactory,
26-
builder: (_, activeFactory, __) {
29+
builder: (_, activeToolFactory, __) {
2730
return Row(
28-
children: [
29-
for (final prop in activeFactory.properties)
30-
_buildProperty(prop),
31-
],
31+
children: propertyWidgetFactories
32+
.createListPropertyWidgetsFrom(activeToolFactory.properties)
33+
.toList(),
3234
);
3335
},
3436
),
3537
),
3638
),
3739
);
3840
}
39-
40-
Widget _buildTheme({required Widget child}) {
41-
return Material(
42-
color: Colors.transparent,
43-
textStyle: TextStyle(
44-
color: Colors.white,
45-
fontSize: 16,
46-
fontFamily: 'Arial',
47-
),
48-
child: Theme(
49-
data: ThemeData(
50-
primarySwatch: Colors.pink,
51-
unselectedWidgetColor: Colors.grey, // Your color
52-
),
53-
child: child),
54-
);
55-
}
56-
57-
Widget _buildProperty(Property prop) {
58-
final val = prop.value();
59-
60-
if (val is String) {
61-
return StringPropertyWidget(property: prop);
62-
} else if (val is double) {
63-
return DoublePropertyWidget(property: prop);
64-
} else if (val is bool) {
65-
return BoolPropertyWidget(property: prop);
66-
}
67-
68-
throw 'Type(${prop.value().runtimeType}) of property is not support';
69-
}
70-
}
71-
72-
class StringPropertyWidget extends StatelessWidget {
73-
final Property property;
74-
75-
const StringPropertyWidget({Key? key, required this.property})
76-
: super(key: key);
77-
78-
@override
79-
Widget build(BuildContext context) {
80-
return _FieldLabel(
81-
text: property.name,
82-
child: Container(
83-
color: Colors.white12,
84-
width: 120,
85-
height: 32,
86-
child: TextFormField(
87-
style: TextStyle(fontSize: 18, color: Colors.white70),
88-
decoration: InputDecoration(
89-
contentPadding: const EdgeInsets.only(left: 5.0, bottom: 14.0),
90-
border: UnderlineInputBorder(),
91-
),
92-
initialValue: property.value(),
93-
onChanged: property.onChange,
94-
),
95-
),
96-
);
97-
}
98-
}
99-
100-
class DoublePropertyWidget extends StatefulWidget {
101-
final Property property;
102-
103-
const DoublePropertyWidget({Key? key, required this.property})
104-
: super(key: key);
105-
106-
@override
107-
_DoublePropertyWidgetState createState() => _DoublePropertyWidgetState();
108-
}
109-
110-
class _DoublePropertyWidgetState extends State<DoublePropertyWidget> {
111-
@override
112-
Widget build(BuildContext context) {
113-
return _FieldLabel(
114-
text: widget.property.name,
115-
child: Row(
116-
children: [
117-
SizedBox(
118-
width: 200,
119-
child: Slider.adaptive(
120-
min: 0.0,
121-
max: 300,
122-
value: widget.property.value() as double,
123-
onChanged: (val) {
124-
setState(() {
125-
widget.property.onChange(val);
126-
});
127-
},
128-
),
129-
),
130-
SizedBox(
131-
width: 32,
132-
child: Text(
133-
(widget.property.value() as double).toStringAsFixed(0),
134-
textAlign: TextAlign.right,
135-
),
136-
)
137-
],
138-
),
139-
);
140-
}
141-
}
142-
143-
class BoolPropertyWidget extends StatefulWidget {
144-
final Property property;
145-
146-
const BoolPropertyWidget({Key? key, required this.property})
147-
: super(key: key);
148-
149-
@override
150-
_BoolPropertyWidgetState createState() => _BoolPropertyWidgetState();
151-
}
152-
153-
class _BoolPropertyWidgetState extends State<BoolPropertyWidget> {
154-
@override
155-
Widget build(BuildContext context) {
156-
return _FieldLabel(
157-
text: widget.property.name,
158-
child: Row(
159-
children: [
160-
Checkbox(
161-
value: widget.property.value() as bool,
162-
onChanged: (val) {
163-
setState(() {
164-
widget.property.onChange(val);
165-
});
166-
},
167-
)
168-
],
169-
),
170-
);
171-
}
172-
}
173-
174-
class _FieldLabel extends StatelessWidget {
175-
final String text;
176-
final Widget child;
177-
178-
const _FieldLabel({
179-
Key? key,
180-
required this.text,
181-
required this.child,
182-
}) : super(key: key);
183-
184-
@override
185-
Widget build(BuildContext context) {
186-
return Row(
187-
children: [
188-
SizedBox(width: 10),
189-
Text(text + ':'),
190-
SizedBox(width: 10),
191-
child,
192-
SizedBox(width: 20),
193-
],
194-
);
195-
}
19641
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import 'package:flutter/material.dart';
2+
3+
import '../../pattern/property.dart';
4+
import 'factories/property_widget_factory.dart';
5+
import 'primitive/filed_label.dart';
6+
7+
class BoolPropertyWidgetFactory implements PropertyWidgetFactory {
8+
@override
9+
Widget createPropertyWidget(Property property) {
10+
return BoolPropertyWidget(property: property);
11+
}
12+
13+
@override
14+
bool isPropertyContain(Property property) => property.value() is bool;
15+
}
16+
17+
class BoolPropertyWidget extends StatefulWidget {
18+
final Property property;
19+
20+
const BoolPropertyWidget({Key? key, required this.property})
21+
: super(key: key);
22+
23+
@override
24+
_BoolPropertyWidgetState createState() => _BoolPropertyWidgetState();
25+
}
26+
27+
class _BoolPropertyWidgetState extends State<BoolPropertyWidget> {
28+
@override
29+
Widget build(BuildContext context) {
30+
return FieldLabel(
31+
text: widget.property.name,
32+
child: Row(
33+
children: [
34+
Checkbox(
35+
value: widget.property.value() as bool,
36+
onChanged: (val) {
37+
setState(() {
38+
widget.property.onChange(val);
39+
});
40+
},
41+
)
42+
],
43+
),
44+
);
45+
}
46+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import 'package:flutter/material.dart';
2+
3+
import '../../pattern/property.dart';
4+
import 'factories/property_widget_factory.dart';
5+
import 'primitive/filed_label.dart';
6+
7+
class DoublePropertyWidgetFactory implements PropertyWidgetFactory {
8+
@override
9+
Widget createPropertyWidget(Property property) {
10+
return DoublePropertyWidget(property: property);
11+
}
12+
13+
@override
14+
bool isPropertyContain(Property property) => property.value() is double;
15+
}
16+
17+
class DoublePropertyWidget extends StatefulWidget {
18+
final Property property;
19+
20+
const DoublePropertyWidget({Key? key, required this.property})
21+
: super(key: key);
22+
23+
@override
24+
_DoublePropertyWidgetState createState() => _DoublePropertyWidgetState();
25+
}
26+
27+
class _DoublePropertyWidgetState extends State<DoublePropertyWidget> {
28+
@override
29+
Widget build(BuildContext context) {
30+
return FieldLabel(
31+
text: widget.property.name,
32+
child: Row(
33+
children: [
34+
SizedBox(
35+
width: 200,
36+
child: Slider.adaptive(
37+
min: 0.0,
38+
max: 300,
39+
value: widget.property.value() as double,
40+
onChanged: (val) {
41+
setState(() {
42+
widget.property.onChange(val);
43+
});
44+
},
45+
),
46+
),
47+
SizedBox(
48+
width: 32,
49+
child: Text(
50+
(widget.property.value() as double).toStringAsFixed(0),
51+
textAlign: TextAlign.right,
52+
),
53+
)
54+
],
55+
),
56+
);
57+
}
58+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import 'package:flutter/widgets.dart';
2+
3+
import '../../../pattern/property.dart';
4+
5+
import 'property_widget_factory.dart';
6+
7+
class PropertyWidgetFactories {
8+
final List<PropertyWidgetFactory> _factories;
9+
10+
PropertyWidgetFactories({
11+
required List<PropertyWidgetFactory> factories,
12+
}) : _factories = factories;
13+
14+
Widget createPropertyWidgetFrom(Property property) {
15+
for (final factory in _factories) {
16+
if (factory.isPropertyContain(property)) {
17+
return factory.createPropertyWidget(property);
18+
}
19+
}
20+
21+
throw 'Value(${property.value()}) property is not support.';
22+
}
23+
24+
Iterable<Widget> createListPropertyWidgetsFrom(
25+
Iterable<Property> properties,
26+
) sync* {
27+
for (final property in properties) {
28+
yield createPropertyWidgetFrom(property);
29+
}
30+
}
31+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import 'package:flutter/widgets.dart';
2+
3+
import '../../../pattern/property.dart';
4+
5+
abstract class PropertyWidgetFactory<T> {
6+
Widget createPropertyWidget(Property property);
7+
8+
bool isPropertyContain(Property value);
9+
}

0 commit comments

Comments
 (0)