1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.deskclock.uidata 18 19 import android.content.SharedPreferences 20 import android.text.TextUtils 21 import android.view.View 22 23 import java.util.Locale 24 25 /** 26 * All tab data is accessed via this model. 27 */ 28 internal class TabModel(private val mPrefs: SharedPreferences) { 29 30 /** The listeners to notify when the selected tab is changed. */ 31 private val mTabListeners: MutableList<TabListener> = ArrayList() 32 33 /** The listeners to notify when the vertical scroll state of the selected tab is changed. */ 34 private val mTabScrollListeners: MutableList<TabScrollListener> = ArrayList() 35 36 /** The scrolled-to-top state of each tab. */ 37 private val mTabScrolledToTop = BooleanArray(UiDataModel.Tab.values().size) 38 39 /** An enumerated value indicating the currently selected tab. */ 40 private var mSelectedTab: UiDataModel.Tab? = null 41 42 init { 43 mTabScrolledToTop.fill(true) 44 } 45 46 // 47 // Selected tab 48 // 49 50 /** 51 * @param tabListener to be notified when the selected tab changes 52 */ addTabListenernull53 fun addTabListener(tabListener: TabListener) { 54 mTabListeners.add(tabListener) 55 } 56 57 /** 58 * @param tabListener to no longer be notified when the selected tab changes 59 */ removeTabListenernull60 fun removeTabListener(tabListener: TabListener) { 61 mTabListeners.remove(tabListener) 62 } 63 64 /** 65 * @return the number of tabs 66 */ 67 val tabCount: Int 68 get() = UiDataModel.Tab.values().size 69 70 /** 71 * @param ordinal the ordinal (left-to-right index) of the tab 72 * @return the tab at the given `ordinal` 73 */ getTabnull74 fun getTab(ordinal: Int): UiDataModel.Tab { 75 return UiDataModel.Tab.values()[ordinal] 76 } 77 78 /** 79 * @param position the position of the tab in the user interface 80 * @return the tab at the given `ordinal` 81 */ getTabAtnull82 fun getTabAt(position: Int): UiDataModel.Tab { 83 val layoutDirection = TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) 84 val ordinal: Int = if (layoutDirection == View.LAYOUT_DIRECTION_RTL) { 85 tabCount - position - 1 86 } else { 87 position 88 } 89 return getTab(ordinal) 90 } 91 92 /** 93 * @return an enumerated value indicating the currently selected primary tab 94 */ 95 val selectedTab: UiDataModel.Tab 96 get() { 97 if (mSelectedTab == null) { 98 mSelectedTab = TabDAO.getSelectedTab(mPrefs) 99 } 100 return mSelectedTab!! 101 } 102 103 /** 104 * @param tab an enumerated value indicating the newly selected primary tab 105 */ setSelectedTabnull106 fun setSelectedTab(tab: UiDataModel.Tab) { 107 val oldSelectedTab = selectedTab 108 if (oldSelectedTab != tab) { 109 mSelectedTab = tab 110 TabDAO.setSelectedTab(mPrefs, tab) 111 112 // Notify of the tab change. 113 for (tl in mTabListeners) { 114 tl.selectedTabChanged(oldSelectedTab, tab) 115 } 116 117 // Notify of the vertical scroll position change if there is one. 118 val tabScrolledToTop = isTabScrolledToTop(tab) 119 if (isTabScrolledToTop(oldSelectedTab) != tabScrolledToTop) { 120 for (tsl in mTabScrollListeners) { 121 tsl.selectedTabScrollToTopChanged(tab, tabScrolledToTop) 122 } 123 } 124 } 125 } 126 127 // 128 // Tab scrolling 129 // 130 131 /** 132 * @param tabScrollListener to be notified when the scroll position of the selected tab changes 133 */ addTabScrollListenernull134 fun addTabScrollListener(tabScrollListener: TabScrollListener) { 135 mTabScrollListeners.add(tabScrollListener) 136 } 137 138 /** 139 * @param tabScrollListener to be notified when the scroll position of the selected tab changes 140 */ removeTabScrollListenernull141 fun removeTabScrollListener(tabScrollListener: TabScrollListener) { 142 mTabScrollListeners.remove(tabScrollListener) 143 } 144 145 /** 146 * Updates the scrolling state in the [UiDataModel] for this tab. 147 * 148 * @param tab an enumerated value indicating the tab reporting its vertical scroll position 149 * @param scrolledToTop `true` iff the vertical scroll position of this tab is at the top 150 */ setTabScrolledToTopnull151 fun setTabScrolledToTop(tab: UiDataModel.Tab, scrolledToTop: Boolean) { 152 if (isTabScrolledToTop(tab) != scrolledToTop) { 153 mTabScrolledToTop[tab.ordinal] = scrolledToTop 154 if (tab == selectedTab) { 155 for (tsl in mTabScrollListeners) { 156 tsl.selectedTabScrollToTopChanged(tab, scrolledToTop) 157 } 158 } 159 } 160 } 161 162 /** 163 * @param tab identifies the tab 164 * @return `true` iff the content in the given `tab` is currently scrolled to top 165 */ isTabScrolledToTopnull166 fun isTabScrolledToTop(tab: UiDataModel.Tab): Boolean { 167 return mTabScrolledToTop[tab.ordinal] 168 } 169 }