-
Notifications
You must be signed in to change notification settings - Fork 67
/
Copy pathMonthViewWrapper.kt
148 lines (124 loc) · 5.08 KB
/
MonthViewWrapper.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package org.fossify.calendar.views
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.FrameLayout
import org.fossify.calendar.databinding.MonthViewBackgroundBinding
import org.fossify.calendar.databinding.MonthViewBinding
import org.fossify.calendar.extensions.config
import org.fossify.calendar.helpers.COLUMN_COUNT
import org.fossify.calendar.helpers.Formatter
import org.fossify.calendar.helpers.ROW_COUNT
import org.fossify.calendar.models.DayMonthly
import org.fossify.commons.extensions.onGlobalLayout
// used in the Monthly view fragment, 1 view per screen
class MonthViewWrapper(context: Context, attrs: AttributeSet, defStyle: Int) : FrameLayout(context, attrs, defStyle) {
private var dayWidth = 0f
private var dayHeight = 0f
private var weekDaysLetterHeight = 0
private var horizontalOffset = 0
private var wereViewsAdded = false
private var isMonthDayView = true
private var days = ArrayList<DayMonthly>()
private var inflater: LayoutInflater
private var binding: MonthViewBinding
private var dayClickCallback: ((day: DayMonthly) -> Unit)? = null
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
init {
val normalTextSize = resources.getDimensionPixelSize(org.fossify.commons.R.dimen.normal_text_size).toFloat()
weekDaysLetterHeight = 2 * normalTextSize.toInt()
inflater = LayoutInflater.from(context)
binding = MonthViewBinding.inflate(inflater, this, true)
setupHorizontalOffset()
onGlobalLayout {
if (!wereViewsAdded && days.isNotEmpty()) {
measureSizes()
addClickableBackgrounds()
binding.monthView.updateDays(days, isMonthDayView)
}
}
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
measureSizes()
var y = 0
var x = 0
var curLeft = dayWidth.toInt()
val end = right + paddingRight
for (i in 0 until childCount) {
val child = getChildAt(i)
if (child is MonthView) {
//ignore the MonthView layout
continue
}
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
val childWidth = child.measuredWidth
val childHeight = child.measuredHeight
val childRight = childLeft + childWidth
val childBottom = childTop + childHeight
child.layout(childLeft.toInt(), childTop.toInt(), childRight.toInt(), childBottom.toInt())
if (curLeft + childWidth <= end) {
curLeft += childWidth
x++
} else {
y++
x = 0
curLeft = childWidth
}
}
}
fun updateDays(newDays: ArrayList<DayMonthly>, addEvents: Boolean, callback: ((DayMonthly) -> Unit)? = null) {
setupHorizontalOffset()
measureSizes()
dayClickCallback = callback
days = newDays
if (dayWidth != 0f && dayHeight != 0f) {
addClickableBackgrounds()
}
isMonthDayView = !addEvents
binding.monthView.updateDays(days, isMonthDayView)
}
private fun setupHorizontalOffset() {
horizontalOffset = if (context.config.showWeekNumbers) {
resources.getDimensionPixelSize(org.fossify.commons.R.dimen.smaller_text_size) * 2
} else {
0
}
}
private fun measureSizes() {
dayWidth = (width - horizontalOffset) / COLUMN_COUNT.toFloat()
dayHeight = (height - weekDaysLetterHeight) / ROW_COUNT.toFloat()
}
private fun addClickableBackgrounds() {
removeAllViews()
binding = MonthViewBinding.inflate(inflater, this, true)
wereViewsAdded = true
days.forEachIndexed { index, day ->
addViewBackground(index % COLUMN_COUNT, index / COLUMN_COUNT, day)
}
}
private fun addViewBackground(viewX: Int, viewY: Int, day: DayMonthly) {
MonthViewBackgroundBinding.inflate(inflater, this, false).root.apply {
if (isMonthDayView) {
background = null
}
//Accessible label composed by day and month
contentDescription = "${day.value} ${Formatter.getMonthName(context, Formatter.getDateTimeFromCode(day.code).monthOfYear)}"
setOnClickListener {
dayClickCallback?.invoke(day)
if (isMonthDayView) {
binding.monthView.updateCurrentlySelectedDay(viewX, viewY)
}
}
addView(this)
}
}
fun togglePrintMode() {
binding.monthView.togglePrintMode()
}
}