• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'dart:math' as math;
6
7import 'package:flutter/material.dart';
8import 'package:flutter/rendering.dart';
9
10import '../rendering/src/sector_layout.dart';
11
12RenderBox initCircle() {
13  return RenderBoxToRenderSectorAdapter(
14    innerRadius: 25.0,
15    child: RenderSectorRing(padding: 0.0),
16  );
17}
18
19class SectorApp extends StatefulWidget {
20  @override
21  SectorAppState createState() => SectorAppState();
22}
23
24class SectorAppState extends State<SectorApp> {
25
26  final RenderBoxToRenderSectorAdapter sectors = initCircle();
27  final math.Random rand = math.Random(1);
28
29  List<double> wantedSectorSizes = <double>[];
30  List<double> actualSectorSizes = <double>[];
31  double get currentTheta => wantedSectorSizes.fold<double>(0.0, (double total, double value) => total + value);
32
33  void addSector() {
34    final double currentTheta = this.currentTheta;
35    if (currentTheta < kTwoPi) {
36      double deltaTheta;
37      if (currentTheta >= kTwoPi - (math.pi * 0.2 + 0.05))
38        deltaTheta = kTwoPi - currentTheta;
39      else
40        deltaTheta = math.pi * rand.nextDouble() / 5.0 + 0.05;
41      wantedSectorSizes.add(deltaTheta);
42      updateEnabledState();
43    }
44  }
45
46  void removeSector() {
47    if (wantedSectorSizes.isNotEmpty) {
48      wantedSectorSizes.removeLast();
49      updateEnabledState();
50    }
51  }
52
53  void doUpdates() {
54    int index = 0;
55    while (index < actualSectorSizes.length && index < wantedSectorSizes.length && actualSectorSizes[index] == wantedSectorSizes[index])
56      index += 1;
57    final RenderSectorRing ring = sectors.child;
58    while (index < actualSectorSizes.length) {
59      ring.remove(ring.lastChild);
60      actualSectorSizes.removeLast();
61    }
62    while (index < wantedSectorSizes.length) {
63      final Color color = Color(((0xFF << 24) + rand.nextInt(0xFFFFFF)) | 0x808080);
64      ring.add(RenderSolidColor(color, desiredDeltaTheta: wantedSectorSizes[index]));
65      actualSectorSizes.add(wantedSectorSizes[index]);
66      index += 1;
67    }
68  }
69
70  static RenderBox initSector(Color color) {
71    final RenderSectorRing ring = RenderSectorRing(padding: 1.0);
72    ring.add(RenderSolidColor(const Color(0xFF909090), desiredDeltaTheta: kTwoPi * 0.15));
73    ring.add(RenderSolidColor(const Color(0xFF909090), desiredDeltaTheta: kTwoPi * 0.15));
74    ring.add(RenderSolidColor(color, desiredDeltaTheta: kTwoPi * 0.2));
75    return RenderBoxToRenderSectorAdapter(
76      innerRadius: 5.0,
77      child: ring,
78    );
79  }
80  RenderBoxToRenderSectorAdapter sectorAddIcon = initSector(const Color(0xFF00DD00));
81  RenderBoxToRenderSectorAdapter sectorRemoveIcon = initSector(const Color(0xFFDD0000));
82
83  bool _enabledAdd = true;
84  bool _enabledRemove = false;
85  void updateEnabledState() {
86    setState(() {
87      _enabledAdd = currentTheta < kTwoPi;
88      _enabledRemove = wantedSectorSizes.isNotEmpty;
89    });
90  }
91
92  Widget buildBody() {
93    return Column(
94      children: <Widget>[
95        Container(
96          padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 25.0),
97          child: Row(
98            children: <Widget>[
99              RaisedButton(
100                onPressed: _enabledAdd ? addSector : null,
101                child: IntrinsicWidth(
102                  child: Row(
103                    children: <Widget>[
104                      Container(
105                        padding: const EdgeInsets.all(4.0),
106                        margin: const EdgeInsets.only(right: 10.0),
107                        child: WidgetToRenderBoxAdapter(renderBox: sectorAddIcon),
108                      ),
109                      const Text('ADD SECTOR'),
110                    ],
111                  ),
112                ),
113              ),
114              RaisedButton(
115                onPressed: _enabledRemove ? removeSector : null,
116                child: IntrinsicWidth(
117                  child: Row(
118                    children: <Widget>[
119                      Container(
120                        padding: const EdgeInsets.all(4.0),
121                        margin: const EdgeInsets.only(right: 10.0),
122                        child: WidgetToRenderBoxAdapter(renderBox: sectorRemoveIcon),
123                      ),
124                      const Text('REMOVE SECTOR'),
125                    ],
126                  ),
127                ),
128              ),
129            ],
130            mainAxisAlignment: MainAxisAlignment.spaceAround,
131          ),
132        ),
133        Expanded(
134          child: Container(
135            margin: const EdgeInsets.all(8.0),
136            decoration: BoxDecoration(
137              border: Border.all()
138            ),
139            padding: const EdgeInsets.all(8.0),
140            child: WidgetToRenderBoxAdapter(
141              renderBox: sectors,
142              onBuild: doUpdates,
143            ),
144          ),
145        ),
146      ],
147      mainAxisAlignment: MainAxisAlignment.spaceBetween,
148    );
149  }
150
151  @override
152  Widget build(BuildContext context) {
153    return MaterialApp(
154      theme: ThemeData.light(),
155      title: 'Sector Layout',
156      home: Scaffold(
157        appBar: AppBar(
158          title: const Text('Sector Layout in a Widget Tree'),
159        ),
160        body: buildBody(),
161      ),
162    );
163  }
164}
165
166void main() {
167  runApp(SectorApp());
168}
169