mobile/android/base/TabsPanel.java

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     4  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 package org.mozilla.gecko;
     8 import org.mozilla.gecko.Telemetry;
     9 import org.mozilla.gecko.TelemetryContract;
    10 import org.mozilla.gecko.animation.PropertyAnimator;
    11 import org.mozilla.gecko.animation.ViewHelper;
    12 import org.mozilla.gecko.widget.IconTabWidget;
    14 import android.content.Context;
    15 import android.content.res.Resources;
    16 import android.graphics.Rect;
    17 import android.os.Build;
    18 import android.util.AttributeSet;
    19 import android.view.LayoutInflater;
    20 import android.view.View;
    21 import android.view.ViewGroup;
    22 import android.widget.Button;
    23 import android.widget.FrameLayout;
    24 import android.widget.ImageButton;
    25 import android.widget.LinearLayout;
    26 import android.widget.RelativeLayout;
    28 public class TabsPanel extends LinearLayout
    29                        implements LightweightTheme.OnChangeListener,
    30                                   IconTabWidget.OnTabChangedListener {
    31     private static final String LOGTAG = "GeckoTabsPanel";
    33     public static enum Panel {
    34         NORMAL_TABS,
    35         PRIVATE_TABS,
    36         REMOTE_TABS
    37     }
    39     public static interface PanelView {
    40         public ViewGroup getLayout();
    41         public void setTabsPanel(TabsPanel panel);
    42         public void show();
    43         public void hide();
    44         public boolean shouldExpand();
    45     }
    47     public static interface TabsLayoutChangeListener {
    48         public void onTabsLayoutChange(int width, int height);
    49     }
    51     private Context mContext;
    52     private final GeckoApp mActivity;
    53     private final LightweightTheme mTheme;
    54     private RelativeLayout mHeader;
    55     private TabsListContainer mTabsContainer;
    56     private PanelView mPanel;
    57     private PanelView mPanelNormal;
    58     private PanelView mPanelPrivate;
    59     private PanelView mPanelRemote;
    60     private RelativeLayout mFooter;
    61     private TabsLayoutChangeListener mLayoutChangeListener;
    63     private IconTabWidget mTabWidget;
    64     private static ImageButton mAddTab;
    66     private Panel mCurrentPanel;
    67     private boolean mIsSideBar;
    68     private boolean mVisible;
    70     public TabsPanel(Context context, AttributeSet attrs) {
    71         super(context, attrs);
    72         mContext = context;
    73         mActivity = (GeckoApp) context;
    74         mTheme = ((GeckoApplication) context.getApplicationContext()).getLightweightTheme();
    76         setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
    77                                                       LinearLayout.LayoutParams.FILL_PARENT));
    78         setOrientation(LinearLayout.VERTICAL);
    80         mCurrentPanel = Panel.NORMAL_TABS;
    81         mVisible = false;
    83         mIsSideBar = false;
    85         LayoutInflater.from(context).inflate(R.layout.tabs_panel, this);
    86         initialize();
    87     }
    89     private void initialize() {
    90         mHeader = (RelativeLayout) findViewById(R.id.tabs_panel_header);
    91         mTabsContainer = (TabsListContainer) findViewById(R.id.tabs_container);
    93         mPanelNormal = (PanelView) findViewById(R.id.normal_tabs);
    94         mPanelNormal.setTabsPanel(this);
    96         mPanelPrivate = (PanelView) findViewById(R.id.private_tabs);
    97         mPanelPrivate.setTabsPanel(this);
    99         mPanelRemote = (PanelView) findViewById(R.id.synced_tabs);
   100         mPanelRemote.setTabsPanel(this);
   102         mFooter = (RelativeLayout) findViewById(R.id.tabs_panel_footer);
   104         mAddTab = (ImageButton) findViewById(R.id.add_tab);
   105         mAddTab.setOnClickListener(new Button.OnClickListener() {
   106             @Override
   107             public void onClick(View v) {
   108                 TabsPanel.this.addTab();
   109             }
   110         });
   112         mTabWidget = (IconTabWidget) findViewById(R.id.tab_widget);
   114         mTabWidget.addTab(R.drawable.tabs_normal, R.string.tabs_normal);
   115         mTabWidget.addTab(R.drawable.tabs_private, R.string.tabs_private);
   117         if (!GeckoProfile.get(mContext).inGuestMode()) {
   118             mTabWidget.addTab(R.drawable.tabs_synced, R.string.tabs_synced);
   119         }
   121         mTabWidget.setTabSelectionListener(this);
   122     }
   124     private void addTab() {
   125         if (mCurrentPanel == Panel.NORMAL_TABS) {
   126             Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.ACTIONBAR, "new_tab");
   127             mActivity.addTab();
   128         } else {
   129             Telemetry.sendUIEvent(TelemetryContract.Event.ACTION, TelemetryContract.Method.ACTIONBAR, "new_private_tab");
   130             mActivity.addPrivateTab();
   131         }
   133         mActivity.autoHideTabs();
   134     }
   136     @Override
   137     public void onTabChanged(int index) {
   138         if (index == 0)
   139             show(Panel.NORMAL_TABS, false);
   140         else if (index == 1)
   141             show(Panel.PRIVATE_TABS, false);
   142         else
   143             show(Panel.REMOTE_TABS, false);
   144     }
   146     private static int getTabContainerHeight(TabsListContainer listContainer) {
   147         Resources resources = listContainer.getContext().getResources();
   149         PanelView panelView = listContainer.getCurrentPanelView();
   150         if (panelView != null && !panelView.shouldExpand()) {
   151             return resources.getDimensionPixelSize(R.dimen.tabs_tray_horizontal_height);
   152         }
   154         int actionBarHeight = resources.getDimensionPixelSize(R.dimen.browser_toolbar_height);
   155         int screenHeight = resources.getDisplayMetrics().heightPixels;
   157         Rect windowRect = new Rect();
   158         listContainer.getWindowVisibleDisplayFrame(windowRect);
   159         int windowHeight = windowRect.bottom - windowRect.top;
   161         // The web content area should have at least 1.5x the height of the action bar.
   162         // The tabs panel shouldn't take less than 50% of the screen height and can take
   163         // up to 80% of the window height.
   164         return (int) Math.max(screenHeight * 0.5f,
   165                               Math.min(windowHeight - 2.5f * actionBarHeight, windowHeight * 0.8f) - actionBarHeight);
   166     }
   168     @Override
   169     public void onAttachedToWindow() {
   170         super.onAttachedToWindow();
   171         mTheme.addListener(this);
   172     }
   174     @Override
   175     public void onDetachedFromWindow() {
   176         super.onDetachedFromWindow();
   177         mTheme.removeListener(this);
   178     }
   180     @Override
   181     public void onLightweightThemeChanged() {
   182         final int background = getResources().getColor(R.color.background_tabs);
   183         final LightweightThemeDrawable drawable = mTheme.getColorDrawable(this, background, true);
   184         if (drawable == null)
   185             return;
   187         drawable.setAlpha(34, 0);
   188         setBackgroundDrawable(drawable);
   189     }
   191     @Override
   192     public void onLightweightThemeReset() {
   193         setBackgroundColor(getContext().getResources().getColor(R.color.background_tabs));
   194     }
   196     @Override
   197     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
   198         super.onLayout(changed, left, top, right, bottom);
   199         onLightweightThemeChanged();
   200     }
   202     // Tabs List Container holds the ListView
   203     public static class TabsListContainer extends FrameLayout {
   204         public TabsListContainer(Context context, AttributeSet attrs) {
   205             super(context, attrs);
   206         }
   208         public PanelView getCurrentPanelView() {
   209             final int childCount = getChildCount();
   210             for (int i = 0; i < childCount; i++) {
   211                 View child = getChildAt(i);
   212                 if (!(child instanceof PanelView))
   213                     continue;
   215                 if (child.getVisibility() == View.VISIBLE)
   216                     return (PanelView) child;
   217             }
   219             return null;
   220         }
   222         @Override
   223         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
   224             if (!GeckoAppShell.getGeckoInterface().hasTabsSideBar()) {
   225                 int heightSpec = MeasureSpec.makeMeasureSpec(getTabContainerHeight(TabsListContainer.this), MeasureSpec.EXACTLY);
   226                 super.onMeasure(widthMeasureSpec, heightSpec);
   227             } else {
   228                 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
   229             }
   230         }
   231     }
   233     // Tabs Panel Toolbar contains the Buttons
   234     public static class TabsPanelToolbar extends LinearLayout 
   235                                          implements LightweightTheme.OnChangeListener {
   236         private final LightweightTheme mTheme;
   238         public TabsPanelToolbar(Context context, AttributeSet attrs) {
   239             super(context, attrs);
   240             mTheme = ((GeckoApplication) context.getApplicationContext()).getLightweightTheme();
   242             setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
   243                                                           (int) context.getResources().getDimension(R.dimen.browser_toolbar_height)));
   245             setOrientation(LinearLayout.HORIZONTAL);
   246         }
   248         @Override
   249         public void onAttachedToWindow() {
   250             super.onAttachedToWindow();
   251             mTheme.addListener(this);
   252         }
   254         @Override
   255         public void onDetachedFromWindow() {
   256             super.onDetachedFromWindow();
   257             mTheme.removeListener(this);
   258         }
   260         @Override
   261         public void onLightweightThemeChanged() {
   262             final int background = getResources().getColor(R.color.background_tabs);
   263             final LightweightThemeDrawable drawable = mTheme.getColorDrawable(this, background);
   264             if (drawable == null)
   265                 return;
   267             drawable.setAlpha(34, 34);
   268             setBackgroundDrawable(drawable);
   269         }
   271         @Override
   272         public void onLightweightThemeReset() {
   273             setBackgroundColor(getContext().getResources().getColor(R.color.background_tabs));
   274         }
   276         @Override
   277         protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
   278             super.onLayout(changed, left, top, right, bottom);
   279             onLightweightThemeChanged();
   280         }
   281     }
   283     public void show(Panel panel) {
   284         show(panel, true);
   285     }
   287     public void show(Panel panel, boolean shouldResize) {
   288         if (!isShown())
   289             setVisibility(View.VISIBLE);
   291         if (mPanel != null) {
   292             // Hide the old panel.
   293             mPanel.hide();
   294         }
   296         final boolean showAnimation = !mVisible;
   297         mVisible = true;
   298         mCurrentPanel = panel;
   300         int index = panel.ordinal();
   301         mTabWidget.setCurrentTab(index);
   303         if (index == 0) {
   304             mPanel = mPanelNormal;
   305         } else if (index == 1) {
   306             mPanel = mPanelPrivate;
   307         } else {
   308             mPanel = mPanelRemote;
   309         }
   311         mPanel.show();
   313         if (mCurrentPanel == Panel.REMOTE_TABS) {
   314             if (mFooter != null)
   315                 mFooter.setVisibility(View.GONE);
   317             mAddTab.setVisibility(View.INVISIBLE);
   318         } else {
   319             if (mFooter != null)
   320                 mFooter.setVisibility(View.VISIBLE);
   322             mAddTab.setVisibility(View.VISIBLE);
   323             mAddTab.setImageLevel(index);
   324         }
   326         if (shouldResize) {
   327             if (isSideBar()) {
   328                 if (showAnimation)
   329                     dispatchLayoutChange(getWidth(), getHeight());
   330             } else {
   331                 int actionBarHeight = mContext.getResources().getDimensionPixelSize(R.dimen.browser_toolbar_height);
   332                 int height = actionBarHeight + getTabContainerHeight(mTabsContainer);
   333                 dispatchLayoutChange(getWidth(), height);
   334             }
   335         }
   336     }
   338     public void hide() {
   339         if (mVisible) {
   340             mVisible = false;
   341             dispatchLayoutChange(0, 0);
   342         }
   343     }
   345     public void refresh() {
   346         removeAllViews();
   348         LayoutInflater.from(mContext).inflate(R.layout.tabs_panel, this);
   349         initialize();
   351         if (mVisible)
   352             show(mCurrentPanel);
   353     }
   355     public void autoHidePanel() {
   356         mActivity.autoHideTabs();
   357     }
   359     @Override
   360     public boolean isShown() {
   361         return mVisible;
   362     }
   364     public boolean isSideBar() {
   365         return mIsSideBar;
   366     }
   368     public void setIsSideBar(boolean isSideBar) {
   369         mIsSideBar = isSideBar;
   370     }
   372     public Panel getCurrentPanel() {
   373         return mCurrentPanel;
   374     }
   376     public void prepareTabsAnimation(PropertyAnimator animator) {
   377         // Not worth doing this on pre-Honeycomb without proper
   378         // hardware accelerated animations.
   379         if (Build.VERSION.SDK_INT < 11) {
   380             return;
   381         }
   383         final Resources resources = getContext().getResources();
   384         final int toolbarHeight = resources.getDimensionPixelSize(R.dimen.browser_toolbar_height);
   385         final int tabsPanelWidth = getWidth();
   387         if (mVisible) {
   388             if (mIsSideBar) {
   389                 ViewHelper.setTranslationX(mHeader, -tabsPanelWidth);
   390             } else {
   391                 ViewHelper.setTranslationY(mHeader, -toolbarHeight);
   392             }
   394             if (mIsSideBar) {
   395                 ViewHelper.setTranslationX(mTabsContainer, -tabsPanelWidth);
   396             } else {
   397                 ViewHelper.setTranslationY(mTabsContainer, -toolbarHeight);
   398                 ViewHelper.setAlpha(mTabsContainer, 0);
   399             }
   401             // The footer view is only present on the sidebar
   402             if (mIsSideBar) {
   403                 ViewHelper.setTranslationX(mFooter, -tabsPanelWidth);
   404             }
   405         }
   407         if (mIsSideBar) {
   408             final int translationX = (mVisible ? 0 : -tabsPanelWidth);
   410             animator.attach(mTabsContainer,
   411                             PropertyAnimator.Property.TRANSLATION_X,
   412                             translationX);
   413             animator.attach(mHeader,
   414                             PropertyAnimator.Property.TRANSLATION_X,
   415                             translationX);
   416             animator.attach(mFooter,
   417                             PropertyAnimator.Property.TRANSLATION_X,
   418                             translationX);
   419         } else {
   420             final int translationY = (mVisible ? 0 : -toolbarHeight);
   422             animator.attach(mTabsContainer,
   423                             PropertyAnimator.Property.ALPHA,
   424                             mVisible ? 1.0f : 0.0f);
   425             animator.attach(mTabsContainer,
   426                             PropertyAnimator.Property.TRANSLATION_Y,
   427                             translationY);
   428             animator.attach(mHeader,
   429                             PropertyAnimator.Property.TRANSLATION_Y,
   430                             translationY);
   431         }
   433         mHeader.setLayerType(View.LAYER_TYPE_HARDWARE, null);
   434         mTabsContainer.setLayerType(View.LAYER_TYPE_HARDWARE, null);
   435     }
   437     public void finishTabsAnimation() {
   438         if (Build.VERSION.SDK_INT < 11) {
   439             return;
   440         }
   442         mHeader.setLayerType(View.LAYER_TYPE_NONE, null);
   443         mTabsContainer.setLayerType(View.LAYER_TYPE_NONE, null);
   445         // If the tray is now hidden, call hide() on current panel and unset it as the current panel
   446         // to avoid hide() being called again when the tray is opened next.
   447         if (!mVisible && mPanel != null) {
   448             mPanel.hide();
   449             mPanel = null;
   450         }
   451     }
   453     public void setTabsLayoutChangeListener(TabsLayoutChangeListener listener) {
   454         mLayoutChangeListener = listener;
   455     }
   457     private void dispatchLayoutChange(int width, int height) {
   458         if (mLayoutChangeListener != null)
   459             mLayoutChangeListener.onTabsLayoutChange(width, height);
   460     }
   461 }

mercurial