michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko; michael@0: michael@0: import org.mozilla.gecko.animation.AnimationUtils; michael@0: import org.mozilla.gecko.menu.GeckoMenu; michael@0: import org.mozilla.gecko.widget.GeckoPopupMenu; michael@0: michael@0: import android.content.Context; michael@0: import android.util.AttributeSet; michael@0: import android.view.LayoutInflater; michael@0: import android.view.Menu; michael@0: import android.view.View; michael@0: import android.view.ViewGroup; michael@0: import android.view.animation.Animation; michael@0: import android.view.animation.ScaleAnimation; michael@0: import android.view.animation.TranslateAnimation; michael@0: import android.widget.Button; michael@0: import android.widget.ImageButton; michael@0: import android.widget.LinearLayout; michael@0: michael@0: class ActionModeCompatView extends LinearLayout implements GeckoMenu.ActionItemBarPresenter { michael@0: private final String LOGTAG = "GeckoActionModeCompatPresenter"; michael@0: michael@0: private static final int SPEC = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); michael@0: michael@0: private Button mTitleView; michael@0: private ImageButton mMenuButton; michael@0: private ViewGroup mActionButtonBar; michael@0: private GeckoPopupMenu mPopupMenu; michael@0: michael@0: // Maximum number of items to show as actions michael@0: private static final int MAX_ACTION_ITEMS = 4; michael@0: michael@0: private int mActionButtonsWidth = 0; michael@0: michael@0: public ActionModeCompatView(Context context) { michael@0: super(context); michael@0: init(context); michael@0: } michael@0: michael@0: public ActionModeCompatView(Context context, AttributeSet attrs) { michael@0: super(context, attrs); michael@0: init(context); michael@0: } michael@0: michael@0: public ActionModeCompatView(Context context, AttributeSet attrs, int style) { michael@0: super(context, attrs, style); michael@0: init(context); michael@0: } michael@0: michael@0: public void init(Context context) { michael@0: LayoutInflater.from(context).inflate(R.layout.actionbar, this); michael@0: michael@0: mTitleView = (Button) findViewById(R.id.actionmode_title); michael@0: mMenuButton = (ImageButton) findViewById(R.id.actionbar_menu); michael@0: mActionButtonBar = (ViewGroup) findViewById(R.id.actionbar_buttons); michael@0: michael@0: mPopupMenu = new GeckoPopupMenu(getContext(), mMenuButton); michael@0: ((GeckoMenu) mPopupMenu.getMenu()).setActionItemBarPresenter(this); michael@0: michael@0: mMenuButton.setOnClickListener(new View.OnClickListener() { michael@0: public void onClick(View v) { michael@0: openMenu(); michael@0: } michael@0: }); michael@0: } michael@0: michael@0: public void initForMode(final ActionModeCompat mode) { michael@0: mTitleView.setOnClickListener(mode); michael@0: mPopupMenu.setOnMenuItemClickListener(mode); michael@0: } michael@0: michael@0: public CharSequence getTitle() { michael@0: return mTitleView.getText(); michael@0: } michael@0: michael@0: public void setTitle(CharSequence title) { michael@0: mTitleView.setText(title); michael@0: } michael@0: michael@0: public void setTitle(int resId) { michael@0: mTitleView.setText(resId); michael@0: } michael@0: michael@0: public Menu getMenu() { michael@0: return mPopupMenu.getMenu(); michael@0: } michael@0: michael@0: public void invalidate() { michael@0: // onFinishInflate may not have been called yet on some versions of Android michael@0: if (mPopupMenu != null && mMenuButton != null) { michael@0: mMenuButton.setVisibility(mPopupMenu.getMenu().hasVisibleItems() ? View.VISIBLE : View.GONE); michael@0: } michael@0: super.invalidate(); michael@0: } michael@0: michael@0: /* GeckoMenu.ActionItemBarPresenter */ michael@0: @Override michael@0: public boolean addActionItem(View actionItem) { michael@0: final int count = mActionButtonBar.getChildCount(); michael@0: if (count >= MAX_ACTION_ITEMS) { michael@0: return false; michael@0: } michael@0: michael@0: int maxWidth = mActionButtonBar.getMeasuredWidth(); michael@0: if (maxWidth == 0) { michael@0: mActionButtonBar.measure(SPEC, SPEC); michael@0: maxWidth = mActionButtonBar.getMeasuredWidth(); michael@0: } michael@0: michael@0: // If the menu button is already visible, no need to account for it michael@0: if (mMenuButton.getVisibility() == View.GONE) { michael@0: // Since we don't know how many items will be added, we always reserve space for the overflow menu michael@0: mMenuButton.measure(SPEC, SPEC); michael@0: maxWidth -= mMenuButton.getMeasuredWidth(); michael@0: } michael@0: michael@0: if (mActionButtonsWidth <= 0) { michael@0: mActionButtonsWidth = 0; michael@0: michael@0: // Loop over child views, measure them, and add their width to the taken width michael@0: for (int i = 0; i < count; i++) { michael@0: View v = mActionButtonBar.getChildAt(i); michael@0: v.measure(SPEC, SPEC); michael@0: mActionButtonsWidth += v.getMeasuredWidth(); michael@0: } michael@0: } michael@0: michael@0: actionItem.measure(SPEC, SPEC); michael@0: int w = actionItem.getMeasuredWidth(); michael@0: if (mActionButtonsWidth + w < maxWidth) { michael@0: // We cache the new width of our children. michael@0: mActionButtonsWidth += w; michael@0: mActionButtonBar.addView(actionItem); michael@0: return true; michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: /* GeckoMenu.ActionItemBarPresenter */ michael@0: @Override michael@0: public void removeActionItem(View actionItem) { michael@0: actionItem.measure(SPEC, SPEC); michael@0: mActionButtonsWidth -= actionItem.getMeasuredWidth(); michael@0: mActionButtonBar.removeView(actionItem); michael@0: } michael@0: michael@0: public void openMenu() { michael@0: mPopupMenu.openMenu(); michael@0: } michael@0: michael@0: public void closeMenu() { michael@0: mPopupMenu.dismiss(); michael@0: } michael@0: michael@0: public void animateIn() { michael@0: long duration = AnimationUtils.getShortDuration(getContext()); michael@0: TranslateAnimation t = new TranslateAnimation(Animation.RELATIVE_TO_SELF, -0.5f, Animation.RELATIVE_TO_SELF, 0f, michael@0: Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f); michael@0: t.setDuration(duration); michael@0: michael@0: ScaleAnimation s = new ScaleAnimation(1f, 1f, 0f, 1f, michael@0: Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); michael@0: s.setDuration((long) (duration * 1.5f)); michael@0: michael@0: mTitleView.startAnimation(t); michael@0: mActionButtonBar.startAnimation(s); michael@0: mMenuButton.startAnimation(s); michael@0: } michael@0: }