summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMahi Kolla <mahikolla@google.com>2021-06-29 23:56:37 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2021-06-29 23:56:37 +0000
commited0be94c76e3f60561f2889ed50e6143d554e4ce (patch)
tree3d7d92a8cb70edac5f12574c019e5f8f0457c0af
parentb93cd7f52ce8e82ea29be680fb66d69249965960 (diff)
parent530f46a9308034c31fb32811173e3c572309c690 (diff)
downloadCalendar-ed0be94c76e3f60561f2889ed50e6143d554e4ce.tar.gz
Merge changes from topic "SimpleDayPickerFragment"
* changes: AOSP/Calendar - Add Kotlin code for SimpleDayPickerFragment.kt. Also uploaded corresponding Android.bp file AOSP/Calendar - Given the changes to SimpleDayPickerFragment.kt, these 3 other files had to be modified to fix build errors AOSP/Calendar - Initial conversion of SimpleDayPickerFragment as performed by Android Studio's automatic converter. AOSP/Calendar - Add Kotlin copy of SimpleDayPickerFragment.java
-rw-r--r--Android.bp1
-rw-r--r--src/com/android/calendar/CalendarController.kt192
-rw-r--r--src/com/android/calendar/EventInfoActivity.kt26
-rw-r--r--src/com/android/calendar/month/MonthByWeekFragment.kt118
-rw-r--r--src/com/android/calendar/month/SimpleDayPickerFragment.kt609
5 files changed, 778 insertions, 168 deletions
diff --git a/Android.bp b/Android.bp
index 130217aa..92fe4a3f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -40,6 +40,7 @@ exclude_srcsd = [
exclude_srcsm = [
"src/**/calendar/month/MonthListView.java",
"src/**/calendar/month/SimpleWeekView.java",
+ "src/**/calendar/month/SimpleDayPickerFragment.java",
"src/**/calendar/AsyncQueryServiceHelper.java",
"src/**/calendar/CalendarApplication.java",
"src/**/calendar/CalendarBackupAgent.java",
diff --git a/src/com/android/calendar/CalendarController.kt b/src/com/android/calendar/CalendarController.kt
index b5484ffc..4d41d3b7 100644
--- a/src/com/android/calendar/CalendarController.kt
+++ b/src/com/android/calendar/CalendarController.kt
@@ -33,17 +33,17 @@ import java.util.LinkedHashMap
import java.util.LinkedList
import java.util.WeakHashMap
-class CalendarController private constructor(context: Context) {
+class CalendarController private constructor(context: Context?) {
private var mContext: Context? = null
// This uses a LinkedHashMap so that we can replace fragments based on the
// view id they are being expanded into since we can't guarantee a reference
// to the handler will be findable
private val eventHandlers: LinkedHashMap<Integer, EventHandler> =
- LinkedHashMap<Integer, EventHandler>(5)
+ LinkedHashMap<Integer, EventHandler>(5)
private val mToBeRemovedEventHandlers: LinkedList<Integer> = LinkedList<Integer>()
private val mToBeAddedEventHandlers: LinkedHashMap<Integer, EventHandler> =
- LinkedHashMap<Integer, EventHandler>()
+ LinkedHashMap<Integer, EventHandler>()
private var mFirstEventHandler: Pair<Integer, EventHandler>? = null
private var mToBeAddedFirstEventHandler: Pair<Integer, EventHandler>? = null
@@ -185,17 +185,17 @@ class CalendarController private constructor(context: Context) {
var extra = if (allDay) ALL_DAY_MASK else 0
extra = when (response) {
Attendees.ATTENDEE_STATUS_NONE -> extra or
- ATTENDEE_STATUS_NONE_MASK.toLong()
+ ATTENDEE_STATUS_NONE_MASK.toLong()
Attendees.ATTENDEE_STATUS_ACCEPTED -> extra or
- ATTENDEE_STATUS_ACCEPTED_MASK.toLong()
+ ATTENDEE_STATUS_ACCEPTED_MASK.toLong()
Attendees.ATTENDEE_STATUS_DECLINED -> extra or
- ATTENDEE_STATUS_DECLINED_MASK.toLong()
+ ATTENDEE_STATUS_DECLINED_MASK.toLong()
Attendees.ATTENDEE_STATUS_TENTATIVE -> extra or
- ATTENDEE_STATUS_TENTATIVE_MASK.toLong()
+ ATTENDEE_STATUS_TENTATIVE_MASK.toLong()
else -> {
Log.wtf(
- TAG,
- "Unknown attendee response $response"
+ TAG,
+ "Unknown attendee response $response"
)
extra or ATTENDEE_STATUS_NONE_MASK.toLong()
}
@@ -217,23 +217,23 @@ class CalendarController private constructor(context: Context) {
}
fun sendEventRelatedEvent(
- sender: Object?,
- eventType: Long,
- eventId: Long,
- startMillis: Long,
- endMillis: Long,
- x: Int,
- y: Int,
- selectedMillis: Long
+ sender: Object?,
+ eventType: Long,
+ eventId: Long,
+ startMillis: Long,
+ endMillis: Long,
+ x: Int,
+ y: Int,
+ selectedMillis: Long
) {
// TODO: pass the real allDay status or at least a status that says we don't know the
// status and have the receiver query the data.
// The current use of this method for VIEW_EVENT is by the day view to show an EventInfo
// so currently the missing allDay status has no effect.
sendEventRelatedEventWithExtra(
- sender, eventType, eventId, startMillis, endMillis, x, y,
- EventInfo.buildViewExtraLong(Attendees.ATTENDEE_STATUS_NONE, false),
- selectedMillis
+ sender, eventType, eventId, startMillis, endMillis, x, y,
+ EventInfo.buildViewExtraLong(Attendees.ATTENDEE_STATUS_NONE, false),
+ selectedMillis
)
}
@@ -252,19 +252,19 @@ class CalendarController private constructor(context: Context) {
* @param selectedMillis The time to specify as selected
*/
fun sendEventRelatedEventWithExtra(
- sender: Object?,
- eventType: Long,
- eventId: Long,
- startMillis: Long,
- endMillis: Long,
- x: Int,
- y: Int,
- extraLong: Long,
- selectedMillis: Long
+ sender: Object?,
+ eventType: Long,
+ eventId: Long,
+ startMillis: Long,
+ endMillis: Long,
+ x: Int,
+ y: Int,
+ extraLong: Long,
+ selectedMillis: Long
) {
sendEventRelatedEventWithExtraWithTitleWithCalendarId(
- sender, eventType, eventId,
- startMillis, endMillis, x, y, extraLong, selectedMillis, null, -1
+ sender, eventType, eventId,
+ startMillis, endMillis, x, y, extraLong, selectedMillis, null, -1
)
}
@@ -285,17 +285,17 @@ class CalendarController private constructor(context: Context) {
* @param calendarId The id of the calendar which the event belongs to
*/
fun sendEventRelatedEventWithExtraWithTitleWithCalendarId(
- sender: Object?,
- eventType: Long,
- eventId: Long,
- startMillis: Long,
- endMillis: Long,
- x: Int,
- y: Int,
- extraLong: Long,
- selectedMillis: Long,
- title: String?,
- calendarId: Long
+ sender: Object?,
+ eventType: Long,
+ eventId: Long,
+ startMillis: Long,
+ endMillis: Long,
+ x: Int,
+ y: Int,
+ extraLong: Long,
+ selectedMillis: Long,
+ title: String?,
+ calendarId: Long
) {
val info = EventInfo()
info.eventType = eventType
@@ -332,16 +332,16 @@ class CalendarController private constructor(context: Context) {
* @param viewType [ViewType]
*/
fun sendEvent(
- sender: Object?,
- eventType: Long,
- start: Time?,
- end: Time?,
- eventId: Long,
- viewType: Int
+ sender: Object?,
+ eventType: Long,
+ start: Time?,
+ end: Time?,
+ eventId: Long,
+ viewType: Int
) {
sendEvent(
- sender, eventType, start, end, start, eventId, viewType, EXTRA_GOTO_TIME, null,
- null
+ sender, eventType, start, end, start, eventId, viewType, EXTRA_GOTO_TIME, null,
+ null
)
}
@@ -349,33 +349,33 @@ class CalendarController private constructor(context: Context) {
* sendEvent() variant with extraLong, search query, and search component name.
*/
fun sendEvent(
- sender: Object?,
- eventType: Long,
- start: Time?,
- end: Time?,
- eventId: Long,
- viewType: Int,
- extraLong: Long,
- query: String?,
- componentName: ComponentName?
+ sender: Object?,
+ eventType: Long,
+ start: Time?,
+ end: Time?,
+ eventId: Long,
+ viewType: Int,
+ extraLong: Long,
+ query: String?,
+ componentName: ComponentName?
) {
sendEvent(
- sender, eventType, start, end, start, eventId, viewType, extraLong, query,
- componentName
+ sender, eventType, start, end, start, eventId, viewType, extraLong, query,
+ componentName
)
}
fun sendEvent(
- sender: Object?,
- eventType: Long,
- start: Time?,
- end: Time?,
- selected: Time?,
- eventId: Long,
- viewType: Int,
- extraLong: Long,
- query: String?,
- componentName: ComponentName?
+ sender: Object?,
+ eventType: Long,
+ start: Time?,
+ end: Time?,
+ selected: Time?,
+ eventId: Long,
+ viewType: Int,
+ extraLong: Long,
+ query: String?,
+ componentName: ComponentName?
) {
val info = EventInfo()
info.eventType = eventType
@@ -414,21 +414,21 @@ class CalendarController private constructor(context: Context) {
} else if (event.viewType != ViewType.EDIT) {
viewType = event.viewType
if (event.viewType == ViewType.AGENDA || event.viewType == ViewType.DAY ||
- Utils.getAllowWeekForDetailView() && event.viewType == ViewType.WEEK) {
+ Utils.getAllowWeekForDetailView() && event.viewType == ViewType.WEEK) {
mDetailViewType = viewType
}
}
if (DEBUG) {
Log.d(TAG, "vvvvvvvvvvvvvvv")
Log.d(
- TAG,
- "Start " + if (event.startTime == null) "null" else event.startTime.toString()
+ TAG,
+ "Start " + if (event.startTime == null) "null" else event.startTime.toString()
)
Log.d(TAG, "End " + if (event.endTime == null) "null" else event.endTime.toString())
Log.d(
- TAG,
- "Select " + if (event.selectedTime == null) "null"
- else event.selectedTime.toString()
+ TAG,
+ "Select " + if (event.selectedTime == null) "null"
+ else event.selectedTime.toString()
)
Log.d(TAG, "mTime " + if (mTime == null) "null" else mTime.toString())
}
@@ -449,7 +449,7 @@ class CalendarController private constructor(context: Context) {
val mtimeMillis: Long = mTime?.toMillis(false) as Long
val temp2 = event.endTime
if (mtimeMillis < startMillis ||
- temp2 != null && mtimeMillis > temp2.toMillis(false)) {
+ temp2 != null && mtimeMillis > temp2.toMillis(false)) {
mTime?.set(event.startTime)
}
}
@@ -466,16 +466,16 @@ class CalendarController private constructor(context: Context) {
}
if (DEBUG) {
Log.d(
- TAG,
- "Start " + if (event.startTime == null) "null" else
- event.startTime.toString()
+ TAG,
+ "Start " + if (event.startTime == null) "null" else
+ event.startTime.toString()
)
Log.d(TAG, "End " + if (event.endTime == null) "null" else
event.endTime.toString())
Log.d(
- TAG,
- "Select " + if (event.selectedTime == null) "null" else
- event.selectedTime.toString()
+ TAG,
+ "Select " + if (event.selectedTime == null) "null" else
+ event.selectedTime.toString()
)
Log.d(TAG, "mTime " + if (mTime == null) "null" else mTime.toString())
Log.d(TAG, "^^^^^^^^^^^^^^^")
@@ -494,8 +494,8 @@ class CalendarController private constructor(context: Context) {
mDispatchInProgressCounter++
if (DEBUG) {
Log.d(
- TAG,
- "sendEvent: Dispatching to " + eventHandlers.size.toString() + " handlers"
+ TAG,
+ "sendEvent: Dispatching to " + eventHandlers.size.toString() + " handlers"
)
}
// Dispatch to event handler(s)
@@ -504,16 +504,16 @@ class CalendarController private constructor(context: Context) {
// Handle the 'first' one before handling the others
val handler: EventHandler? = mFirstEventHandler?.second
if (handler != null && handler.supportedEventTypes and event.eventType != 0L &&
- !mToBeRemovedEventHandlers.contains(mFirstEventHandler?.first)) {
+ !mToBeRemovedEventHandlers.contains(mFirstEventHandler?.first)) {
handler.handleEvent(event)
handled = true
}
}
val handlers: MutableIterator<MutableMap.MutableEntry<Integer,
- CalendarController.EventHandler>> = eventHandlers.entries.iterator()
+ CalendarController.EventHandler>> = eventHandlers.entries.iterator()
while (handlers.hasNext()) {
val entry: MutableMap.MutableEntry<Integer,
- CalendarController.EventHandler> = handlers.next()
+ CalendarController.EventHandler> = handlers.next()
val key: Int = entry.key.toInt()
val temp4 = mFirstEventHandler
if (temp4 != null && key.toInt() == temp4.first.toInt()) {
@@ -522,7 +522,7 @@ class CalendarController private constructor(context: Context) {
}
val eventHandler: EventHandler = entry.value
if (eventHandler != null &&
- eventHandler.supportedEventTypes and event.eventType != 0L) {
+ eventHandler.supportedEventTypes and event.eventType != 0L) {
if (mToBeRemovedEventHandlers.contains(key as Integer)) {
continue
}
@@ -569,7 +569,7 @@ class CalendarController private constructor(context: Context) {
synchronized(this) {
if (mDispatchInProgressCounter > 0) {
mToBeAddedEventHandlers.put(key,
- eventHandler as CalendarController.EventHandler)
+ eventHandler as CalendarController.EventHandler)
} else {
eventHandlers.put(key, eventHandler as CalendarController.EventHandler)
}
@@ -687,7 +687,7 @@ class CalendarController private constructor(context: Context) {
const val MIN_CALENDAR_WEEK = 0
const val MAX_CALENDAR_WEEK = 3497 // weeks between 1/1/1970 and 1/1/2037
private val instances: WeakHashMap<Context, WeakReference<CalendarController>> =
- WeakHashMap<Context, WeakReference<CalendarController>>()
+ WeakHashMap<Context, WeakReference<CalendarController>>()
/**
* Pass to the ExtraLong parameter for EventType.GO_TO to signal the time
@@ -704,7 +704,7 @@ class CalendarController private constructor(context: Context) {
*
* @param context The activity if at all possible.
*/
- @JvmStatic fun getInstance(context: Context): CalendarController {
+ @JvmStatic fun getInstance(context: Context?): CalendarController? {
synchronized(instances) {
var controller: CalendarController? = null
val weakController: WeakReference<CalendarController>? = instances.get(context)
@@ -735,9 +735,9 @@ class CalendarController private constructor(context: Context) {
mUpdateTimezone.run()
mTime?.setToNow()
mDetailViewType = Utils.getSharedPreference(
- mContext,
- GeneralPreferences.KEY_DETAILED_VIEW,
- GeneralPreferences.DEFAULT_DETAILED_VIEW
+ mContext,
+ GeneralPreferences.KEY_DETAILED_VIEW,
+ GeneralPreferences.DEFAULT_DETAILED_VIEW
)
}
} \ No newline at end of file
diff --git a/src/com/android/calendar/EventInfoActivity.kt b/src/com/android/calendar/EventInfoActivity.kt
index 8c15b992..c0a1b9cd 100644
--- a/src/com/android/calendar/EventInfoActivity.kt
+++ b/src/com/android/calendar/EventInfoActivity.kt
@@ -76,8 +76,8 @@ class EventInfoActivity : Activity() {
mStartMillis = intent.getLongExtra(EXTRA_EVENT_BEGIN_TIME, 0)
mEndMillis = intent.getLongExtra(EXTRA_EVENT_END_TIME, 0)
attendeeResponse = intent.getIntExtra(
- ATTENDEE_STATUS,
- Attendees.ATTENDEE_STATUS_NONE
+ ATTENDEE_STATUS,
+ Attendees.ATTENDEE_STATUS_NONE
)
val data: Uri? = intent.getData()
if (data != null) {
@@ -117,10 +117,10 @@ class EventInfoActivity : Activity() {
// close the activity and show the event in AllInOne.
val res: Resources = getResources()
if (!res.getBoolean(R.bool.agenda_show_event_info_full_screen) &&
- !res.getBoolean(R.bool.show_event_info_full_screen)
+ !res.getBoolean(R.bool.show_event_info_full_screen)
) {
CalendarController.getInstance(this)
- .launchViewEvent(mEventId, mStartMillis, mEndMillis, attendeeResponse)
+ ?.launchViewEvent(mEventId, mStartMillis, mEndMillis, attendeeResponse)
finish()
return
}
@@ -140,13 +140,13 @@ class EventInfoActivity : Activity() {
val fragmentManager: FragmentManager = getFragmentManager()
val ft: FragmentTransaction = fragmentManager.beginTransaction()
mInfoFragment = EventInfoFragment(
- this,
- mEventId,
- mStartMillis,
- mEndMillis,
- attendeeResponse,
- isDialog,
- if (isDialog) EventInfoFragment.DIALOG_WINDOW_STYLE
+ this,
+ mEventId,
+ mStartMillis,
+ mEndMillis,
+ attendeeResponse,
+ isDialog,
+ if (isDialog) EventInfoFragment.DIALOG_WINDOW_STYLE
else EventInfoFragment.FULL_WINDOW_STYLE
)
ft.replace(R.id.main_frame, mInfoFragment)
@@ -174,8 +174,8 @@ class EventInfoActivity : Activity() {
protected override fun onResume() {
super.onResume()
getContentResolver().registerContentObserver(
- CalendarContract.Events.CONTENT_URI,
- true, mObserver
+ CalendarContract.Events.CONTENT_URI,
+ true, mObserver
)
}
diff --git a/src/com/android/calendar/month/MonthByWeekFragment.kt b/src/com/android/calendar/month/MonthByWeekFragment.kt
index d03b7464..7c1eec9a 100644
--- a/src/com/android/calendar/month/MonthByWeekFragment.kt
+++ b/src/com/android/calendar/month/MonthByWeekFragment.kt
@@ -53,10 +53,10 @@ import java.util.Calendar
import java.util.HashMap
class MonthByWeekFragment @JvmOverloads constructor(
- initialTime: Long = System.currentTimeMillis(),
- protected var mIsMiniMonth: Boolean = true
+ initialTime: Long = System.currentTimeMillis(),
+ protected var mIsMiniMonth: Boolean = true
) : SimpleDayPickerFragment(initialTime), CalendarController.EventHandler,
- LoaderManager.LoaderCallbacks<Cursor?>, OnScrollListener, OnTouchListener {
+ LoaderManager.LoaderCallbacks<Cursor?>, OnScrollListener, OnTouchListener {
protected var mMinimumTwoMonthFlingVelocity = 0f
protected var mHideDeclined = false
protected var mFirstLoadedJulianDay = 0
@@ -83,7 +83,7 @@ class MonthByWeekFragment @JvmOverloads constructor(
mFirstVisibleDay.timezone = tz
mFirstVisibleDay.normalize(true)
if (mAdapter != null) {
- mAdapter.refresh()
+ mAdapter?.refresh()
}
}
}
@@ -115,9 +115,9 @@ class MonthByWeekFragment @JvmOverloads constructor(
override fun run() {
if (!mIsDetached) {
mLoader = getLoaderManager().initLoader(
- 0, null,
- this@MonthByWeekFragment
- ) as CursorLoader
+ 0, null,
+ this@MonthByWeekFragment
+ ) as? CursorLoader
}
}
}
@@ -129,7 +129,7 @@ class MonthByWeekFragment @JvmOverloads constructor(
* @return The new Uri to use
*/
private fun updateUri(): Uri {
- val child: SimpleWeekView? = mListView.getChildAt(0) as? SimpleWeekView
+ val child: SimpleWeekView? = mListView?.getChildAt(0) as? SimpleWeekView
if (child != null) {
val julianDay: Int = child?.getFirstJulianDay()
mFirstLoadedJulianDay = julianDay
@@ -169,7 +169,7 @@ class MonthByWeekFragment @JvmOverloads constructor(
var where = WHERE_CALENDARS_VISIBLE
if (mHideDeclined || !mShowDetailsInMonth) {
where += (" AND " + Instances.SELF_ATTENDEE_STATUS.toString() + "!=" +
- Attendees.ATTENDEE_STATUS_DECLINED)
+ Attendees.ATTENDEE_STATUS_DECLINED)
}
return where
}
@@ -191,7 +191,7 @@ class MonthByWeekFragment @JvmOverloads constructor(
super.onAttach(activity)
mTZUpdater.run()
if (mAdapter != null) {
- mAdapter.setSelectedDay(mSelectedDay)
+ mAdapter?.setSelectedDay(mSelectedDay)
}
mIsDetached = false
val viewConfig: ViewConfiguration = ViewConfiguration.get(activity)
@@ -212,7 +212,7 @@ class MonthByWeekFragment @JvmOverloads constructor(
super.onDetach()
if (mShowCalendarControls) {
if (mListView != null) {
- mListView.removeCallbacks(mLoadingRunnable)
+ mListView?.removeCallbacks(mLoadingRunnable)
}
}
}
@@ -227,24 +227,24 @@ class MonthByWeekFragment @JvmOverloads constructor(
weekParams.put(SimpleWeeksAdapter.WEEK_PARAMS_WEEK_START, mFirstDayOfWeek)
weekParams.put(MonthByWeekAdapter.WEEK_PARAMS_IS_MINI, if (mIsMiniMonth) 1 else 0)
weekParams.put(
- SimpleWeeksAdapter.WEEK_PARAMS_JULIAN_DAY,
- Time.getJulianDay(mSelectedDay.toMillis(true), mSelectedDay.gmtoff)
+ SimpleWeeksAdapter.WEEK_PARAMS_JULIAN_DAY,
+ Time.getJulianDay(mSelectedDay.toMillis(true), mSelectedDay.gmtoff)
)
weekParams.put(SimpleWeeksAdapter.WEEK_PARAMS_DAYS_PER_WEEK, mDaysPerWeek)
if (mAdapter == null) {
mAdapter = MonthByWeekAdapter(getActivity(), weekParams)
- mAdapter.registerDataSetObserver(mObserver)
+ mAdapter?.registerDataSetObserver(mObserver)
} else {
- mAdapter.updateParams(weekParams)
+ mAdapter?.updateParams(weekParams)
}
- mAdapter.notifyDataSetChanged()
+ mAdapter?.notifyDataSetChanged()
}
@Override
override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
): View {
val v: View
v = if (mIsMiniMonth) {
@@ -252,27 +252,27 @@ class MonthByWeekFragment @JvmOverloads constructor(
} else {
inflater.inflate(R.layout.full_month_by_week, container, false)
}
- mDayNamesHeader = v.findViewById(R.id.day_names) as ViewGroup
+ mDayNamesHeader = v.findViewById(R.id.day_names) as? ViewGroup
return v
}
@Override
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
- mListView.setSelector(StateListDrawable())
- mListView.setOnTouchListener(this)
+ mListView?.setSelector(StateListDrawable())
+ mListView?.setOnTouchListener(this)
if (!mIsMiniMonth) {
- mListView.setBackgroundColor(getResources().getColor(R.color.month_bgcolor))
+ mListView?.setBackgroundColor(getResources().getColor(R.color.month_bgcolor))
}
// To get a smoother transition when showing this fragment, delay loading of events until
// the fragment is expended fully and the calendar controls are gone.
if (mShowCalendarControls) {
- mListView.postDelayed(mLoadingRunnable, mEventsLoadingDelay.toLong())
+ mListView?.postDelayed(mLoadingRunnable, mEventsLoadingDelay.toLong())
} else {
- mLoader = getLoaderManager().initLoader(0, null, this) as CursorLoader
+ mLoader = getLoaderManager().initLoader(0, null, this) as? CursorLoader
}
- mAdapter.setListView(mListView)
+ mAdapter?.setListView(mListView)
}
@Override
@@ -284,8 +284,8 @@ class MonthByWeekFragment @JvmOverloads constructor(
mDayLabels = arrayOfNulls<String>(7)
for (i in Calendar.SUNDAY..Calendar.SATURDAY) {
mDayLabels[i - Calendar.SUNDAY] = DateUtils.getDayOfWeekString(
- i,
- DateUtils.LENGTH_MEDIUM
+ i,
+ DateUtils.LENGTH_MEDIUM
).toUpperCase()
}
}
@@ -299,13 +299,13 @@ class MonthByWeekFragment @JvmOverloads constructor(
var loader: CursorLoader?
synchronized(mUpdateLoader) {
mFirstLoadedJulianDay =
- (Time.getJulianDay(mSelectedDay.toMillis(true), mSelectedDay.gmtoff) -
- mNumWeeks * 7 / 2)
+ (Time.getJulianDay(mSelectedDay.toMillis(true), mSelectedDay.gmtoff) -
+ mNumWeeks * 7 / 2)
mEventUri = updateUri()
val where = updateWhere()
loader = CursorLoader(
- getActivity(), mEventUri, Event.EVENT_PROJECTION, where,
- null /* WHERE_CALENDARS_SELECTED_ARGS */, INSTANCES_SORT_ORDER
+ getActivity(), mEventUri, Event.EVENT_PROJECTION, where,
+ null /* WHERE_CALENDARS_SELECTED_ARGS */, INSTANCES_SORT_ORDER
)
loader?.setUpdateThrottle(LOADER_THROTTLE_DELAY.toLong())
}
@@ -326,7 +326,7 @@ class MonthByWeekFragment @JvmOverloads constructor(
}
mDaysPerWeek = Utils.getDaysPerWeek(mContext)
updateHeader()
- mAdapter.setSelectedDay(mSelectedDay)
+ mAdapter?.setSelectedDay(mSelectedDay)
mTZUpdater.run()
mTodayUpdater.run()
goTo(mSelectedDay.toMillis(true), false, true, false)
@@ -337,8 +337,8 @@ class MonthByWeekFragment @JvmOverloads constructor(
synchronized(mUpdateLoader) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(
- TAG,
- "Found " + data?.getCount()?.toString() + " cursor entries for uri " + mEventUri
+ TAG,
+ "Found " + data?.getCount()?.toString() + " cursor entries for uri " + mEventUri
)
}
val cLoader: CursorLoader = loader as CursorLoader
@@ -353,11 +353,11 @@ class MonthByWeekFragment @JvmOverloads constructor(
}
val events: ArrayList<Event?>? = ArrayList<Event?>()
Event.buildEventsFromCursor(
- events, data, mContext, mFirstLoadedJulianDay, mLastLoadedJulianDay
+ events, data, mContext, mFirstLoadedJulianDay, mLastLoadedJulianDay
)
(mAdapter as MonthByWeekAdapter).setEvents(
- mFirstLoadedJulianDay,
- mLastLoadedJulianDay - mFirstLoadedJulianDay + 1, events
+ mFirstLoadedJulianDay,
+ mLastLoadedJulianDay - mFirstLoadedJulianDay + 1, events
)
}
}
@@ -382,29 +382,29 @@ class MonthByWeekFragment @JvmOverloads constructor(
if (event?.eventType === EventType.GO_TO) {
var animate = true
if (mDaysPerWeek * mNumWeeks * 2 < Math.abs(
- Time.getJulianDay(event?.selectedTime?.toMillis(true) as Long,
- event?.selectedTime?.gmtoff as Long) -
- Time.getJulianDay(mFirstVisibleDay?.toMillis(true) as Long,
- mFirstVisibleDay?.gmtoff as Long) -
- mDaysPerWeek * mNumWeeks / 2L
- )
+ Time.getJulianDay(event?.selectedTime?.toMillis(true) as Long,
+ event?.selectedTime?.gmtoff as Long) -
+ Time.getJulianDay(mFirstVisibleDay?.toMillis(true) as Long,
+ mFirstVisibleDay?.gmtoff as Long) -
+ mDaysPerWeek * mNumWeeks / 2L
+ )
) {
animate = false
}
mDesiredDay.set(event?.selectedTime)
mDesiredDay.normalize(true)
val animateToday = event?.extraLong and
- CalendarController.EXTRA_GOTO_TODAY.toLong() != 0L
+ CalendarController.EXTRA_GOTO_TODAY.toLong() != 0L
val delayAnimation: Boolean =
- goTo(event?.selectedTime?.toMillis(true)?.toLong() as Long, animate, true, false)
+ goTo(event?.selectedTime?.toMillis(true)?.toLong() as Long, animate, true, false)
if (animateToday) {
// If we need to flash today start the animation after any
// movement from listView has ended.
mHandler.postDelayed(object : Runnable {
@Override
override fun run() {
- (mAdapter as MonthByWeekAdapter).animateToday()
- mAdapter.notifyDataSetChanged()
+ (mAdapter as? MonthByWeekAdapter)?.animateToday()
+ mAdapter?.notifyDataSetChanged()
}
}, if (delayAnimation) GOTO_SCROLL_DURATION.toLong() else 0L)
}
@@ -418,29 +418,29 @@ class MonthByWeekFragment @JvmOverloads constructor(
super.setMonthDisplayed(time, updateHighlight)
if (!mIsMiniMonth) {
var useSelected = false
- if (time.year == mDesiredDay.year && time.month === mDesiredDay.month) {
+ if (time.year == mDesiredDay.year && time.month == mDesiredDay.month) {
mSelectedDay.set(mDesiredDay)
- mAdapter.setSelectedDay(mDesiredDay)
+ mAdapter?.setSelectedDay(mDesiredDay)
useSelected = true
} else {
mSelectedDay.set(time)
- mAdapter.setSelectedDay(time)
+ mAdapter?.setSelectedDay(time)
}
- val controller: CalendarController = CalendarController.getInstance(mContext)
+ val controller: CalendarController? = CalendarController.getInstance(mContext)
if (mSelectedDay.minute >= 30) {
mSelectedDay.minute = 30
} else {
mSelectedDay.minute = 0
}
val newTime: Long = mSelectedDay.normalize(true)
- if (newTime != controller.time && mUserScrolled) {
+ if (newTime != controller?.time && mUserScrolled) {
val offset: Long =
- if (useSelected) 0 else DateUtils.WEEK_IN_MILLIS * mNumWeeks / 3.toLong()
- controller.time = (newTime + offset)
+ if (useSelected) 0 else DateUtils.WEEK_IN_MILLIS * mNumWeeks / 3.toLong()
+ controller?.time = (newTime + offset)
}
- controller.sendEvent(
- this as Object?, EventType.UPDATE_TITLE, time, time, time, -1,
- ViewType.CURRENT, DateUtils.FORMAT_SHOW_DATE.toLong() or
+ controller?.sendEvent(
+ this as Object?, EventType.UPDATE_TITLE, time, time, time, -1,
+ ViewType.CURRENT, DateUtils.FORMAT_SHOW_DATE.toLong() or
DateUtils.FORMAT_NO_MONTH_DAY.toLong() or
DateUtils.FORMAT_SHOW_YEAR.toLong(), null, null
)
@@ -479,7 +479,7 @@ class MonthByWeekFragment @JvmOverloads constructor(
// Selection and selection args for adding event queries
private val WHERE_CALENDARS_VISIBLE: String = Calendars.VISIBLE.toString() + "=1"
private val INSTANCES_SORT_ORDER: String = (Instances.START_DAY.toString() + "," +
- Instances.START_MINUTE + "," + Instances.TITLE)
+ Instances.START_MINUTE + "," + Instances.TITLE)
protected var mShowDetailsInMonth = false
private const val WEEKS_BUFFER = 1
diff --git a/src/com/android/calendar/month/SimpleDayPickerFragment.kt b/src/com/android/calendar/month/SimpleDayPickerFragment.kt
new file mode 100644
index 00000000..d3c43e66
--- /dev/null
+++ b/src/com/android/calendar/month/SimpleDayPickerFragment.kt
@@ -0,0 +1,609 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.calendar.month
+
+import com.android.calendar.R
+import com.android.calendar.Utils
+import android.app.Activity
+import android.app.ListFragment
+import android.content.Context
+import android.content.res.Resources
+import android.database.DataSetObserver
+import android.os.Bundle
+import android.os.Handler
+import android.text.TextUtils
+import android.text.format.DateUtils
+import android.text.format.Time
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewConfiguration
+import android.view.ViewGroup
+import android.view.accessibility.AccessibilityEvent
+import android.widget.AbsListView
+import android.widget.AbsListView.OnScrollListener
+import android.widget.ListView
+import android.widget.TextView
+import java.util.Calendar
+import java.util.HashMap
+import java.util.Locale
+
+/**
+ *
+ *
+ * This displays a titled list of weeks with selectable days. It can be
+ * configured to display the week number, start the week on a given day, show a
+ * reduced number of days, or display an arbitrary number of weeks at a time. By
+ * overriding methods and changing variables this fragment can be customized to
+ * easily display a month selection component in a given style.
+ *
+ */
+open class SimpleDayPickerFragment(initialTime: Long) : ListFragment(), OnScrollListener {
+ protected var WEEK_MIN_VISIBLE_HEIGHT = 12
+ protected var BOTTOM_BUFFER = 20
+ protected var mSaturdayColor = 0
+ protected var mSundayColor = 0
+ protected var mDayNameColor = 0
+
+ // You can override these numbers to get a different appearance
+ @JvmField protected var mNumWeeks = 6
+ @JvmField protected var mShowWeekNumber = false
+ @JvmField protected var mDaysPerWeek = 7
+
+ // These affect the scroll speed and feel
+ protected var mFriction = 1.0f
+ @JvmField protected var mContext: Context? = null
+ @JvmField protected var mHandler: Handler = Handler()
+ protected var mMinimumFlingVelocity = 0f
+
+ // highlighted time
+ @JvmField protected var mSelectedDay: Time = Time()
+ @JvmField protected var mAdapter: SimpleWeeksAdapter? = null
+ @JvmField protected var mListView: ListView? = null
+ @JvmField protected var mDayNamesHeader: ViewGroup? = null
+ @JvmField protected var mDayLabels: Array<String?> = arrayOfNulls(7)
+
+ // disposable variable used for time calculations
+ @JvmField protected var mTempTime: Time = Time()
+
+ // When the week starts; numbered like Time.<WEEKDAY> (e.g. SUNDAY=0).
+ @JvmField protected var mFirstDayOfWeek = 0
+
+ // The first day of the focus month
+ @JvmField protected var mFirstDayOfMonth: Time = Time()
+
+ // The first day that is visible in the view
+ @JvmField protected var mFirstVisibleDay: Time = Time()
+
+ // The name of the month to display
+ protected var mMonthName: TextView? = null
+
+ // The last name announced by accessibility
+ protected var mPrevMonthName: CharSequence? = null
+
+ // which month should be displayed/highlighted [0-11]
+ protected var mCurrentMonthDisplayed = 0
+
+ // used for tracking during a scroll
+ protected var mPreviousScrollPosition: Long = 0
+
+ // used for tracking which direction the view is scrolling
+ protected var mIsScrollingUp = false
+
+ // used for tracking what state listview is in
+ protected var mPreviousScrollState: Int = OnScrollListener.SCROLL_STATE_IDLE
+
+ // used for tracking what state listview is in
+ protected var mCurrentScrollState: Int = OnScrollListener.SCROLL_STATE_IDLE
+
+ // This causes an update of the view at midnight
+ @JvmField protected var mTodayUpdater: Runnable = object : Runnable {
+ @Override
+ override fun run() {
+ val midnight = Time(mFirstVisibleDay.timezone)
+ midnight.setToNow()
+ val currentMillis: Long = midnight.toMillis(true)
+ midnight.hour = 0
+ midnight.minute = 0
+ midnight.second = 0
+ midnight.monthDay++
+ val millisToMidnight: Long = midnight.normalize(true) - currentMillis
+ mHandler?.postDelayed(this, millisToMidnight)
+ if (mAdapter != null) {
+ mAdapter?.notifyDataSetChanged()
+ }
+ }
+ }
+
+ // This allows us to update our position when a day is tapped
+ @JvmField protected var mObserver: DataSetObserver = object : DataSetObserver() {
+ @Override
+ override fun onChanged() {
+ val day: Time = mAdapter!!.getSelectedDay()
+ if (day.year !== mSelectedDay.year || day.yearDay !== mSelectedDay.yearDay) {
+ goTo(day.toMillis(true), true, true, false)
+ }
+ }
+ }
+
+ @Override
+ override fun onAttach(activity: Activity) {
+ super.onAttach(activity)
+ mContext = activity
+ val tz: String = Time.getCurrentTimezone()
+ val viewConfig: ViewConfiguration = ViewConfiguration.get(activity)
+ mMinimumFlingVelocity = (viewConfig.getScaledMinimumFlingVelocity()).toFloat()
+
+ // Ensure we're in the correct time zone
+ mSelectedDay.switchTimezone(tz)
+ mSelectedDay.normalize(true)
+ mFirstDayOfMonth.timezone = tz
+ mFirstDayOfMonth.normalize(true)
+ mFirstVisibleDay.timezone = tz
+ mFirstVisibleDay.normalize(true)
+ mTempTime.timezone = tz
+ val res: Resources = activity.getResources()
+ mSaturdayColor = res.getColor(R.color.month_saturday)
+ mSundayColor = res.getColor(R.color.month_sunday)
+ mDayNameColor = res.getColor(R.color.month_day_names_color)
+
+ // Adjust sizes for screen density
+ if (mScale == 0f) {
+ mScale = activity.getResources().getDisplayMetrics().density
+ if (mScale != 1f) {
+ WEEK_MIN_VISIBLE_HEIGHT *= mScale.toInt()
+ BOTTOM_BUFFER *= mScale.toInt()
+ LIST_TOP_OFFSET *= mScale.toInt()
+ }
+ }
+ setUpAdapter()
+ setListAdapter(mAdapter)
+ }
+
+ /**
+ * Creates a new adapter if necessary and sets up its parameters. Override
+ * this method to provide a custom adapter.
+ */
+ protected open fun setUpAdapter() {
+ val weekParams: HashMap<String, Int> = HashMap<String, Int>()
+ weekParams.put(SimpleWeeksAdapter.WEEK_PARAMS_NUM_WEEKS, mNumWeeks)
+ weekParams.put(SimpleWeeksAdapter.WEEK_PARAMS_SHOW_WEEK, if (mShowWeekNumber) 1 else 0)
+ weekParams.put(SimpleWeeksAdapter.WEEK_PARAMS_WEEK_START, mFirstDayOfWeek)
+ weekParams.put(SimpleWeeksAdapter.WEEK_PARAMS_JULIAN_DAY,
+ Time.getJulianDay(mSelectedDay.toMillis(false), mSelectedDay.gmtoff))
+ if (mAdapter == null) {
+ mAdapter = SimpleWeeksAdapter(getActivity(), weekParams)
+ mAdapter?.registerDataSetObserver(mObserver)
+ } else {
+ mAdapter?.updateParams(weekParams)
+ }
+ // refresh the view with the new parameters
+ mAdapter?.notifyDataSetChanged()
+ }
+
+ @Override
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ }
+
+ @Override
+ override fun onActivityCreated(savedInstanceState: Bundle?) {
+ super.onActivityCreated(savedInstanceState)
+ setUpListView()
+ setUpHeader()
+ mMonthName = getView()?.findViewById(R.id.month_name) as? TextView
+ val child = mListView?.getChildAt(0) as? SimpleWeekView
+ if (child == null) {
+ return
+ }
+ val julianDay: Int = child.getFirstJulianDay()
+ mFirstVisibleDay.setJulianDay(julianDay)
+ // set the title to the month of the second week
+ mTempTime.setJulianDay(julianDay + DAYS_PER_WEEK)
+ setMonthDisplayed(mTempTime, true)
+ }
+
+ /**
+ * Sets up the strings to be used by the header. Override this method to use
+ * different strings or modify the view params.
+ */
+ protected open fun setUpHeader() {
+ mDayLabels = arrayOfNulls(7)
+ for (i in Calendar.SUNDAY..Calendar.SATURDAY) {
+ mDayLabels[i - Calendar.SUNDAY] = DateUtils.getDayOfWeekString(i,
+ DateUtils.LENGTH_SHORTEST).toUpperCase()
+ }
+ }
+
+ /**
+ * Sets all the required fields for the list view. Override this method to
+ * set a different list view behavior.
+ */
+ protected fun setUpListView() {
+ // Configure the listview
+ mListView = getListView()
+ // Transparent background on scroll
+ mListView?.setCacheColorHint(0)
+ // No dividers
+ mListView?.setDivider(null)
+ // Items are clickable
+ mListView?.setItemsCanFocus(true)
+ // The thumb gets in the way, so disable it
+ mListView?.setFastScrollEnabled(false)
+ mListView?.setVerticalScrollBarEnabled(false)
+ mListView?.setOnScrollListener(this)
+ mListView?.setFadingEdgeLength(0)
+ // Make the scrolling behavior nicer
+ mListView?.setFriction(ViewConfiguration.getScrollFriction() * mFriction)
+ }
+
+ @Override
+ override fun onResume() {
+ super.onResume()
+ setUpAdapter()
+ doResumeUpdates()
+ }
+
+ @Override
+ override fun onPause() {
+ super.onPause()
+ mHandler.removeCallbacks(mTodayUpdater)
+ }
+
+ @Override
+ override fun onSaveInstanceState(outState: Bundle) {
+ outState.putLong(KEY_CURRENT_TIME, mSelectedDay.toMillis(true))
+ }
+
+ /**
+ * Updates the user preference fields. Override this to use a different
+ * preference space.
+ */
+ protected open fun doResumeUpdates() {
+ // Get default week start based on locale, subtracting one for use with android Time.
+ val cal: Calendar = Calendar.getInstance(Locale.getDefault())
+ mFirstDayOfWeek = cal.getFirstDayOfWeek() - 1
+ mShowWeekNumber = false
+ updateHeader()
+ goTo(mSelectedDay.toMillis(true), false, false, false)
+ mAdapter?.setSelectedDay(mSelectedDay)
+ mTodayUpdater.run()
+ }
+
+ /**
+ * Fixes the day names header to provide correct spacing and updates the
+ * label text. Override this to set up a custom header.
+ */
+ protected fun updateHeader() {
+ var label: TextView = mDayNamesHeader!!.findViewById(R.id.wk_label) as TextView
+ if (mShowWeekNumber) {
+ label.setVisibility(View.VISIBLE)
+ } else {
+ label.setVisibility(View.GONE)
+ }
+ val offset = mFirstDayOfWeek - 1
+ for (i in 1..7) {
+ label = mDayNamesHeader!!.getChildAt(i) as TextView
+ if (i < mDaysPerWeek + 1) {
+ val position = (offset + i) % 7
+ label.setText(mDayLabels[position])
+ label.setVisibility(View.VISIBLE)
+ if (position == Time.SATURDAY) {
+ label.setTextColor(mSaturdayColor)
+ } else if (position == Time.SUNDAY) {
+ label.setTextColor(mSundayColor)
+ } else {
+ label.setTextColor(mDayNameColor)
+ }
+ } else {
+ label.setVisibility(View.GONE)
+ }
+ }
+ mDayNamesHeader?.invalidate()
+ }
+
+ @Override
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View {
+ val v: View = inflater.inflate(R.layout.month_by_week,
+ container, false)
+ mDayNamesHeader = v.findViewById(R.id.day_names) as ViewGroup
+ return v
+ }
+
+ /**
+ * Returns the UTC millis since epoch representation of the currently
+ * selected time.
+ *
+ * @return
+ */
+ val selectedTime: Long
+ get() = mSelectedDay.toMillis(true)
+
+ /**
+ * This moves to the specified time in the view. If the time is not already
+ * in range it will move the list so that the first of the month containing
+ * the time is at the top of the view. If the new time is already in view
+ * the list will not be scrolled unless forceScroll is true. This time may
+ * optionally be highlighted as selected as well.
+ *
+ * @param time The time to move to
+ * @param animate Whether to scroll to the given time or just redraw at the
+ * new location
+ * @param setSelected Whether to set the given time as selected
+ * @param forceScroll Whether to recenter even if the time is already
+ * visible
+ * @return Whether or not the view animated to the new location
+ */
+ fun goTo(time: Long, animate: Boolean, setSelected: Boolean, forceScroll: Boolean): Boolean {
+ if (time == -1L) {
+ Log.e(TAG, "time is invalid")
+ return false
+ }
+
+ // Set the selected day
+ if (setSelected) {
+ mSelectedDay.set(time)
+ mSelectedDay.normalize(true)
+ }
+
+ // If this view isn't returned yet we won't be able to load the lists
+ // current position, so return after setting the selected day.
+ if (!isResumed()) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "We're not visible yet")
+ }
+ return false
+ }
+ mTempTime.set(time)
+ var millis: Long = mTempTime.normalize(true)
+ // Get the week we're going to
+ // TODO push Util function into Calendar public api.
+ var position: Int = Utils.getWeeksSinceEpochFromJulianDay(
+ Time.getJulianDay(millis, mTempTime.gmtoff), mFirstDayOfWeek)
+ var child: View?
+ var i = 0
+ var top = 0
+ // Find a child that's completely in the view
+ do {
+ child = mListView?.getChildAt(i++)
+ if (child == null) {
+ break
+ }
+ top = child.getTop()
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "child at " + (i - 1) + " has top " + top)
+ }
+ } while (top < 0)
+
+ // Compute the first and last position visible
+ val firstPosition: Int
+ firstPosition = if (child != null) {
+ mListView!!.getPositionForView(child)
+ } else {
+ 0
+ }
+ var lastPosition = firstPosition + mNumWeeks - 1
+ if (top > BOTTOM_BUFFER) {
+ lastPosition--
+ }
+ if (setSelected) {
+ mAdapter?.setSelectedDay(mSelectedDay)
+ }
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "GoTo position $position")
+ }
+ // Check if the selected day is now outside of our visible range
+ // and if so scroll to the month that contains it
+ if (position < firstPosition || position > lastPosition || forceScroll) {
+ mFirstDayOfMonth.set(mTempTime)
+ mFirstDayOfMonth.monthDay = 1
+ millis = mFirstDayOfMonth.normalize(true)
+ setMonthDisplayed(mFirstDayOfMonth, true)
+ position = Utils.getWeeksSinceEpochFromJulianDay(
+ Time.getJulianDay(millis, mFirstDayOfMonth.gmtoff), mFirstDayOfWeek)
+ mPreviousScrollState = OnScrollListener.SCROLL_STATE_FLING
+ if (animate) {
+ mListView?.smoothScrollToPositionFromTop(
+ position, LIST_TOP_OFFSET, GOTO_SCROLL_DURATION)
+ return true
+ } else {
+ mListView?.setSelectionFromTop(position, LIST_TOP_OFFSET)
+ // Perform any after scroll operations that are needed
+ onScrollStateChanged(mListView, OnScrollListener.SCROLL_STATE_IDLE)
+ }
+ } else if (setSelected) {
+ // Otherwise just set the selection
+ setMonthDisplayed(mSelectedDay, true)
+ }
+ return false
+ }
+
+ /**
+ * Updates the title and selected month if the view has moved to a new
+ * month.
+ */
+ @Override
+ override fun onScroll(
+ view: AbsListView, firstVisibleItem: Int, visibleItemCount: Int, totalItemCount: Int) {
+ val child = view.getChildAt(0) as? SimpleWeekView
+ if (child == null) {
+ return
+ }
+
+ // Figure out where we are
+ val currScroll: Long = (view.getFirstVisiblePosition() * child.getHeight() -
+ child.getBottom()).toLong()
+ mFirstVisibleDay.setJulianDay(child.getFirstJulianDay())
+
+ // If we have moved since our last call update the direction
+ mIsScrollingUp = if (currScroll < mPreviousScrollPosition) {
+ true
+ } else if (currScroll > mPreviousScrollPosition) {
+ false
+ } else {
+ return
+ }
+ mPreviousScrollPosition = currScroll
+ mPreviousScrollState = mCurrentScrollState
+ updateMonthHighlight(mListView as? AbsListView)
+ }
+
+ /**
+ * Figures out if the month being shown has changed and updates the
+ * highlight if needed
+ *
+ * @param view The ListView containing the weeks
+ */
+ private fun updateMonthHighlight(view: AbsListView?) {
+ var child = view?.getChildAt(0) as? SimpleWeekView
+ if (child == null) {
+ return
+ }
+
+ // Figure out where we are
+ val offset = if (child?.getBottom() < WEEK_MIN_VISIBLE_HEIGHT) 1 else 0
+ // Use some hysteresis for checking which month to highlight. This
+ // causes the month to transition when two full weeks of a month are
+ // visible.
+ child = view?.getChildAt(SCROLL_HYST_WEEKS + offset) as? SimpleWeekView
+ if (child == null) {
+ return
+ }
+
+ // Find out which month we're moving into
+ val month: Int
+ month = if (mIsScrollingUp) {
+ child?.getFirstMonth()
+ } else {
+ child?.getLastMonth()
+ }
+
+ // And how it relates to our current highlighted month
+ val monthDiff: Int
+ monthDiff = if (mCurrentMonthDisplayed == 11 && month == 0) {
+ 1
+ } else if (mCurrentMonthDisplayed == 0 && month == 11) {
+ -1
+ } else {
+ month - mCurrentMonthDisplayed
+ }
+
+ // Only switch months if we're scrolling away from the currently
+ // selected month
+ if (monthDiff != 0) {
+ var julianDay: Int = child.getFirstJulianDay()
+ if (mIsScrollingUp) {
+ // Takes the start of the week
+ } else {
+ // Takes the start of the following week
+ julianDay += DAYS_PER_WEEK
+ }
+ mTempTime.setJulianDay(julianDay)
+ setMonthDisplayed(mTempTime, false)
+ }
+ }
+
+ /**
+ * Sets the month displayed at the top of this view based on time. Override
+ * to add custom events when the title is changed.
+ *
+ * @param time A day in the new focus month.
+ * @param updateHighlight TODO(epastern):
+ */
+ protected open fun setMonthDisplayed(time: Time, updateHighlight: Boolean) {
+ val oldMonth: CharSequence = mMonthName!!.getText()
+ mMonthName?.setText(Utils.formatMonthYear(mContext, time))
+ mMonthName?.invalidate()
+ if (!TextUtils.equals(oldMonth, mMonthName?.getText())) {
+ mMonthName?.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED)
+ }
+ mCurrentMonthDisplayed = time.month
+ if (updateHighlight) {
+ mAdapter?.updateFocusMonth(mCurrentMonthDisplayed)
+ }
+ }
+
+ @Override
+ override fun onScrollStateChanged(view: AbsListView?, scrollState: Int) {
+ // use a post to prevent re-entering onScrollStateChanged before it
+ // exits
+ mScrollStateChangedRunnable.doScrollStateChange(view, scrollState)
+ }
+
+ @JvmField protected var mScrollStateChangedRunnable: ScrollStateRunnable = ScrollStateRunnable()
+
+ protected inner class ScrollStateRunnable : Runnable {
+ private var mNewState = 0
+
+ /**
+ * Sets up the runnable with a short delay in case the scroll state
+ * immediately changes again.
+ *
+ * @param view The list view that changed state
+ * @param scrollState The new state it changed to
+ */
+ fun doScrollStateChange(view: AbsListView?, scrollState: Int) {
+ mHandler.removeCallbacks(this)
+ mNewState = scrollState
+ mHandler.postDelayed(this, SCROLL_CHANGE_DELAY.toLong())
+ }
+
+ override fun run() {
+ mCurrentScrollState = mNewState
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG,
+ "new scroll state: $mNewState old state: $mPreviousScrollState")
+ }
+ // Fix the position after a scroll or a fling ends
+ if (mNewState == OnScrollListener.SCROLL_STATE_IDLE
+ && mPreviousScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
+ mPreviousScrollState = mNewState
+ mAdapter?.updateFocusMonth(mCurrentMonthDisplayed)
+ } else {
+ mPreviousScrollState = mNewState
+ }
+ }
+ }
+
+ companion object {
+ private const val TAG = "MonthFragment"
+ private const val KEY_CURRENT_TIME = "current_time"
+
+ // Affects when the month selection will change while scrolling up
+ protected const val SCROLL_HYST_WEEKS = 2
+
+ // How long the GoTo fling animation should last
+ @JvmStatic protected val GOTO_SCROLL_DURATION = 500
+
+ // How long to wait after receiving an onScrollStateChanged notification
+ // before acting on it
+ protected const val SCROLL_CHANGE_DELAY = 40
+
+ // The number of days to display in each week
+ const val DAYS_PER_WEEK = 7
+
+ // The size of the month name displayed above the week list
+ protected const val MINI_MONTH_NAME_TEXT_SIZE = 18
+ var LIST_TOP_OFFSET = -1 // so that the top line will be under the separator
+ private var mScale = 0f
+ }
+
+ init {
+ goTo(initialTime, false, true, true)
+ mHandler = Handler()
+ }
+} \ No newline at end of file