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
39 changes: 28 additions & 11 deletions core/src/main/java/com/alamkanak/weekview/CalendarRenderer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import android.graphics.Paint
import android.graphics.RectF
import android.text.StaticLayout
import androidx.collection.ArrayMap
import com.alamkanak.weekview.WeekView.DrawBase
import java.util.Calendar
import kotlin.math.max
import kotlin.math.min

internal class CalendarRenderer(
viewState: ViewState,
private val viewState: ViewState,
eventChipsCacheProvider: EventChipsCacheProvider
) : Renderer {

Expand All @@ -29,9 +30,21 @@ internal class CalendarRenderer(
override fun render(canvas: Canvas) {
eventsUpdater.update()

drawAdditional(canvas, DrawBase.CANVAS)
for (drawer in drawers) {
drawer.draw(canvas)
drawer.draw(canvas, viewState)
drawAdditional(canvas, drawer.base)
}
drawAdditional(canvas, DrawBase.TOP)
}

private fun drawAdditional(canvas: Canvas, base: DrawBase) {
val drawers = viewState.additionalDrawers[base]
if (drawers.isNullOrEmpty()) return

val saveCount = canvas.save()
drawers.forEach { it.draw(canvas, viewState) }
canvas.restoreToCount(saveCount)
}
}

Expand Down Expand Up @@ -107,9 +120,10 @@ private class SingleEventsUpdater(

private class DayBackgroundDrawer(
private val viewState: ViewState
) : Drawer {
) : WeekView.Drawer {
override val base = DrawBase.BACKGROUND

override fun draw(canvas: Canvas) {
override fun draw(canvas: Canvas, bounds: WeekView.DrawBounds) {
canvas.drawInBounds(viewState.calendarGridBounds) {
viewState.dateRangeWithStartPixels.forEach { (date, startPixel) ->
drawDayBackground(date, startPixel, canvas)
Expand Down Expand Up @@ -167,9 +181,10 @@ private class DayBackgroundDrawer(

private class BackgroundGridDrawer(
private val viewState: ViewState
) : Drawer {
) : WeekView.Drawer {
override val base = DrawBase.GRID

override fun draw(canvas: Canvas) {
override fun draw(canvas: Canvas, bounds: WeekView.DrawBounds) {
canvas.drawInBounds(viewState.calendarGridBounds) {
if (viewState.showHourSeparators) {
drawHourLines()
Expand Down Expand Up @@ -201,7 +216,7 @@ private class BackgroundGridDrawer(
private fun Canvas.drawHourLine(hour: Int) {
val heightOfHour = (viewState.hourHeight * (hour - viewState.minHour))
val verticalOffset = viewState.headerHeight + viewState.currentOrigin.y + heightOfHour
val horizontalOffset = if (viewState.isLtr) viewState.timeColumnWidth else 0f
val horizontalOffset = viewState.calendarGridBounds.left

drawHorizontalLine(
verticalOffset = verticalOffset,
Expand All @@ -216,11 +231,12 @@ private class SingleEventsDrawer(
private val viewState: ViewState,
private val chipsCacheProvider: EventChipsCacheProvider,
private val eventLabels: ArrayMap<String, StaticLayout>
) : Drawer {
) : WeekView.Drawer {
override val base = DrawBase.EVENTS

private val eventChipDrawer = EventChipDrawer(viewState)

override fun draw(canvas: Canvas) {
override fun draw(canvas: Canvas, bounds: WeekView.DrawBounds) {
canvas.drawInBounds(viewState.calendarGridBounds) {
for (date in viewState.dateRange) {
drawEventsForDate(date)
Expand All @@ -241,9 +257,10 @@ private class SingleEventsDrawer(

private class NowLineDrawer(
private val viewState: ViewState
) : Drawer {
) : WeekView.Drawer {
override val base = DrawBase.NOWLINE

override fun draw(canvas: Canvas) {
override fun draw(canvas: Canvas, bounds: WeekView.DrawBounds) {
if (viewState.showNowLine.not()) {
return
}
Expand Down
6 changes: 3 additions & 3 deletions core/src/main/java/com/alamkanak/weekview/HeaderRenderer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ private class HeaderUpdater(
private class DateLabelsDrawer(
private val viewState: ViewState,
private val dateLabelLayouts: SparseArray<StaticLayout>
) : Drawer {
) : DrawerInternal {

override fun draw(canvas: Canvas) {
canvas.drawInBounds(viewState.headerBounds) {
Expand Down Expand Up @@ -240,7 +240,7 @@ private class AllDayEventsUpdater(
internal class AllDayEventsDrawer(
private val viewState: ViewState,
private val allDayEventLayouts: ArrayMap<EventChip, StaticLayout>
) : Drawer {
) : DrawerInternal {

private val eventChipDrawer = EventChipDrawer(viewState)

Expand Down Expand Up @@ -319,7 +319,7 @@ internal class AllDayEventsDrawer(
private class HeaderDrawer(
context: Context,
private val viewState: ViewState
) : Drawer {
) : DrawerInternal {

private val upArrow: Drawable by lazy {
checkNotNull(ContextCompat.getDrawable(context, R.drawable.ic_arrow_up))
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/java/com/alamkanak/weekview/Renderers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ internal interface Updater {
fun update()
}

internal interface Drawer {
internal interface DrawerInternal {
fun draw(canvas: Canvas)
}

Expand Down
20 changes: 11 additions & 9 deletions core/src/main/java/com/alamkanak/weekview/ViewState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@ import android.graphics.Typeface
import android.os.Build
import android.text.TextPaint
import android.view.View
import java.util.Calendar
import java.util.*
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.min

typealias DateFormatter = (Calendar) -> String
typealias TimeFormatter = (Int) -> String

internal class ViewState {
internal class ViewState : WeekView.DrawBounds {

// View
var viewWidth: Int = 0
var viewHeight: Int = 0
override var viewWidth: Int = 0
override var viewHeight: Int = 0

var isLtr: Boolean = true
override var isLtr: Boolean = true

// Calendar state
var firstVisibleDate: Calendar = today()
Expand Down Expand Up @@ -64,7 +64,7 @@ internal class ViewState {
var eventMarginVertical: Int = 0
var singleDayHorizontalPadding: Int = 0

var hourHeight: Float = 0f
override var hourHeight: Float = 0f
var minHourHeight: Float = 0f
var maxHourHeight: Float = 0f
var effectiveMinHourHeight: Float = 0f
Expand Down Expand Up @@ -95,6 +95,8 @@ internal class ViewState {

var typeface: Typeface = Typeface.DEFAULT

var additionalDrawers: Map<WeekView.DrawBase, List<WeekView.Drawer>> = emptyMap()

var timeColumnWidth: Float = 0f
var timeColumnTextHeight: Float = 0f

Expand Down Expand Up @@ -134,13 +136,13 @@ internal class ViewState {

// In LTR: Dates in the past have origin.x > 0, dates in the future have origin.x < 0
// In RTL: Dates in the past have origin.x < 0, dates in the future have origin.x > 0
var currentOrigin = PointF(0f, 0f)
override var currentOrigin = PointF(0f, 0f)

val headerBackgroundPaint = Paint()

val headerBackgroundWithShadowPaint = Paint()

val dayWidth: Float
override val dayWidth: Float
get() = (viewWidth - timeColumnWidth) / numberOfVisibleDays

val drawableDayWidth: Float
Expand Down Expand Up @@ -237,7 +239,7 @@ internal class ViewState {

private val _calendarGridBounds: RectF = RectF()

val calendarGridBounds: RectF
override val calendarGridBounds: RectF
get() = _calendarGridBounds.apply {
left = if (isLtr) timeColumnWidth else 0f
top = headerHeight
Expand Down
48 changes: 48 additions & 0 deletions core/src/main/java/com/alamkanak/weekview/WeekView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.annotation.SuppressLint
import android.content.Context
import android.content.res.Configuration
import android.graphics.Canvas
import android.graphics.PointF
import android.graphics.RectF
import android.graphics.Typeface
import android.os.Parcelable
Expand Down Expand Up @@ -1354,6 +1355,53 @@ class WeekView @JvmOverloads constructor(
invalidate()
}

/*
***********************************************************************************************
*
* Custom drawers
*
***********************************************************************************************
*/

/**
* Bounds available to [Drawer] to draw on the [Canvas] during rendering.
*/
@PublicApi
interface DrawBounds {
val calendarGridBounds: RectF
val currentOrigin: PointF
val viewWidth: Int
val viewHeight: Int
val dayWidth: Float
val hourHeight: Float
val isLtr: Boolean
}

@PublicApi
enum class DrawBase {
CANVAS, BACKGROUND, GRID, EVENTS, NOWLINE, TOP;
}

@PublicApi
interface Drawer {
fun draw(canvas: Canvas, bounds: DrawBounds)
val base: DrawBase
}

/**
* Additional drawers that will be draw on the view during rendering.
*
* Each drawer will draw on top of the layer specified by [Drawer.base]. Drawers with the same
* base will draw in the order specified in the list.
*/
@PublicApi
var additionalDrawers: List<Drawer>
get() = viewState.additionalDrawers.values.flatten()
set(value) {
viewState.additionalDrawers = value.groupBy { it.base }
invalidate()
}

/*
***********************************************************************************************
*
Expand Down
8 changes: 8 additions & 0 deletions sample/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".ui.main.MainActivity" />
</activity>
<activity
android:name=".ui.CustomDrawersActivity"
android:label="@string/week_view"
android:parentActivityName=".ui.main.MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".ui.main.MainActivity" />
</activity>
</application>

</manifest>
Loading