blob: 72d9781e0abd4b3cfb285cbdfcb4e0bf9cf7b283 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.keyboard_accessory.sheet_component;
import static org.chromium.chrome.browser.keyboard_accessory.sheet_component.AccessorySheetProperties.ACTIVE_TAB_INDEX;
import static org.chromium.chrome.browser.keyboard_accessory.sheet_component.AccessorySheetProperties.NO_ACTIVE_TAB;
import static org.chromium.chrome.browser.keyboard_accessory.sheet_component.AccessorySheetProperties.PAGE_CHANGE_LISTENER;
import static org.chromium.chrome.browser.keyboard_accessory.sheet_component.AccessorySheetProperties.TABS;
import static org.chromium.chrome.browser.keyboard_accessory.sheet_component.AccessorySheetProperties.TOP_SHADOW_VISIBLE;
import static org.chromium.chrome.browser.keyboard_accessory.sheet_component.AccessorySheetProperties.VISIBLE;
import android.support.annotation.Nullable;
import android.support.annotation.Px;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.RecyclerView;
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.browser.keyboard_accessory.data.KeyboardAccessoryData;
import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyObservable;
/**
* Contains the controller logic of the AccessorySheet component.
* It communicates with data providers and native backends to update a model based on {@link
* AccessorySheetProperties}.
*/
class AccessorySheetMediator implements PropertyObservable.PropertyObserver<PropertyKey> {
private final PropertyModel mModel;
private final RecyclerView.OnScrollListener mScrollListener =
new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (recyclerView == null) return;
mModel.set(TOP_SHADOW_VISIBLE, recyclerView.canScrollVertically(-1));
}
};
AccessorySheetMediator(PropertyModel model) {
mModel = model;
mModel.addObserver(this);
}
@Nullable
KeyboardAccessoryData.Tab getTab() {
if (mModel.get(ACTIVE_TAB_INDEX) == NO_ACTIVE_TAB) return null;
return mModel.get(TABS).get(mModel.get(ACTIVE_TAB_INDEX));
}
@VisibleForTesting
PropertyModel getModelForTesting() {
return mModel;
}
void show() {
mModel.set(VISIBLE, true);
}
void setHeight(int height) {
mModel.set(AccessorySheetProperties.HEIGHT, height);
}
@Px
int getHeight() {
return mModel.get(AccessorySheetProperties.HEIGHT);
}
void hide() {
mModel.set(VISIBLE, false);
}
boolean isShown() {
return mModel.get(VISIBLE);
}
RecyclerView.OnScrollListener getScrollListener() {
return mScrollListener;
}
void setTabs(KeyboardAccessoryData.Tab[] tabs) {
mModel.get(TABS).set(tabs);
mModel.set(ACTIVE_TAB_INDEX, mModel.get(TABS).size() - 1);
}
void setActiveTab(int position) {
assert position < mModel.get(TABS).size()
|| position >= 0 : position + " is not a valid tab index!";
mModel.set(ACTIVE_TAB_INDEX, position);
}
/**
* Returns the position of a tab which needs to become the active tab. If the tab to be deleted
* is the active tab, return the item on its left. If it was the first item in the list, return
* the new first item. If no items remain, return {@link
* AccessorySheetProperties#NO_ACTIVE_TAB}.
* @param tabToBeDeleted The tab to be removed from the list.
* @return The position of the tab which should become active.
*/
private int getNextActiveTab(KeyboardAccessoryData.Tab tabToBeDeleted) {
int activeTab = mModel.get(ACTIVE_TAB_INDEX);
for (int i = 0; i <= activeTab; i++) {
KeyboardAccessoryData.Tab tabLeftToActiveTab = mModel.get(TABS).get(i);
// If we delete the active tab or a tab left to it, the new active tab moves left.
if (tabLeftToActiveTab == tabToBeDeleted) {
--activeTab;
break;
}
}
if (activeTab >= 0) return activeTab; // The new active tab is valid.
// If there are items left, take the first one.
int itemCountAfterDeletion = mModel.get(TABS).size() - 1;
return itemCountAfterDeletion > 0 ? 0 : NO_ACTIVE_TAB;
}
@Override
public void onPropertyChanged(PropertyObservable<PropertyKey> source, PropertyKey propertyKey) {
if (propertyKey == VISIBLE) {
if (mModel.get(VISIBLE) && getTab() != null && getTab().getListener() != null) {
getTab().getListener().onTabShown();
}
return;
}
if (propertyKey == ACTIVE_TAB_INDEX || propertyKey == AccessorySheetProperties.HEIGHT
|| propertyKey == TOP_SHADOW_VISIBLE || propertyKey == PAGE_CHANGE_LISTENER) {
return;
}
assert false : "Every property update needs to be handled explicitly!";
}
void setOnPageChangeListener(ViewPager.OnPageChangeListener onPageChangeListener) {
mModel.set(PAGE_CHANGE_LISTENER, onPageChangeListener);
}
}