Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
michael@0 | 3 | * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | package org.mozilla.gecko; |
michael@0 | 6 | |
michael@0 | 7 | import org.mozilla.gecko.animation.AnimationUtils; |
michael@0 | 8 | import org.mozilla.gecko.menu.GeckoMenu; |
michael@0 | 9 | import org.mozilla.gecko.widget.GeckoPopupMenu; |
michael@0 | 10 | |
michael@0 | 11 | import android.content.Context; |
michael@0 | 12 | import android.util.AttributeSet; |
michael@0 | 13 | import android.view.LayoutInflater; |
michael@0 | 14 | import android.view.Menu; |
michael@0 | 15 | import android.view.View; |
michael@0 | 16 | import android.view.ViewGroup; |
michael@0 | 17 | import android.view.animation.Animation; |
michael@0 | 18 | import android.view.animation.ScaleAnimation; |
michael@0 | 19 | import android.view.animation.TranslateAnimation; |
michael@0 | 20 | import android.widget.Button; |
michael@0 | 21 | import android.widget.ImageButton; |
michael@0 | 22 | import android.widget.LinearLayout; |
michael@0 | 23 | |
michael@0 | 24 | class ActionModeCompatView extends LinearLayout implements GeckoMenu.ActionItemBarPresenter { |
michael@0 | 25 | private final String LOGTAG = "GeckoActionModeCompatPresenter"; |
michael@0 | 26 | |
michael@0 | 27 | private static final int SPEC = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); |
michael@0 | 28 | |
michael@0 | 29 | private Button mTitleView; |
michael@0 | 30 | private ImageButton mMenuButton; |
michael@0 | 31 | private ViewGroup mActionButtonBar; |
michael@0 | 32 | private GeckoPopupMenu mPopupMenu; |
michael@0 | 33 | |
michael@0 | 34 | // Maximum number of items to show as actions |
michael@0 | 35 | private static final int MAX_ACTION_ITEMS = 4; |
michael@0 | 36 | |
michael@0 | 37 | private int mActionButtonsWidth = 0; |
michael@0 | 38 | |
michael@0 | 39 | public ActionModeCompatView(Context context) { |
michael@0 | 40 | super(context); |
michael@0 | 41 | init(context); |
michael@0 | 42 | } |
michael@0 | 43 | |
michael@0 | 44 | public ActionModeCompatView(Context context, AttributeSet attrs) { |
michael@0 | 45 | super(context, attrs); |
michael@0 | 46 | init(context); |
michael@0 | 47 | } |
michael@0 | 48 | |
michael@0 | 49 | public ActionModeCompatView(Context context, AttributeSet attrs, int style) { |
michael@0 | 50 | super(context, attrs, style); |
michael@0 | 51 | init(context); |
michael@0 | 52 | } |
michael@0 | 53 | |
michael@0 | 54 | public void init(Context context) { |
michael@0 | 55 | LayoutInflater.from(context).inflate(R.layout.actionbar, this); |
michael@0 | 56 | |
michael@0 | 57 | mTitleView = (Button) findViewById(R.id.actionmode_title); |
michael@0 | 58 | mMenuButton = (ImageButton) findViewById(R.id.actionbar_menu); |
michael@0 | 59 | mActionButtonBar = (ViewGroup) findViewById(R.id.actionbar_buttons); |
michael@0 | 60 | |
michael@0 | 61 | mPopupMenu = new GeckoPopupMenu(getContext(), mMenuButton); |
michael@0 | 62 | ((GeckoMenu) mPopupMenu.getMenu()).setActionItemBarPresenter(this); |
michael@0 | 63 | |
michael@0 | 64 | mMenuButton.setOnClickListener(new View.OnClickListener() { |
michael@0 | 65 | public void onClick(View v) { |
michael@0 | 66 | openMenu(); |
michael@0 | 67 | } |
michael@0 | 68 | }); |
michael@0 | 69 | } |
michael@0 | 70 | |
michael@0 | 71 | public void initForMode(final ActionModeCompat mode) { |
michael@0 | 72 | mTitleView.setOnClickListener(mode); |
michael@0 | 73 | mPopupMenu.setOnMenuItemClickListener(mode); |
michael@0 | 74 | } |
michael@0 | 75 | |
michael@0 | 76 | public CharSequence getTitle() { |
michael@0 | 77 | return mTitleView.getText(); |
michael@0 | 78 | } |
michael@0 | 79 | |
michael@0 | 80 | public void setTitle(CharSequence title) { |
michael@0 | 81 | mTitleView.setText(title); |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | public void setTitle(int resId) { |
michael@0 | 85 | mTitleView.setText(resId); |
michael@0 | 86 | } |
michael@0 | 87 | |
michael@0 | 88 | public Menu getMenu() { |
michael@0 | 89 | return mPopupMenu.getMenu(); |
michael@0 | 90 | } |
michael@0 | 91 | |
michael@0 | 92 | public void invalidate() { |
michael@0 | 93 | // onFinishInflate may not have been called yet on some versions of Android |
michael@0 | 94 | if (mPopupMenu != null && mMenuButton != null) { |
michael@0 | 95 | mMenuButton.setVisibility(mPopupMenu.getMenu().hasVisibleItems() ? View.VISIBLE : View.GONE); |
michael@0 | 96 | } |
michael@0 | 97 | super.invalidate(); |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | /* GeckoMenu.ActionItemBarPresenter */ |
michael@0 | 101 | @Override |
michael@0 | 102 | public boolean addActionItem(View actionItem) { |
michael@0 | 103 | final int count = mActionButtonBar.getChildCount(); |
michael@0 | 104 | if (count >= MAX_ACTION_ITEMS) { |
michael@0 | 105 | return false; |
michael@0 | 106 | } |
michael@0 | 107 | |
michael@0 | 108 | int maxWidth = mActionButtonBar.getMeasuredWidth(); |
michael@0 | 109 | if (maxWidth == 0) { |
michael@0 | 110 | mActionButtonBar.measure(SPEC, SPEC); |
michael@0 | 111 | maxWidth = mActionButtonBar.getMeasuredWidth(); |
michael@0 | 112 | } |
michael@0 | 113 | |
michael@0 | 114 | // If the menu button is already visible, no need to account for it |
michael@0 | 115 | if (mMenuButton.getVisibility() == View.GONE) { |
michael@0 | 116 | // Since we don't know how many items will be added, we always reserve space for the overflow menu |
michael@0 | 117 | mMenuButton.measure(SPEC, SPEC); |
michael@0 | 118 | maxWidth -= mMenuButton.getMeasuredWidth(); |
michael@0 | 119 | } |
michael@0 | 120 | |
michael@0 | 121 | if (mActionButtonsWidth <= 0) { |
michael@0 | 122 | mActionButtonsWidth = 0; |
michael@0 | 123 | |
michael@0 | 124 | // Loop over child views, measure them, and add their width to the taken width |
michael@0 | 125 | for (int i = 0; i < count; i++) { |
michael@0 | 126 | View v = mActionButtonBar.getChildAt(i); |
michael@0 | 127 | v.measure(SPEC, SPEC); |
michael@0 | 128 | mActionButtonsWidth += v.getMeasuredWidth(); |
michael@0 | 129 | } |
michael@0 | 130 | } |
michael@0 | 131 | |
michael@0 | 132 | actionItem.measure(SPEC, SPEC); |
michael@0 | 133 | int w = actionItem.getMeasuredWidth(); |
michael@0 | 134 | if (mActionButtonsWidth + w < maxWidth) { |
michael@0 | 135 | // We cache the new width of our children. |
michael@0 | 136 | mActionButtonsWidth += w; |
michael@0 | 137 | mActionButtonBar.addView(actionItem); |
michael@0 | 138 | return true; |
michael@0 | 139 | } |
michael@0 | 140 | |
michael@0 | 141 | return false; |
michael@0 | 142 | } |
michael@0 | 143 | |
michael@0 | 144 | /* GeckoMenu.ActionItemBarPresenter */ |
michael@0 | 145 | @Override |
michael@0 | 146 | public void removeActionItem(View actionItem) { |
michael@0 | 147 | actionItem.measure(SPEC, SPEC); |
michael@0 | 148 | mActionButtonsWidth -= actionItem.getMeasuredWidth(); |
michael@0 | 149 | mActionButtonBar.removeView(actionItem); |
michael@0 | 150 | } |
michael@0 | 151 | |
michael@0 | 152 | public void openMenu() { |
michael@0 | 153 | mPopupMenu.openMenu(); |
michael@0 | 154 | } |
michael@0 | 155 | |
michael@0 | 156 | public void closeMenu() { |
michael@0 | 157 | mPopupMenu.dismiss(); |
michael@0 | 158 | } |
michael@0 | 159 | |
michael@0 | 160 | public void animateIn() { |
michael@0 | 161 | long duration = AnimationUtils.getShortDuration(getContext()); |
michael@0 | 162 | TranslateAnimation t = new TranslateAnimation(Animation.RELATIVE_TO_SELF, -0.5f, Animation.RELATIVE_TO_SELF, 0f, |
michael@0 | 163 | Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f); |
michael@0 | 164 | t.setDuration(duration); |
michael@0 | 165 | |
michael@0 | 166 | ScaleAnimation s = new ScaleAnimation(1f, 1f, 0f, 1f, |
michael@0 | 167 | Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); |
michael@0 | 168 | s.setDuration((long) (duration * 1.5f)); |
michael@0 | 169 | |
michael@0 | 170 | mTitleView.startAnimation(t); |
michael@0 | 171 | mActionButtonBar.startAnimation(s); |
michael@0 | 172 | mMenuButton.startAnimation(s); |
michael@0 | 173 | } |
michael@0 | 174 | } |