Skip to content

Commit d94f5a5

Browse files
Merge pull request #40 from syncfusion/UpdateCalendarSource
Implementation the Calendar Control in MAUI Toolkit
2 parents 1d0f3bd + 557ba7a commit d94f5a5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+27650
-1
lines changed

maui/src/AssemblyInfo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Runtime.CompilerServices;
22

33
[assembly: InternalsVisibleTo("Syncfusion.Maui.Toolkit.UnitTest")]
4+
[assembly: XmlnsDefinition("http://schemas.syncfusion.com/maui/toolkit", "Syncfusion.Maui.Toolkit.Calendar")]
45
[assembly: XmlnsDefinition("http://schemas.syncfusion.com/maui/toolkit", "Syncfusion.Maui.Toolkit.Carousel")]
56
[assembly: XmlnsDefinition("http://schemas.syncfusion.com/maui/toolkit", "Syncfusion.Maui.Toolkit.Charts")]
67
[assembly: XmlnsDefinition("http://schemas.syncfusion.com/maui/toolkit", "Syncfusion.Maui.Toolkit.Chips")]
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using Microsoft.Maui.Layouts;
2+
3+
namespace Syncfusion.Maui.Toolkit.Calendar
4+
{
5+
/// <summary>
6+
/// Custom calendar layout that used to measure and arrange the children by using <see cref="CalendarLayoutManager"/>.
7+
/// </summary>
8+
internal abstract class CalendarLayout : Layout
9+
{
10+
#region Internal Methods
11+
12+
/// <summary>
13+
/// Method used to measure the children based on width and height value.
14+
/// </summary>
15+
/// <param name="widthConstraint">The maximum width request of the layout.</param>
16+
/// <param name="heightConstraint">The maximum height request of the layout.</param>
17+
/// <returns>The maximum size of the layout.</returns>
18+
internal abstract Size LayoutMeasure(double widthConstraint, double heightConstraint);
19+
20+
/// <summary>
21+
/// Method used to arrange the children with in the bounds.
22+
/// </summary>
23+
/// <param name="bounds">The size of the layout.</param>
24+
/// <returns>The size.</returns>
25+
internal abstract Size LayoutArrangeChildren(Rect bounds);
26+
27+
#endregion
28+
29+
#region Override Method
30+
31+
/// <summary>
32+
/// Creates new layout manager.
33+
/// </summary>
34+
/// <returns>Returns calendar layout manager.</returns>
35+
protected override ILayoutManager CreateLayoutManager()
36+
{
37+
return new CalendarLayoutManager(this);
38+
}
39+
40+
#endregion
41+
}
42+
43+
/// <summary>
44+
/// Layout manager used to handle the measure and arrangement logic of the <see cref="CalendarLayout"/> children.
45+
/// </summary>
46+
internal class CalendarLayoutManager : LayoutManager
47+
{
48+
#region Fields
49+
50+
readonly CalendarLayout _layout;
51+
52+
#endregion
53+
54+
#region Constructor
55+
56+
/// <summary>
57+
/// Initializes a new instance of the <see cref="CalendarLayoutManager"/> class.
58+
/// </summary>
59+
/// <param name="layout">The calendar layout instance.</param>
60+
public CalendarLayoutManager(CalendarLayout layout)
61+
: base(layout)
62+
{
63+
_layout = layout;
64+
}
65+
66+
#endregion
67+
68+
#region Override Methods
69+
70+
/// <summary>
71+
/// Method used to arrange the calendar layout children with in the bounds.
72+
/// </summary>
73+
/// <param name="bounds">The size of the layout.</param>
74+
/// <returns>The size.</returns>
75+
public override Size ArrangeChildren(Rect bounds)
76+
{
77+
return _layout.LayoutArrangeChildren(bounds);
78+
}
79+
80+
/// <summary>
81+
/// Method used to measure the calendar layout children based on width and height value.
82+
/// </summary>
83+
/// <param name="widthConstraint">The maximum width request of the layout.</param>
84+
/// <param name="heightConstraint">The maximum height request of the layout.</param>
85+
/// <returns>The maximum size of the layout.</returns>
86+
public override Size Measure(double widthConstraint, double heightConstraint)
87+
{
88+
return _layout.LayoutMeasure(widthConstraint, heightConstraint);
89+
}
90+
91+
#endregion
92+
}
93+
}
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
namespace Syncfusion.Maui.Toolkit.Calendar
2+
{
3+
/// <summary>
4+
/// Represents a class which holds the information for calendar elements like header, view header and looping panel in vertical stack layout and arranged in Calendar.
5+
/// </summary>
6+
internal class CalendarVerticalStackLayout : CalendarLayout
7+
{
8+
#region Fields
9+
10+
/// <summary>
11+
/// Holds the calendar header height details and its value updated while header height property changed.
12+
/// </summary>
13+
double _headerHeight;
14+
15+
/// <summary>
16+
/// Holds the calendar footer height details and its value updated while footer height property changed.
17+
/// </summary>
18+
double _footerHeight;
19+
20+
/// <summary>
21+
/// The month view header height. Only for month view.
22+
/// </summary>
23+
double _monthViewHeaderHeight;
24+
25+
/// <summary>
26+
/// Holds the show action button layout in calendar. Action button layout shows action buttons and today button.
27+
/// </summary>
28+
bool _showFooterLayout;
29+
30+
#endregion
31+
32+
#region Constructor
33+
34+
/// <summary>
35+
/// Initializes a new instance of the <see cref="CalendarVerticalStackLayout"/> class.
36+
/// </summary>
37+
/// <param name="headerHeight">The header height.</param>
38+
/// <param name="showFooterLayout">The show action layout value.</param>
39+
/// <param name="footerHeight">The footer height.</param>
40+
internal CalendarVerticalStackLayout(double headerHeight, bool showFooterLayout, double footerHeight)
41+
{
42+
_monthViewHeaderHeight = 0;
43+
_headerHeight = headerHeight;
44+
_footerHeight = footerHeight;
45+
_showFooterLayout = showFooterLayout;
46+
//// TODO: Child layouts get the parent flow direction hence while arranging child elements the framework automatically reverses the direction.
47+
//// In other platforms, child elements' flow direction is not set and always has left flow direction so we have to manually arrange child elements.
48+
//// The draw view is still needed to configure manually and not take the parent direction.
49+
//// Due to this inconsistent behavior in windows, set flow direction to LTR for the inner layout of the calendar, so we manually arrange and draw child elements for all the platforms as common.
50+
//// The draw view does not arrange based on the flow direction. https://github.com/dotnet/maui/issues/6978
51+
FlowDirection = Microsoft.Maui.FlowDirection.LeftToRight;
52+
}
53+
54+
#endregion
55+
56+
#region Internal Methods
57+
58+
/// <summary>
59+
/// Update the header height value when the calendar header height changed.
60+
/// </summary>
61+
/// <param name="headerHeight">Updated calendar header height value.</param>
62+
internal void UpdateHeaderHeight(double headerHeight)
63+
{
64+
_headerHeight = headerHeight;
65+
66+
//// In android platform some time's the InvalidateMeasure doesn't trigger the layout measure.So the view doesn't renderer properly. Hence calling measure and arrange directly without InvalidateMeasure.
67+
#if __ANDROID__
68+
this.TriggerInvalidateMeasure();
69+
#else
70+
InvalidateMeasure();
71+
#endif
72+
}
73+
74+
/// <summary>
75+
/// Update the footer height value when the calendar footer height changed.
76+
/// </summary>
77+
/// <param name="footerHeight">The footer height.</param>
78+
internal void UpdateFooterHeight(double footerHeight)
79+
{
80+
_footerHeight = footerHeight;
81+
#if ANDROID
82+
this.TriggerInvalidateMeasure();
83+
#else
84+
InvalidateMeasure();
85+
#endif
86+
}
87+
88+
/// <summary>
89+
/// Update show action button value when the calendar show action button property changed.
90+
/// </summary>
91+
/// <param name="isActionButtonLayout">The show action buttons value.</param>
92+
internal void UpdateActionButtonHeight(bool isActionButtonLayout)
93+
{
94+
if (_showFooterLayout == isActionButtonLayout)
95+
{
96+
return;
97+
}
98+
99+
_showFooterLayout = isActionButtonLayout;
100+
//// In android platform some time's the InvalidateMeasure doesn't trigger the layout measure.So the view doesn't renderer properly. Hence calling measure and arrange directly without InvalidateMeasure.
101+
#if __ANDROID__
102+
this.TriggerInvalidateMeasure();
103+
#else
104+
InvalidateMeasure();
105+
#endif
106+
}
107+
108+
/// <summary>
109+
/// Method to update the month view header height.
110+
/// </summary>
111+
/// <param name="viewHeaderHeight">The view header height.</param>
112+
internal void UpdateViewHeaderHeight(double viewHeaderHeight)
113+
{
114+
_monthViewHeaderHeight = viewHeaderHeight;
115+
116+
//// In android platform some time's the InvalidateMeasure doesn't trigger the layout measure.So the view doesn't renderer properly. Hence calling measure and arrange directly without InvalidateMeasure.
117+
#if __ANDROID__
118+
this.TriggerInvalidateMeasure();
119+
#else
120+
InvalidateMeasure();
121+
#endif
122+
}
123+
124+
/// <summary>
125+
/// Updates the flow direction.
126+
/// </summary>
127+
internal void UpdateFlowDirection()
128+
{
129+
//// In android platform some time's InvalidateMeasure does not trigger while the calendar identifier is changed at run time. So the header view doesn't render properly.
130+
//// Hence calling measure and arrange directly without InvalidateMeasure.
131+
#if __ANDROID__
132+
this.TriggerInvalidateMeasure();
133+
#else
134+
InvalidateMeasure();
135+
#endif
136+
}
137+
138+
#endregion
139+
140+
#region Internal Override Methods
141+
142+
/// <summary>
143+
/// Method used to arrange the children with in the bounds.
144+
/// </summary>
145+
/// <param name="bounds">The size of the layout.</param>
146+
/// <returns>The layout size.</returns>
147+
internal override Size LayoutArrangeChildren(Rect bounds)
148+
{
149+
double width = bounds.Width;
150+
double height = bounds.Height;
151+
//// bounds.Top and bounds.Left specified on arrange because iOS header icon not drawn correctly when set left and top as 0.
152+
double topPosition = bounds.Top;
153+
double footerButtonHeight = _showFooterLayout ? _footerHeight : 0;
154+
foreach (var child in Children)
155+
{
156+
if (child is HeaderLayout)
157+
{
158+
// main header layout which contains date and navigation arrows
159+
child.Arrange(new Rect(bounds.Left, topPosition, width, _headerHeight));
160+
}
161+
else if (child is MonthViewHeader)
162+
{
163+
child.Arrange(new Rect(bounds.Left, topPosition + _headerHeight, width, _monthViewHeaderHeight));
164+
}
165+
else if (child is CustomSnapLayout)
166+
{
167+
//// Swiping panel which holds view header and calendar views.
168+
child.Arrange(new Rect(bounds.Left, topPosition + _headerHeight + _monthViewHeaderHeight, width, height - _headerHeight - _monthViewHeaderHeight - footerButtonHeight));
169+
}
170+
else if (child is FooterLayout)
171+
{
172+
child.Arrange(new Rect(bounds.Left, topPosition + height - footerButtonHeight, width, footerButtonHeight));
173+
}
174+
}
175+
176+
return bounds.Size;
177+
}
178+
179+
/// <summary>
180+
/// Method used to measure the children based on width and height value.
181+
/// </summary>
182+
/// <param name="widthConstraint">The maximum width request of the layout.</param>
183+
/// <param name="heightConstraint">The maximum height request of the layout.</param>
184+
/// <returns>The maximum size of the layout.</returns>
185+
internal override Size LayoutMeasure(double widthConstraint, double heightConstraint)
186+
{
187+
double footerButtonHeight = _showFooterLayout ? _footerHeight : 0;
188+
foreach (var child in Children)
189+
{
190+
if (child is HeaderLayout)
191+
{
192+
// main header layout which contains date and navigation arrows.
193+
child.Measure(widthConstraint, _headerHeight);
194+
}
195+
else if (child is MonthViewHeader)
196+
{
197+
//// Month view header which holds month view header(Day of Week).
198+
child.Measure(widthConstraint, _monthViewHeaderHeight);
199+
}
200+
else if (child is CustomSnapLayout)
201+
{
202+
//// Swiping panel which holds view header and calendar views.
203+
child.Measure(widthConstraint, heightConstraint - _headerHeight - _monthViewHeaderHeight - footerButtonHeight);
204+
}
205+
else if (child is FooterLayout)
206+
{
207+
child.Measure(widthConstraint, footerButtonHeight);
208+
}
209+
}
210+
211+
return new Size(widthConstraint, heightConstraint);
212+
}
213+
214+
#endregion
215+
}
216+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
namespace Syncfusion.Maui.Toolkit.Calendar
2+
{
3+
/// <summary>
4+
/// Defines the calendar element of the SfCalendar.
5+
/// </summary>
6+
public enum CalendarElement
7+
{
8+
/// <summary>
9+
/// Defines the calendar header element.
10+
/// </summary>
11+
Header,
12+
13+
/// <summary>
14+
/// Defines the calendar month view header element.
15+
/// </summary>
16+
ViewHeader,
17+
18+
/// <summary>
19+
/// Defines the calendar cell element.
20+
/// </summary>
21+
CalendarCell,
22+
23+
/// <summary>
24+
/// Defines the week number element
25+
/// </summary>
26+
/// <remarks>This is applicable for the month view</remarks>
27+
WeekNumber,
28+
}
29+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
namespace Syncfusion.Maui.Toolkit.Calendar
2+
{
3+
/// <summary>
4+
/// Defines the calendar special date icons of the SfCalendar.
5+
/// </summary>
6+
public enum CalendarIcon
7+
{
8+
/// <summary>
9+
/// Defines the dot icon.
10+
/// </summary>
11+
Dot,
12+
13+
/// <summary>
14+
/// Defines the square icon.
15+
/// </summary>
16+
Square,
17+
18+
/// <summary>
19+
/// Defines the triangle icon.
20+
/// </summary>
21+
Triangle,
22+
23+
/// <summary>
24+
/// Defines the heart icon.
25+
/// </summary>
26+
Heart,
27+
28+
/// <summary>
29+
/// Defines the diamond icon.
30+
/// </summary>
31+
Diamond,
32+
33+
/// <summary>
34+
/// Defines the star icon.
35+
/// </summary>
36+
Star,
37+
38+
/// <summary>
39+
/// Defines the bell icon.
40+
/// </summary>
41+
Bell,
42+
}
43+
}

0 commit comments

Comments
 (0)