1
0
mirror of https://github.com/flutter/samples.git synced 2025-11-13 00:08:24 +00:00
Files
samples/web/charts/flutter/lib/src/base_chart_state.dart
2019-05-07 13:32:08 -07:00

180 lines
5.5 KiB
Dart

// Copyright 2018 the Charts project authors. Please see the AUTHORS file
// for details.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'package:flutter_web_ui/ui.dart' show TextDirection;
import 'package:flutter_web/material.dart'
show
AnimationController,
BuildContext,
State,
TickerProviderStateMixin,
Widget;
import 'package:charts_common/common.dart' as common;
import 'package:flutter_web/widgets.dart'
show Directionality, LayoutId, CustomMultiChildLayout;
import 'behaviors/chart_behavior.dart'
show BuildableBehavior, ChartBehavior, ChartStateBehavior;
import 'base_chart.dart' show BaseChart;
import 'chart_container.dart' show ChartContainer;
import 'chart_state.dart' show ChartState;
import 'chart_gesture_detector.dart' show ChartGestureDetector;
import 'widget_layout_delegate.dart';
class BaseChartState<D> extends State<BaseChart<D>>
with TickerProviderStateMixin
implements ChartState {
// Animation
AnimationController _animationController;
double _animationValue = 0.0;
Widget _oldWidget;
ChartGestureDetector _chartGestureDetector;
bool _configurationChanged = false;
final autoBehaviorWidgets = <ChartBehavior>[];
final addedBehaviorWidgets = <ChartBehavior>[];
final addedCommonBehaviorsByRole = <String, common.ChartBehavior>{};
final addedSelectionChangedListenersByType =
<common.SelectionModelType, common.SelectionModelListener<D>>{};
final addedSelectionUpdatedListenersByType =
<common.SelectionModelType, common.SelectionModelListener<D>>{};
final _behaviorAnimationControllers =
<ChartStateBehavior, AnimationController>{};
static const chartContainerLayoutID = 'chartContainer';
@override
void initState() {
super.initState();
_animationController = new AnimationController(vsync: this)
..addListener(_animationTick);
}
@override
void requestRebuild() {
setState(() {});
}
@override
void markChartDirty() {
_configurationChanged = true;
}
@override
void resetChartDirtyFlag() {
_configurationChanged = false;
}
@override
bool get chartIsDirty => _configurationChanged;
/// Builds the common chart canvas widget.
Widget _buildChartContainer() {
final chartContainer = new ChartContainer<D>(
oldChartWidget: _oldWidget,
chartWidget: widget,
chartState: this,
animationValue: _animationValue,
rtl: Directionality.of(context) == TextDirection.rtl,
rtlSpec: widget.rtlSpec,
userManagedState: widget.userManagedState,
);
_oldWidget = widget;
final desiredGestures = widget.getDesiredGestures(this);
if (desiredGestures.isNotEmpty) {
_chartGestureDetector ??= new ChartGestureDetector();
return _chartGestureDetector.makeWidget(
context, chartContainer, desiredGestures);
} else {
return chartContainer;
}
}
@override
Widget build(BuildContext context) {
final chartWidgets = <LayoutId>[];
final idAndBehaviorMap = <String, BuildableBehavior>{};
// Add the common chart canvas widget.
chartWidgets.add(new LayoutId(
id: chartContainerLayoutID, child: _buildChartContainer()));
// Add widget for each behavior that can build widgets
addedCommonBehaviorsByRole.forEach((id, behavior) {
if (behavior is BuildableBehavior) {
assert(id != chartContainerLayoutID);
final buildableBehavior = behavior as BuildableBehavior;
idAndBehaviorMap[id] = buildableBehavior;
final widget = buildableBehavior.build(context);
chartWidgets.add(new LayoutId(id: id, child: widget));
}
});
final isRTL = Directionality.of(context) == TextDirection.rtl;
return new CustomMultiChildLayout(
delegate: new WidgetLayoutDelegate(
chartContainerLayoutID, idAndBehaviorMap, isRTL),
children: chartWidgets);
}
@override
void dispose() {
_animationController.dispose();
_behaviorAnimationControllers
.forEach((_, controller) => controller?.dispose());
_behaviorAnimationControllers.clear();
super.dispose();
}
@override
void setAnimation(Duration transition) {
_playAnimation(transition);
}
void _playAnimation(Duration duration) {
_animationController.duration = duration;
_animationController.forward(from: (duration == Duration.zero) ? 1.0 : 0.0);
_animationValue = _animationController.value;
}
void _animationTick() {
setState(() {
_animationValue = _animationController.value;
});
}
/// Get animation controller to be used by [behavior].
AnimationController getAnimationController(ChartStateBehavior behavior) {
_behaviorAnimationControllers[behavior] ??=
new AnimationController(vsync: this);
return _behaviorAnimationControllers[behavior];
}
/// Dispose of animation controller used by [behavior].
void disposeAnimationController(ChartStateBehavior behavior) {
final controller = _behaviorAnimationControllers.remove(behavior);
controller?.dispose();
}
}