Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions lib/src/ui/custom_widgets/current_time_mark_painter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_customizable_calendar/src/ui/themes/themes.dart';

class CurrentTimeMarkPainter extends CustomPainter {
const CurrentTimeMarkPainter({
required this.currentTime,
required this.theme,
}) : super(repaint: currentTime);

final ValueListenable<DateTime> currentTime;

final TimeMarkTheme theme;

@override
void paint(Canvas canvas, Size size) {
final secondExtent = size.height / Duration.secondsPerDay;
final dayDate = DateUtils.dateOnly(currentTime.value);
final timeDiff = currentTime.value.difference(dayDate);
final currentTimeOffset = timeDiff.inSeconds * secondExtent;
final dy = currentTimeOffset - theme.strokeWidth / 2;
final lineLength = theme.drawOnEventArea ? size.width : theme.length;

canvas.drawLine(
Offset(0, dy),
Offset(lineLength, dy),
theme.painter,
);
}

@override
bool shouldRepaint(covariant CurrentTimeMarkPainter oldDelegate) =>
theme != oldDelegate.theme || currentTime != oldDelegate.currentTime;
}
119 changes: 119 additions & 0 deletions lib/src/ui/custom_widgets/event_area_hour_line_painter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import 'package:flutter/material.dart';
import 'package:flutter_customizable_calendar/src/ui/themes/themes.dart';
import 'package:flutter_customizable_calendar/src/utils/utils.dart';

import 'current_time_mark_painter.dart';

/// It displays a time scale of a day view (with hours and minutes marks).
class EventAreaHourLinePainter extends StatefulWidget {
/// Creates view of a time scale.
const EventAreaHourLinePainter({
super.key,
this.theme = const TimeScaleTheme(),
});

/// Customization params for the view
final TimeScaleTheme theme;

@override
State<EventAreaHourLinePainter> createState() => _EventAreaHourLinePainterState();
}

class _EventAreaHourLinePainterState extends State<EventAreaHourLinePainter> {
final _clock = ClockNotifier.instance();

@override
Widget build(BuildContext context) {
return CustomPaint(
size: Size(
MediaQuery.sizeOf(context).width,
widget.theme.hourExtent * Duration.hoursPerDay,
),
painter: _hourLinePainter,
foregroundPainter: widget.theme.currentTimeMarkTheme.drawOnEventArea
? _currentTimeMark
: null,
);
}

@override
void dispose() {
_clock.dispose();
super.dispose();
}

CustomPainter get _hourLinePainter => _HourLinePainter(
dayDate: _clock.value,
theme: widget.theme,
);

CustomPainter get _currentTimeMark => CurrentTimeMarkPainter(
currentTime: _clock,
theme: widget.theme.currentTimeMarkTheme,
);
}

class _HourLinePainter extends CustomPainter {
final TimeScaleTheme theme;
final DateTime dayDate;

_HourLinePainter({required this.theme, required this.dayDate});

@override
void paint(Canvas canvas, Size size) {
final hourExtent = size.height / Duration.hoursPerDay;
final quarterHeight = hourExtent / 4;

for (var hour = 0; hour < Duration.hoursPerDay; hour++) {
final hourOffset = hourExtent * hour;

// Draw half-hour marks
if (theme.drawHourMarks && theme.hourMarkTheme.drawOnEventArea) {
final line = theme.hourMarkTheme;
final dy = hourOffset - line.strokeWidth / 2;

// Make sure the line has a start and end point that are different
canvas.drawLine(
Offset(0, dy), // Start point
Offset(size.width, dy), // End point
line.painter,
);
}

// Draw half-hour marks
if (theme.drawHalfHourMarks && theme.halfHourMarkTheme.drawOnEventArea) {
final line = theme.halfHourMarkTheme;
final dy = hourOffset + quarterHeight * 2 - line.strokeWidth / 2;

canvas.drawLine(
Offset(0, dy),
Offset(size.width, dy),
line.painter,
);
}

if (theme.drawQuarterHourMarks && theme.quarterHourMarkTheme.drawOnEventArea) {
final line = theme.quarterHourMarkTheme;
final dy1 = hourOffset + quarterHeight - line.strokeWidth / 2;
final dy2 = hourOffset + quarterHeight * 3 - line.strokeWidth / 2;

canvas
..drawLine(
Offset(0, dy1),
Offset(0 + size.width, dy1),
line.painter,
)
..drawLine(
Offset(0, dy2),
Offset(0 + size.width, dy2),
line.painter,
);
}
}
}

@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
33 changes: 2 additions & 31 deletions lib/src/ui/custom_widgets/time_scale.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_customizable_calendar/src/ui/themes/themes.dart';
import 'package:flutter_customizable_calendar/src/utils/utils.dart';
import 'package:flutter_customizable_calendar/src/ui/custom_widgets/current_time_mark_painter.dart';

/// It displays a time scale of a day view (with hours and minutes marks).
class TimeScale extends StatefulWidget {
Expand Down Expand Up @@ -48,7 +49,7 @@ class _TimeScaleState extends State<TimeScale> {
theme: widget.theme,
);

CustomPainter get _currentTimeMark => _CurrentTimeMarkPainter(
CustomPainter get _currentTimeMark => CurrentTimeMarkPainter(
currentTime: _clock,
theme: widget.theme.currentTimeMarkTheme,
);
Expand Down Expand Up @@ -151,33 +152,3 @@ class _ScalePainter extends CustomPainter {
}
}
}

class _CurrentTimeMarkPainter extends CustomPainter {
const _CurrentTimeMarkPainter({
required this.currentTime,
required this.theme,
}) : super(repaint: currentTime);

final ValueListenable<DateTime> currentTime;

final TimeMarkTheme theme;

@override
void paint(Canvas canvas, Size size) {
final secondExtent = size.height / Duration.secondsPerDay;
final dayDate = DateUtils.dateOnly(currentTime.value);
final timeDiff = currentTime.value.difference(dayDate);
final currentTimeOffset = timeDiff.inSeconds * secondExtent;
final dy = currentTimeOffset - theme.strokeWidth / 2;

canvas.drawLine(
Offset(0, dy),
Offset(theme.length, dy),
theme.painter,
);
}

@override
bool shouldRepaint(covariant _CurrentTimeMarkPainter oldDelegate) =>
theme != oldDelegate.theme || currentTime != oldDelegate.currentTime;
}
8 changes: 7 additions & 1 deletion lib/src/ui/themes/time_mark_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ class TimeMarkTheme extends Equatable {
this.color = Colors.grey,
this.strokeWidth = 2,
this.strokeCap = StrokeCap.square,
this.drawOnEventArea = false
});

/// Length of the line
/// Length of the line on the time scale
final double length;

/// Color of the line
Expand All @@ -22,6 +23,9 @@ class TimeMarkTheme extends Equatable {
/// The kind of finish to place on the end of line
final StrokeCap strokeCap;

/// Enable the mark on the event area
final bool drawOnEventArea;

/// A painter which contains the given parameters
Paint get painter => Paint()
..color = color
Expand All @@ -43,12 +47,14 @@ class TimeMarkTheme extends Equatable {
Color? color,
double? strokeWidth,
StrokeCap? strokeCap,
bool? drawOnEventArea,
}) {
return TimeMarkTheme(
length: length ?? this.length,
color: color ?? this.color,
strokeWidth: strokeWidth ?? this.strokeWidth,
strokeCap: strokeCap ?? this.strokeCap,
drawOnEventArea: drawOnEventArea ?? this.drawOnEventArea,
);
}
}
15 changes: 15 additions & 0 deletions lib/src/ui/themes/time_scale_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ class TimeScaleTheme extends Equatable {
length: 48,
color: Colors.red,
),
this.drawHourMarks = false,
this.hourMarkTheme = const TimeMarkTheme(
length: 0,
drawOnEventArea: true,
),
this.drawHalfHourMarks = true,
this.halfHourMarkTheme = const TimeMarkTheme(length: 16),
this.drawQuarterHourMarks = true,
Expand All @@ -45,6 +50,12 @@ class TimeScaleTheme extends Equatable {
/// Current time mark customization parameters
final TimeMarkTheme currentTimeMarkTheme;

/// Whether a hour mark is need to be shown or not
final bool drawHourMarks;

/// An hour mark customization theme
final TimeMarkTheme hourMarkTheme;

/// Whether a half of an hour mark is need to show
final bool drawHalfHourMarks;

Expand Down Expand Up @@ -86,6 +97,8 @@ class TimeScaleTheme extends Equatable {
double? width,
double? hourExtent,
TimeMarkTheme? currentTimeMarkTheme,
bool? drawHourMarks,
TimeMarkTheme? hourMarkTheme,
bool? drawHalfHourMarks,
TimeMarkTheme? halfHourMarkTheme,
bool? drawQuarterHourMarks,
Expand All @@ -98,6 +111,8 @@ class TimeScaleTheme extends Equatable {
width: width ?? this.width,
hourExtent: hourExtent ?? this.hourExtent,
currentTimeMarkTheme: currentTimeMarkTheme ?? this.currentTimeMarkTheme,
drawHourMarks: drawHourMarks ?? this.drawHourMarks,
hourMarkTheme: hourMarkTheme ?? this.hourMarkTheme,
drawHalfHourMarks: drawHalfHourMarks ?? this.drawHalfHourMarks,
halfHourMarkTheme: halfHourMarkTheme ?? this.halfHourMarkTheme,
drawQuarterHourMarks: drawQuarterHourMarks ?? this.drawQuarterHourMarks,
Expand Down
40 changes: 24 additions & 16 deletions lib/src/ui/views/days_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:flutter_customizable_calendar/src/domain/models/models.dart';
import 'package:flutter_customizable_calendar/src/ui/controllers/controllers.dart';
import 'package:flutter_customizable_calendar/src/ui/custom_widgets/all_days_events_list.dart';
import 'package:flutter_customizable_calendar/src/ui/custom_widgets/custom_widgets.dart';
import 'package:flutter_customizable_calendar/src/ui/custom_widgets/event_area_hour_line_painter.dart';
import 'package:flutter_customizable_calendar/src/ui/themes/themes.dart';
import 'package:flutter_customizable_calendar/src/utils/utils.dart';

Expand Down Expand Up @@ -627,22 +628,29 @@ class _DaysViewState<T extends FloatingCalendarEvent> extends State<DaysView<T>>
theme: theme.timeScaleTheme,
),
Expanded(
child: ColoredBox(
color: Colors.transparent, // Needs for hitTesting
child: EventsLayout<T>(
dayDate: dayDate,
viewType: CalendarView.days,
overlayKey: _overlayKey,
layoutsKeys: DaysViewKeys.layouts,
eventsKeys: DaysViewKeys.events,
timelineTheme: widget.timelineTheme,
breaks: widget.breaks,
events: _events,
elevatedEvent: _elevatedEvent,
onEventTap: widget.onEventTap,
eventBuilders: widget.eventBuilders,
),
),
child: Stack(
children: [
EventAreaHourLinePainter(
theme: theme.timeScaleTheme,
),
ColoredBox(
color: Colors.transparent, // Needs for hitTesting
child: EventsLayout<T>(
dayDate: dayDate,
viewType: CalendarView.days,
overlayKey: _overlayKey,
layoutsKeys: DaysViewKeys.layouts,
eventsKeys: DaysViewKeys.events,
timelineTheme: widget.timelineTheme,
breaks: widget.breaks,
events: _events,
elevatedEvent: _elevatedEvent,
onEventTap: widget.onEventTap,
eventBuilders: widget.eventBuilders,
),
),
],
)
),
],
),
Expand Down
36 changes: 21 additions & 15 deletions lib/src/ui/views/week_view/week_view_timeline_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_customizable_calendar/flutter_customizable_calendar.dart';
import 'package:flutter_customizable_calendar/src/ui/custom_widgets/all_days_events_list.dart';
import 'package:flutter_customizable_calendar/src/ui/custom_widgets/event_area_hour_line_painter.dart';
import 'package:flutter_customizable_calendar/src/ui/views/week_view/week_view_timeline_widget.dart';
import 'package:flutter_customizable_calendar/src/utils/utils.dart';

Expand Down Expand Up @@ -268,7 +269,6 @@ class _WeekViewTimelinePageState<T extends FloatingCalendarEvent>
WeekViewTimelineWidget(
days: weekDays,
scrollTo: (offset) {
if (offset == .0) return;
_timelineController.jumpTo(offset);
},
initialScrollOffset:
Expand Down Expand Up @@ -401,20 +401,26 @@ class _WeekViewTimelinePageState<T extends FloatingCalendarEvent>
bottom: widget.theme.padding.bottom,
),
color: Colors.transparent, // Needs for hitTesting
child: EventsLayout<T>(
// key: ValueKey(dayDate),
dayDate: dayDate,
eventBuilders: widget.eventBuilders,
viewType: CalendarView.week,
overlayKey: widget.overlayKey,
layoutsKeys: widget.layoutKeys,
eventsKeys: widget.eventKeys,
timelineTheme: widget.theme,
breaks: widget.breaks,
events: widget.events,
elevatedEvent: widget.elevatedEvent,
onEventTap: widget.onEventTap,
),
child: Stack(
children: [
EventAreaHourLinePainter(
theme: widget.theme.timeScaleTheme,
),
EventsLayout<T>(
key: ValueKey(dayDate),
dayDate: dayDate,
eventBuilders: widget.eventBuilders,
viewType: CalendarView.week,
overlayKey: widget.overlayKey,
layoutsKeys: widget.layoutKeys,
eventsKeys: widget.eventKeys,
timelineTheme: widget.theme,
breaks: widget.breaks,
events: widget.events,
elevatedEvent: widget.elevatedEvent,
onEventTap: widget.onEventTap,
),
])
),
),
);
Expand Down