233 lines
8.4 KiB
Kotlin
233 lines
8.4 KiB
Kotlin
/*
|
|
* 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
|
|
|
|
import com.android.calendar.CalendarController.EventInfo
|
|
import com.android.calendar.CalendarController.EventType
|
|
import android.app.Fragment
|
|
import android.content.Context
|
|
import android.os.Bundle
|
|
import android.text.format.Time
|
|
import android.view.LayoutInflater
|
|
import android.view.View
|
|
import android.view.ViewGroup
|
|
import android.widget.FrameLayout.LayoutParams
|
|
import android.view.animation.Animation
|
|
import android.view.animation.AnimationUtils
|
|
import android.widget.ProgressBar
|
|
import android.widget.ViewSwitcher
|
|
import android.widget.ViewSwitcher.ViewFactory
|
|
|
|
/**
|
|
* This is the base class for Day and Week Activities.
|
|
*/
|
|
class DayFragment : Fragment, CalendarController.EventHandler, ViewFactory {
|
|
protected var mProgressBar: ProgressBar? = null
|
|
protected var mViewSwitcher: ViewSwitcher? = null
|
|
protected var mInAnimationForward: Animation? = null
|
|
protected var mOutAnimationForward: Animation? = null
|
|
protected var mInAnimationBackward: Animation? = null
|
|
protected var mOutAnimationBackward: Animation? = null
|
|
var mEventLoader: EventLoader? = null
|
|
var mSelectedDay: Time = Time()
|
|
private val mTZUpdater: Runnable = object : Runnable {
|
|
override fun run() {
|
|
if (!this@DayFragment.isAdded()) {
|
|
return
|
|
}
|
|
val tz: String? = Utils.getTimeZone(getActivity(), this)
|
|
mSelectedDay.timezone = tz
|
|
mSelectedDay.normalize(true)
|
|
}
|
|
}
|
|
private var mNumDays = 0
|
|
|
|
constructor() {
|
|
mSelectedDay.setToNow()
|
|
}
|
|
|
|
constructor(timeMillis: Long, numOfDays: Int) {
|
|
mNumDays = numOfDays
|
|
if (timeMillis == 0L) {
|
|
mSelectedDay.setToNow()
|
|
} else {
|
|
mSelectedDay.set(timeMillis)
|
|
}
|
|
}
|
|
|
|
override fun onCreate(icicle: Bundle?) {
|
|
super.onCreate(icicle)
|
|
val context: Context = getActivity()
|
|
mInAnimationForward = AnimationUtils.loadAnimation(context, R.anim.slide_left_in)
|
|
mOutAnimationForward = AnimationUtils.loadAnimation(context, R.anim.slide_left_out)
|
|
mInAnimationBackward = AnimationUtils.loadAnimation(context, R.anim.slide_right_in)
|
|
mOutAnimationBackward = AnimationUtils.loadAnimation(context, R.anim.slide_right_out)
|
|
mEventLoader = EventLoader(context)
|
|
}
|
|
|
|
override fun onCreateView(
|
|
inflater: LayoutInflater?,
|
|
container: ViewGroup?,
|
|
savedInstanceState: Bundle?
|
|
): View? {
|
|
val v: View? = inflater?.inflate(R.layout.day_activity, null)
|
|
mViewSwitcher = v?.findViewById(R.id.switcher) as? ViewSwitcher
|
|
mViewSwitcher?.setFactory(this)
|
|
mViewSwitcher?.getCurrentView()?.requestFocus()
|
|
(mViewSwitcher?.getCurrentView() as? DayView)?.updateTitle()
|
|
return v
|
|
}
|
|
|
|
override fun makeView(): View {
|
|
mTZUpdater.run()
|
|
val view = DayView(getActivity(), CalendarController
|
|
.getInstance(getActivity()), mViewSwitcher, mEventLoader, mNumDays)
|
|
view.setId(DayFragment.Companion.VIEW_ID)
|
|
view.setLayoutParams(LayoutParams(
|
|
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT))
|
|
view.setSelected(mSelectedDay, false, false)
|
|
return view
|
|
}
|
|
|
|
override fun onResume() {
|
|
super.onResume()
|
|
mEventLoader!!.startBackgroundThread()
|
|
mTZUpdater.run()
|
|
eventsChanged()
|
|
var view: DayView? = mViewSwitcher?.getCurrentView() as? DayView
|
|
view?.handleOnResume()
|
|
view?.restartCurrentTimeUpdates()
|
|
view = mViewSwitcher?.getNextView() as? DayView
|
|
view?.handleOnResume()
|
|
view?.restartCurrentTimeUpdates()
|
|
}
|
|
|
|
override fun onSaveInstanceState(outState: Bundle?) {
|
|
super.onSaveInstanceState(outState)
|
|
}
|
|
|
|
override fun onPause() {
|
|
super.onPause()
|
|
var view: DayView? = mViewSwitcher?.getCurrentView() as? DayView
|
|
view?.cleanup()
|
|
view = mViewSwitcher?.getNextView() as? DayView
|
|
view?.cleanup()
|
|
mEventLoader!!.stopBackgroundThread()
|
|
|
|
// Stop events cross-fade animation
|
|
view?.stopEventsAnimation()
|
|
(mViewSwitcher?.getNextView() as? DayView)?.stopEventsAnimation()
|
|
}
|
|
|
|
fun startProgressSpinner() {
|
|
// start the progress spinner
|
|
mProgressBar?.setVisibility(View.VISIBLE)
|
|
}
|
|
|
|
fun stopProgressSpinner() {
|
|
// stop the progress spinner
|
|
mProgressBar?.setVisibility(View.GONE)
|
|
}
|
|
|
|
private fun goTo(goToTime: Time?, ignoreTime: Boolean, animateToday: Boolean) {
|
|
if (mViewSwitcher == null) {
|
|
// The view hasn't been set yet. Just save the time and use it later.
|
|
mSelectedDay.set(goToTime)
|
|
return
|
|
}
|
|
val currentView: DayView? = mViewSwitcher?.getCurrentView() as? DayView
|
|
|
|
// How does goTo time compared to what's already displaying?
|
|
val diff: Int = currentView?.compareToVisibleTimeRange(goToTime as Time) as Int
|
|
if (diff == 0) {
|
|
// In visible range. No need to switch view
|
|
currentView.setSelected(goToTime, ignoreTime, animateToday)
|
|
} else {
|
|
// Figure out which way to animate
|
|
if (diff > 0) {
|
|
mViewSwitcher?.setInAnimation(mInAnimationForward)
|
|
mViewSwitcher?.setOutAnimation(mOutAnimationForward)
|
|
} else {
|
|
mViewSwitcher?.setInAnimation(mInAnimationBackward)
|
|
mViewSwitcher?.setOutAnimation(mOutAnimationBackward)
|
|
}
|
|
val next: DayView? = mViewSwitcher?.getNextView() as? DayView
|
|
if (ignoreTime) {
|
|
next!!.firstVisibleHour = currentView.firstVisibleHour
|
|
}
|
|
next?.setSelected(goToTime, ignoreTime, animateToday)
|
|
next?.reloadEvents()
|
|
mViewSwitcher?.showNext()
|
|
next?.requestFocus()
|
|
next?.updateTitle()
|
|
next?.restartCurrentTimeUpdates()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the selected time in milliseconds. The milliseconds are measured
|
|
* in UTC milliseconds from the epoch and uniquely specifies any selectable
|
|
* time.
|
|
*
|
|
* @return the selected time in milliseconds
|
|
*/
|
|
val selectedTimeInMillis: Long
|
|
get() {
|
|
if (mViewSwitcher == null) {
|
|
return -1
|
|
}
|
|
val view: DayView = mViewSwitcher?.getCurrentView() as DayView ?: return -1
|
|
return view.selectedTimeInMillis
|
|
}
|
|
|
|
override fun eventsChanged() {
|
|
if (mViewSwitcher == null) {
|
|
return
|
|
}
|
|
var view: DayView? = mViewSwitcher?.getCurrentView() as? DayView
|
|
view?.clearCachedEvents()
|
|
view?.reloadEvents()
|
|
view = mViewSwitcher?.getNextView() as? DayView
|
|
view?.clearCachedEvents()
|
|
}
|
|
|
|
val nextView: DayView?
|
|
get() = mViewSwitcher?.getNextView() as? DayView
|
|
override val supportedEventTypes: Long
|
|
get() = CalendarController.EventType.GO_TO or CalendarController.EventType.EVENTS_CHANGED
|
|
|
|
override fun handleEvent(msg: CalendarController.EventInfo?) {
|
|
if (msg?.eventType == CalendarController.EventType.GO_TO) {
|
|
// TODO support a range of time
|
|
// TODO support event_id
|
|
// TODO support select message
|
|
goTo(msg.selectedTime, msg.extraLong and CalendarController.EXTRA_GOTO_DATE != 0L,
|
|
msg.extraLong and CalendarController.EXTRA_GOTO_TODAY != 0L)
|
|
} else if (msg?.eventType == CalendarController.EventType.EVENTS_CHANGED) {
|
|
eventsChanged()
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
/**
|
|
* The view id used for all the views we create. It's OK to have all child
|
|
* views have the same ID. This ID is used to pick which view receives
|
|
* focus when a view hierarchy is saved / restore
|
|
*/
|
|
private const val VIEW_ID = 1
|
|
protected const val BUNDLE_KEY_RESTORE_TIME = "key_restore_time"
|
|
}
|
|
} |