Skip to content
This repository was archived by the owner on Mar 17, 2025. It is now read-only.

Commit 68a8b7f

Browse files
committed
setCursor
1 parent e160067 commit 68a8b7f

9 files changed

Lines changed: 130 additions & 64 deletions

File tree

example/flutter_01.png

165 KB
Loading

example/lib/main.dart

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import 'package:example/state_visualizer.dart';
21
import 'package:flutter/material.dart';
32
import 'package:interactive_timeline/interactive_timeline.dart';
43

@@ -32,10 +31,23 @@ class MyHomePage extends StatefulWidget {
3231
}
3332

3433
class _MyHomePageState extends State<MyHomePage> {
35-
InteractiveTimelineCubit timelineCubit = InteractiveTimelineCubit(
36-
minCursor: DateTime.now().subtract(Duration(hours: 1)),
37-
maxCursor: DateTime.now().add(Duration(hours: 1)),
38-
);
34+
InteractiveTimelineCubit timelineCubit = InteractiveTimelineCubit();
35+
36+
@override
37+
void initState() {
38+
// TODO: implement initState
39+
super.initState();
40+
// after build
41+
WidgetsBinding.instance.addPostFrameCallback((_) {
42+
timelineCubit.setMinMax(
43+
minCursor: DateTime.now().subtract(Duration(hours: 1)),
44+
maxCursor: DateTime.now().add(Duration(hours: 1)),
45+
);
46+
timelineCubit.setCursor(
47+
DateTime.now().subtract(Duration(minutes: 30)),
48+
);
49+
});
50+
}
3951

4052
@override
4153
Widget build(BuildContext context) {
@@ -47,7 +59,7 @@ class _MyHomePageState extends State<MyHomePage> {
4759
child: Column(
4860
mainAxisAlignment: MainAxisAlignment.center,
4961
children: <Widget>[
50-
StateVisualizer(cubit: timelineCubit),
62+
InteractiveTimelineDebug(cubit: timelineCubit),
5163
InteractiveTimeline(
5264
width: MediaQuery.of(context).size.width,
5365
height: 100,

example/lib/state_visualizer.dart

Lines changed: 0 additions & 36 deletions
This file was deleted.

lib/interactive_timeline.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ library interactive_timeline;
66
export 'src/cubit.dart';
77
export 'src/widget.dart';
88
export 'src/utils.dart';
9+
export 'src/debug.dart';

lib/src/cubit.dart

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'dart:math';
44
import 'package:equatable/equatable.dart';
55
import 'package:flutter/material.dart';
66
import 'package:flutter_bloc/flutter_bloc.dart';
7+
import 'package:interactive_timeline/src/utils.dart' as utils;
78

89
// timeline cubit
910
class InteractiveTimelineCubit extends Cubit<InteractiveTimelineState> {
@@ -23,11 +24,7 @@ class InteractiveTimelineCubit extends Cubit<InteractiveTimelineState> {
2324
minCursor,
2425
maxCursor,
2526
}) : super(
26-
InteractiveTimelineState.initializeAtTime(
27-
initialTime ?? DateTime.now(),
28-
minCursor,
29-
maxCursor,
30-
),
27+
InteractiveTimelineState.initializeAtTime(initialTime ?? DateTime.now()),
3128
);
3229

3330
double _restrictZoomLevel(double secondsPerScreenWidth) {
@@ -104,8 +101,21 @@ class InteractiveTimelineCubit extends Cubit<InteractiveTimelineState> {
104101
}
105102
}
106103

107-
// TODO: Using null won't clear the variables
108-
void setMinMax({DateTime? min, DateTime? max}) => emit(state.overwrite(minCursor: min, maxCursor: max));
104+
void setMinMax({DateTime? minCursor, DateTime? maxCursor}) {
105+
var newState = state.setMinMaxCursor(minCursor: minCursor, maxCursor: maxCursor);
106+
newState = newState.overwrite(
107+
middleCursor: newState.cropMinMaxCursor(newState.middleCursor),
108+
);
109+
emit(newState);
110+
}
111+
112+
void setCursor(DateTime cursor) {
113+
emit(
114+
state.overwrite(
115+
middleCursor: state.cropMinMaxCursor(cursor),
116+
),
117+
);
118+
}
109119

110120
void _tickTimer(Duration duration) {
111121
if (!state.isInteracting) {
@@ -123,12 +133,14 @@ class InteractiveTimelineCubit extends Cubit<InteractiveTimelineState> {
123133
}
124134
}
125135

126-
void initialize(double width, double height) {
136+
void initialize(double width, double height, [DateTime? minCursor, DateTime? maxCursor]) {
127137
emit(state.overwrite(
128138
secondsPerScreenWidth: initialZoomLevel, // default zoom level
129139
middleCursor: initialTime,
130140
width: width,
131141
height: height,
142+
minCursor: minCursor,
143+
maxCursor: maxCursor,
132144
));
133145
}
134146
}
@@ -167,24 +179,36 @@ class InteractiveTimelineState extends Equatable {
167179
@override
168180
List<Object> get props => [width, height, secondsPerPixel, secondsPerScreenWidth, secondsPerScreenWidthBeforeZoom, middleCursor, leftCursor, rightCursor, isPlaying, isInteracting];
169181

170-
static InteractiveTimelineState initializeAtTime(DateTime time, DateTime? minCursor, DateTime? maxCursor) {
182+
static InteractiveTimelineState initializeAtTime(DateTime time) {
171183
return InteractiveTimelineState(
172-
width: 0,
173-
height: 0,
174-
secondsPerPixel: 0,
175-
secondsPerScreenWidth: 0,
176-
secondsPerScreenWidthBeforeZoom: 0,
184+
width: 1,
185+
height: 1,
186+
secondsPerPixel: 1,
187+
secondsPerScreenWidth: 1,
188+
secondsPerScreenWidthBeforeZoom: 1,
177189
middleCursor: time,
178190
leftCursor: time,
179191
rightCursor: time,
180-
minCursor: minCursor,
181-
maxCursor: maxCursor,
192+
minCursor: null,
193+
maxCursor: null,
182194
playTimer: null,
183195
isPlaying: false,
184196
isInteracting: false,
185197
);
186198
}
187199

200+
bool insideMinMaxCursor(DateTime cursor, [DateTime? minCursor, DateTime? maxCursor]) => utils.insideMinMaxCursor(
201+
cursor,
202+
minCursor ?? this.minCursor,
203+
maxCursor ?? this.maxCursor,
204+
);
205+
206+
DateTime cropMinMaxCursor(DateTime cursor, [DateTime? minCursor, DateTime? maxCursor]) => utils.cropMinMaxCursor(
207+
cursor,
208+
minCursor ?? this.minCursor,
209+
maxCursor ?? this.maxCursor,
210+
);
211+
188212
DateTime getLeftCursor(double width, double secondsPerPixel) {
189213
return middleCursor.subtract(
190214
Duration(milliseconds: ((width / 2) * secondsPerPixel * 1000).toInt()),
@@ -197,10 +221,23 @@ class InteractiveTimelineState extends Equatable {
197221
);
198222
}
199223

200-
bool insideMinMaxCursor(DateTime time) {
201-
if (minCursor != null) if (time.isBefore(minCursor!)) return false;
202-
if (maxCursor != null) if (time.isAfter(maxCursor!)) return false;
203-
return true;
224+
// minCursor and maxCursor should be changable to null (.overwrite would fall back when passed null)
225+
InteractiveTimelineState setMinMaxCursor({DateTime? minCursor, DateTime? maxCursor}) {
226+
return InteractiveTimelineState(
227+
width: width,
228+
height: height,
229+
secondsPerPixel: secondsPerPixel,
230+
secondsPerScreenWidth: secondsPerScreenWidth,
231+
secondsPerScreenWidthBeforeZoom: secondsPerScreenWidthBeforeZoom,
232+
middleCursor: middleCursor,
233+
leftCursor: leftCursor,
234+
rightCursor: rightCursor,
235+
minCursor: minCursor,
236+
maxCursor: maxCursor,
237+
playTimer: playTimer,
238+
isPlaying: isPlaying,
239+
isInteracting: isInteracting,
240+
);
204241
}
205242

206243
InteractiveTimelineState overwrite({

lib/src/debug.dart

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:interactive_timeline/interactive_timeline.dart';
3+
4+
class InteractiveTimelineDebug extends StatelessWidget {
5+
const InteractiveTimelineDebug({
6+
Key? key,
7+
required this.cubit,
8+
}) : super(key: key);
9+
final InteractiveTimelineCubit cubit;
10+
11+
@override
12+
Widget build(BuildContext context) {
13+
return InteractiveTimelineBlocBuilder(
14+
bloc: cubit,
15+
builder: (context, state) {
16+
return Column(
17+
children: [
18+
Text('width: ${state.width}'),
19+
Text('height: ${state.height}'),
20+
Text('secondsPerPixel: ${state.secondsPerPixel}'),
21+
Text('secondsPerScreenWidth: ${state.secondsPerScreenWidth}'),
22+
Text('secondsPerScreenWidthBeforeZoom: ${state.secondsPerScreenWidthBeforeZoom}'),
23+
Text('middleCursor: ${state.middleCursor}'),
24+
Text('leftCursor: ${state.leftCursor}'),
25+
Text('rightCursor: ${state.rightCursor}'),
26+
Text('minCursor: ${state.minCursor}'),
27+
Text('maxCursor: ${state.maxCursor}'),
28+
Text('playTimer: ${state.playTimer}'),
29+
Text('isPlaying: ${state.isPlaying}'),
30+
Text('isInteracting: ${state.isInteracting}'),
31+
],
32+
);
33+
},
34+
);
35+
}
36+
}

lib/src/utils.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,15 @@ class TimelineRenderOptions {
4242
this.candleGroups = defaultCandleGroups,
4343
});
4444
}
45+
46+
bool insideMinMaxCursor(DateTime time, DateTime? minCursor, DateTime? maxCursor) {
47+
if (minCursor != null) if (time.isBefore(minCursor)) return false;
48+
if (maxCursor != null) if (time.isAfter(maxCursor)) return false;
49+
return true;
50+
}
51+
52+
DateTime cropMinMaxCursor(DateTime cursor, DateTime? minCursor, DateTime? maxCursor) {
53+
if (minCursor != null) if (cursor.isBefore(minCursor)) return minCursor;
54+
if (maxCursor != null) if (cursor.isAfter(maxCursor)) return maxCursor;
55+
return cursor;
56+
}

lib/src/widget.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ class InteractiveTimeline extends StatefulWidget {
1010
TimelineRenderOptions renderOptions;
1111
EdgeInsets padding;
1212
Color color;
13+
DateTime? minCursor;
14+
DateTime? maxCursor;
1315
InteractiveTimeline({
1416
Key? key,
1517
required this.width,
@@ -18,6 +20,8 @@ class InteractiveTimeline extends StatefulWidget {
1820
this.renderOptions = const TimelineRenderOptions(),
1921
this.padding = const EdgeInsets.all(0),
2022
this.color = Colors.transparent,
23+
this.minCursor,
24+
this.maxCursor,
2125
}) : super(key: key);
2226

2327
@override
@@ -27,7 +31,7 @@ class InteractiveTimeline extends StatefulWidget {
2731
class _InteractiveTimelineState extends State<InteractiveTimeline> {
2832
@override
2933
void initState() {
30-
widget.cubit.initialize(widget.width, widget.height);
34+
widget.cubit.initialize(widget.width, widget.height, widget.minCursor, widget.maxCursor);
3135
super.initState();
3236
}
3337

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: interactive_timeline
22
description: Draggable and zoomable interactive timeline.
3-
version: 1.0.0-dev.3
3+
version: 1.0.0-dev.4
44
# homepage: https://www.example.com
55

66
environment:

0 commit comments

Comments
 (0)