Skip to content

Commit

Permalink
Implement custom Calendar Event View to highlight deleted Events
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobkoerber committed Dec 17, 2024
1 parent 3fa09df commit 1d9e822
Show file tree
Hide file tree
Showing 8 changed files with 293 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import 'package:flutter/material.dart';

import 'package:campus_flutter/base/util/diagonalStripePattern/stripe_pattern_painter.dart';

/// source: https://github.com/LuuNgocLan/flutter-snippets/blob/main/flutter_stripe_canvas/lib/diagonal_stripe/diagonal_stripe_pattern_view.dart
class DiagonalStripePatternView extends StatelessWidget {
final double? stripeWidth;
final double? gapWidth;
final double? rotateDegree;
final Color? stripeColor;
final Color? bgColor;

const DiagonalStripePatternView({
super.key,
this.stripeColor,
this.stripeWidth,
this.gapWidth,
this.rotateDegree,
this.bgColor,
});

@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
/// Cut the excess border around the frame by using ClipRRect
return ClipRRect(
child: CustomPaint(
/// The screen size we grabbed a few lines earlie
/// default: Size.zero
size: Size(constraints.maxWidth, constraints.maxHeight),

/// use foregroundPainter as overlay mark
foregroundPainter: StripePatternPainter(
stripeColor: stripeColor ??
const Color(0xFF222222).withValues(alpha: 0.08),
bgColor: bgColor,
),
),
);
},
);
}
}
82 changes: 82 additions & 0 deletions lib/base/util/diagonalStripePattern/stripe_pattern_painter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import 'dart:math';

import 'package:flutter/material.dart';

/// source: https://github.com/LuuNgocLan/flutter-snippets/blob/main/flutter_stripe_canvas/lib/diagonal_stripe/stripe_pattern_painter.dart
class StripePatternPainter extends CustomPainter {
final double stripeWidth;
final double gapWidth;
final double rotateDegree;
final Color stripeColor;
final Color bgColor;

StripePatternPainter({
this.stripeWidth = 5.0,
this.gapWidth = 5.0,
this.rotateDegree = 45.0,
this.stripeColor = Colors.grey,
Color? bgColor,
}) : bgColor = bgColor ?? Colors.transparent;

@override
void paint(Canvas canvas, Size size) {
/// Expand canvas size
const offsetX = 0.0;
const offsetY = 0.0;
final width = size.width + offsetX * 2;
final height = size.height + offsetY * 2;

/// Shift canvas to top,left with offsetX,Y
canvas.translate(-offsetX, -offsetY);

/// Calculate the biggest diagonal of the screen.
final double diagonal = sqrt(width * width + height * height);

/// jointSize: distance from right edge of (i) stripe to right one of next stripe
final double jointSize = stripeWidth + gapWidth;

/// Calculate the number of iterations needed to cover the diagonal of the screen.
final int numIterations = (diagonal / jointSize).ceil();

/// convert degree to radian
final rotateRadian = pi / 180 * rotateDegree;

/// calculate the xOffset, yOffset according to the trigonometric formula
final xOffset = jointSize / sin(rotateRadian);
final yOffset = jointSize / sin(pi / 2 - rotateRadian);

/// config stroke paint object
final paint = Paint()
..color = stripeColor
..style = PaintingStyle.stroke
..strokeWidth = stripeWidth;
final path = Path();

/// setup the path
for (int i = 0; i < numIterations; i++) {
/// start point on Y axis -> xStart = 0
final double yStart = i * yOffset;

/// end point on X axis -> yEnd = 0
final double xEnd = i * xOffset;

/// make line start -> end
path.moveTo(0, yStart);
path.lineTo(xEnd, 0);
}

/// draw path on canvas by using paint object
canvas.drawPath(path, paint);

/// Fill the pattern area background with the patternColor.
final patternPaint = Paint()
..color = bgColor
..style = PaintingStyle.fill;
canvas.drawRect(Offset.zero & size, patternPaint);
}

@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return oldDelegate != this;
}
}
3 changes: 1 addition & 2 deletions lib/calendarComponent/model/calendar_data_source.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ class MeetingDataSource extends CalendarDataSource {
@override
String getSubject(int index) {
final calendarEvent = cast<CalendarEvent>(appointments![index])!;
final location = calendarEvent.locations.firstOrNull ?? "";
return "${calendarEvent.title}\n$location";
return calendarEvent.subject;
}

@override
Expand Down
11 changes: 10 additions & 1 deletion lib/calendarComponent/model/calendar_event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ class CalendarEvent extends Searchable {
}

String get timePeriod {
return "${DateFormat.Hm().format(startDate)} - ${DateFormat.Hm().format(endDate)}";
return "${DateFormat.Hm().format(
startDate,
)} - ${DateFormat.Hm().format(
endDate,
)}";
}

String _dateTimePeriod(BuildContext context) {
Expand Down Expand Up @@ -67,6 +71,11 @@ class CalendarEvent extends Searchable {
return status == "CANCEL";
}

String get subject {
final location = locations.firstOrNull ?? "";
return "$title\n$location";
}

void setColor(Color? color) {
this.color = color?.value;
}
Expand Down
9 changes: 9 additions & 0 deletions lib/calendarComponent/views/calendar_day_view.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'package:campus_flutter/calendarComponent/model/calendar_data_source.dart';
import 'package:campus_flutter/calendarComponent/model/calendar_event.dart';
import 'package:campus_flutter/calendarComponent/services/calendar_view_service.dart';
import 'package:campus_flutter/calendarComponent/viewModels/calendar_viewmodel.dart';
import 'package:campus_flutter/calendarComponent/views/calendar_event_view.dart';
import 'package:campus_flutter/calendarComponent/views/calendars_view.dart';
import 'package:campus_flutter/main.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -55,6 +57,13 @@ class CalendarDayView extends ConsumerWidget {
endHour: 22,
timeFormat: "HH:mm",
),
appointmentBuilder: (context, details) {
final calendarEvent = details.appointments.first as CalendarEvent;
return CalendarEventView(
calendarEvent: calendarEvent,
bounds: details.bounds,
);
},
),
),
),
Expand Down
128 changes: 128 additions & 0 deletions lib/calendarComponent/views/calendar_event_view.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import 'package:campus_flutter/base/util/diagonalStripePattern/diagonal_stripe_pattern_view.dart';
import 'package:campus_flutter/calendarComponent/model/calendar_event.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';

class CalendarEventView extends StatelessWidget {
const CalendarEventView({
super.key,
required this.calendarEvent,
required this.bounds,
this.isMonthly = false,
});

final CalendarEvent calendarEvent;
final Rect bounds;
final bool isMonthly;

@override
Widget build(BuildContext context) {
if (!(calendarEvent.isVisible ?? true)) {
return _hiddenCalendarEvent(context);
} else {
return _visibleCalendarEvent(context);
}
}

Widget _hiddenCalendarEvent(BuildContext context) {
return SizedBox(
height: bounds.height,
width: bounds.width,
child: Stack(
children: [
DiagonalStripePatternView(
stripeColor: calendarEvent.getColor(),
bgColor: calendarEvent.getColor().withValues(
alpha: Theme.of(context).brightness == Brightness.light
? 0.625
: 0.5,
),
),
_content(context),
],
),
);
}

Widget _visibleCalendarEvent(BuildContext context) {
return Container(
height: bounds.height,
width: bounds.width,
decoration: BoxDecoration(color: calendarEvent.getColor()),
child: _content(context),
);
}

Widget _content(BuildContext context) {
final padding = 2.5;
final style = Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.w600,
);

return Padding(
padding: EdgeInsets.only(
top: padding,
left: padding,
right: padding,
bottom: 2.5,
),
child: isMonthly
? Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: _text(style, padding, context),
),
_timePeriod(style),
],
)
: _text(style, padding, context),
);
}

Widget _text(
TextStyle? style,
double padding,
BuildContext context,
) {
return Text(
calendarEvent.subject,
style: style,
maxLines: _calculateLineLimit(style, padding, context),
);
}

Widget _timePeriod(TextStyle? style) {
return Text(
calendarEvent.timePeriod,
style: style,
maxLines: 1,
);
}

int? _calculateLineLimit(
TextStyle? style,
double padding,
BuildContext context,
) {
var absoluteHeight = bounds.height - padding * 2;

if (style == null) {
return null;
}

final lineHeight = (style.height ?? 0.0) * (style.fontSize ?? 0.0);

if (lineHeight == 0.0) {
return null;
}

if (isMonthly) {
absoluteHeight = absoluteHeight - lineHeight;
}

return (absoluteHeight / lineHeight).floor();
}
}
10 changes: 10 additions & 0 deletions lib/calendarComponent/views/calendar_month_view.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'package:campus_flutter/calendarComponent/model/calendar_data_source.dart';
import 'package:campus_flutter/calendarComponent/model/calendar_event.dart';
import 'package:campus_flutter/calendarComponent/services/calendar_view_service.dart';
import 'package:campus_flutter/calendarComponent/viewModels/calendar_viewmodel.dart';
import 'package:campus_flutter/calendarComponent/views/calendar_event_view.dart';
import 'package:campus_flutter/calendarComponent/views/calendars_view.dart';
import 'package:campus_flutter/main.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -59,6 +61,14 @@ class CalendarMonthView extends ConsumerWidget {
}
},
appointmentTimeTextFormat: "HH:mm",
appointmentBuilder: (context, details) {
final calendarEvent = details.appointments.first as CalendarEvent;
return CalendarEventView(
calendarEvent: calendarEvent,
bounds: details.bounds,
isMonthly: true,
);
},
),
),
),
Expand Down
9 changes: 9 additions & 0 deletions lib/calendarComponent/views/calendar_week_view.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'package:campus_flutter/calendarComponent/model/calendar_data_source.dart';
import 'package:campus_flutter/calendarComponent/model/calendar_event.dart';
import 'package:campus_flutter/calendarComponent/services/calendar_view_service.dart';
import 'package:campus_flutter/calendarComponent/viewModels/calendar_viewmodel.dart';
import 'package:campus_flutter/calendarComponent/views/calendar_event_view.dart';
import 'package:campus_flutter/calendarComponent/views/calendars_view.dart';
import 'package:campus_flutter/main.dart';
import 'package:campus_flutter/settingsComponent/views/settings_view.dart';
Expand Down Expand Up @@ -62,6 +64,13 @@ class CalendarWeekView extends ConsumerWidget {
endHour: 22,
timeFormat: "HH:mm",
),
appointmentBuilder: (context, details) {
final calendarEvent = details.appointments.first as CalendarEvent;
return CalendarEventView(
calendarEvent: calendarEvent,
bounds: details.bounds,
);
},
),
),
),
Expand Down

0 comments on commit 1d9e822

Please sign in to comment.