diff --git a/compose-multiplatform/library/src/commonMain/kotlin/com/kizitonwose/calendar/compose/Calendar.kt b/compose-multiplatform/library/src/commonMain/kotlin/com/kizitonwose/calendar/compose/Calendar.kt index 7da01948..2ab84694 100644 --- a/compose-multiplatform/library/src/commonMain/kotlin/com/kizitonwose/calendar/compose/Calendar.kt +++ b/compose-multiplatform/library/src/commonMain/kotlin/com/kizitonwose/calendar/compose/Calendar.kt @@ -308,7 +308,7 @@ public fun HeatMapCalendar( * @param modifier the modifier to apply to this calendar. * @param state the state object to be used to control or observe the calendar's properties. * Examples: `startYear`, `endYear`, `firstDayOfWeek`, `firstVisibleYear`, `outDateStyle`. - * @param columns the number of months columns in each year on the calendar. + * @param monthColumns the number of month columns in each year. Must be from 1 to 12. * @param calendarScrollPaged the scrolling behavior of the calendar. When `true`, the calendar will * snap to the nearest year after a scroll or swipe action. When `false`, the calendar scrolls normally. * @param userScrollEnabled whether the scrolling via the user gestures or accessibility actions @@ -319,10 +319,11 @@ public fun HeatMapCalendar( * content after it has been clipped, which is not possible via [modifier] param. You can use it * to add a padding before the first year or after the last one. If you want to add a spacing * between each year, use the [yearContainer] composable or the [yearBodyContentPadding] parameter. - * @param yearBodyContentPadding a padding around the year body content. Alternatively, you can - * also provide a [yearBody] with the desired padding to achieve the same result. - * @param monthVerticalSpacing the vertical spacing between month rows. - * @param monthHorizontalSpacing the horizontal spacing between month columns. + * @param yearBodyContentPadding a padding around the year body content, this is the grid in which + * the months in each year are shown, excluding the year header and footer. Alternatively, you can + * provide a [yearBody] with the desired padding to achieve the same result. + * @param monthVerticalSpacing the vertical spacing between month rows in each year. + * @param monthHorizontalSpacing the horizontal spacing between month columns in each year. * @param contentHeightMode Determines how the height of the month and day content is calculated. * @param isMonthVisible Determines if a month is shown on the calendar grid. For example, you can * use this to hide all past months. @@ -361,7 +362,7 @@ public fun HeatMapCalendar( public fun HorizontalYearCalendar( modifier: Modifier = Modifier, state: YearCalendarState = rememberYearCalendarState(), - columns: Int = 3, + monthColumns: Int = 3, calendarScrollPaged: Boolean = true, userScrollEnabled: Boolean = true, reverseLayout: Boolean = false, @@ -383,7 +384,7 @@ public fun HorizontalYearCalendar( ): Unit = YearCalendar( modifier = modifier, state = state, - columns = columns, + monthColumns = monthColumns, calendarScrollPaged = calendarScrollPaged, userScrollEnabled = userScrollEnabled, isHorizontal = true, @@ -411,7 +412,7 @@ public fun HorizontalYearCalendar( * @param modifier the modifier to apply to this calendar. * @param state the state object to be used to control or observe the calendar's properties. * Examples: `startYear`, `endYear`, `firstDayOfWeek`, `firstVisibleYear`, `outDateStyle`. - * @param columns the number of months columns in each year on the calendar. + * @param monthColumns the number of month columns in each year. Must be from 1 to 12. * @param calendarScrollPaged the scrolling behavior of the calendar. When `true`, the calendar will * snap to the nearest year after a scroll or swipe action. When `false`, the calendar scrolls normally. * @param userScrollEnabled whether the scrolling via the user gestures or accessibility actions @@ -422,10 +423,11 @@ public fun HorizontalYearCalendar( * content after it has been clipped, which is not possible via [modifier] param. You can use it * to add a padding before the first year or after the last one. If you want to add a spacing * between each year, use the [yearContainer] composable or the [yearBodyContentPadding] parameter. - * @param yearBodyContentPadding a padding around the year body content. Alternatively, you can - * also provide a [yearBody] with the desired padding to achieve the same result. - * @param monthVerticalSpacing the vertical spacing between month rows. - * @param monthHorizontalSpacing the horizontal spacing between month columns. + * @param yearBodyContentPadding a padding around the year body content, this is the grid in which + * the months in each year are shown, excluding the year header and footer. Alternatively, you can + * provide a [yearBody] with the desired padding to achieve the same result. + * @param monthVerticalSpacing the vertical spacing between month rows in each year. + * @param monthHorizontalSpacing the horizontal spacing between month columns in each year. * @param contentHeightMode Determines how the height of the month and day content is calculated. * @param isMonthVisible Determines if a month is shown on the calendar grid. For example, you can * use this to hide all past months. @@ -464,7 +466,7 @@ public fun HorizontalYearCalendar( public fun VerticalYearCalendar( modifier: Modifier = Modifier, state: YearCalendarState = rememberYearCalendarState(), - columns: Int = 3, + monthColumns: Int = 3, calendarScrollPaged: Boolean = true, userScrollEnabled: Boolean = true, reverseLayout: Boolean = false, @@ -486,7 +488,7 @@ public fun VerticalYearCalendar( ): Unit = YearCalendar( modifier = modifier, state = state, - columns = columns, + monthColumns = monthColumns, calendarScrollPaged = calendarScrollPaged, userScrollEnabled = userScrollEnabled, isHorizontal = false, @@ -512,7 +514,7 @@ public fun VerticalYearCalendar( private fun YearCalendar( modifier: Modifier, state: YearCalendarState, - columns: Int, + monthColumns: Int, calendarScrollPaged: Boolean, userScrollEnabled: Boolean, isHorizontal: Boolean, @@ -533,6 +535,7 @@ private fun YearCalendar( yearFooter: (@Composable ColumnScope.(CalendarYear) -> Unit)?, yearContainer: (@Composable LazyItemScope.(CalendarYear, container: @Composable () -> Unit) -> Unit)?, ) { + require(monthColumns in 1..12) { "Param `monthColumns` must be 1..12" } if (isHorizontal) { LazyRow( modifier = modifier, @@ -545,7 +548,7 @@ private fun YearCalendar( YearCalendarMonths( yearCount = state.calendarInfo.indexCount, yearData = { offset -> state.store[offset] }, - columns = columns, + monthColumns = monthColumns, monthVerticalSpacing = monthVerticalSpacing, monthHorizontalSpacing = monthHorizontalSpacing, yearBodyContentPadding = yearBodyContentPadding, @@ -574,7 +577,7 @@ private fun YearCalendar( YearCalendarMonths( yearCount = state.calendarInfo.indexCount, yearData = { offset -> state.store[offset] }, - columns = columns, + monthColumns = monthColumns, monthVerticalSpacing = monthVerticalSpacing, monthHorizontalSpacing = monthHorizontalSpacing, yearBodyContentPadding = yearBodyContentPadding, diff --git a/compose-multiplatform/library/src/commonMain/kotlin/com/kizitonwose/calendar/compose/yearcalendar/YearCalendarMonths.kt b/compose-multiplatform/library/src/commonMain/kotlin/com/kizitonwose/calendar/compose/yearcalendar/YearCalendarMonths.kt index f2366b0b..c7fd21c0 100644 --- a/compose-multiplatform/library/src/commonMain/kotlin/com/kizitonwose/calendar/compose/yearcalendar/YearCalendarMonths.kt +++ b/compose-multiplatform/library/src/commonMain/kotlin/com/kizitonwose/calendar/compose/yearcalendar/YearCalendarMonths.kt @@ -21,12 +21,13 @@ import com.kizitonwose.calendar.compose.or import com.kizitonwose.calendar.core.CalendarDay import com.kizitonwose.calendar.core.CalendarMonth import com.kizitonwose.calendar.core.CalendarYear +import kotlin.math.min @Suppress("FunctionName") internal fun LazyListScope.YearCalendarMonths( yearCount: Int, yearData: (offset: Int) -> CalendarYear, - columns: Int, + monthColumns: Int, monthVerticalSpacing: Dp, monthHorizontalSpacing: Dp, yearBodyContentPadding: PaddingValues, @@ -74,8 +75,8 @@ internal fun LazyListScope.YearCalendarMonths( .fillMaxWidth() .then(if (fillHeight) Modifier.weight(1f) else Modifier.wrapContentHeight()) .padding(yearBodyContentPadding), - columns = columns, - itemCount = months.count(), + monthColumns = monthColumns, + monthCount = months.count(), fillHeight = fillHeight, monthVerticalSpacing = monthVerticalSpacing, monthHorizontalSpacing = monthHorizontalSpacing, @@ -139,11 +140,11 @@ internal fun LazyListScope.YearCalendarMonths( @Composable private fun CalendarGrid( - columns: Int, + monthColumns: Int, fillHeight: Boolean, monthVerticalSpacing: Dp, monthHorizontalSpacing: Dp, - itemCount: Int, + monthCount: Int, modifier: Modifier = Modifier, content: @Composable BoxScope.(Int) -> Unit, ) { @@ -151,13 +152,10 @@ private fun CalendarGrid( modifier = modifier, verticalArrangement = Arrangement.spacedBy(monthVerticalSpacing), ) { - var rows = (itemCount / columns) - if (itemCount.mod(columns) > 0) { - rows += 1 - } + val rows = (monthCount / monthColumns) + min(monthCount % monthColumns, 1) for (rowId in 0 until rows) { - val firstIndex = rowId * columns + val firstIndex = rowId * monthColumns Row( modifier = Modifier.then( @@ -165,13 +163,13 @@ private fun CalendarGrid( ), horizontalArrangement = Arrangement.spacedBy(monthHorizontalSpacing), ) { - for (columnId in 0 until columns) { + for (columnId in 0 until monthColumns) { val index = firstIndex + columnId Box( modifier = Modifier .weight(1f), ) { - if (index < itemCount) { + if (index < monthCount) { content(index) } } diff --git a/compose-multiplatform/sample/src/commonMain/kotlin/Example10Page.kt b/compose-multiplatform/sample/src/commonMain/kotlin/Example10Page.kt index 0cacf2e6..9322c986 100644 --- a/compose-multiplatform/sample/src/commonMain/kotlin/Example10Page.kt +++ b/compose-multiplatform/sample/src/commonMain/kotlin/Example10Page.kt @@ -108,7 +108,7 @@ fun Example10Page(adjacentYears: Int = 50) { .fillMaxSize() .testTag("Calendar"), state = state, - columns = if (isPortrait) { + monthColumns = if (isPortrait) { 3 } else { if (isTablet) 4 else 6 diff --git a/compose-multiplatform/sample/src/commonMain/kotlin/ListPage.kt b/compose-multiplatform/sample/src/commonMain/kotlin/ListPage.kt index f226b615..e5be8bf0 100644 --- a/compose-multiplatform/sample/src/commonMain/kotlin/ListPage.kt +++ b/compose-multiplatform/sample/src/commonMain/kotlin/ListPage.kt @@ -69,7 +69,7 @@ enum class Page(val title: String, val subtitle: String, val showToolBar: Boolea ), Example10( title = "Example 10", - subtitle = "Horizontal year calendar - Year header and paged scrolling. Best suited for large screens.", + subtitle = "Horizontal year calendar - Paged scrolling, shows the \"Fill\" implementation of YearContentHeightMode property. Best suited for large screens.", showToolBar = true, ), Example11( diff --git a/compose/src/main/java/com/kizitonwose/calendar/compose/Calendar.kt b/compose/src/main/java/com/kizitonwose/calendar/compose/Calendar.kt index 81a50ddc..4b94a024 100644 --- a/compose/src/main/java/com/kizitonwose/calendar/compose/Calendar.kt +++ b/compose/src/main/java/com/kizitonwose/calendar/compose/Calendar.kt @@ -1,5 +1,6 @@ package com.kizitonwose.calendar.compose +import androidx.annotation.IntRange import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.PaddingValues @@ -308,7 +309,7 @@ public fun HeatMapCalendar( * @param modifier the modifier to apply to this calendar. * @param state the state object to be used to control or observe the calendar's properties. * Examples: `startYear`, `endYear`, `firstDayOfWeek`, `firstVisibleYear`, `outDateStyle`. - * @param columns the number of months columns in each year on the calendar. + * @param monthColumns the number of month columns in each year. Must be from 1 to 12. * @param calendarScrollPaged the scrolling behavior of the calendar. When `true`, the calendar will * snap to the nearest year after a scroll or swipe action. When `false`, the calendar scrolls normally. * @param userScrollEnabled whether the scrolling via the user gestures or accessibility actions @@ -319,10 +320,11 @@ public fun HeatMapCalendar( * content after it has been clipped, which is not possible via [modifier] param. You can use it * to add a padding before the first year or after the last one. If you want to add a spacing * between each year, use the [yearContainer] composable or the [yearBodyContentPadding] parameter. - * @param yearBodyContentPadding a padding around the year body content. Alternatively, you can - * also provide a [yearBody] with the desired padding to achieve the same result. - * @param monthVerticalSpacing the vertical spacing between month rows. - * @param monthHorizontalSpacing the horizontal spacing between month columns. + * @param yearBodyContentPadding a padding around the year body content, this is the grid in which + * the months in each year are shown, excluding the year header and footer. Alternatively, you can + * provide a [yearBody] with the desired padding to achieve the same result. + * @param monthVerticalSpacing the vertical spacing between month rows in each year. + * @param monthHorizontalSpacing the horizontal spacing between month columns in each year. * @param contentHeightMode Determines how the height of the month and day content is calculated. * @param isMonthVisible Determines if a month is shown on the calendar grid. For example, you can * use this to hide all past months. @@ -361,7 +363,7 @@ public fun HeatMapCalendar( public fun HorizontalYearCalendar( modifier: Modifier = Modifier, state: YearCalendarState = rememberYearCalendarState(), - columns: Int = 3, + @IntRange(from = 1, to = 12) monthColumns: Int = 3, calendarScrollPaged: Boolean = true, userScrollEnabled: Boolean = true, reverseLayout: Boolean = false, @@ -383,7 +385,7 @@ public fun HorizontalYearCalendar( ): Unit = YearCalendar( modifier = modifier, state = state, - columns = columns, + monthColumns = monthColumns, calendarScrollPaged = calendarScrollPaged, userScrollEnabled = userScrollEnabled, isHorizontal = true, @@ -411,7 +413,7 @@ public fun HorizontalYearCalendar( * @param modifier the modifier to apply to this calendar. * @param state the state object to be used to control or observe the calendar's properties. * Examples: `startYear`, `endYear`, `firstDayOfWeek`, `firstVisibleYear`, `outDateStyle`. - * @param columns the number of months columns in each year on the calendar. + * @param monthColumns the number of month columns in each year. Must be from 1 to 12. * @param calendarScrollPaged the scrolling behavior of the calendar. When `true`, the calendar will * snap to the nearest year after a scroll or swipe action. When `false`, the calendar scrolls normally. * @param userScrollEnabled whether the scrolling via the user gestures or accessibility actions @@ -422,10 +424,11 @@ public fun HorizontalYearCalendar( * content after it has been clipped, which is not possible via [modifier] param. You can use it * to add a padding before the first year or after the last one. If you want to add a spacing * between each year, use the [yearContainer] composable or the [yearBodyContentPadding] parameter. - * @param yearBodyContentPadding a padding around the year body content. Alternatively, you can - * also provide a [yearBody] with the desired padding to achieve the same result. - * @param monthVerticalSpacing the vertical spacing between month rows. - * @param monthHorizontalSpacing the horizontal spacing between month columns. + * @param yearBodyContentPadding a padding around the year body content, this is the grid in which + * the months in each year are shown, excluding the year header and footer. Alternatively, you can + * provide a [yearBody] with the desired padding to achieve the same result. + * @param monthVerticalSpacing the vertical spacing between month rows in each year. + * @param monthHorizontalSpacing the horizontal spacing between month columns in each year. * @param contentHeightMode Determines how the height of the month and day content is calculated. * @param isMonthVisible Determines if a month is shown on the calendar grid. For example, you can * use this to hide all past months. @@ -464,7 +467,7 @@ public fun HorizontalYearCalendar( public fun VerticalYearCalendar( modifier: Modifier = Modifier, state: YearCalendarState = rememberYearCalendarState(), - columns: Int = 3, + @IntRange(from = 1, to = 12) monthColumns: Int = 3, calendarScrollPaged: Boolean = true, userScrollEnabled: Boolean = true, reverseLayout: Boolean = false, @@ -486,7 +489,7 @@ public fun VerticalYearCalendar( ): Unit = YearCalendar( modifier = modifier, state = state, - columns = columns, + monthColumns = monthColumns, calendarScrollPaged = calendarScrollPaged, userScrollEnabled = userScrollEnabled, isHorizontal = false, @@ -512,7 +515,7 @@ public fun VerticalYearCalendar( private fun YearCalendar( modifier: Modifier, state: YearCalendarState, - columns: Int, + monthColumns: Int, calendarScrollPaged: Boolean, userScrollEnabled: Boolean, isHorizontal: Boolean, @@ -533,6 +536,7 @@ private fun YearCalendar( yearFooter: (@Composable ColumnScope.(CalendarYear) -> Unit)?, yearContainer: (@Composable LazyItemScope.(CalendarYear, container: @Composable () -> Unit) -> Unit)?, ) { + require(monthColumns in 1..12) { "Param `monthColumns` must be 1..12" } if (isHorizontal) { LazyRow( modifier = modifier, @@ -545,7 +549,7 @@ private fun YearCalendar( YearCalendarMonths( yearCount = state.calendarInfo.indexCount, yearData = { offset -> state.store[offset] }, - columns = columns, + monthColumns = monthColumns, monthVerticalSpacing = monthVerticalSpacing, monthHorizontalSpacing = monthHorizontalSpacing, yearBodyContentPadding = yearBodyContentPadding, @@ -574,7 +578,7 @@ private fun YearCalendar( YearCalendarMonths( yearCount = state.calendarInfo.indexCount, yearData = { offset -> state.store[offset] }, - columns = columns, + monthColumns = monthColumns, monthVerticalSpacing = monthVerticalSpacing, monthHorizontalSpacing = monthHorizontalSpacing, yearBodyContentPadding = yearBodyContentPadding, diff --git a/compose/src/main/java/com/kizitonwose/calendar/compose/yearcalendar/YearCalendarMonths.kt b/compose/src/main/java/com/kizitonwose/calendar/compose/yearcalendar/YearCalendarMonths.kt index 3c2bbe80..ec437ebb 100644 --- a/compose/src/main/java/com/kizitonwose/calendar/compose/yearcalendar/YearCalendarMonths.kt +++ b/compose/src/main/java/com/kizitonwose/calendar/compose/yearcalendar/YearCalendarMonths.kt @@ -21,12 +21,13 @@ import com.kizitonwose.calendar.compose.or import com.kizitonwose.calendar.core.CalendarDay import com.kizitonwose.calendar.core.CalendarMonth import com.kizitonwose.calendar.core.CalendarYear +import kotlin.math.min @Suppress("FunctionName") internal fun LazyListScope.YearCalendarMonths( yearCount: Int, yearData: (offset: Int) -> CalendarYear, - columns: Int, + monthColumns: Int, monthVerticalSpacing: Dp, monthHorizontalSpacing: Dp, yearBodyContentPadding: PaddingValues, @@ -74,8 +75,8 @@ internal fun LazyListScope.YearCalendarMonths( .fillMaxWidth() .then(if (fillHeight) Modifier.weight(1f) else Modifier.wrapContentHeight()) .padding(yearBodyContentPadding), - columns = columns, - itemCount = months.count(), + monthColumns = monthColumns, + monthCount = months.count(), fillHeight = fillHeight, monthVerticalSpacing = monthVerticalSpacing, monthHorizontalSpacing = monthHorizontalSpacing, @@ -139,11 +140,11 @@ internal fun LazyListScope.YearCalendarMonths( @Composable private fun CalendarGrid( - columns: Int, + monthColumns: Int, fillHeight: Boolean, monthVerticalSpacing: Dp, monthHorizontalSpacing: Dp, - itemCount: Int, + monthCount: Int, modifier: Modifier = Modifier, content: @Composable BoxScope.(Int) -> Unit, ) { @@ -151,13 +152,10 @@ private fun CalendarGrid( modifier = modifier, verticalArrangement = Arrangement.spacedBy(monthVerticalSpacing), ) { - var rows = (itemCount / columns) - if (itemCount.mod(columns) > 0) { - rows += 1 - } + val rows = (monthCount / monthColumns) + min(monthCount % monthColumns, 1) for (rowId in 0 until rows) { - val firstIndex = rowId * columns + val firstIndex = rowId * monthColumns Row( modifier = Modifier.then( @@ -165,13 +163,13 @@ private fun CalendarGrid( ), horizontalArrangement = Arrangement.spacedBy(monthHorizontalSpacing), ) { - for (columnId in 0 until columns) { + for (columnId in 0 until monthColumns) { val index = firstIndex + columnId Box( modifier = Modifier .weight(1f), ) { - if (index < itemCount) { + if (index < monthCount) { content(index) } } diff --git a/sample/src/main/java/com/kizitonwose/calendar/sample/compose/Example10Page.kt b/sample/src/main/java/com/kizitonwose/calendar/sample/compose/Example10Page.kt index d0dae98d..dbedbb7a 100644 --- a/sample/src/main/java/com/kizitonwose/calendar/sample/compose/Example10Page.kt +++ b/sample/src/main/java/com/kizitonwose/calendar/sample/compose/Example10Page.kt @@ -107,7 +107,7 @@ fun Example10Page(adjacentYears: Long = 50) { .fillMaxSize() .testTag("Calendar"), state = state, - columns = if (isPortrait) { + monthColumns = if (isPortrait) { 3 } else { if (isTablet) 4 else 6 diff --git a/sample/src/main/java/com/kizitonwose/calendar/sample/compose/ListPage.kt b/sample/src/main/java/com/kizitonwose/calendar/sample/compose/ListPage.kt index f63c0bdd..45790286 100644 --- a/sample/src/main/java/com/kizitonwose/calendar/sample/compose/ListPage.kt +++ b/sample/src/main/java/com/kizitonwose/calendar/sample/compose/ListPage.kt @@ -71,7 +71,7 @@ enum class Page(val title: String, val subtitle: String, val showToolBar: Boolea ), Example10( title = "Example 10", - subtitle = "Horizontal year calendar - Year header and paged scrolling. Best suited for large screens.", + subtitle = "Horizontal year calendar - Paged scrolling, shows the \"Fill\" implementation of YearContentHeightMode property. Best suited for large screens.", showToolBar = true, ), Example11(