| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.systemui.statusbar.phone; |
| |
| import android.content.Context; |
| import android.os.Bundle; |
| import android.os.Parcelable; |
| import android.util.AttributeSet; |
| import android.util.Log; |
| import android.view.MotionEvent; |
| import android.view.View; |
| import android.widget.FrameLayout; |
| |
| public abstract class PanelBar extends FrameLayout { |
| public static final boolean DEBUG = false; |
| public static final String TAG = PanelBar.class.getSimpleName(); |
| private static final boolean SPEW = false; |
| private static final String PANEL_BAR_SUPER_PARCELABLE = "panel_bar_super_parcelable"; |
| private static final String STATE = "state"; |
| private boolean mBouncerShowing; |
| private boolean mExpanded; |
| protected float mPanelFraction; |
| |
| public static final void LOG(String fmt, Object... args) { |
| if (!DEBUG) return; |
| Log.v(TAG, String.format(fmt, args)); |
| } |
| |
| public static final int STATE_CLOSED = 0; |
| public static final int STATE_OPENING = 1; |
| public static final int STATE_OPEN = 2; |
| |
| PanelView mPanel; |
| private int mState = STATE_CLOSED; |
| private boolean mTracking; |
| |
| public void go(int state) { |
| if (DEBUG) LOG("go state: %d -> %d", mState, state); |
| mState = state; |
| } |
| |
| @Override |
| protected Parcelable onSaveInstanceState() { |
| Bundle bundle = new Bundle(); |
| bundle.putParcelable(PANEL_BAR_SUPER_PARCELABLE, super.onSaveInstanceState()); |
| bundle.putInt(STATE, mState); |
| return bundle; |
| } |
| |
| @Override |
| protected void onRestoreInstanceState(Parcelable state) { |
| if (state == null || !(state instanceof Bundle)) { |
| super.onRestoreInstanceState(state); |
| return; |
| } |
| |
| Bundle bundle = (Bundle) state; |
| super.onRestoreInstanceState(bundle.getParcelable(PANEL_BAR_SUPER_PARCELABLE)); |
| if (((Bundle) state).containsKey(STATE)) { |
| go(bundle.getInt(STATE, STATE_CLOSED)); |
| } |
| } |
| |
| public PanelBar(Context context, AttributeSet attrs) { |
| super(context, attrs); |
| } |
| |
| @Override |
| protected void onFinishInflate() { |
| super.onFinishInflate(); |
| } |
| |
| public void setPanel(PanelView pv) { |
| mPanel = pv; |
| pv.setBar(this); |
| } |
| |
| public void setBouncerShowing(boolean showing) { |
| mBouncerShowing = showing; |
| int important = showing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS |
| : IMPORTANT_FOR_ACCESSIBILITY_AUTO; |
| |
| setImportantForAccessibility(important); |
| updateVisibility(); |
| |
| if (mPanel != null) mPanel.setImportantForAccessibility(important); |
| } |
| |
| public float getExpansionFraction() { |
| return mPanelFraction; |
| } |
| |
| public boolean isExpanded() { |
| return mExpanded; |
| } |
| |
| private void updateVisibility() { |
| mPanel.setVisibility(mExpanded || mBouncerShowing ? VISIBLE : INVISIBLE); |
| } |
| |
| public boolean panelEnabled() { |
| return true; |
| } |
| |
| @Override |
| public boolean onTouchEvent(MotionEvent event) { |
| // Allow subclasses to implement enable/disable semantics |
| if (!panelEnabled()) { |
| if (event.getAction() == MotionEvent.ACTION_DOWN) { |
| Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)", |
| (int) event.getX(), (int) event.getY())); |
| } |
| return false; |
| } |
| |
| if (event.getAction() == MotionEvent.ACTION_DOWN) { |
| final PanelView panel = mPanel; |
| if (panel == null) { |
| // panel is not there, so we'll eat the gesture |
| Log.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)", |
| (int) event.getX(), (int) event.getY())); |
| return true; |
| } |
| boolean enabled = panel.isEnabled(); |
| if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel, |
| (enabled ? "" : " (disabled)")); |
| if (!enabled) { |
| // panel is disabled, so we'll eat the gesture |
| Log.v(TAG, String.format( |
| "onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)", |
| panel, (int) event.getX(), (int) event.getY())); |
| return true; |
| } |
| } |
| return mPanel == null || mPanel.onTouchEvent(event); |
| } |
| |
| public abstract void panelScrimMinFractionChanged(float minFraction); |
| |
| /** |
| * @param frac the fraction from the expansion in [0, 1] |
| * @param expanded whether the panel is currently expanded; this is independent from the |
| * fraction as the panel also might be expanded if the fraction is 0 |
| */ |
| public void panelExpansionChanged(float frac, boolean expanded) { |
| boolean fullyClosed = true; |
| boolean fullyOpened = false; |
| if (SPEW) LOG("panelExpansionChanged: start state=%d", mState); |
| PanelView pv = mPanel; |
| mExpanded = expanded; |
| mPanelFraction = frac; |
| updateVisibility(); |
| // adjust any other panels that may be partially visible |
| if (expanded) { |
| if (mState == STATE_CLOSED) { |
| go(STATE_OPENING); |
| onPanelPeeked(); |
| } |
| fullyClosed = false; |
| final float thisFrac = pv.getExpandedFraction(); |
| if (SPEW) LOG("panelExpansionChanged: -> %s: f=%.1f", pv.getName(), thisFrac); |
| fullyOpened = thisFrac >= 1f; |
| } |
| if (fullyOpened && !mTracking) { |
| go(STATE_OPEN); |
| onPanelFullyOpened(); |
| } else if (fullyClosed && !mTracking && mState != STATE_CLOSED) { |
| go(STATE_CLOSED); |
| onPanelCollapsed(); |
| } |
| |
| if (SPEW) LOG("panelExpansionChanged: end state=%d [%s%s ]", mState, |
| fullyOpened?" fullyOpened":"", fullyClosed?" fullyClosed":""); |
| } |
| |
| public void collapsePanel(boolean animate, boolean delayed, float speedUpFactor) { |
| boolean waiting = false; |
| PanelView pv = mPanel; |
| if (animate && !pv.isFullyCollapsed()) { |
| pv.collapse(delayed, speedUpFactor); |
| waiting = true; |
| } else { |
| pv.resetViews(); |
| pv.setExpandedFraction(0); // just in case |
| pv.cancelPeek(); |
| } |
| if (DEBUG) LOG("collapsePanel: animate=%s waiting=%s", animate, waiting); |
| if (!waiting && mState != STATE_CLOSED) { |
| // it's possible that nothing animated, so we replicate the termination |
| // conditions of panelExpansionChanged here |
| go(STATE_CLOSED); |
| onPanelCollapsed(); |
| } |
| } |
| |
| public void onPanelPeeked() { |
| if (DEBUG) LOG("onPanelPeeked"); |
| } |
| |
| public boolean isClosed() { |
| return mState == STATE_CLOSED; |
| } |
| |
| public void onPanelCollapsed() { |
| if (DEBUG) LOG("onPanelCollapsed"); |
| } |
| |
| public void onPanelFullyOpened() { |
| if (DEBUG) LOG("onPanelFullyOpened"); |
| } |
| |
| public void onTrackingStarted() { |
| mTracking = true; |
| } |
| |
| public void onTrackingStopped(boolean expand) { |
| mTracking = false; |
| } |
| |
| public void onExpandingFinished() { |
| if (DEBUG) LOG("onExpandingFinished"); |
| } |
| |
| public void onClosingFinished() { |
| |
| } |
| } |