1 /* 2 * Copyright (C) 2015 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 22 import java.util.ArrayList; 23 import java.util.Arrays; 24 import java.util.List; 25 import java.util.Locale; 26 27 import static android.view.View.LAYOUT_DIRECTION_RTL; 28 import static com.android.deskclock.uidata.UiDataModel.Tab; 29 30 /** 31 * All tab data is accessed via this model. 32 */ 33 final class TabModel { 34 35 private final SharedPreferences mPrefs; 36 37 /** The listeners to notify when the selected tab is changed. */ 38 private final List<TabListener> mTabListeners = new ArrayList<>(); 39 40 /** The listeners to notify when the vertical scroll state of the selected tab is changed. */ 41 private final List<TabScrollListener> mTabScrollListeners = new ArrayList<>(); 42 43 /** The scrolled-to-top state of each tab. */ 44 private final boolean[] mTabScrolledToTop = new boolean[Tab.values().length]; 45 46 /** An enumerated value indicating the currently selected tab. */ 47 private Tab mSelectedTab; 48 TabModel(SharedPreferences prefs)49 TabModel(SharedPreferences prefs) { 50 mPrefs = prefs; 51 Arrays.fill(mTabScrolledToTop, true); 52 } 53 54 // 55 // Selected tab 56 // 57 58 /** 59 * @param tabListener to be notified when the selected tab changes 60 */ addTabListener(TabListener tabListener)61 void addTabListener(TabListener tabListener) { 62 mTabListeners.add(tabListener); 63 } 64 65 /** 66 * @param tabListener to no longer be notified when the selected tab changes 67 */ removeTabListener(TabListener tabListener)68 void removeTabListener(TabListener tabListener) { 69 mTabListeners.remove(tabListener); 70 } 71 72 /** 73 * @return the number of tabs 74 */ getTabCount()75 int getTabCount() { 76 return Tab.values().length; 77 } 78 79 /** 80 * @param ordinal the ordinal (left-to-right index) of the tab 81 * @return the tab at the given {@code ordinal} 82 */ getTab(int ordinal)83 Tab getTab(int ordinal) { 84 return Tab.values()[ordinal]; 85 } 86 87 /** 88 * @param position the position of the tab in the user interface 89 * @return the tab at the given {@code ordinal} 90 */ getTabAt(int position)91 Tab getTabAt(int position) { 92 final int ordinal; 93 if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == LAYOUT_DIRECTION_RTL) { 94 ordinal = getTabCount() - position - 1; 95 } else { 96 ordinal = position; 97 } 98 return getTab(ordinal); 99 } 100 101 /** 102 * @return an enumerated value indicating the currently selected primary tab 103 */ getSelectedTab()104 Tab getSelectedTab() { 105 if (mSelectedTab == null) { 106 mSelectedTab = TabDAO.getSelectedTab(mPrefs); 107 } 108 return mSelectedTab; 109 } 110 111 /** 112 * @param tab an enumerated value indicating the newly selected primary tab 113 */ setSelectedTab(Tab tab)114 void setSelectedTab(Tab tab) { 115 final Tab oldSelectedTab = getSelectedTab(); 116 if (oldSelectedTab != tab) { 117 mSelectedTab = tab; 118 TabDAO.setSelectedTab(mPrefs, tab); 119 120 // Notify of the tab change. 121 for (TabListener tl : mTabListeners) { 122 tl.selectedTabChanged(oldSelectedTab, tab); 123 } 124 125 // Notify of the vertical scroll position change if there is one. 126 final boolean tabScrolledToTop = isTabScrolledToTop(tab); 127 if (isTabScrolledToTop(oldSelectedTab) != tabScrolledToTop) { 128 for (TabScrollListener tsl : mTabScrollListeners) { 129 tsl.selectedTabScrollToTopChanged(tab, tabScrolledToTop); 130 } 131 } 132 } 133 } 134 135 // 136 // Tab scrolling 137 // 138 139 /** 140 * @param tabScrollListener to be notified when the scroll position of the selected tab changes 141 */ addTabScrollListener(TabScrollListener tabScrollListener)142 void addTabScrollListener(TabScrollListener tabScrollListener) { 143 mTabScrollListeners.add(tabScrollListener); 144 } 145 146 /** 147 * @param tabScrollListener to be notified when the scroll position of the selected tab changes 148 */ removeTabScrollListener(TabScrollListener tabScrollListener)149 void removeTabScrollListener(TabScrollListener tabScrollListener) { 150 mTabScrollListeners.remove(tabScrollListener); 151 } 152 153 /** 154 * Updates the scrolling state in the {@link UiDataModel} for this tab. 155 * 156 * @param tab an enumerated value indicating the tab reporting its vertical scroll position 157 * @param scrolledToTop {@code true} iff the vertical scroll position of this tab is at the top 158 */ setTabScrolledToTop(Tab tab, boolean scrolledToTop)159 void setTabScrolledToTop(Tab tab, boolean scrolledToTop) { 160 if (isTabScrolledToTop(tab) != scrolledToTop) { 161 mTabScrolledToTop[tab.ordinal()] = scrolledToTop; 162 if (tab == getSelectedTab()) { 163 for (TabScrollListener tsl : mTabScrollListeners) { 164 tsl.selectedTabScrollToTopChanged(tab, scrolledToTop); 165 } 166 } 167 } 168 } 169 170 /** 171 * @param tab identifies the tab 172 * @return {@code true} iff the content in the given {@code tab} is currently scrolled to top 173 */ isTabScrolledToTop(Tab tab)174 boolean isTabScrolledToTop(Tab tab) { 175 return mTabScrolledToTop[tab.ordinal()]; 176 } 177 }