Skip to content

Commit 39e2264

Browse files
committed
Add timelines components temporary
1 parent d8a7d27 commit 39e2264

9 files changed

+685
-19
lines changed

example/lib/main.dart

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,86 @@ class MyHomePage extends StatefulWidget {
2828
}
2929

3030
class _MyHomePageState extends State<MyHomePage> {
31+
void _addEvent() {
32+
// TODO: implements
33+
}
34+
3135
@override
3236
Widget build(BuildContext context) {
33-
return Container();
37+
return TimelinesTheme(
38+
data: TimelinesThemeData(),
39+
child: Scaffold(
40+
appBar: AppBar(
41+
title: Text(widget.title),
42+
),
43+
body: ListView.builder(
44+
shrinkWrap: true,
45+
itemBuilder: (context, index) {
46+
if (index == 20) {
47+
return TimelinesTheme(
48+
data: TimelinesThemeData.horizontal(),
49+
child: SizedBox(
50+
height: 100,
51+
child: ListView.builder(
52+
scrollDirection: Axis.horizontal,
53+
shrinkWrap: true,
54+
itemBuilder: (context, index) {
55+
return TimelinesTile(
56+
child: Card(
57+
child: Text("BYE"),
58+
),
59+
);
60+
},
61+
),
62+
),
63+
);
64+
}
65+
66+
final child = Padding(
67+
padding: const EdgeInsets.all(8.0),
68+
child: Card(
69+
child: Container(
70+
padding: EdgeInsets.all(20.0),
71+
width: 200.0,
72+
child: Text(
73+
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
74+
overflow: TextOverflow.ellipsis,
75+
maxLines: 4,
76+
),
77+
),
78+
),
79+
);
80+
if (index == 3) {
81+
return TimelinesTile(
82+
child: child,
83+
eventPosition: 0.5,
84+
eventChild: CircleIndicator(
85+
child: Padding(
86+
padding: const EdgeInsets.all(4.0),
87+
child: CircularProgressIndicator(
88+
strokeWidth: 2.0,
89+
valueColor: AlwaysStoppedAnimation(Colors.white),
90+
),
91+
),
92+
),
93+
);
94+
}
95+
96+
return TimelinesTile(
97+
child: child,
98+
eventPosition: 0.5,
99+
drawStartLine: index > 0,
100+
drawEndLine: index < 19,
101+
);
102+
},
103+
itemCount: 21,
104+
),
105+
floatingActionButton: FloatingActionButton(
106+
onPressed: _addEvent,
107+
tooltip: 'Increment',
108+
child: Icon(Icons.add),
109+
),
110+
),
111+
);
34112
}
35113
}

lib/src/timelines_event.dart

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:timelines/timelines.dart';
3+
4+
import 'timelines_indicators.dart';
5+
import 'timelines_line.dart';
6+
7+
class TimelinesEvent extends StatelessWidget {
8+
/// TODO
9+
final Axis direction;
10+
11+
/// TODO rename ? childPosition, point, childPoint, ....
12+
/// 0-1
13+
final double position;
14+
15+
/// TODO
16+
final TimelinesLineStyle lineStyle;
17+
18+
/// TODO
19+
final bool drawStartLine;
20+
21+
/// TODO
22+
final bool drawEndLine;
23+
24+
/// The widget below this widget in the tree.
25+
///
26+
/// {@macro flutter.widgets.child}
27+
final Widget child;
28+
29+
const TimelinesEvent({
30+
Key key,
31+
this.direction,
32+
this.position = 0.5,
33+
this.lineStyle = TimelinesLineStyle.solid,
34+
this.drawStartLine = true,
35+
this.drawEndLine = true,
36+
@required this.child,
37+
}) : assert(0 <= position && position <= 1),
38+
super(key: key);
39+
40+
TimelinesEvent.circle({
41+
Key key,
42+
Axis direction,
43+
double position = 0.5,
44+
TimelinesLineStyle lineStyle,
45+
bool drawStartLine = true,
46+
bool drawEndLine = true,
47+
double indicatorSize = 15.0,
48+
Widget indicatorChild,
49+
}) : this(
50+
key: key,
51+
direction: direction,
52+
position: position,
53+
lineStyle: lineStyle,
54+
drawStartLine: drawStartLine,
55+
drawEndLine: drawEndLine,
56+
child: CircleIndicator(
57+
size: indicatorSize,
58+
child: indicatorChild,
59+
),
60+
);
61+
62+
@override
63+
Widget build(BuildContext context) {
64+
final direction = this.direction ?? TimelinesTheme.of(context).direction;
65+
Widget result = child;
66+
67+
/// TODO line from style
68+
/// if (lineStyle ... )
69+
final startLine = SolidLine(direction: direction);
70+
final endLine = SolidLine(direction: direction);
71+
72+
switch (direction) {
73+
case Axis.vertical:
74+
result = Column(
75+
mainAxisSize: MainAxisSize.min,
76+
children: [
77+
Flexible(
78+
flex: (position * 10).toInt(),
79+
child: startLine ?? TransparentLine(),
80+
),
81+
child,
82+
Flexible(
83+
flex: ((1 - position) * 10).toInt(),
84+
child: endLine ?? TransparentLine(),
85+
),
86+
],
87+
);
88+
break;
89+
case Axis.horizontal:
90+
result = Row(
91+
mainAxisSize: MainAxisSize.min,
92+
children: [
93+
Flexible(
94+
flex: (position * 10).toInt(),
95+
child: startLine ?? TransparentLine(),
96+
),
97+
child,
98+
Flexible(
99+
flex: ((1 - position) * 10).toInt(),
100+
child: endLine ?? TransparentLine(),
101+
),
102+
],
103+
);
104+
break;
105+
}
106+
107+
return result;
108+
}
109+
}
110+
111+
class TransparentLine extends StatelessWidget {
112+
const TransparentLine();
113+
114+
@override
115+
Widget build(BuildContext context) {
116+
return Container();
117+
}
118+
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import 'dart:ui';
2+
3+
import 'package:flutter/foundation.dart';
4+
import 'package:flutter/material.dart';
5+
import 'package:flutter/widgets.dart';
6+
import 'package:timelines/src/timelines_theme.dart';
7+
8+
/// Controls the default color and size of indicators in a widget subtree.
9+
///
10+
/// The timelines indicator theme is honored by [CircleIndicator] and [T O D O] widgets.
11+
class TimelinesIndicatorTheme extends InheritedTheme {
12+
/// Creates an timelines indicator theme that controls the color and size of descendant widgets.
13+
///
14+
/// Both [data] and [child] arguments must not be null.
15+
const TimelinesIndicatorTheme({
16+
Key key,
17+
@required this.data,
18+
@required Widget child,
19+
}) : assert(data != null),
20+
assert(child != null),
21+
super(key: key, child: child);
22+
23+
/// The color and size to use for timelines indicators in this subtree.
24+
final TimelinesIndicatorThemeData data;
25+
26+
/// The data from the closest instance of this class that encloses the given
27+
/// context.
28+
///
29+
/// Defaults to the current [TimelinesThemeData.indicatorTheme].
30+
///
31+
/// Typical usage is as follows:
32+
///
33+
/// ```dart
34+
/// TimelinesIndicatorThemeData theme = TimelinesIndicatorTheme.of(context);
35+
/// ```
36+
static TimelinesIndicatorThemeData of(BuildContext context) {
37+
final TimelinesIndicatorThemeData timelinesIndicatorThemeData =
38+
_getInheritedTimelinesIndicatorThemeData(context).resolve(context);
39+
return timelinesIndicatorThemeData.isConcrete
40+
? timelinesIndicatorThemeData
41+
: timelinesIndicatorThemeData.copyWith(
42+
size: timelinesIndicatorThemeData.size ?? const TimelinesIndicatorThemeData.fallback().size,
43+
color: timelinesIndicatorThemeData.color ?? const TimelinesIndicatorThemeData.fallback().color,
44+
);
45+
}
46+
47+
static TimelinesIndicatorThemeData _getInheritedTimelinesIndicatorThemeData(BuildContext context) {
48+
final TimelinesIndicatorTheme timelinesIndicatorTheme =
49+
context.dependOnInheritedWidgetOfExactType<TimelinesIndicatorTheme>();
50+
return timelinesIndicatorTheme?.data ?? const TimelinesIndicatorThemeData.fallback();
51+
}
52+
53+
@override
54+
bool updateShouldNotify(TimelinesIndicatorTheme oldWidget) => data != oldWidget.data;
55+
56+
@override
57+
Widget wrap(BuildContext context, Widget child) {
58+
final TimelinesIndicatorTheme iconTheme = context.findAncestorWidgetOfExactType<TimelinesIndicatorTheme>();
59+
return identical(this, iconTheme) ? child : TimelinesIndicatorTheme(data: data, child: child);
60+
}
61+
62+
@override
63+
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
64+
super.debugFillProperties(properties);
65+
data.debugFillProperties(properties);
66+
}
67+
}
68+
69+
/// Defines the color and size of indicators.
70+
///
71+
/// Used by [TimelinesIndicatorTheme] to control the color and size of indicators in a
72+
/// widget subtree.
73+
///
74+
/// To obtain the current timelines indicator theme, use [TimelinesIndicatorTheme.of]. To convert an timelines indicator
75+
/// theme to a version with all the fields filled in, use [new TimelinesIndicatorThemeData.fallback].
76+
@immutable
77+
class TimelinesIndicatorThemeData with Diagnosticable {
78+
/// Creates an timelines indicator theme data.
79+
const TimelinesIndicatorThemeData({this.color, this.size});
80+
81+
/// Creates an timelines indicator them with some reasonable default values.
82+
///
83+
/// The [color] is blue and the [size] is 15.0.
84+
const TimelinesIndicatorThemeData.fallback()
85+
: color = Colors.blue,
86+
size = 15.0;
87+
88+
/// Creates a copy of this timelines indicator theme but with the given fields replaced with
89+
/// the new values.
90+
TimelinesIndicatorThemeData copyWith({Color color, double opacity, double size}) {
91+
return TimelinesIndicatorThemeData(
92+
color: color ?? this.color,
93+
size: size ?? this.size,
94+
);
95+
}
96+
97+
/// Called by [TimelinesIndicatorTheme.of] to convert this instance to an [TimelinesINdicatorThemeData]
98+
/// that fits the given [BuildContext].
99+
///
100+
/// This method gives the ambient [TimelinesIndicatorThemeData] a chance to update itself,
101+
/// after it's been retrieved by [TimelinesIndicatorTheme.of], and before being returned as
102+
/// the final result.
103+
///
104+
/// The default implementation returns this [TimelinesIndicatorThemeData] as-is.
105+
TimelinesIndicatorThemeData resolve(BuildContext context) => this;
106+
107+
/// Whether all the properties of this object are non-null.
108+
bool get isConcrete => color != null && size != null;
109+
110+
/// The default color for indicators.
111+
final Color color;
112+
113+
/// The default size for indicators.
114+
final double size;
115+
116+
/// Linearly interpolate between two themes.
117+
///
118+
/// {@macro dart.ui.shadow.lerp}
119+
static TimelinesIndicatorThemeData lerp(TimelinesIndicatorThemeData a, TimelinesIndicatorThemeData b, double t) {
120+
assert(t != null);
121+
return TimelinesIndicatorThemeData(
122+
color: Color.lerp(a?.color, b?.color, t),
123+
size: lerpDouble(a?.size, b?.size, t),
124+
);
125+
}
126+
127+
@override
128+
bool operator ==(Object other) {
129+
if (other.runtimeType != runtimeType) return false;
130+
return other is TimelinesIndicatorThemeData && other.color == color && other.size == size;
131+
}
132+
133+
@override
134+
int get hashCode => hashValues(color, size);
135+
136+
@override
137+
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
138+
super.debugFillProperties(properties);
139+
properties.add(ColorProperty('color', color, defaultValue: null, level: DiagnosticLevel.debug));
140+
properties.add(DoubleProperty('size', size, defaultValue: null, level: DiagnosticLevel.debug));
141+
}
142+
}

lib/src/timelines_indicators.dart

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:timelines/src/timelines_indicator_theme.dart';
3+
4+
class CircleIndicator extends StatelessWidget {
5+
final double size;
6+
7+
final Color color;
8+
9+
final Widget child;
10+
11+
const CircleIndicator({
12+
Key key,
13+
this.size = 15.0,
14+
this.color,
15+
this.child,
16+
}) : super(key: key);
17+
18+
@override
19+
Widget build(BuildContext context) {
20+
final color = this.color ?? TimelinesIndicatorTheme.of(context).color;
21+
return Container(
22+
width: size,
23+
height: size,
24+
child: child,
25+
decoration: BoxDecoration(
26+
shape: BoxShape.circle,
27+
color: color,
28+
),
29+
);
30+
}
31+
}

0 commit comments

Comments
 (0)