Skip to content

Commit

Permalink
Replace WeekViewEntity with more versatile WeekViewItem
Browse files Browse the repository at this point in the history
  • Loading branch information
thellmund committed Dec 19, 2021
1 parent b2dd221 commit 7d0beab
Show file tree
Hide file tree
Showing 33 changed files with 830 additions and 578 deletions.
22 changes: 19 additions & 3 deletions core/src/main/java/com/alamkanak/weekview/CalendarExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ internal fun Calendar.format(): String {
return sdf.format(time)
}

fun Calendar.computeDifferenceWithFirstDayOfWeek(): Int {
internal fun Calendar.computeDifferenceWithFirstDayOfWeek(): Int {
val firstDayOfWeek = firstDayOfWeek
return if (firstDayOfWeek == Calendar.MONDAY && dayOfWeek == Calendar.SUNDAY) {
// Special case, because Calendar.MONDAY has constant value 2 and Calendar.SUNDAY has
Expand All @@ -323,18 +323,34 @@ fun Calendar.computeDifferenceWithFirstDayOfWeek(): Int {
}
}

fun Calendar.previousFirstDayOfWeek(): Calendar {
internal fun Calendar.previousFirstDayOfWeek(): Calendar {
val result = this - Days(1)
while (result.dayOfWeek != firstDayOfWeek) {
result.add(Calendar.DATE, -1)
}
return result
}

fun Calendar.nextFirstDayOfWeek(): Calendar {
internal fun Calendar.nextFirstDayOfWeek(): Calendar {
val result = this + Days(1)
while (result.dayOfWeek != firstDayOfWeek) {
result.add(Calendar.DATE, 1)
}
return result
}

internal fun Calendar.limitToMinHour(minHour: Int): Calendar {
return if (hour < minHour) {
withTimeAtStartOfPeriod(hour = minHour)
} else {
this
}
}

internal fun Calendar.limitToMaxHour(maxHour: Int): Calendar {
return if (hour >= maxHour) {
withTimeAtEndOfPeriod(hour = maxHour)
} else {
this
}
}
16 changes: 12 additions & 4 deletions core/src/main/java/com/alamkanak/weekview/CalendarRenderer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ private class SingleEventsUpdater(
}

val eventChips = chipsCache?.normalEventChipsByDate(date).orEmpty().filter {
it.event.isWithin(viewState.minHour, viewState.maxHour)
it.item.isWithin(viewState.minHour, viewState.maxHour)
}

eventChips.calculateBounds(startPixel = modifiedStartPixel)
Expand Down Expand Up @@ -244,11 +244,19 @@ private class SingleEventsDrawer(
return
}

val sortedEventChips = eventChips.sortedBy {
it.event.id == viewState.dragState?.eventId
val (backgroundChips, foregroundChips) = eventChips.partition {
it.item.configuration.arrangement == WeekViewItem.Arrangement.Background
}

for (eventChip in sortedEventChips) {
val draggedEventId = viewState.dragState?.eventId

val sortedChips = mutableListOf<EventChip>().apply {
// Make sure that the currently dragged chip is rendered above all other chips
this += backgroundChips.sortedBy { it.item.id == draggedEventId }
this += foregroundChips.sortedBy { it.item.id == draggedEventId }
}

for (eventChip in sortedChips) {
val textLayout = eventLabels[eventChip.id]
eventChipDrawer.draw(eventChip, canvas = this, textLayout)
}
Expand Down
28 changes: 15 additions & 13 deletions core/src/main/java/com/alamkanak/weekview/DragHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ internal class DragHandler(

private val executor = DragScrollExecutor()

private val draggedEvent: ResolvedWeekViewEntity?
private val draggedEvent: WeekViewItem?
get() {
val eventsCache = eventsCacheProvider() ?: return null
val eventId = viewState.dragState?.eventId ?: return null
Expand All @@ -30,8 +30,8 @@ internal class DragHandler(

fun startDragAndDrop(eventChip: EventChip, x: Float, y: Float) {
viewState.dragState = DragState(
eventId = eventChip.eventId,
draggedEventStartTime = eventChip.event.startTime,
eventId = eventChip.itemId,
draggedEventStartTime = eventChip.item.timing.startTime,
dragStartTime = requireNotNull(touchHandler.calculateTimeFromPoint(x, y)),
)

Expand Down Expand Up @@ -84,10 +84,12 @@ internal class DragHandler(

private fun updateDraggedEvent(newStartTime: Calendar) {
val originalEvent = draggedEvent ?: return
val updatedEvent = originalEvent.createCopy(
startTime = newStartTime,
endTime = newStartTime + Minutes(originalEvent.durationInMinutes),
)
val updatedEvent = originalEvent
// TODO
// .copyWith(
// startTime = newStartTime,
// endTime = newStartTime + Minutes(originalEvent.durationInMinutes),
// )

val eventsProcessor = eventsProcessorProvider() ?: return
eventsProcessor.updateDraggedEntity(updatedEvent, viewState)
Expand Down Expand Up @@ -116,7 +118,7 @@ internal class DragHandler(
}

val draggedEvent = draggedEvent ?: return@execute
updateDraggedEvent(newStartTime = draggedEvent.startTime - Minutes(15))
updateDraggedEvent(newStartTime = draggedEvent.timing.startTime - Minutes(15))

val distance = viewState.hourHeight / 4f
navigator.scrollVerticallyBy(distance = distance * (-1))
Expand All @@ -132,7 +134,7 @@ internal class DragHandler(
}

val draggedEvent = draggedEvent ?: return@execute
updateDraggedEvent(newStartTime = draggedEvent.startTime + Minutes(15))
updateDraggedEvent(newStartTime = draggedEvent.timing.startTime + Minutes(15))

val distance = viewState.hourHeight / 4f
navigator.scrollVerticallyBy(distance = distance)
Expand All @@ -142,19 +144,19 @@ internal class DragHandler(
private fun scrollLeft() {
executor.execute(delay = 600) {
val draggedEvent = draggedEvent ?: return@execute
updateDraggedEvent(newStartTime = draggedEvent.startTime - Days(1))
updateDraggedEvent(newStartTime = draggedEvent.timing.startTime - Days(1))

val date = draggedEvent.startTime.atStartOfDay
val date = draggedEvent.timing.startTime.atStartOfDay
navigator.scrollHorizontallyTo(date - Days(1))
}
}

private fun scrollRight() {
executor.execute(delay = 600) {
val draggedEvent = draggedEvent ?: return@execute
updateDraggedEvent(newStartTime = draggedEvent.startTime + Days(1))
updateDraggedEvent(newStartTime = draggedEvent.timing.startTime + Days(1))

val date = draggedEvent.startTime.atStartOfDay
val date = draggedEvent.timing.startTime.atStartOfDay
navigator.scrollHorizontallyTo(date + Days(1))
}
}
Expand Down
18 changes: 9 additions & 9 deletions core/src/main/java/com/alamkanak/weekview/EventChip.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import android.graphics.RectF
import java.util.Calendar

/**
* This class encapsulates a [ResolvedWeekViewEntity] and its visual representation, a [RectF] which
* is drawn to the screen. There may be more than one [EventChip] for any [ResolvedWeekViewEntity],
* for instance in the case of multi-day events.
* This class encapsulates a [WeekViewItem] and its visual representation, a [RectF] which is drawn
* to the screen. There may be more than one [EventChip] for any [WeekViewItem], for instance in the
* case of multi-day events.
*/
internal data class EventChip(
val event: ResolvedWeekViewEntity,
val item: WeekViewItem,
val index: Int,
val startTime: Calendar,
val endTime: Calendar,
Expand All @@ -18,12 +18,12 @@ internal data class EventChip(
/**
* A unique ID of this [EventChip].
*/
val id: String = "${event.id}-$index"
val id: String = "${item.id}-$index"

/**
* The ID of this [EventChip]'s [ResolvedWeekViewEntity].
* The ID of this [EventChip]'s [WeekViewItem].
*/
val eventId: Long = event.id
val itemId: Long = item.id

/**
* The bounds in which [EventChip] will be drawn.
Expand Down Expand Up @@ -62,10 +62,10 @@ internal data class EventChip(
var minutesFromStartHour: Int = 0

val startsOnEarlierDay: Boolean
get() = event.startTime < startTime
get() = item.timing.startTime < startTime

val endsOnLaterDay: Boolean
get() = event.endTime > endTime
get() = item.timing.endTime > endTime

fun setEmpty() {
bounds.setEmpty()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,10 @@ internal class EventChipBoundsCalculator(
eventChip: EventChip,
startPixel: Float
): RectF {
val drawableWidth = when (eventChip.event) {
is ResolvedWeekViewEntity.Event<*> -> viewState.drawableDayWidth
is ResolvedWeekViewEntity.BlockedTime -> viewState.dayWidth
}
val respectDayGap = eventChip.item.configuration.respectDayGap
val drawableWidth = if (respectDayGap) viewState.drawableDayWidth else viewState.dayWidth

val isBlockedTime = eventChip.event is ResolvedWeekViewEntity.BlockedTime
val leftOffset = if (viewState.isLtr || isBlockedTime) 0 else viewState.columnGap
val leftOffset = if (viewState.isLtr || !respectDayGap) 0 else viewState.columnGap

val minutesFromStart = eventChip.minutesFromStartHour
val top = calculateDistanceFromTop(minutesFromStart)
Expand All @@ -27,7 +24,7 @@ internal class EventChipBoundsCalculator(
val partialEventEndsAtEndOfDay = eventChip.endTime.isAtEndOfPeriod(hour = viewState.maxHour)
val fullEventContinuesOnNextDay = eventChip.endsOnLaterDay

if (!(partialEventEndsAtEndOfDay && fullEventContinuesOnNextDay) && !isBlockedTime) {
if (!(partialEventEndsAtEndOfDay && fullEventContinuesOnNextDay)) {
// There's only one case where we don't render a vertical margin: The partial event ends
// at midnight, but the full event continues continues on the next day.
bottom -= viewState.eventMarginVertical
Expand All @@ -49,7 +46,7 @@ internal class EventChipBoundsCalculator(
right -= viewState.singleDayHorizontalPadding * 2
}

val isBeingDragged = eventChip.eventId == viewState.dragState?.eventId
val isBeingDragged = eventChip.itemId == viewState.dragState?.eventId
if (isBeingDragged) {
left = startPixel + leftOffset
right = left + drawableWidth
Expand Down
52 changes: 20 additions & 32 deletions core/src/main/java/com/alamkanak/weekview/EventChipDrawer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,39 +17,27 @@ internal class EventChipDrawer(
private val backgroundPaint = Paint()
private val borderPaint = Paint()

private val patternPaint = Paint(Paint.ANTI_ALIAS_FLAG)

internal fun draw(
eventChip: EventChip,
canvas: Canvas,
textLayout: StaticLayout?
) = with(canvas) {
val entity = eventChip.event
val item = eventChip.item
val bounds = eventChip.bounds
val cornerRadius = (entity.style.cornerRadius ?: viewState.eventCornerRadius).toFloat()
val cornerRadius = (item.style.cornerRadius ?: viewState.eventCornerRadius).toFloat()

val isBeingDragged = entity.id == viewState.dragState?.eventId
updateBackgroundPaint(entity, isBeingDragged, backgroundPaint)
val isBeingDragged = item.id == viewState.dragState?.eventId
updateBackgroundPaint(item, isBeingDragged, backgroundPaint)
drawRoundRect(bounds, cornerRadius, cornerRadius, backgroundPaint)

val pattern = entity.style.pattern
if (pattern != null) {
drawPattern(
pattern = pattern,
bounds = eventChip.bounds,
isLtr = viewState.isLtr,
paint = patternPaint
)
}

val borderWidth = entity.style.borderWidth
val borderWidth = item.style.borderWidth
if (borderWidth != null && borderWidth > 0) {
updateBorderPaint(entity, borderPaint)
updateBorderPaint(item, borderPaint)
val borderBounds = bounds.insetBy(borderWidth / 2f)
drawRoundRect(borderBounds, cornerRadius, cornerRadius, borderPaint)
}

if (entity.isMultiDay && entity.isNotAllDay) {
if (item.isMultiDay && item.isNotAllDay) {
drawCornersForMultiDayEvents(eventChip, cornerRadius)
}

Expand All @@ -62,11 +50,11 @@ internal class EventChipDrawer(
eventChip: EventChip,
cornerRadius: Float
) {
val event = eventChip.event
val item = eventChip.item
val bounds = eventChip.bounds

val isBeingDragged = event.id == viewState.dragState?.eventId
updateBackgroundPaint(event, isBeingDragged, backgroundPaint)
val isBeingDragged = item.id == viewState.dragState?.eventId
updateBackgroundPaint(item, isBeingDragged, backgroundPaint)

if (eventChip.startsOnEarlierDay) {
val topRect = RectF(bounds)
Expand All @@ -80,7 +68,7 @@ internal class EventChipDrawer(
drawRect(bottomRect, backgroundPaint)
}

if (event.style.borderWidth != null) {
if (item.style.borderWidth != null) {
drawMultiDayBorderStroke(eventChip, cornerRadius)
}
}
Expand All @@ -89,14 +77,14 @@ internal class EventChipDrawer(
eventChip: EventChip,
cornerRadius: Float
) {
val event = eventChip.event
val item = eventChip.item
val bounds = eventChip.bounds

val borderWidth = event.style.borderWidth ?: 0
val borderWidth = item.style.borderWidth ?: 0
val borderStart = bounds.left + borderWidth / 2
val borderEnd = bounds.right - borderWidth / 2

updateBorderPaint(event, backgroundPaint)
updateBorderPaint(item, backgroundPaint)

if (eventChip.startsOnEarlierDay) {
drawVerticalLine(
Expand Down Expand Up @@ -143,7 +131,7 @@ internal class EventChipDrawer(
bounds.right - viewState.eventPaddingHorizontal
}

val verticalOffset = if (eventChip.event.isAllDay) {
val verticalOffset = if (eventChip.item.isAllDay) {
(bounds.height() - textLayout.height) / 2f
} else {
viewState.eventPaddingVertical.toFloat()
Expand All @@ -155,11 +143,11 @@ internal class EventChipDrawer(
}

private fun updateBackgroundPaint(
entity: ResolvedWeekViewEntity,
item: WeekViewItem,
isBeingDragged: Boolean,
paint: Paint
) = with(paint) {
color = entity.style.backgroundColor ?: viewState.defaultEventColor
color = item.style.backgroundColor ?: viewState.defaultEventColor
isAntiAlias = true
strokeWidth = 0f
style = Paint.Style.FILL
Expand All @@ -172,12 +160,12 @@ internal class EventChipDrawer(
}

private fun updateBorderPaint(
entity: ResolvedWeekViewEntity,
item: WeekViewItem,
paint: Paint
) = with(paint) {
color = entity.style.borderColor ?: viewState.defaultEventColor
color = item.style.borderColor ?: viewState.defaultEventColor
isAntiAlias = true
strokeWidth = entity.style.borderWidth?.toFloat() ?: 0f
strokeWidth = item.style.borderWidth?.toFloat() ?: 0f
style = Paint.Style.STROKE
}
}
Loading

0 comments on commit 7d0beab

Please sign in to comment.