blob: 67c21cc7dbb75f24667a1c8d27101775b877b45d [file] [log] [blame]
// Copyright 2014 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.widget.accessibility;
import android.content.Context;
import android.content.res.ColorStateList;
import android.support.design.widget.TabLayout;
import android.support.v7.content.res.AppCompatResources;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
import org.chromium.chrome.browser.util.FeatureUtilities;
import org.chromium.chrome.browser.widget.TintedImageView;
import org.chromium.chrome.browser.widget.accessibility.AccessibilityTabModelAdapter.AccessibilityTabModelAdapterListener;
/**
* A wrapper around the Android views in the Accessibility tab switcher. This
* will show two {@link ListView}s, one for each
* {@link org.chromium.chrome.browser.tabmodel.TabModel} to
* represent.
*/
public class AccessibilityTabModelWrapper extends LinearLayout {
private AccessibilityTabModelListView mAccessibilityView;
private LinearLayout mStackButtonWrapper;
private ImageButton mStandardButton;
private ImageButton mIncognitoButton;
private View mModernLayout;
private TabLayout mModernStackButtonWrapper;
private TabLayout.Tab mModernStandardButton;
private TabLayout.Tab mModernIncognitoButton;
private TintedImageView mModernStandardButtonIcon;
private TintedImageView mModernIncognitoButtonIcon;
private ColorStateList mTabIconDarkColor;
private ColorStateList mTabIconLightColor;
private ColorStateList mTabIconSelectedDarkColor;
private ColorStateList mTabIconSelectedLightColor;
private TabModelSelector mTabModelSelector;
private TabModelSelectorObserver mTabModelSelectorObserver =
new EmptyTabModelSelectorObserver() {
@Override
public void onChange() {
getAdapter().notifyDataSetChanged();
updateVisibilityForLayoutOrStackButton();
}
@Override
public void onNewTabCreated(Tab tab) {
getAdapter().notifyDataSetChanged();
}
};
// TODO(bauerb): Use View#isAttachedToWindow() as soon as we are guaranteed
// to run against API version 19.
private boolean mIsAttachedToWindow;
private class ButtonOnClickListener implements View.OnClickListener {
private final boolean mIncognito;
public ButtonOnClickListener(boolean incognito) {
mIncognito = incognito;
}
@Override
public void onClick(View v) {
setSelectedModel(mIncognito);
}
}
public AccessibilityTabModelWrapper(Context context) {
super(context);
}
public AccessibilityTabModelWrapper(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AccessibilityTabModelWrapper(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
/**
* Initialize android views after creation.
*
* @param listener A {@link AccessibilityTabModelAdapterListener} to pass tab events back to the
* parent.
*/
public void setup(AccessibilityTabModelAdapterListener listener) {
if (FeatureUtilities.isChromeModernDesignEnabled()) {
mTabIconDarkColor =
AppCompatResources.getColorStateList(getContext(), R.color.dark_mode_tint);
mTabIconSelectedDarkColor =
AppCompatResources.getColorStateList(getContext(), R.color.light_active_color);
mTabIconLightColor =
AppCompatResources.getColorStateList(getContext(), R.color.white_alpha_70);
mTabIconSelectedLightColor =
AppCompatResources.getColorStateList(getContext(), R.color.white_mode_tint);
// Setting scaleY here to make sure the icons are not flipped due to the scaleY of its
// container layout.
mModernStandardButtonIcon = new TintedImageView(getContext());
mModernStandardButtonIcon.setImageResource(R.drawable.btn_normal_tabs);
mModernStandardButtonIcon.setScaleY(-1.0f);
mModernIncognitoButtonIcon = new TintedImageView(getContext());
mModernIncognitoButtonIcon.setImageResource(R.drawable.btn_incognito_tabs);
mModernIncognitoButtonIcon.setScaleY(-1.0f);
setDividerDrawable(null);
((ListView) findViewById(R.id.list_view)).setDivider(null);
mModernLayout = findViewById(R.id.tab_wrapper);
mModernStackButtonWrapper = findViewById(R.id.tab_layout);
mModernStandardButton =
mModernStackButtonWrapper.newTab()
.setCustomView(mModernStandardButtonIcon)
.setContentDescription(
R.string.accessibility_tab_switcher_standard_stack);
mModernStackButtonWrapper.addTab(mModernStandardButton);
mModernIncognitoButton =
mModernStackButtonWrapper.newTab()
.setCustomView(mModernIncognitoButtonIcon)
.setContentDescription(
ChromeFeatureList.isEnabled(ChromeFeatureList.INCOGNITO_STRINGS)
? R.string.accessibility_tab_switcher_private_stack
: R.string.accessibility_tab_switcher_incognito_stack);
mModernStackButtonWrapper.addTab(mModernIncognitoButton);
mModernStackButtonWrapper.addOnTabSelectedListener(
new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
setSelectedModel(mModernIncognitoButton.isSelected());
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {}
@Override
public void onTabReselected(TabLayout.Tab tab) {}
});
} else {
mStackButtonWrapper = (LinearLayout) findViewById(R.id.button_wrapper);
mStandardButton = (ImageButton) findViewById(R.id.standard_tabs_button);
mStandardButton.setOnClickListener(new ButtonOnClickListener(false));
mIncognitoButton = (ImageButton) findViewById(R.id.incognito_tabs_button);
mIncognitoButton.setOnClickListener(new ButtonOnClickListener(true));
}
mAccessibilityView = (AccessibilityTabModelListView) findViewById(R.id.list_view);
AccessibilityTabModelAdapter adapter = getAdapter();
adapter.setListener(listener);
}
/**
* @param modelSelector A {@link TabModelSelector} to provide information
* about open tabs.
*/
public void setTabModelSelector(TabModelSelector modelSelector) {
if (mIsAttachedToWindow) {
mTabModelSelector.removeObserver(mTabModelSelectorObserver);
}
mTabModelSelector = modelSelector;
if (mIsAttachedToWindow) {
modelSelector.addObserver(mTabModelSelectorObserver);
}
setStateBasedOnModel();
}
/**
* Set the bottom model selector buttons and list view contents based on the
* TabModelSelector.
*/
public void setStateBasedOnModel() {
if (mTabModelSelector == null) return;
boolean incognitoSelected = mTabModelSelector.isIncognitoSelected();
updateVisibilityForLayoutOrStackButton();
if (FeatureUtilities.isChromeModernDesignEnabled()) {
if (incognitoSelected) {
setBackgroundColor(ApiCompatibilityUtils.getColor(
getResources(), R.color.incognito_modern_primary_color));
mModernStackButtonWrapper.setSelectedTabIndicatorColor(
mTabIconSelectedLightColor.getDefaultColor());
mModernStandardButtonIcon.setTint(mTabIconLightColor);
mModernIncognitoButtonIcon.setTint(mTabIconSelectedLightColor);
} else {
setBackgroundColor(ApiCompatibilityUtils.getColor(
getResources(), R.color.modern_primary_color));
mModernStackButtonWrapper.setSelectedTabIndicatorColor(
mTabIconSelectedDarkColor.getDefaultColor());
mModernStandardButtonIcon.setTint(mTabIconSelectedDarkColor);
mModernIncognitoButtonIcon.setTint(mTabIconDarkColor);
}
// Ensure the tab in tab layout is correctly selected when tab switcher is
// first opened.
if (incognitoSelected && !mModernIncognitoButton.isSelected()) {
mModernIncognitoButton.select();
} else if (!incognitoSelected && !mModernStandardButton.isSelected()) {
mModernStandardButton.select();
}
} else {
if (incognitoSelected) {
mIncognitoButton.setBackgroundResource(R.drawable.btn_bg_holo_active);
mStandardButton.setBackgroundResource(R.drawable.btn_bg_holo);
} else {
mIncognitoButton.setBackgroundResource(R.drawable.btn_bg_holo);
mStandardButton.setBackgroundResource(R.drawable.btn_bg_holo_active);
}
}
mAccessibilityView.setContentDescription(incognitoSelected
? getContext().getString(
ChromeFeatureList.isEnabled(ChromeFeatureList.INCOGNITO_STRINGS)
? R.string.accessibility_tab_switcher_private_stack
: R.string.accessibility_tab_switcher_incognito_stack)
: getContext().getString(
R.string.accessibility_tab_switcher_standard_stack));
getAdapter().setTabModel(mTabModelSelector.getModel(incognitoSelected));
}
private AccessibilityTabModelAdapter getAdapter() {
return (AccessibilityTabModelAdapter) mAccessibilityView.getAdapter();
}
/**
* Set either standard or incognito tab model as currently selected.
* @param incognitoSelected Whether the incognito tab model is selected.
*/
private void setSelectedModel(boolean incognitoSelected) {
if (mTabModelSelector == null
|| incognitoSelected == mTabModelSelector.isIncognitoSelected()) {
return;
}
mTabModelSelector.commitAllTabClosures();
mTabModelSelector.selectModel(incognitoSelected);
setStateBasedOnModel();
int stackAnnouncementId = incognitoSelected
? (ChromeFeatureList.isEnabled(ChromeFeatureList.INCOGNITO_STRINGS)
? R.string.accessibility_tab_switcher_private_stack_selected
: R.string.accessibility_tab_switcher_incognito_stack_selected)
: R.string.accessibility_tab_switcher_standard_stack_selected;
AccessibilityTabModelWrapper.this.announceForAccessibility(
getResources().getString(stackAnnouncementId));
}
private void updateVisibilityForLayoutOrStackButton() {
boolean incognitoEnabled =
mTabModelSelector.getModel(true).getComprehensiveModel().getCount() > 0;
if (FeatureUtilities.isChromeModernDesignEnabled()) {
mModernLayout.setVisibility(incognitoEnabled ? View.VISIBLE : View.GONE);
} else {
mStackButtonWrapper.setVisibility(incognitoEnabled ? View.VISIBLE : View.GONE);
}
}
@Override
protected void onAttachedToWindow() {
mTabModelSelector.addObserver(mTabModelSelectorObserver);
mIsAttachedToWindow = true;
super.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
mIsAttachedToWindow = false;
super.onDetachedFromWindow();
}
}