Merge pull request #1722 from Naveen3Singh/fix_event_offset
Properly handle repeating events
This commit is contained in:
commit
99f0e0f21e
|
@ -2,4 +2,4 @@ package com.simplemobiletools.calendar.pro.extensions
|
|||
|
||||
import android.util.Range
|
||||
|
||||
fun Range<Int>.touch(other: Range<Int>) = (upper >= other.lower && lower <= other.upper) || (other.upper >= lower && other.lower <= upper)
|
||||
fun Range<Int>.intersects(other: Range<Int>) = (upper >= other.lower && lower <= other.upper) || (other.upper >= lower && other.lower <= upper)
|
||||
|
|
|
@ -103,7 +103,7 @@ class MonthFragment : Fragment(), MonthlyCalendar {
|
|||
contentDescription = text
|
||||
|
||||
if (activity != null) {
|
||||
setTextColor(activity!!.getProperTextColor())
|
||||
setTextColor(requireActivity().getProperTextColor())
|
||||
}
|
||||
}
|
||||
updateDays(days)
|
||||
|
|
|
@ -35,6 +35,9 @@ import kotlinx.android.synthetic.main.week_event_marker.view.*
|
|||
import org.joda.time.DateTime
|
||||
import org.joda.time.Days
|
||||
import java.util.*
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class WeekFragment : Fragment(), WeeklyCalendar {
|
||||
private val WEEKLY_EVENT_ID_LABEL = "event_id_label"
|
||||
|
@ -132,7 +135,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
|||
}
|
||||
|
||||
val initialScrollY = (rowHeight * config.startWeeklyAt).toInt()
|
||||
updateScrollY(Math.max(listener?.getCurrScrollY() ?: 0, initialScrollY))
|
||||
updateScrollY(max(listener?.getCurrScrollY() ?: 0, initialScrollY))
|
||||
}
|
||||
|
||||
wasFragmentInit = true
|
||||
|
@ -361,7 +364,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
|||
prevScaleSpanY = detector.currentSpanY
|
||||
|
||||
val wantedFactor = config.weeklyViewItemHeightMultiplier - (SCALE_RANGE * percent)
|
||||
var newFactor = Math.max(Math.min(wantedFactor, MAX_SCALE_FACTOR), MIN_SCALE_FACTOR)
|
||||
var newFactor = max(min(wantedFactor, MAX_SCALE_FACTOR), MIN_SCALE_FACTOR)
|
||||
if (scrollView.height > defaultRowHeight * newFactor * 24) {
|
||||
newFactor = scrollView.height / 24f / defaultRowHeight
|
||||
}
|
||||
|
@ -422,7 +425,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
|||
rowHeight = context?.getWeeklyViewItemHeight() ?: return
|
||||
|
||||
val oneDp = res.getDimension(R.dimen.one_dp).toInt()
|
||||
val fullHeight = Math.max(rowHeight.toInt() * 24, scrollView.height + oneDp)
|
||||
val fullHeight = max(rowHeight.toInt() * 24, scrollView.height + oneDp)
|
||||
scrollView.layoutParams.height = fullHeight - oneDp
|
||||
mView.week_horizontal_grid_holder.layoutParams.height = fullHeight
|
||||
mView.week_events_columns_holder.layoutParams.height = fullHeight
|
||||
|
@ -440,7 +443,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
|||
|
||||
val minuteHeight = rowHeight / 60
|
||||
val minimalHeight = res.getDimension(R.dimen.weekly_view_minimal_event_height).toInt()
|
||||
val density = Math.round(res.displayMetrics.density)
|
||||
val density = res.displayMetrics.density.roundToInt()
|
||||
|
||||
for (event in events) {
|
||||
val startDateTime = Formatter.getDateTimeFromTS(event.startTS)
|
||||
|
@ -493,7 +496,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
|||
eventsCollisionChecked.add(eventId)
|
||||
val eventWeeklyViewsToCheck = eventDayList.filter { !eventsCollisionChecked.contains(it.key) }
|
||||
for ((toCheckId, eventWeeklyViewToCheck) in eventWeeklyViewsToCheck) {
|
||||
val areTouching = eventWeeklyView.range.touch(eventWeeklyViewToCheck.range)
|
||||
val areTouching = eventWeeklyView.range.intersects(eventWeeklyViewToCheck.range)
|
||||
val doHaveCommonMinutes = if (areTouching) {
|
||||
eventWeeklyView.range.upper > eventWeeklyViewToCheck.range.lower || (eventWeeklyView.range.lower == eventWeeklyView.range.upper &&
|
||||
eventWeeklyView.range.upper == eventWeeklyViewToCheck.range.lower)
|
||||
|
@ -507,7 +510,7 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
|||
val slotRange = Array(eventWeeklyView.slot_max) { it + 1 }
|
||||
val collisionEventWeeklyViews = eventDayList.filter { eventWeeklyView.collisions.contains(it.key) }
|
||||
for ((_, collisionEventWeeklyView) in collisionEventWeeklyViews) {
|
||||
if (collisionEventWeeklyView.range.touch(eventWeeklyViewToCheck.range)) {
|
||||
if (collisionEventWeeklyView.range.intersects(eventWeeklyViewToCheck.range)) {
|
||||
slotRange[collisionEventWeeklyView.slot - 1] = nextSlot
|
||||
}
|
||||
}
|
||||
|
@ -723,8 +726,8 @@ class WeekFragment : Fragment(), WeeklyCalendar {
|
|||
val startDateTime = Formatter.getDateTimeFromTS(event.startTS)
|
||||
val endDateTime = Formatter.getDateTimeFromTS(event.endTS)
|
||||
|
||||
val minTS = Math.max(startDateTime.seconds(), weekTimestamp)
|
||||
val maxTS = Math.min(endDateTime.seconds(), weekTimestamp + 2 * WEEK_SECONDS)
|
||||
val minTS = max(startDateTime.seconds(), weekTimestamp)
|
||||
val maxTS = min(endDateTime.seconds(), weekTimestamp + 2 * WEEK_SECONDS)
|
||||
|
||||
// fix a visual glitch with all-day events or events lasting multiple days starting at midnight on monday, being shown the previous week too
|
||||
if (minTS == maxTS && (minTS - weekTimestamp == WEEK_SECONDS.toLong())) {
|
||||
|
|
|
@ -8,8 +8,7 @@ import com.simplemobiletools.calendar.pro.interfaces.MonthlyCalendar
|
|||
import com.simplemobiletools.calendar.pro.models.DayMonthly
|
||||
import com.simplemobiletools.calendar.pro.models.Event
|
||||
import org.joda.time.DateTime
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.math.min
|
||||
|
||||
class MonthlyCalendarImpl(val callback: MonthlyCalendar, val context: Context) {
|
||||
private val DAYS_CNT = 42
|
||||
|
@ -83,25 +82,25 @@ class MonthlyCalendarImpl(val callback: MonthlyCalendar, val context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
// it works more often than not, dont touch
|
||||
// it works more often than not, don't touch
|
||||
private fun markDaysWithEvents(days: ArrayList<DayMonthly>) {
|
||||
val dayEvents = HashMap<String, ArrayList<Event>>()
|
||||
mEvents.forEach {
|
||||
val startDateTime = Formatter.getDateTimeFromTS(it.startTS)
|
||||
val endDateTime = Formatter.getDateTimeFromTS(it.endTS)
|
||||
mEvents.forEach { event ->
|
||||
val startDateTime = Formatter.getDateTimeFromTS(event.startTS)
|
||||
val endDateTime = Formatter.getDateTimeFromTS(event.endTS)
|
||||
val endCode = Formatter.getDayCodeFromDateTime(endDateTime)
|
||||
|
||||
var currDay = startDateTime
|
||||
var dayCode = Formatter.getDayCodeFromDateTime(currDay)
|
||||
var currDayEvents = dayEvents[dayCode] ?: ArrayList()
|
||||
currDayEvents.add(it)
|
||||
currDayEvents.add(event)
|
||||
dayEvents[dayCode] = currDayEvents
|
||||
|
||||
while (Formatter.getDayCodeFromDateTime(currDay) != endCode) {
|
||||
currDay = currDay.plusDays(1)
|
||||
dayCode = Formatter.getDayCodeFromDateTime(currDay)
|
||||
currDayEvents = dayEvents[dayCode] ?: ArrayList()
|
||||
currDayEvents.add(it)
|
||||
currDayEvents.add(event)
|
||||
dayEvents[dayCode] = currDayEvents
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +113,7 @@ class MonthlyCalendarImpl(val callback: MonthlyCalendar, val context: Context) {
|
|||
|
||||
private fun isToday(targetDate: DateTime, curDayInMonth: Int): Boolean {
|
||||
val targetMonthDays = targetDate.dayOfMonth().maximumValue
|
||||
return targetDate.withDayOfMonth(Math.min(curDayInMonth, targetMonthDays)).toString(Formatter.DAYCODE_PATTERN) == mToday
|
||||
return targetDate.withDayOfMonth(min(curDayInMonth, targetMonthDays)).toString(Formatter.DAYCODE_PATTERN) == mToday
|
||||
}
|
||||
|
||||
private val monthName: String
|
||||
|
|
|
@ -23,6 +23,8 @@ import com.simplemobiletools.commons.helpers.LOWER_ALPHA
|
|||
import com.simplemobiletools.commons.helpers.MEDIUM_ALPHA
|
||||
import org.joda.time.DateTime
|
||||
import org.joda.time.Days
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
// used in the Monthly view fragment, 1 view per screen
|
||||
class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(context, attrs, defStyle) {
|
||||
|
@ -113,16 +115,15 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
|
|||
}
|
||||
|
||||
private fun groupAllEvents() {
|
||||
days.forEach {
|
||||
val day = it
|
||||
day.dayEvents.forEach {
|
||||
val event = it
|
||||
days.forEach { day ->
|
||||
|
||||
day.dayEvents.forEach { event ->
|
||||
// make sure we properly handle events lasting multiple days and repeating ones
|
||||
val lastEvent = allEvents.lastOrNull { it.id == event.id }
|
||||
val daysCnt = getEventLastingDaysCount(event)
|
||||
val validDayEvent = isDayValid(event, day.code)
|
||||
if ((lastEvent == null || lastEvent.startDayIndex + daysCnt <= day.indexOnMonthView) && !validDayEvent) {
|
||||
|
||||
if ((lastEvent == null || lastEvent.startDayIndex + daysCnt <= findLastDay(event).indexOnMonthView) && !validDayEvent) {
|
||||
val monthViewEvent = MonthViewEvent(
|
||||
event.id!!, event.title, event.startTS, event.endTS, event.color, day.indexOnMonthView,
|
||||
daysCnt, day.indexOnMonthView, event.getIsAllDay(), event.isPastEvent, event.isTask(), event.isTaskCompleted()
|
||||
|
@ -133,8 +134,9 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
|
|||
}
|
||||
|
||||
allEvents =
|
||||
allEvents.asSequence().sortedWith(compareBy({ -it.daysCnt }, { !it.isAllDay }, { it.startTS }, { it.endTS }, { it.startDayIndex }, { it.title }))
|
||||
.toMutableList() as ArrayList<MonthViewEvent>
|
||||
allEvents.asSequence().sortedWith(
|
||||
compareBy({ -it.daysCnt }, { !it.isAllDay }, { it.startTS }, { it.endTS }, { it.startDayIndex }, { it.title })
|
||||
).toMutableList() as ArrayList<MonthViewEvent>
|
||||
}
|
||||
|
||||
override fun onDraw(canvas: Canvas) {
|
||||
|
@ -255,8 +257,8 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
|
|||
|
||||
private fun drawEvent(event: MonthViewEvent, canvas: Canvas) {
|
||||
var verticalOffset = 0
|
||||
for (i in 0 until Math.min(event.daysCnt, 7 - event.startDayIndex % 7)) {
|
||||
verticalOffset = Math.max(verticalOffset, dayVerticalOffsets[event.startDayIndex + i])
|
||||
for (i in 0 until min(event.daysCnt, 7 - event.startDayIndex % 7)) {
|
||||
verticalOffset = max(verticalOffset, dayVerticalOffsets[event.startDayIndex + i])
|
||||
}
|
||||
val xPos = event.startDayIndex % 7 * dayWidth + horizontalOffset
|
||||
val yPos = (event.startDayIndex / 7) * dayHeight
|
||||
|
@ -285,7 +287,7 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
|
|||
}
|
||||
|
||||
val startDayIndex = days[event.originalStartDayIndex]
|
||||
val endDayIndex = days[Math.min(event.startDayIndex + event.daysCnt - 1, 41)]
|
||||
val endDayIndex = days[min(event.startDayIndex + event.daysCnt - 1, 41)]
|
||||
bgRectF.set(bgLeft, bgTop, bgRight, bgBottom)
|
||||
canvas.drawRoundRect(bgRectF, BG_CORNER_RADIUS, BG_CORNER_RADIUS, getEventBackgroundColor(event, startDayIndex, endDayIndex))
|
||||
|
||||
|
@ -301,7 +303,7 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
|
|||
|
||||
drawEventTitle(event, canvas, xPos + taskIconWidth, yPos + verticalOffset, bgRight - bgLeft - smallPadding - taskIconWidth, specificEventTitlePaint)
|
||||
|
||||
for (i in 0 until Math.min(event.daysCnt, 7 - event.startDayIndex % 7)) {
|
||||
for (i in 0 until min(event.daysCnt, 7 - event.startDayIndex % 7)) {
|
||||
dayVerticalOffsets.put(event.startDayIndex + i, verticalOffset + eventTitleHeight + smallPadding * 2)
|
||||
}
|
||||
}
|
||||
|
@ -429,6 +431,12 @@ class MonthView(context: Context, attrs: AttributeSet, defStyle: Int) : View(con
|
|||
return event.startTS != event.endTS && Formatter.getDateTimeFromTS(event.endTS) == Formatter.getDateTimeFromTS(date.seconds()).withTimeAtStartOfDay()
|
||||
}
|
||||
|
||||
private fun findLastDay(event: Event): DayMonthly {
|
||||
return days.last { day ->
|
||||
day.dayEvents.find { it.id == event.id } != null
|
||||
}
|
||||
}
|
||||
|
||||
fun togglePrintMode() {
|
||||
isPrintVersion = !isPrintVersion
|
||||
textColor = if (isPrintVersion) {
|
||||
|
|
|
@ -59,7 +59,10 @@ class MonthViewWrapper(context: Context, attrs: AttributeSet, defStyle: Int) : F
|
|||
continue
|
||||
}
|
||||
|
||||
child.measure(MeasureSpec.makeMeasureSpec(dayWidth.toInt(), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dayHeight.toInt(), MeasureSpec.EXACTLY))
|
||||
child.measure(
|
||||
MeasureSpec.makeMeasureSpec(dayWidth.toInt(), MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(dayHeight.toInt(), MeasureSpec.EXACTLY)
|
||||
)
|
||||
|
||||
val childLeft = x * dayWidth + horizontalOffset - child.translationX
|
||||
val childTop = y * dayHeight + weekDaysLetterHeight - child.translationY
|
||||
|
|
Loading…
Reference in New Issue