Skip to content

Commit

Permalink
feat: Fixes issue #412: ✨ Add support for RTL directionality
Browse files Browse the repository at this point in the history
  • Loading branch information
shubham-jitiya-simform committed Jan 16, 2025
1 parent 469cc29 commit 619cf99
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 46 deletions.
15 changes: 9 additions & 6 deletions example/lib/pages/week_view_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ class _WeekViewDemoState extends State<WeekViewDemo> {
webWidget: WebHomePage(
selectedView: CalendarView.week,
),
mobileWidget: Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
elevation: 8,
onPressed: () => context.pushRoute(CreateEventPage()),
mobileWidget: Directionality(
textDirection: TextDirection.rtl,
child: Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
elevation: 8,
onPressed: () => context.pushRoute(CreateEventPage()),
),
body: WeekViewWidget(),
),
body: WeekViewWidget(),
),
);
}
Expand Down
27 changes: 27 additions & 0 deletions example/lib/widgets/week_view_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ class WeekViewWidget extends StatelessWidget {
return WeekView(
key: state,
width: width,
// textDirection: TextDirection.rtl,
headerStringBuilder: (DateTime date, {DateTime? secondaryDate}) =>
_weekStringBuilder(
date,
secondaryDate: secondaryDate,
textDirection: Directionality.of(context),
),
showWeekends: true,
showLiveTimeLineInAllDays: true,
eventArranger: SideEventArranger(maxWidth: 30),
Expand All @@ -22,6 +29,7 @@ class WeekViewWidget extends StatelessWidget {
liveTimeIndicatorSettings: LiveTimeIndicatorSettings(
color: Colors.redAccent,
showTime: true,
showTimeBackgroundView: true,
),
onTimestampTap: (date) {
SnackBar snackBar = SnackBar(
Expand All @@ -45,4 +53,23 @@ class WeekViewWidget extends StatelessWidget {
},
);
}

String _weekStringBuilder(DateTime date,
{DateTime? secondaryDate, TextDirection? textDirection}) {
final dateString = "${date.day} / ${date.month} / ${date.year}";
final secondaryDateString = secondaryDate != null
? "${secondaryDate.day} / ${secondaryDate.month} / ${secondaryDate.year}"
: "";
// Unicode character for Left-to-Right Embedding
// (to enforce LTR in the string)
const ltr = '\u202A';
// Unicode character for Pop Directional Formatting
// (to close the directional formatting)
const pop = '\u202C';
if (textDirection == TextDirection.rtl) {
return "$ltr${secondaryDateString} to ${dateString}$pop";
} else {
return "$ltr${dateString} to ${secondaryDateString}$pop";
}
}
}
4 changes: 3 additions & 1 deletion lib/src/components/_internal_components.dart
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,11 @@ class _LiveTimeIndicatorState extends State<LiveTimeIndicator> {
size: Size(widget.width, widget.liveTimeIndicatorSettings.height),
painter: CurrentTimeLinePainter(
color: widget.liveTimeIndicatorSettings.color,
textDirection: Directionality.of(context),
height: widget.liveTimeIndicatorSettings.height,
width: widget.width - widget.timeLineWidth - 12,
offset: Offset(
widget.timeLineWidth + widget.liveTimeIndicatorSettings.offset,
widget.liveTimeIndicatorSettings.offset,
(_currentTime.getTotalMinutes - startMinutes) *
widget.heightPerMinute,
),
Expand Down
22 changes: 14 additions & 8 deletions lib/src/components/day_view_components.dart
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,16 @@ class DefaultTimeLineMark extends StatelessWidget {
/// Text style for time string.
final TextStyle? markingStyle;

final TextDirection? textDirection;

/// Time marker for timeline used in week and day view.
const DefaultTimeLineMark({
Key? key,
required this.date,
this.markingStyle,
this.timeStringBuilder,
}) : super(key: key);
const DefaultTimeLineMark(
{Key? key,
required this.date,
this.markingStyle,
this.timeStringBuilder,
this.textDirection})
: super(key: key);

@override
Widget build(BuildContext context) {
Expand All @@ -139,10 +142,13 @@ class DefaultTimeLineMark extends StatelessWidget {
return Transform.translate(
offset: Offset(0, -7.5),
child: Padding(
padding: const EdgeInsets.only(right: 7.0),
padding: const EdgeInsets.only(right: 7.0, left: 7.0),
child: Text(
timeString,
textAlign: TextAlign.right,
// textDirection: Directionality.of(context),
textAlign: Directionality.of(context) == TextDirection.ltr
? TextAlign.right
: TextAlign.left,
style: markingStyle ??
TextStyle(
fontSize: 15.0,
Expand Down
36 changes: 31 additions & 5 deletions lib/src/painters.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ class HourLinePainter extends CustomPainter {
}
}

// TODO(Shubham): Draws vertical line at start disable it to remove leading vertical line

if (showVerticalLine) {
if (lineStyle == LineStyle.dashed) {
var startY = 0.0;
Expand Down Expand Up @@ -261,10 +263,12 @@ class CurrentTimeLinePainter extends CustomPainter {

/// Height of time indicator.
final double height;
final double width;

/// offset of time indicator.
final Offset offset;

// TODO(Shubham): Update docs
/// Flag to show bullet at left side or not.
final bool showBullet;

Expand All @@ -282,6 +286,7 @@ class CurrentTimeLinePainter extends CustomPainter {

/// Width of time backgroud view.
final double timeBackgroundViewWidth;
final TextDirection textDirection;

/// Paints a single horizontal line at [offset].
CurrentTimeLinePainter({
Expand All @@ -294,28 +299,43 @@ class CurrentTimeLinePainter extends CustomPainter {
required this.showTime,
required this.showTimeBackgroundView,
required this.timeBackgroundViewWidth,
required this.width,
this.textDirection = TextDirection.ltr,
});

@override
void paint(Canvas canvas, Size size) {
// TODO(Shubham): Check size.width is line width or not
canvas.drawLine(
Offset(offset.dx - (showBullet ? 0 : 8), offset.dy),
Offset(size.width, offset.dy),
Offset(
textDirection == TextDirection.ltr ? size.width : width, offset.dy),
Paint()
..color = color
..strokeWidth = height,
);

if (showBullet) {
canvas.drawCircle(
Offset(offset.dx, offset.dy), bulletRadius, Paint()..color = color);
if (textDirection == TextDirection.ltr) {
canvas.drawCircle(
Offset(offset.dx + timeBackgroundViewWidth, offset.dy),
bulletRadius,
Paint()..color = color);
} else {
canvas.drawCircle(Offset(offset.dx + width, offset.dy), bulletRadius,
Paint()..color = color);
}
}

if (showTimeBackgroundView) {
final dx = textDirection == TextDirection.ltr
? offset.dx - 4
: offset.dx + width + 4;

canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromLTWH(
max(3, offset.dx - 68),
max(3, dx),
offset.dy - 11,
timeBackgroundViewWidth,
24,
Expand All @@ -341,7 +361,13 @@ class CurrentTimeLinePainter extends CustomPainter {
),
)
..layout()
..paint(canvas, Offset(offset.dx - 62, offset.dy - 6));
..paint(
canvas,
Offset(
textDirection == TextDirection.ltr
? offset.dx
: offset.dx + width + 7,
offset.dy - 6));
}
}

Expand Down
100 changes: 74 additions & 26 deletions lib/src/week_view/_internal_week_view_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ class InternalWeekViewPage<T extends Object?> extends StatefulWidget {
/// This method will be called when user taps on timestamp in timeline.
final TimestampCallback? onTimestampTap;

final TextDirection textDirection;

/// A single page for week view.
const InternalWeekViewPage({
Key? key,
Expand Down Expand Up @@ -216,6 +218,7 @@ class InternalWeekViewPage<T extends Object?> extends StatefulWidget {
required this.weekViewScrollController,
this.lastScrollOffset = 0.0,
this.keepScrollOffset = false,
this.textDirection = TextDirection.ltr,
}) : super(key: key);

@override
Expand Down Expand Up @@ -251,6 +254,7 @@ class _InternalWeekViewPageState<T extends Object?>
@override
Widget build(BuildContext context) {
final filteredDates = _filteredDate();
final textDirection = Directionality.of(context);
return Container(
height: widget.height + widget.weekTitleHeight,
width: widget.width,
Expand Down Expand Up @@ -311,6 +315,7 @@ class _InternalWeekViewPageState<T extends Object?>
vertical: 2,
horizontal: 1,
),
// TODO(Shubham): Add direction
child: Text(
widget.fullDayHeaderTitle,
textAlign:
Expand Down Expand Up @@ -353,25 +358,50 @@ class _InternalWeekViewPageState<T extends Object?>
width: widget.width,
child: Stack(
children: [
CustomPaint(
size: Size(widget.width, widget.height),
painter: HourLinePainter(
lineColor: widget.hourIndicatorSettings.color,
lineHeight: widget.hourIndicatorSettings.height,
offset: widget.timeLineWidth +
widget.hourIndicatorSettings.offset,
minuteHeight: widget.heightPerMinute,
verticalLineOffset: widget.verticalLineOffset,
showVerticalLine: widget.showVerticalLine,
lineStyle: widget.hourIndicatorSettings.lineStyle,
dashWidth: widget.hourIndicatorSettings.dashWidth,
dashSpaceWidth:
widget.hourIndicatorSettings.dashSpaceWidth,
emulateVerticalOffsetBy: widget.emulateVerticalOffsetBy,
startHour: widget.startHour,
endHour: widget.endHour,
// TODO(Shubham): Width of horizontal paint line
if (true)
Positioned(
left: Directionality.of(context) == TextDirection.ltr
? widget.timeLineWidth
: 0,
// TODO(Shubham): Check padding of 6 from somewhere
right: Directionality.of(context) == TextDirection.ltr
? 0
: widget.timeLineWidth + 6,
child: CustomPaint(
size: Size(
widget.width,
widget.height,
),
painter: HourLinePainter(
lineColor: widget.hourIndicatorSettings.color,
lineHeight: widget.hourIndicatorSettings.height,
offset: 0,
// TODO(Shubham): Update offset
// offset:
// Directionality.of(context) == TextDirection.ltr
// ? widget.timeLineWidth +
// widget.hourIndicatorSettings.offset
// : 0,
// offset:
// Directionality.of(context) == TextDirection.ltr
// ? widget.timeLineWidth +
// widget.hourIndicatorSettings.offset
// : widget.width - widget.timeLineWidth,
minuteHeight: widget.heightPerMinute,
verticalLineOffset: widget.verticalLineOffset,
showVerticalLine: widget.showVerticalLine,
lineStyle: widget.hourIndicatorSettings.lineStyle,
dashWidth: widget.hourIndicatorSettings.dashWidth,
dashSpaceWidth:
widget.hourIndicatorSettings.dashSpaceWidth,
emulateVerticalOffsetBy:
widget.emulateVerticalOffsetBy,
startHour: widget.startHour,
endHour: widget.endHour,
),
),
),
),
if (widget.showHalfHours)
CustomPaint(
size: Size(widget.width, widget.height),
Expand Down Expand Up @@ -408,7 +438,9 @@ class _InternalWeekViewPageState<T extends Object?>
),
),
Align(
alignment: Alignment.centerRight,
alignment: Directionality.of(context) == TextDirection.ltr
? Alignment.centerRight
: Alignment.centerLeft,
child: SizedBox(
width: widget.weekTitleWidth * filteredDates.length,
height: widget.height,
Expand All @@ -420,12 +452,28 @@ class _InternalWeekViewPageState<T extends Object?>
decoration: widget.showVerticalLine
? BoxDecoration(
border: Border(
right: BorderSide(
color: widget
.hourIndicatorSettings.color,
width: widget
.hourIndicatorSettings.height,
),
left: widget.textDirection ==
TextDirection.ltr
? BorderSide.none
: BorderSide(
color: widget
.hourIndicatorSettings
.color,
width: widget
.hourIndicatorSettings
.height,
),
right: widget.textDirection ==
TextDirection.ltr
? BorderSide(
color: widget
.hourIndicatorSettings
.color,
width: widget
.hourIndicatorSettings
.height,
)
: BorderSide.none,
),
)
: null,
Expand Down Expand Up @@ -486,7 +534,7 @@ class _InternalWeekViewPageState<T extends Object?>
LiveTimeIndicator(
liveTimeIndicatorSettings:
widget.liveTimeIndicatorSettings,
width: widget.width,
width: widget.width - 8,
height: widget.height,
heightPerMinute: widget.heightPerMinute,
timeLineWidth: widget.timeLineWidth,
Expand Down
Loading

0 comments on commit 619cf99

Please sign in to comment.