Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- |
michael@0 | 2 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | package org.mozilla.gecko.toolbar; |
michael@0 | 7 | |
michael@0 | 8 | import java.util.ArrayList; |
michael@0 | 9 | import java.util.Arrays; |
michael@0 | 10 | import java.util.EnumSet; |
michael@0 | 11 | import java.util.List; |
michael@0 | 12 | |
michael@0 | 13 | import org.json.JSONObject; |
michael@0 | 14 | import org.mozilla.gecko.BrowserApp; |
michael@0 | 15 | import org.mozilla.gecko.GeckoAppShell; |
michael@0 | 16 | import org.mozilla.gecko.GeckoApplication; |
michael@0 | 17 | import org.mozilla.gecko.GeckoProfile; |
michael@0 | 18 | import org.mozilla.gecko.LightweightTheme; |
michael@0 | 19 | import org.mozilla.gecko.R; |
michael@0 | 20 | import org.mozilla.gecko.Tab; |
michael@0 | 21 | import org.mozilla.gecko.Tabs; |
michael@0 | 22 | import org.mozilla.gecko.Telemetry; |
michael@0 | 23 | import org.mozilla.gecko.TelemetryContract; |
michael@0 | 24 | import org.mozilla.gecko.animation.PropertyAnimator; |
michael@0 | 25 | import org.mozilla.gecko.animation.PropertyAnimator.PropertyAnimationListener; |
michael@0 | 26 | import org.mozilla.gecko.animation.ViewHelper; |
michael@0 | 27 | import org.mozilla.gecko.menu.GeckoMenu; |
michael@0 | 28 | import org.mozilla.gecko.menu.MenuPopup; |
michael@0 | 29 | import org.mozilla.gecko.toolbar.ToolbarDisplayLayout.OnStopListener; |
michael@0 | 30 | import org.mozilla.gecko.toolbar.ToolbarDisplayLayout.OnTitleChangeListener; |
michael@0 | 31 | import org.mozilla.gecko.toolbar.ToolbarDisplayLayout.UpdateFlags; |
michael@0 | 32 | import org.mozilla.gecko.util.Clipboard; |
michael@0 | 33 | import org.mozilla.gecko.util.GeckoEventListener; |
michael@0 | 34 | import org.mozilla.gecko.util.HardwareUtils; |
michael@0 | 35 | import org.mozilla.gecko.util.MenuUtils; |
michael@0 | 36 | import org.mozilla.gecko.widget.ThemedImageButton; |
michael@0 | 37 | import org.mozilla.gecko.widget.ThemedImageView; |
michael@0 | 38 | import org.mozilla.gecko.widget.ThemedRelativeLayout; |
michael@0 | 39 | |
michael@0 | 40 | import android.content.Context; |
michael@0 | 41 | import android.content.res.Resources; |
michael@0 | 42 | import android.graphics.Bitmap; |
michael@0 | 43 | import android.graphics.drawable.BitmapDrawable; |
michael@0 | 44 | import android.graphics.drawable.Drawable; |
michael@0 | 45 | import android.graphics.drawable.StateListDrawable; |
michael@0 | 46 | import android.os.Build; |
michael@0 | 47 | import android.text.TextUtils; |
michael@0 | 48 | import android.util.AttributeSet; |
michael@0 | 49 | import android.util.Log; |
michael@0 | 50 | import android.view.ContextMenu; |
michael@0 | 51 | import android.view.KeyEvent; |
michael@0 | 52 | import android.view.LayoutInflater; |
michael@0 | 53 | import android.view.MenuInflater; |
michael@0 | 54 | import android.view.MotionEvent; |
michael@0 | 55 | import android.view.View; |
michael@0 | 56 | import android.view.ViewGroup; |
michael@0 | 57 | import android.view.animation.AccelerateInterpolator; |
michael@0 | 58 | import android.view.animation.Interpolator; |
michael@0 | 59 | import android.view.inputmethod.InputMethodManager; |
michael@0 | 60 | import android.widget.Button; |
michael@0 | 61 | import android.widget.ImageButton; |
michael@0 | 62 | import android.widget.ImageView; |
michael@0 | 63 | import android.widget.LinearLayout; |
michael@0 | 64 | import android.widget.PopupWindow; |
michael@0 | 65 | import android.widget.RelativeLayout; |
michael@0 | 66 | |
michael@0 | 67 | /** |
michael@0 | 68 | * {@code BrowserToolbar} is single entry point for users of the toolbar |
michael@0 | 69 | * subsystem i.e. this should be the only import outside the 'toolbar' |
michael@0 | 70 | * package. |
michael@0 | 71 | * |
michael@0 | 72 | * {@code BrowserToolbar} serves at the single event bus for all |
michael@0 | 73 | * sub-components in the toolbar. It tracks tab events and gecko messages |
michael@0 | 74 | * and update the state of its inner components accordingly. |
michael@0 | 75 | * |
michael@0 | 76 | * It has two states, display and edit, which are controlled by |
michael@0 | 77 | * ToolbarEditLayout and ToolbarDisplayLayout. In display state, the toolbar |
michael@0 | 78 | * displays the current state for the selected tab. In edit state, it shows |
michael@0 | 79 | * a text entry for searching bookmarks/history. {@code BrowserToolbar} |
michael@0 | 80 | * provides public API to enter, cancel, and commit the edit state as well |
michael@0 | 81 | * as a set of listeners to allow {@code BrowserToolbar} users to react |
michael@0 | 82 | * to state changes accordingly. |
michael@0 | 83 | */ |
michael@0 | 84 | public class BrowserToolbar extends ThemedRelativeLayout |
michael@0 | 85 | implements Tabs.OnTabsChangedListener, |
michael@0 | 86 | GeckoMenu.ActionItemBarPresenter, |
michael@0 | 87 | GeckoEventListener { |
michael@0 | 88 | private static final String LOGTAG = "GeckoToolbar"; |
michael@0 | 89 | |
michael@0 | 90 | public interface OnActivateListener { |
michael@0 | 91 | public void onActivate(); |
michael@0 | 92 | } |
michael@0 | 93 | |
michael@0 | 94 | public interface OnCommitListener { |
michael@0 | 95 | public void onCommit(); |
michael@0 | 96 | } |
michael@0 | 97 | |
michael@0 | 98 | public interface OnDismissListener { |
michael@0 | 99 | public void onDismiss(); |
michael@0 | 100 | } |
michael@0 | 101 | |
michael@0 | 102 | public interface OnFilterListener { |
michael@0 | 103 | public void onFilter(String searchText, AutocompleteHandler handler); |
michael@0 | 104 | } |
michael@0 | 105 | |
michael@0 | 106 | public interface OnStartEditingListener { |
michael@0 | 107 | public void onStartEditing(); |
michael@0 | 108 | } |
michael@0 | 109 | |
michael@0 | 110 | public interface OnStopEditingListener { |
michael@0 | 111 | public void onStopEditing(); |
michael@0 | 112 | } |
michael@0 | 113 | |
michael@0 | 114 | private enum UIMode { |
michael@0 | 115 | EDIT, |
michael@0 | 116 | DISPLAY |
michael@0 | 117 | } |
michael@0 | 118 | |
michael@0 | 119 | enum ForwardButtonAnimation { |
michael@0 | 120 | SHOW, |
michael@0 | 121 | HIDE |
michael@0 | 122 | } |
michael@0 | 123 | |
michael@0 | 124 | private ToolbarDisplayLayout urlDisplayLayout; |
michael@0 | 125 | private ToolbarEditLayout urlEditLayout; |
michael@0 | 126 | private View urlBarEntry; |
michael@0 | 127 | private RelativeLayout.LayoutParams urlBarEntryDefaultLayoutParams; |
michael@0 | 128 | private RelativeLayout.LayoutParams urlBarEntryShrunkenLayoutParams; |
michael@0 | 129 | private ImageView urlBarTranslatingEdge; |
michael@0 | 130 | private boolean isSwitchingTabs; |
michael@0 | 131 | private ShapedButton tabsButton; |
michael@0 | 132 | private ImageButton backButton; |
michael@0 | 133 | private ImageButton forwardButton; |
michael@0 | 134 | |
michael@0 | 135 | private ToolbarProgressView progressBar; |
michael@0 | 136 | private TabCounter tabsCounter; |
michael@0 | 137 | private ThemedImageButton menuButton; |
michael@0 | 138 | private ThemedImageView menuIcon; |
michael@0 | 139 | private LinearLayout actionItemBar; |
michael@0 | 140 | private MenuPopup menuPopup; |
michael@0 | 141 | private List<View> focusOrder; |
michael@0 | 142 | |
michael@0 | 143 | private final ThemedImageView editCancel; |
michael@0 | 144 | |
michael@0 | 145 | private boolean shouldShrinkURLBar = false; |
michael@0 | 146 | |
michael@0 | 147 | private OnActivateListener activateListener; |
michael@0 | 148 | private OnFocusChangeListener focusChangeListener; |
michael@0 | 149 | private OnStartEditingListener startEditingListener; |
michael@0 | 150 | private OnStopEditingListener stopEditingListener; |
michael@0 | 151 | |
michael@0 | 152 | private final BrowserApp activity; |
michael@0 | 153 | private boolean hasSoftMenuButton; |
michael@0 | 154 | |
michael@0 | 155 | private UIMode uiMode; |
michael@0 | 156 | private boolean isAnimatingEntry; |
michael@0 | 157 | |
michael@0 | 158 | private int urlBarViewOffset; |
michael@0 | 159 | private int defaultForwardMargin; |
michael@0 | 160 | |
michael@0 | 161 | private static final Interpolator buttonsInterpolator = new AccelerateInterpolator(); |
michael@0 | 162 | |
michael@0 | 163 | private static final int FORWARD_ANIMATION_DURATION = 450; |
michael@0 | 164 | |
michael@0 | 165 | private final LightweightTheme theme; |
michael@0 | 166 | |
michael@0 | 167 | public BrowserToolbar(Context context) { |
michael@0 | 168 | this(context, null); |
michael@0 | 169 | } |
michael@0 | 170 | |
michael@0 | 171 | public BrowserToolbar(Context context, AttributeSet attrs) { |
michael@0 | 172 | super(context, attrs); |
michael@0 | 173 | theme = ((GeckoApplication) context.getApplicationContext()).getLightweightTheme(); |
michael@0 | 174 | |
michael@0 | 175 | // BrowserToolbar is attached to BrowserApp only. |
michael@0 | 176 | activity = (BrowserApp) context; |
michael@0 | 177 | |
michael@0 | 178 | // Inflate the content. |
michael@0 | 179 | LayoutInflater.from(context).inflate(R.layout.browser_toolbar, this); |
michael@0 | 180 | |
michael@0 | 181 | Tabs.registerOnTabsChangedListener(this); |
michael@0 | 182 | isSwitchingTabs = true; |
michael@0 | 183 | isAnimatingEntry = false; |
michael@0 | 184 | |
michael@0 | 185 | registerEventListener("Reader:Click"); |
michael@0 | 186 | registerEventListener("Reader:LongClick"); |
michael@0 | 187 | |
michael@0 | 188 | final Resources res = getResources(); |
michael@0 | 189 | urlBarViewOffset = res.getDimensionPixelSize(R.dimen.url_bar_offset_left); |
michael@0 | 190 | defaultForwardMargin = res.getDimensionPixelSize(R.dimen.forward_default_offset); |
michael@0 | 191 | urlDisplayLayout = (ToolbarDisplayLayout) findViewById(R.id.display_layout); |
michael@0 | 192 | urlBarEntry = findViewById(R.id.url_bar_entry); |
michael@0 | 193 | urlEditLayout = (ToolbarEditLayout) findViewById(R.id.edit_layout); |
michael@0 | 194 | |
michael@0 | 195 | urlBarEntryDefaultLayoutParams = (RelativeLayout.LayoutParams) urlBarEntry.getLayoutParams(); |
michael@0 | 196 | // API level 19 adds a RelativeLayout.LayoutParams copy constructor, so we explicitly cast |
michael@0 | 197 | // to ViewGroup.MarginLayoutParams to ensure consistency across platforms. |
michael@0 | 198 | urlBarEntryShrunkenLayoutParams = new RelativeLayout.LayoutParams( |
michael@0 | 199 | (ViewGroup.MarginLayoutParams) urlBarEntryDefaultLayoutParams); |
michael@0 | 200 | urlBarEntryShrunkenLayoutParams.addRule(RelativeLayout.ALIGN_RIGHT, R.id.edit_layout); |
michael@0 | 201 | urlBarEntryShrunkenLayoutParams.rightMargin = 0; |
michael@0 | 202 | |
michael@0 | 203 | // This will clip the translating edge's image at 60% of its width |
michael@0 | 204 | urlBarTranslatingEdge = (ImageView) findViewById(R.id.url_bar_translating_edge); |
michael@0 | 205 | if (urlBarTranslatingEdge != null) { |
michael@0 | 206 | urlBarTranslatingEdge.getDrawable().setLevel(6000); |
michael@0 | 207 | } |
michael@0 | 208 | |
michael@0 | 209 | tabsButton = (ShapedButton) findViewById(R.id.tabs); |
michael@0 | 210 | tabsCounter = (TabCounter) findViewById(R.id.tabs_counter); |
michael@0 | 211 | if (Build.VERSION.SDK_INT >= 11) { |
michael@0 | 212 | tabsCounter.setLayerType(View.LAYER_TYPE_SOFTWARE, null); |
michael@0 | 213 | } |
michael@0 | 214 | |
michael@0 | 215 | backButton = (ImageButton) findViewById(R.id.back); |
michael@0 | 216 | setButtonEnabled(backButton, false); |
michael@0 | 217 | forwardButton = (ImageButton) findViewById(R.id.forward); |
michael@0 | 218 | setButtonEnabled(forwardButton, false); |
michael@0 | 219 | |
michael@0 | 220 | menuButton = (ThemedImageButton) findViewById(R.id.menu); |
michael@0 | 221 | menuIcon = (ThemedImageView) findViewById(R.id.menu_icon); |
michael@0 | 222 | actionItemBar = (LinearLayout) findViewById(R.id.menu_items); |
michael@0 | 223 | hasSoftMenuButton = !HardwareUtils.hasMenuButton(); |
michael@0 | 224 | |
michael@0 | 225 | editCancel = (ThemedImageView) findViewById(R.id.edit_cancel); |
michael@0 | 226 | |
michael@0 | 227 | // We use different layouts on phones and tablets, so adjust the focus |
michael@0 | 228 | // order appropriately. |
michael@0 | 229 | focusOrder = new ArrayList<View>(); |
michael@0 | 230 | if (HardwareUtils.isTablet()) { |
michael@0 | 231 | focusOrder.addAll(Arrays.asList(tabsButton, backButton, forwardButton, this)); |
michael@0 | 232 | focusOrder.addAll(urlDisplayLayout.getFocusOrder()); |
michael@0 | 233 | focusOrder.addAll(Arrays.asList(actionItemBar, menuButton)); |
michael@0 | 234 | } else { |
michael@0 | 235 | focusOrder.add(this); |
michael@0 | 236 | focusOrder.addAll(urlDisplayLayout.getFocusOrder()); |
michael@0 | 237 | focusOrder.addAll(Arrays.asList(tabsButton, menuButton)); |
michael@0 | 238 | } |
michael@0 | 239 | |
michael@0 | 240 | setUIMode(UIMode.DISPLAY); |
michael@0 | 241 | } |
michael@0 | 242 | |
michael@0 | 243 | @Override |
michael@0 | 244 | public void onAttachedToWindow() { |
michael@0 | 245 | super.onAttachedToWindow(); |
michael@0 | 246 | |
michael@0 | 247 | setOnClickListener(new Button.OnClickListener() { |
michael@0 | 248 | @Override |
michael@0 | 249 | public void onClick(View v) { |
michael@0 | 250 | if (activateListener != null) { |
michael@0 | 251 | activateListener.onActivate(); |
michael@0 | 252 | } |
michael@0 | 253 | } |
michael@0 | 254 | }); |
michael@0 | 255 | |
michael@0 | 256 | setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() { |
michael@0 | 257 | @Override |
michael@0 | 258 | public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { |
michael@0 | 259 | // We don't the context menu while editing |
michael@0 | 260 | if (isEditing()) { |
michael@0 | 261 | return; |
michael@0 | 262 | } |
michael@0 | 263 | |
michael@0 | 264 | // NOTE: Use MenuUtils.safeSetVisible because some actions might |
michael@0 | 265 | // be on the Page menu |
michael@0 | 266 | |
michael@0 | 267 | MenuInflater inflater = activity.getMenuInflater(); |
michael@0 | 268 | inflater.inflate(R.menu.titlebar_contextmenu, menu); |
michael@0 | 269 | |
michael@0 | 270 | String clipboard = Clipboard.getText(); |
michael@0 | 271 | if (TextUtils.isEmpty(clipboard)) { |
michael@0 | 272 | menu.findItem(R.id.pasteandgo).setVisible(false); |
michael@0 | 273 | menu.findItem(R.id.paste).setVisible(false); |
michael@0 | 274 | } |
michael@0 | 275 | |
michael@0 | 276 | Tab tab = Tabs.getInstance().getSelectedTab(); |
michael@0 | 277 | if (tab != null) { |
michael@0 | 278 | String url = tab.getURL(); |
michael@0 | 279 | if (url == null) { |
michael@0 | 280 | menu.findItem(R.id.copyurl).setVisible(false); |
michael@0 | 281 | menu.findItem(R.id.add_to_launcher).setVisible(false); |
michael@0 | 282 | MenuUtils.safeSetVisible(menu, R.id.share, false); |
michael@0 | 283 | } |
michael@0 | 284 | |
michael@0 | 285 | MenuUtils.safeSetVisible(menu, R.id.subscribe, tab.hasFeeds()); |
michael@0 | 286 | MenuUtils.safeSetVisible(menu, R.id.add_search_engine, tab.hasOpenSearch()); |
michael@0 | 287 | } else { |
michael@0 | 288 | // if there is no tab, remove anything tab dependent |
michael@0 | 289 | menu.findItem(R.id.copyurl).setVisible(false); |
michael@0 | 290 | menu.findItem(R.id.add_to_launcher).setVisible(false); |
michael@0 | 291 | MenuUtils.safeSetVisible(menu, R.id.share, false); |
michael@0 | 292 | MenuUtils.safeSetVisible(menu, R.id.subscribe, false); |
michael@0 | 293 | MenuUtils.safeSetVisible(menu, R.id.add_search_engine, false); |
michael@0 | 294 | } |
michael@0 | 295 | |
michael@0 | 296 | MenuUtils.safeSetVisible(menu, R.id.share, !GeckoProfile.get(getContext()).inGuestMode()); |
michael@0 | 297 | } |
michael@0 | 298 | }); |
michael@0 | 299 | |
michael@0 | 300 | urlDisplayLayout.setOnStopListener(new OnStopListener() { |
michael@0 | 301 | @Override |
michael@0 | 302 | public Tab onStop() { |
michael@0 | 303 | final Tab tab = Tabs.getInstance().getSelectedTab(); |
michael@0 | 304 | if (tab != null) { |
michael@0 | 305 | tab.doStop(); |
michael@0 | 306 | return tab; |
michael@0 | 307 | } |
michael@0 | 308 | |
michael@0 | 309 | return null; |
michael@0 | 310 | } |
michael@0 | 311 | }); |
michael@0 | 312 | |
michael@0 | 313 | urlDisplayLayout.setOnTitleChangeListener(new OnTitleChangeListener() { |
michael@0 | 314 | @Override |
michael@0 | 315 | public void onTitleChange(CharSequence title) { |
michael@0 | 316 | final String contentDescription; |
michael@0 | 317 | if (title != null) { |
michael@0 | 318 | contentDescription = title.toString(); |
michael@0 | 319 | } else { |
michael@0 | 320 | contentDescription = activity.getString(R.string.url_bar_default_text); |
michael@0 | 321 | } |
michael@0 | 322 | |
michael@0 | 323 | // The title and content description should |
michael@0 | 324 | // always be sync. |
michael@0 | 325 | setContentDescription(contentDescription); |
michael@0 | 326 | } |
michael@0 | 327 | }); |
michael@0 | 328 | |
michael@0 | 329 | urlEditLayout.setOnFocusChangeListener(new View.OnFocusChangeListener() { |
michael@0 | 330 | @Override |
michael@0 | 331 | public void onFocusChange(View v, boolean hasFocus) { |
michael@0 | 332 | // This will select the url bar when entering editing mode. |
michael@0 | 333 | setSelected(hasFocus); |
michael@0 | 334 | if (focusChangeListener != null) { |
michael@0 | 335 | focusChangeListener.onFocusChange(v, hasFocus); |
michael@0 | 336 | } |
michael@0 | 337 | } |
michael@0 | 338 | }); |
michael@0 | 339 | |
michael@0 | 340 | tabsButton.setOnClickListener(new Button.OnClickListener() { |
michael@0 | 341 | @Override |
michael@0 | 342 | public void onClick(View v) { |
michael@0 | 343 | toggleTabs(); |
michael@0 | 344 | } |
michael@0 | 345 | }); |
michael@0 | 346 | tabsButton.setImageLevel(0); |
michael@0 | 347 | |
michael@0 | 348 | backButton.setOnClickListener(new Button.OnClickListener() { |
michael@0 | 349 | @Override |
michael@0 | 350 | public void onClick(View view) { |
michael@0 | 351 | Tabs.getInstance().getSelectedTab().doBack(); |
michael@0 | 352 | } |
michael@0 | 353 | }); |
michael@0 | 354 | backButton.setOnLongClickListener(new Button.OnLongClickListener() { |
michael@0 | 355 | @Override |
michael@0 | 356 | public boolean onLongClick(View view) { |
michael@0 | 357 | return Tabs.getInstance().getSelectedTab().showBackHistory(); |
michael@0 | 358 | } |
michael@0 | 359 | }); |
michael@0 | 360 | |
michael@0 | 361 | forwardButton.setOnClickListener(new Button.OnClickListener() { |
michael@0 | 362 | @Override |
michael@0 | 363 | public void onClick(View view) { |
michael@0 | 364 | Tabs.getInstance().getSelectedTab().doForward(); |
michael@0 | 365 | } |
michael@0 | 366 | }); |
michael@0 | 367 | forwardButton.setOnLongClickListener(new Button.OnLongClickListener() { |
michael@0 | 368 | @Override |
michael@0 | 369 | public boolean onLongClick(View view) { |
michael@0 | 370 | return Tabs.getInstance().getSelectedTab().showForwardHistory(); |
michael@0 | 371 | } |
michael@0 | 372 | }); |
michael@0 | 373 | |
michael@0 | 374 | if (editCancel != null) { |
michael@0 | 375 | editCancel.setOnClickListener(new OnClickListener() { |
michael@0 | 376 | @Override |
michael@0 | 377 | public void onClick(View v) { |
michael@0 | 378 | // If we exit editing mode during the animation, |
michael@0 | 379 | // we're put into an inconsistent state (bug 1017276). |
michael@0 | 380 | if (!isAnimatingEntry) { |
michael@0 | 381 | Telemetry.sendUIEvent(TelemetryContract.Event.CANCEL, |
michael@0 | 382 | TelemetryContract.Method.ACTIONBAR, |
michael@0 | 383 | getResources().getResourceEntryName(editCancel.getId())); |
michael@0 | 384 | cancelEdit(); |
michael@0 | 385 | } |
michael@0 | 386 | } |
michael@0 | 387 | }); |
michael@0 | 388 | } |
michael@0 | 389 | |
michael@0 | 390 | if (hasSoftMenuButton) { |
michael@0 | 391 | menuButton.setVisibility(View.VISIBLE); |
michael@0 | 392 | menuIcon.setVisibility(View.VISIBLE); |
michael@0 | 393 | |
michael@0 | 394 | menuButton.setOnClickListener(new Button.OnClickListener() { |
michael@0 | 395 | @Override |
michael@0 | 396 | public void onClick(View view) { |
michael@0 | 397 | activity.openOptionsMenu(); |
michael@0 | 398 | } |
michael@0 | 399 | }); |
michael@0 | 400 | } |
michael@0 | 401 | } |
michael@0 | 402 | |
michael@0 | 403 | public void setProgressBar(ToolbarProgressView progressBar) { |
michael@0 | 404 | this.progressBar = progressBar; |
michael@0 | 405 | } |
michael@0 | 406 | |
michael@0 | 407 | public void refresh() { |
michael@0 | 408 | urlDisplayLayout.dismissSiteIdentityPopup(); |
michael@0 | 409 | } |
michael@0 | 410 | |
michael@0 | 411 | public boolean onBackPressed() { |
michael@0 | 412 | // If we exit editing mode during the animation, |
michael@0 | 413 | // we're put into an inconsistent state (bug 1017276). |
michael@0 | 414 | if (isEditing() && !isAnimatingEntry) { |
michael@0 | 415 | Telemetry.sendUIEvent(TelemetryContract.Event.CANCEL, |
michael@0 | 416 | TelemetryContract.Method.BACK); |
michael@0 | 417 | cancelEdit(); |
michael@0 | 418 | return true; |
michael@0 | 419 | } |
michael@0 | 420 | |
michael@0 | 421 | return urlDisplayLayout.dismissSiteIdentityPopup(); |
michael@0 | 422 | } |
michael@0 | 423 | |
michael@0 | 424 | @Override |
michael@0 | 425 | public boolean onTouchEvent(MotionEvent event) { |
michael@0 | 426 | // If the motion event has occured below the toolbar (due to the scroll |
michael@0 | 427 | // offset), let it pass through to the page. |
michael@0 | 428 | if (event != null && event.getY() > getHeight() + ViewHelper.getTranslationY(this)) { |
michael@0 | 429 | return false; |
michael@0 | 430 | } |
michael@0 | 431 | |
michael@0 | 432 | return super.onTouchEvent(event); |
michael@0 | 433 | } |
michael@0 | 434 | |
michael@0 | 435 | @Override |
michael@0 | 436 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { |
michael@0 | 437 | super.onSizeChanged(w, h, oldw, oldh); |
michael@0 | 438 | |
michael@0 | 439 | if (h != oldh) { |
michael@0 | 440 | // Post this to happen outside of onSizeChanged, as this may cause |
michael@0 | 441 | // a layout change and relayouts within a layout change don't work. |
michael@0 | 442 | post(new Runnable() { |
michael@0 | 443 | @Override |
michael@0 | 444 | public void run() { |
michael@0 | 445 | activity.refreshToolbarHeight(); |
michael@0 | 446 | } |
michael@0 | 447 | }); |
michael@0 | 448 | } |
michael@0 | 449 | } |
michael@0 | 450 | |
michael@0 | 451 | @Override |
michael@0 | 452 | public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) { |
michael@0 | 453 | Log.d(LOGTAG, "onTabChanged: " + msg); |
michael@0 | 454 | final Tabs tabs = Tabs.getInstance(); |
michael@0 | 455 | |
michael@0 | 456 | // These conditions are split into three phases: |
michael@0 | 457 | // * Always do first |
michael@0 | 458 | // * Handling specific to the selected tab |
michael@0 | 459 | // * Always do afterwards. |
michael@0 | 460 | |
michael@0 | 461 | switch (msg) { |
michael@0 | 462 | case ADDED: |
michael@0 | 463 | case CLOSED: |
michael@0 | 464 | updateTabCount(tabs.getDisplayCount()); |
michael@0 | 465 | break; |
michael@0 | 466 | case RESTORED: |
michael@0 | 467 | // TabCount fixup after OOM |
michael@0 | 468 | case SELECTED: |
michael@0 | 469 | urlDisplayLayout.dismissSiteIdentityPopup(); |
michael@0 | 470 | updateTabCount(tabs.getDisplayCount()); |
michael@0 | 471 | isSwitchingTabs = true; |
michael@0 | 472 | break; |
michael@0 | 473 | } |
michael@0 | 474 | |
michael@0 | 475 | if (tabs.isSelectedTab(tab)) { |
michael@0 | 476 | final EnumSet<UpdateFlags> flags = EnumSet.noneOf(UpdateFlags.class); |
michael@0 | 477 | |
michael@0 | 478 | // Progress-related handling |
michael@0 | 479 | switch (msg) { |
michael@0 | 480 | case START: |
michael@0 | 481 | updateProgressVisibility(tab, Tab.LOAD_PROGRESS_INIT); |
michael@0 | 482 | // Fall through. |
michael@0 | 483 | case ADDED: |
michael@0 | 484 | case LOCATION_CHANGE: |
michael@0 | 485 | case LOAD_ERROR: |
michael@0 | 486 | case LOADED: |
michael@0 | 487 | case STOP: |
michael@0 | 488 | flags.add(UpdateFlags.PROGRESS); |
michael@0 | 489 | if (progressBar.getVisibility() == View.VISIBLE) { |
michael@0 | 490 | progressBar.animateProgress(tab.getLoadProgress()); |
michael@0 | 491 | } |
michael@0 | 492 | break; |
michael@0 | 493 | |
michael@0 | 494 | case SELECTED: |
michael@0 | 495 | flags.add(UpdateFlags.PROGRESS); |
michael@0 | 496 | updateProgressVisibility(); |
michael@0 | 497 | break; |
michael@0 | 498 | } |
michael@0 | 499 | |
michael@0 | 500 | switch (msg) { |
michael@0 | 501 | case STOP: |
michael@0 | 502 | // Reset the title in case we haven't navigated |
michael@0 | 503 | // to a new page yet. |
michael@0 | 504 | flags.add(UpdateFlags.TITLE); |
michael@0 | 505 | // Fall through. |
michael@0 | 506 | case START: |
michael@0 | 507 | case CLOSED: |
michael@0 | 508 | case ADDED: |
michael@0 | 509 | updateBackButton(tab); |
michael@0 | 510 | updateForwardButton(tab); |
michael@0 | 511 | break; |
michael@0 | 512 | |
michael@0 | 513 | case SELECTED: |
michael@0 | 514 | flags.add(UpdateFlags.PRIVATE_MODE); |
michael@0 | 515 | setPrivateMode(tab.isPrivate()); |
michael@0 | 516 | // Fall through. |
michael@0 | 517 | case LOAD_ERROR: |
michael@0 | 518 | flags.add(UpdateFlags.TITLE); |
michael@0 | 519 | // Fall through. |
michael@0 | 520 | case LOCATION_CHANGE: |
michael@0 | 521 | // A successful location change will cause Tab to notify |
michael@0 | 522 | // us of a title change, so we don't update the title here. |
michael@0 | 523 | flags.add(UpdateFlags.FAVICON); |
michael@0 | 524 | flags.add(UpdateFlags.SITE_IDENTITY); |
michael@0 | 525 | |
michael@0 | 526 | updateBackButton(tab); |
michael@0 | 527 | updateForwardButton(tab); |
michael@0 | 528 | break; |
michael@0 | 529 | |
michael@0 | 530 | case TITLE: |
michael@0 | 531 | flags.add(UpdateFlags.TITLE); |
michael@0 | 532 | break; |
michael@0 | 533 | |
michael@0 | 534 | case FAVICON: |
michael@0 | 535 | flags.add(UpdateFlags.FAVICON); |
michael@0 | 536 | break; |
michael@0 | 537 | |
michael@0 | 538 | case SECURITY_CHANGE: |
michael@0 | 539 | flags.add(UpdateFlags.SITE_IDENTITY); |
michael@0 | 540 | break; |
michael@0 | 541 | } |
michael@0 | 542 | |
michael@0 | 543 | if (!flags.isEmpty()) { |
michael@0 | 544 | updateDisplayLayout(tab, flags); |
michael@0 | 545 | } |
michael@0 | 546 | } |
michael@0 | 547 | |
michael@0 | 548 | switch (msg) { |
michael@0 | 549 | case SELECTED: |
michael@0 | 550 | case LOAD_ERROR: |
michael@0 | 551 | case LOCATION_CHANGE: |
michael@0 | 552 | isSwitchingTabs = false; |
michael@0 | 553 | } |
michael@0 | 554 | } |
michael@0 | 555 | |
michael@0 | 556 | private void updateProgressVisibility() { |
michael@0 | 557 | final Tab selectedTab = Tabs.getInstance().getSelectedTab(); |
michael@0 | 558 | updateProgressVisibility(selectedTab, selectedTab.getLoadProgress()); |
michael@0 | 559 | } |
michael@0 | 560 | |
michael@0 | 561 | private void updateProgressVisibility(Tab selectedTab, int progress) { |
michael@0 | 562 | if (!isEditing() && selectedTab.getState() == Tab.STATE_LOADING) { |
michael@0 | 563 | progressBar.setProgress(progress); |
michael@0 | 564 | progressBar.setVisibility(View.VISIBLE); |
michael@0 | 565 | } else { |
michael@0 | 566 | progressBar.setVisibility(View.GONE); |
michael@0 | 567 | } |
michael@0 | 568 | } |
michael@0 | 569 | |
michael@0 | 570 | private boolean isVisible() { |
michael@0 | 571 | return ViewHelper.getTranslationY(this) == 0; |
michael@0 | 572 | } |
michael@0 | 573 | |
michael@0 | 574 | @Override |
michael@0 | 575 | public void setNextFocusDownId(int nextId) { |
michael@0 | 576 | super.setNextFocusDownId(nextId); |
michael@0 | 577 | tabsButton.setNextFocusDownId(nextId); |
michael@0 | 578 | backButton.setNextFocusDownId(nextId); |
michael@0 | 579 | forwardButton.setNextFocusDownId(nextId); |
michael@0 | 580 | urlDisplayLayout.setNextFocusDownId(nextId); |
michael@0 | 581 | menuButton.setNextFocusDownId(nextId); |
michael@0 | 582 | } |
michael@0 | 583 | |
michael@0 | 584 | private int getUrlBarEntryTranslation() { |
michael@0 | 585 | if (editCancel == null) { |
michael@0 | 586 | // We are on tablet, and there is no animation so return a translation of 0. |
michael@0 | 587 | return 0; |
michael@0 | 588 | } |
michael@0 | 589 | |
michael@0 | 590 | // Find the distance from the right-edge of the url bar (where we're translating from) to |
michael@0 | 591 | // the left-edge of the cancel button (where we're translating to; note that the cancel |
michael@0 | 592 | // button must be laid out, i.e. not View.GONE). |
michael@0 | 593 | final LayoutParams lp = (LayoutParams) urlEditLayout.getLayoutParams(); |
michael@0 | 594 | return editCancel.getLeft() - lp.leftMargin - urlBarEntry.getRight(); |
michael@0 | 595 | } |
michael@0 | 596 | |
michael@0 | 597 | private int getUrlBarCurveTranslation() { |
michael@0 | 598 | return getWidth() - tabsButton.getLeft(); |
michael@0 | 599 | } |
michael@0 | 600 | |
michael@0 | 601 | private boolean canDoBack(Tab tab) { |
michael@0 | 602 | return (tab.canDoBack() && !isEditing()); |
michael@0 | 603 | } |
michael@0 | 604 | |
michael@0 | 605 | private boolean canDoForward(Tab tab) { |
michael@0 | 606 | return (tab.canDoForward() && !isEditing()); |
michael@0 | 607 | } |
michael@0 | 608 | |
michael@0 | 609 | private void addTab() { |
michael@0 | 610 | activity.addTab(); |
michael@0 | 611 | } |
michael@0 | 612 | |
michael@0 | 613 | private void toggleTabs() { |
michael@0 | 614 | if (activity.areTabsShown()) { |
michael@0 | 615 | if (activity.hasTabsSideBar()) |
michael@0 | 616 | activity.hideTabs(); |
michael@0 | 617 | } else { |
michael@0 | 618 | // hide the virtual keyboard |
michael@0 | 619 | InputMethodManager imm = |
michael@0 | 620 | (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); |
michael@0 | 621 | imm.hideSoftInputFromWindow(tabsButton.getWindowToken(), 0); |
michael@0 | 622 | |
michael@0 | 623 | Tab tab = Tabs.getInstance().getSelectedTab(); |
michael@0 | 624 | if (tab != null) { |
michael@0 | 625 | if (!tab.isPrivate()) |
michael@0 | 626 | activity.showNormalTabs(); |
michael@0 | 627 | else |
michael@0 | 628 | activity.showPrivateTabs(); |
michael@0 | 629 | } |
michael@0 | 630 | } |
michael@0 | 631 | } |
michael@0 | 632 | |
michael@0 | 633 | private void updateTabCountAndAnimate(int count) { |
michael@0 | 634 | // Don't animate if the toolbar is hidden. |
michael@0 | 635 | if (!isVisible()) { |
michael@0 | 636 | updateTabCount(count); |
michael@0 | 637 | return; |
michael@0 | 638 | } |
michael@0 | 639 | |
michael@0 | 640 | // If toolbar is in edit mode on a phone, this means the entry is expanded |
michael@0 | 641 | // and the tabs button is translated offscreen. Don't trigger tabs counter |
michael@0 | 642 | // updates until the tabs button is back on screen. |
michael@0 | 643 | // See stopEditing() |
michael@0 | 644 | if (!isEditing() || HardwareUtils.isTablet()) { |
michael@0 | 645 | tabsCounter.setCount(count); |
michael@0 | 646 | |
michael@0 | 647 | tabsButton.setContentDescription((count > 1) ? |
michael@0 | 648 | activity.getString(R.string.num_tabs, count) : |
michael@0 | 649 | activity.getString(R.string.one_tab)); |
michael@0 | 650 | } |
michael@0 | 651 | } |
michael@0 | 652 | |
michael@0 | 653 | private void updateTabCount(int count) { |
michael@0 | 654 | // If toolbar is in edit mode on a phone, this means the entry is expanded |
michael@0 | 655 | // and the tabs button is translated offscreen. Don't trigger tabs counter |
michael@0 | 656 | // updates until the tabs button is back on screen. |
michael@0 | 657 | // See stopEditing() |
michael@0 | 658 | if (isEditing() && !HardwareUtils.isTablet()) { |
michael@0 | 659 | return; |
michael@0 | 660 | } |
michael@0 | 661 | |
michael@0 | 662 | // Set TabCounter based on visibility |
michael@0 | 663 | if (isVisible() && ViewHelper.getAlpha(tabsCounter) != 0 && !isEditing()) { |
michael@0 | 664 | tabsCounter.setCountWithAnimation(count); |
michael@0 | 665 | } else { |
michael@0 | 666 | tabsCounter.setCount(count); |
michael@0 | 667 | } |
michael@0 | 668 | |
michael@0 | 669 | // Update A11y information |
michael@0 | 670 | tabsButton.setContentDescription((count > 1) ? |
michael@0 | 671 | activity.getString(R.string.num_tabs, count) : |
michael@0 | 672 | activity.getString(R.string.one_tab)); |
michael@0 | 673 | } |
michael@0 | 674 | |
michael@0 | 675 | private void updateDisplayLayout(Tab tab, EnumSet<UpdateFlags> flags) { |
michael@0 | 676 | if (isSwitchingTabs) { |
michael@0 | 677 | flags.add(UpdateFlags.DISABLE_ANIMATIONS); |
michael@0 | 678 | } |
michael@0 | 679 | |
michael@0 | 680 | urlDisplayLayout.updateFromTab(tab, flags); |
michael@0 | 681 | |
michael@0 | 682 | if (flags.contains(UpdateFlags.TITLE)) { |
michael@0 | 683 | if (!isEditing()) { |
michael@0 | 684 | urlEditLayout.setText(tab.getURL()); |
michael@0 | 685 | } |
michael@0 | 686 | } |
michael@0 | 687 | |
michael@0 | 688 | if (flags.contains(UpdateFlags.PROGRESS)) { |
michael@0 | 689 | updateFocusOrder(); |
michael@0 | 690 | } |
michael@0 | 691 | } |
michael@0 | 692 | |
michael@0 | 693 | private void updateFocusOrder() { |
michael@0 | 694 | View prevView = null; |
michael@0 | 695 | |
michael@0 | 696 | // If the element that has focus becomes disabled or invisible, focus |
michael@0 | 697 | // is given to the URL bar. |
michael@0 | 698 | boolean needsNewFocus = false; |
michael@0 | 699 | |
michael@0 | 700 | for (View view : focusOrder) { |
michael@0 | 701 | if (view.getVisibility() != View.VISIBLE || !view.isEnabled()) { |
michael@0 | 702 | if (view.hasFocus()) { |
michael@0 | 703 | needsNewFocus = true; |
michael@0 | 704 | } |
michael@0 | 705 | continue; |
michael@0 | 706 | } |
michael@0 | 707 | |
michael@0 | 708 | if (view == actionItemBar) { |
michael@0 | 709 | final int childCount = actionItemBar.getChildCount(); |
michael@0 | 710 | for (int child = 0; child < childCount; child++) { |
michael@0 | 711 | View childView = actionItemBar.getChildAt(child); |
michael@0 | 712 | if (prevView != null) { |
michael@0 | 713 | childView.setNextFocusLeftId(prevView.getId()); |
michael@0 | 714 | prevView.setNextFocusRightId(childView.getId()); |
michael@0 | 715 | } |
michael@0 | 716 | prevView = childView; |
michael@0 | 717 | } |
michael@0 | 718 | } else { |
michael@0 | 719 | if (prevView != null) { |
michael@0 | 720 | view.setNextFocusLeftId(prevView.getId()); |
michael@0 | 721 | prevView.setNextFocusRightId(view.getId()); |
michael@0 | 722 | } |
michael@0 | 723 | prevView = view; |
michael@0 | 724 | } |
michael@0 | 725 | } |
michael@0 | 726 | |
michael@0 | 727 | if (needsNewFocus) { |
michael@0 | 728 | requestFocus(); |
michael@0 | 729 | } |
michael@0 | 730 | } |
michael@0 | 731 | |
michael@0 | 732 | public void onEditSuggestion(String suggestion) { |
michael@0 | 733 | if (!isEditing()) { |
michael@0 | 734 | return; |
michael@0 | 735 | } |
michael@0 | 736 | |
michael@0 | 737 | urlEditLayout.onEditSuggestion(suggestion); |
michael@0 | 738 | } |
michael@0 | 739 | |
michael@0 | 740 | public void setTitle(CharSequence title) { |
michael@0 | 741 | urlDisplayLayout.setTitle(title); |
michael@0 | 742 | } |
michael@0 | 743 | |
michael@0 | 744 | public void prepareTabsAnimation(PropertyAnimator animator, boolean tabsAreShown) { |
michael@0 | 745 | if (!tabsAreShown) { |
michael@0 | 746 | PropertyAnimator buttonsAnimator = |
michael@0 | 747 | new PropertyAnimator(animator.getDuration(), buttonsInterpolator); |
michael@0 | 748 | |
michael@0 | 749 | buttonsAnimator.attach(tabsCounter, |
michael@0 | 750 | PropertyAnimator.Property.ALPHA, |
michael@0 | 751 | 1.0f); |
michael@0 | 752 | |
michael@0 | 753 | if (hasSoftMenuButton && !HardwareUtils.isTablet()) { |
michael@0 | 754 | buttonsAnimator.attach(menuIcon, |
michael@0 | 755 | PropertyAnimator.Property.ALPHA, |
michael@0 | 756 | 1.0f); |
michael@0 | 757 | } |
michael@0 | 758 | |
michael@0 | 759 | buttonsAnimator.start(); |
michael@0 | 760 | |
michael@0 | 761 | return; |
michael@0 | 762 | } |
michael@0 | 763 | |
michael@0 | 764 | ViewHelper.setAlpha(tabsCounter, 0.0f); |
michael@0 | 765 | |
michael@0 | 766 | if (hasSoftMenuButton && !HardwareUtils.isTablet()) { |
michael@0 | 767 | ViewHelper.setAlpha(menuIcon, 0.0f); |
michael@0 | 768 | } |
michael@0 | 769 | } |
michael@0 | 770 | |
michael@0 | 771 | public void finishTabsAnimation(boolean tabsAreShown) { |
michael@0 | 772 | if (tabsAreShown) { |
michael@0 | 773 | return; |
michael@0 | 774 | } |
michael@0 | 775 | |
michael@0 | 776 | PropertyAnimator animator = new PropertyAnimator(150); |
michael@0 | 777 | |
michael@0 | 778 | animator.attach(tabsCounter, |
michael@0 | 779 | PropertyAnimator.Property.ALPHA, |
michael@0 | 780 | 1.0f); |
michael@0 | 781 | |
michael@0 | 782 | if (hasSoftMenuButton && !HardwareUtils.isTablet()) { |
michael@0 | 783 | animator.attach(menuIcon, |
michael@0 | 784 | PropertyAnimator.Property.ALPHA, |
michael@0 | 785 | 1.0f); |
michael@0 | 786 | } |
michael@0 | 787 | |
michael@0 | 788 | animator.start(); |
michael@0 | 789 | } |
michael@0 | 790 | |
michael@0 | 791 | public void setOnActivateListener(OnActivateListener listener) { |
michael@0 | 792 | activateListener = listener; |
michael@0 | 793 | } |
michael@0 | 794 | |
michael@0 | 795 | public void setOnCommitListener(OnCommitListener listener) { |
michael@0 | 796 | urlEditLayout.setOnCommitListener(listener); |
michael@0 | 797 | } |
michael@0 | 798 | |
michael@0 | 799 | public void setOnDismissListener(OnDismissListener listener) { |
michael@0 | 800 | urlEditLayout.setOnDismissListener(listener); |
michael@0 | 801 | } |
michael@0 | 802 | |
michael@0 | 803 | public void setOnFilterListener(OnFilterListener listener) { |
michael@0 | 804 | urlEditLayout.setOnFilterListener(listener); |
michael@0 | 805 | } |
michael@0 | 806 | |
michael@0 | 807 | public void setOnFocusChangeListener(OnFocusChangeListener listener) { |
michael@0 | 808 | focusChangeListener = listener; |
michael@0 | 809 | } |
michael@0 | 810 | |
michael@0 | 811 | public void setOnStartEditingListener(OnStartEditingListener listener) { |
michael@0 | 812 | startEditingListener = listener; |
michael@0 | 813 | } |
michael@0 | 814 | |
michael@0 | 815 | public void setOnStopEditingListener(OnStopEditingListener listener) { |
michael@0 | 816 | stopEditingListener = listener; |
michael@0 | 817 | } |
michael@0 | 818 | |
michael@0 | 819 | private void showUrlEditLayout() { |
michael@0 | 820 | setUrlEditLayoutVisibility(true, null); |
michael@0 | 821 | } |
michael@0 | 822 | |
michael@0 | 823 | private void showUrlEditLayout(PropertyAnimator animator) { |
michael@0 | 824 | setUrlEditLayoutVisibility(true, animator); |
michael@0 | 825 | } |
michael@0 | 826 | |
michael@0 | 827 | private void hideUrlEditLayout() { |
michael@0 | 828 | setUrlEditLayoutVisibility(false, null); |
michael@0 | 829 | } |
michael@0 | 830 | |
michael@0 | 831 | private void hideUrlEditLayout(PropertyAnimator animator) { |
michael@0 | 832 | setUrlEditLayoutVisibility(false, animator); |
michael@0 | 833 | } |
michael@0 | 834 | |
michael@0 | 835 | private void setUrlEditLayoutVisibility(final boolean showEditLayout, PropertyAnimator animator) { |
michael@0 | 836 | if (showEditLayout) { |
michael@0 | 837 | urlEditLayout.prepareShowAnimation(animator); |
michael@0 | 838 | } |
michael@0 | 839 | |
michael@0 | 840 | if (animator == null) { |
michael@0 | 841 | final View viewToShow = (showEditLayout ? urlEditLayout : urlDisplayLayout); |
michael@0 | 842 | final View viewToHide = (showEditLayout ? urlDisplayLayout : urlEditLayout); |
michael@0 | 843 | |
michael@0 | 844 | viewToHide.setVisibility(View.GONE); |
michael@0 | 845 | viewToShow.setVisibility(View.VISIBLE); |
michael@0 | 846 | |
michael@0 | 847 | final int cancelVisibility = (showEditLayout ? View.VISIBLE : View.INVISIBLE); |
michael@0 | 848 | setCancelVisibility(cancelVisibility); |
michael@0 | 849 | return; |
michael@0 | 850 | } |
michael@0 | 851 | |
michael@0 | 852 | animator.addPropertyAnimationListener(new PropertyAnimationListener() { |
michael@0 | 853 | @Override |
michael@0 | 854 | public void onPropertyAnimationStart() { |
michael@0 | 855 | if (!showEditLayout) { |
michael@0 | 856 | urlEditLayout.setVisibility(View.GONE); |
michael@0 | 857 | urlDisplayLayout.setVisibility(View.VISIBLE); |
michael@0 | 858 | |
michael@0 | 859 | setCancelVisibility(View.INVISIBLE); |
michael@0 | 860 | } |
michael@0 | 861 | } |
michael@0 | 862 | |
michael@0 | 863 | @Override |
michael@0 | 864 | public void onPropertyAnimationEnd() { |
michael@0 | 865 | if (showEditLayout) { |
michael@0 | 866 | urlDisplayLayout.setVisibility(View.GONE); |
michael@0 | 867 | urlEditLayout.setVisibility(View.VISIBLE); |
michael@0 | 868 | |
michael@0 | 869 | setCancelVisibility(View.VISIBLE); |
michael@0 | 870 | } |
michael@0 | 871 | } |
michael@0 | 872 | }); |
michael@0 | 873 | } |
michael@0 | 874 | |
michael@0 | 875 | private void setCancelVisibility(final int visibility) { |
michael@0 | 876 | if (editCancel != null) { |
michael@0 | 877 | editCancel.setVisibility(visibility); |
michael@0 | 878 | } |
michael@0 | 879 | } |
michael@0 | 880 | |
michael@0 | 881 | /** |
michael@0 | 882 | * Disables and dims all toolbar elements which are not |
michael@0 | 883 | * related to editing mode. |
michael@0 | 884 | */ |
michael@0 | 885 | private void updateChildrenForEditing() { |
michael@0 | 886 | // This is for the tablet UI only |
michael@0 | 887 | if (!HardwareUtils.isTablet()) { |
michael@0 | 888 | return; |
michael@0 | 889 | } |
michael@0 | 890 | |
michael@0 | 891 | // Disable toolbar elemens while in editing mode |
michael@0 | 892 | final boolean enabled = !isEditing(); |
michael@0 | 893 | |
michael@0 | 894 | // This alpha value has to be in sync with the one used |
michael@0 | 895 | // in setButtonEnabled(). |
michael@0 | 896 | final float alpha = (enabled ? 1.0f : 0.24f); |
michael@0 | 897 | |
michael@0 | 898 | if (!enabled) { |
michael@0 | 899 | tabsCounter.onEnterEditingMode(); |
michael@0 | 900 | } |
michael@0 | 901 | |
michael@0 | 902 | tabsButton.setEnabled(enabled); |
michael@0 | 903 | ViewHelper.setAlpha(tabsCounter, alpha); |
michael@0 | 904 | menuButton.setEnabled(enabled); |
michael@0 | 905 | ViewHelper.setAlpha(menuIcon, alpha); |
michael@0 | 906 | |
michael@0 | 907 | final int actionItemsCount = actionItemBar.getChildCount(); |
michael@0 | 908 | for (int i = 0; i < actionItemsCount; i++) { |
michael@0 | 909 | actionItemBar.getChildAt(i).setEnabled(enabled); |
michael@0 | 910 | } |
michael@0 | 911 | ViewHelper.setAlpha(actionItemBar, alpha); |
michael@0 | 912 | |
michael@0 | 913 | final Tab tab = Tabs.getInstance().getSelectedTab(); |
michael@0 | 914 | if (tab != null) { |
michael@0 | 915 | setButtonEnabled(backButton, canDoBack(tab)); |
michael@0 | 916 | setButtonEnabled(forwardButton, canDoForward(tab)); |
michael@0 | 917 | |
michael@0 | 918 | // Once the editing mode is finished, we have to ensure that the |
michael@0 | 919 | // forward button slides away if necessary. This is because we might |
michael@0 | 920 | // have only disabled it (without hiding it) when the toolbar entered |
michael@0 | 921 | // editing mode. |
michael@0 | 922 | if (!isEditing()) { |
michael@0 | 923 | animateForwardButton(canDoForward(tab) ? |
michael@0 | 924 | ForwardButtonAnimation.SHOW : ForwardButtonAnimation.HIDE); |
michael@0 | 925 | } |
michael@0 | 926 | } |
michael@0 | 927 | } |
michael@0 | 928 | |
michael@0 | 929 | private void setUIMode(final UIMode uiMode) { |
michael@0 | 930 | this.uiMode = uiMode; |
michael@0 | 931 | urlEditLayout.setEnabled(uiMode == UIMode.EDIT); |
michael@0 | 932 | } |
michael@0 | 933 | |
michael@0 | 934 | /** |
michael@0 | 935 | * Returns whether or not the URL bar is in editing mode (url bar is expanded, hiding the new |
michael@0 | 936 | * tab button). Note that selection state is independent of editing mode. |
michael@0 | 937 | */ |
michael@0 | 938 | public boolean isEditing() { |
michael@0 | 939 | return (uiMode == UIMode.EDIT); |
michael@0 | 940 | } |
michael@0 | 941 | |
michael@0 | 942 | public boolean isAnimating() { |
michael@0 | 943 | return isAnimatingEntry; |
michael@0 | 944 | } |
michael@0 | 945 | |
michael@0 | 946 | public void startEditing(String url, PropertyAnimator animator) { |
michael@0 | 947 | if (isEditing()) { |
michael@0 | 948 | return; |
michael@0 | 949 | } |
michael@0 | 950 | |
michael@0 | 951 | urlEditLayout.setText(url != null ? url : ""); |
michael@0 | 952 | |
michael@0 | 953 | setUIMode(UIMode.EDIT); |
michael@0 | 954 | updateChildrenForEditing(); |
michael@0 | 955 | |
michael@0 | 956 | updateProgressVisibility(); |
michael@0 | 957 | |
michael@0 | 958 | if (startEditingListener != null) { |
michael@0 | 959 | startEditingListener.onStartEditing(); |
michael@0 | 960 | } |
michael@0 | 961 | |
michael@0 | 962 | final int curveTranslation = getUrlBarCurveTranslation(); |
michael@0 | 963 | final int entryTranslation = getUrlBarEntryTranslation(); |
michael@0 | 964 | shouldShrinkURLBar = (entryTranslation < 0); |
michael@0 | 965 | |
michael@0 | 966 | if (urlBarTranslatingEdge != null) { |
michael@0 | 967 | urlBarTranslatingEdge.setVisibility(View.VISIBLE); |
michael@0 | 968 | if (shouldShrinkURLBar) { |
michael@0 | 969 | urlBarEntry.setLayoutParams(urlBarEntryShrunkenLayoutParams); |
michael@0 | 970 | } |
michael@0 | 971 | } |
michael@0 | 972 | |
michael@0 | 973 | if (Build.VERSION.SDK_INT < 11) { |
michael@0 | 974 | showEditingWithoutAnimation(entryTranslation, curveTranslation); |
michael@0 | 975 | } else if (HardwareUtils.isTablet()) { |
michael@0 | 976 | // No animation. |
michael@0 | 977 | showUrlEditLayout(); |
michael@0 | 978 | } else { |
michael@0 | 979 | showEditingWithPhoneAnimation(animator, entryTranslation, curveTranslation); |
michael@0 | 980 | } |
michael@0 | 981 | } |
michael@0 | 982 | |
michael@0 | 983 | private void showEditingWithoutAnimation(final int entryTranslation, |
michael@0 | 984 | final int curveTranslation) { |
michael@0 | 985 | showUrlEditLayout(); |
michael@0 | 986 | |
michael@0 | 987 | if (urlBarTranslatingEdge != null) { |
michael@0 | 988 | ViewHelper.setTranslationX(urlBarTranslatingEdge, entryTranslation); |
michael@0 | 989 | } |
michael@0 | 990 | |
michael@0 | 991 | // Prevent taps through the editing mode cancel button (bug 1001243). |
michael@0 | 992 | tabsButton.setEnabled(false); |
michael@0 | 993 | |
michael@0 | 994 | ViewHelper.setTranslationX(tabsButton, curveTranslation); |
michael@0 | 995 | ViewHelper.setTranslationX(tabsCounter, curveTranslation); |
michael@0 | 996 | ViewHelper.setTranslationX(actionItemBar, curveTranslation); |
michael@0 | 997 | |
michael@0 | 998 | if (hasSoftMenuButton) { |
michael@0 | 999 | // Prevent tabs through the editing mode cancel button (bug 1001243). |
michael@0 | 1000 | menuButton.setEnabled(false); |
michael@0 | 1001 | |
michael@0 | 1002 | ViewHelper.setTranslationX(menuButton, curveTranslation); |
michael@0 | 1003 | ViewHelper.setTranslationX(menuIcon, curveTranslation); |
michael@0 | 1004 | } |
michael@0 | 1005 | } |
michael@0 | 1006 | |
michael@0 | 1007 | private void showEditingWithPhoneAnimation(final PropertyAnimator animator, |
michael@0 | 1008 | final int entryTranslation, final int curveTranslation) { |
michael@0 | 1009 | if (isAnimatingEntry) |
michael@0 | 1010 | return; |
michael@0 | 1011 | |
michael@0 | 1012 | urlDisplayLayout.prepareStartEditingAnimation(); |
michael@0 | 1013 | |
michael@0 | 1014 | // Slide toolbar elements. |
michael@0 | 1015 | if (urlBarTranslatingEdge != null) { |
michael@0 | 1016 | animator.attach(urlBarTranslatingEdge, |
michael@0 | 1017 | PropertyAnimator.Property.TRANSLATION_X, |
michael@0 | 1018 | entryTranslation); |
michael@0 | 1019 | } |
michael@0 | 1020 | |
michael@0 | 1021 | animator.attach(tabsButton, |
michael@0 | 1022 | PropertyAnimator.Property.TRANSLATION_X, |
michael@0 | 1023 | curveTranslation); |
michael@0 | 1024 | animator.attach(tabsCounter, |
michael@0 | 1025 | PropertyAnimator.Property.TRANSLATION_X, |
michael@0 | 1026 | curveTranslation); |
michael@0 | 1027 | animator.attach(actionItemBar, |
michael@0 | 1028 | PropertyAnimator.Property.TRANSLATION_X, |
michael@0 | 1029 | curveTranslation); |
michael@0 | 1030 | |
michael@0 | 1031 | if (hasSoftMenuButton) { |
michael@0 | 1032 | animator.attach(menuButton, |
michael@0 | 1033 | PropertyAnimator.Property.TRANSLATION_X, |
michael@0 | 1034 | curveTranslation); |
michael@0 | 1035 | |
michael@0 | 1036 | animator.attach(menuIcon, |
michael@0 | 1037 | PropertyAnimator.Property.TRANSLATION_X, |
michael@0 | 1038 | curveTranslation); |
michael@0 | 1039 | } |
michael@0 | 1040 | |
michael@0 | 1041 | showUrlEditLayout(animator); |
michael@0 | 1042 | |
michael@0 | 1043 | animator.addPropertyAnimationListener(new PropertyAnimator.PropertyAnimationListener() { |
michael@0 | 1044 | @Override |
michael@0 | 1045 | public void onPropertyAnimationStart() { |
michael@0 | 1046 | } |
michael@0 | 1047 | |
michael@0 | 1048 | @Override |
michael@0 | 1049 | public void onPropertyAnimationEnd() { |
michael@0 | 1050 | isAnimatingEntry = false; |
michael@0 | 1051 | } |
michael@0 | 1052 | }); |
michael@0 | 1053 | |
michael@0 | 1054 | isAnimatingEntry = true; |
michael@0 | 1055 | } |
michael@0 | 1056 | |
michael@0 | 1057 | /** |
michael@0 | 1058 | * Exits edit mode without updating the toolbar title. |
michael@0 | 1059 | * |
michael@0 | 1060 | * @return the url that was entered |
michael@0 | 1061 | */ |
michael@0 | 1062 | public String cancelEdit() { |
michael@0 | 1063 | Telemetry.stopUISession(TelemetryContract.Session.AWESOMESCREEN); |
michael@0 | 1064 | return stopEditing(); |
michael@0 | 1065 | } |
michael@0 | 1066 | |
michael@0 | 1067 | /** |
michael@0 | 1068 | * Exits edit mode, updating the toolbar title with the url that was just entered. |
michael@0 | 1069 | * |
michael@0 | 1070 | * @return the url that was entered |
michael@0 | 1071 | */ |
michael@0 | 1072 | public String commitEdit() { |
michael@0 | 1073 | final String url = stopEditing(); |
michael@0 | 1074 | if (!TextUtils.isEmpty(url)) { |
michael@0 | 1075 | setTitle(url); |
michael@0 | 1076 | } |
michael@0 | 1077 | return url; |
michael@0 | 1078 | } |
michael@0 | 1079 | |
michael@0 | 1080 | private String stopEditing() { |
michael@0 | 1081 | final String url = urlEditLayout.getText(); |
michael@0 | 1082 | if (!isEditing()) { |
michael@0 | 1083 | return url; |
michael@0 | 1084 | } |
michael@0 | 1085 | setUIMode(UIMode.DISPLAY); |
michael@0 | 1086 | |
michael@0 | 1087 | updateChildrenForEditing(); |
michael@0 | 1088 | |
michael@0 | 1089 | if (stopEditingListener != null) { |
michael@0 | 1090 | stopEditingListener.onStopEditing(); |
michael@0 | 1091 | } |
michael@0 | 1092 | |
michael@0 | 1093 | updateProgressVisibility(); |
michael@0 | 1094 | |
michael@0 | 1095 | // The animation looks cleaner if the text in the URL bar is |
michael@0 | 1096 | // not selected so clear the selection by clearing focus. |
michael@0 | 1097 | urlEditLayout.clearFocus(); |
michael@0 | 1098 | |
michael@0 | 1099 | if (Build.VERSION.SDK_INT < 11) { |
michael@0 | 1100 | stopEditingWithoutAnimation(); |
michael@0 | 1101 | } else if (HardwareUtils.isTablet()) { |
michael@0 | 1102 | // No animation. |
michael@0 | 1103 | hideUrlEditLayout(); |
michael@0 | 1104 | } else { |
michael@0 | 1105 | stopEditingWithPhoneAnimation(); |
michael@0 | 1106 | } |
michael@0 | 1107 | |
michael@0 | 1108 | return url; |
michael@0 | 1109 | } |
michael@0 | 1110 | |
michael@0 | 1111 | private void stopEditingWithoutAnimation() { |
michael@0 | 1112 | hideUrlEditLayout(); |
michael@0 | 1113 | |
michael@0 | 1114 | updateTabCountAndAnimate(Tabs.getInstance().getDisplayCount()); |
michael@0 | 1115 | |
michael@0 | 1116 | if (urlBarTranslatingEdge != null) { |
michael@0 | 1117 | urlBarTranslatingEdge.setVisibility(View.INVISIBLE); |
michael@0 | 1118 | ViewHelper.setTranslationX(urlBarTranslatingEdge, 0); |
michael@0 | 1119 | if (shouldShrinkURLBar) { |
michael@0 | 1120 | urlBarEntry.setLayoutParams(urlBarEntryDefaultLayoutParams); |
michael@0 | 1121 | } |
michael@0 | 1122 | } |
michael@0 | 1123 | |
michael@0 | 1124 | tabsButton.setEnabled(true); |
michael@0 | 1125 | |
michael@0 | 1126 | ViewHelper.setTranslationX(tabsButton, 0); |
michael@0 | 1127 | ViewHelper.setTranslationX(tabsCounter, 0); |
michael@0 | 1128 | ViewHelper.setTranslationX(actionItemBar, 0); |
michael@0 | 1129 | |
michael@0 | 1130 | if (hasSoftMenuButton) { |
michael@0 | 1131 | menuButton.setEnabled(true); |
michael@0 | 1132 | |
michael@0 | 1133 | ViewHelper.setTranslationX(menuButton, 0); |
michael@0 | 1134 | ViewHelper.setTranslationX(menuIcon, 0); |
michael@0 | 1135 | } |
michael@0 | 1136 | } |
michael@0 | 1137 | |
michael@0 | 1138 | private void stopEditingWithPhoneAnimation() { |
michael@0 | 1139 | final PropertyAnimator contentAnimator = new PropertyAnimator(250); |
michael@0 | 1140 | contentAnimator.setUseHardwareLayer(false); |
michael@0 | 1141 | |
michael@0 | 1142 | // Slide the toolbar back to its original size. |
michael@0 | 1143 | if (urlBarTranslatingEdge != null) { |
michael@0 | 1144 | contentAnimator.attach(urlBarTranslatingEdge, |
michael@0 | 1145 | PropertyAnimator.Property.TRANSLATION_X, |
michael@0 | 1146 | 0); |
michael@0 | 1147 | } |
michael@0 | 1148 | |
michael@0 | 1149 | contentAnimator.attach(tabsButton, |
michael@0 | 1150 | PropertyAnimator.Property.TRANSLATION_X, |
michael@0 | 1151 | 0); |
michael@0 | 1152 | contentAnimator.attach(tabsCounter, |
michael@0 | 1153 | PropertyAnimator.Property.TRANSLATION_X, |
michael@0 | 1154 | 0); |
michael@0 | 1155 | contentAnimator.attach(actionItemBar, |
michael@0 | 1156 | PropertyAnimator.Property.TRANSLATION_X, |
michael@0 | 1157 | 0); |
michael@0 | 1158 | |
michael@0 | 1159 | if (hasSoftMenuButton) { |
michael@0 | 1160 | contentAnimator.attach(menuButton, |
michael@0 | 1161 | PropertyAnimator.Property.TRANSLATION_X, |
michael@0 | 1162 | 0); |
michael@0 | 1163 | |
michael@0 | 1164 | contentAnimator.attach(menuIcon, |
michael@0 | 1165 | PropertyAnimator.Property.TRANSLATION_X, |
michael@0 | 1166 | 0); |
michael@0 | 1167 | } |
michael@0 | 1168 | |
michael@0 | 1169 | hideUrlEditLayout(contentAnimator); |
michael@0 | 1170 | |
michael@0 | 1171 | contentAnimator.addPropertyAnimationListener(new PropertyAnimator.PropertyAnimationListener() { |
michael@0 | 1172 | @Override |
michael@0 | 1173 | public void onPropertyAnimationStart() { |
michael@0 | 1174 | } |
michael@0 | 1175 | |
michael@0 | 1176 | @Override |
michael@0 | 1177 | public void onPropertyAnimationEnd() { |
michael@0 | 1178 | if (urlBarTranslatingEdge != null) { |
michael@0 | 1179 | urlBarTranslatingEdge.setVisibility(View.INVISIBLE); |
michael@0 | 1180 | if (shouldShrinkURLBar) { |
michael@0 | 1181 | urlBarEntry.setLayoutParams(urlBarEntryDefaultLayoutParams); |
michael@0 | 1182 | } |
michael@0 | 1183 | } |
michael@0 | 1184 | |
michael@0 | 1185 | PropertyAnimator buttonsAnimator = new PropertyAnimator(300); |
michael@0 | 1186 | urlDisplayLayout.prepareStopEditingAnimation(buttonsAnimator); |
michael@0 | 1187 | buttonsAnimator.start(); |
michael@0 | 1188 | |
michael@0 | 1189 | isAnimatingEntry = false; |
michael@0 | 1190 | |
michael@0 | 1191 | // Trigger animation to update the tabs counter once the |
michael@0 | 1192 | // tabs button is back on screen. |
michael@0 | 1193 | updateTabCountAndAnimate(Tabs.getInstance().getDisplayCount()); |
michael@0 | 1194 | } |
michael@0 | 1195 | }); |
michael@0 | 1196 | |
michael@0 | 1197 | isAnimatingEntry = true; |
michael@0 | 1198 | contentAnimator.start(); |
michael@0 | 1199 | } |
michael@0 | 1200 | |
michael@0 | 1201 | private void setButtonEnabled(ImageButton button, boolean enabled) { |
michael@0 | 1202 | final Drawable drawable = button.getDrawable(); |
michael@0 | 1203 | if (drawable != null) { |
michael@0 | 1204 | // This alpha value has to be in sync with the one used |
michael@0 | 1205 | // in updateChildrenForEditing(). |
michael@0 | 1206 | drawable.setAlpha(enabled ? 255 : 61); |
michael@0 | 1207 | } |
michael@0 | 1208 | |
michael@0 | 1209 | button.setEnabled(enabled); |
michael@0 | 1210 | } |
michael@0 | 1211 | |
michael@0 | 1212 | public void updateBackButton(Tab tab) { |
michael@0 | 1213 | setButtonEnabled(backButton, canDoBack(tab)); |
michael@0 | 1214 | } |
michael@0 | 1215 | |
michael@0 | 1216 | private void animateForwardButton(final ForwardButtonAnimation animation) { |
michael@0 | 1217 | // If the forward button is not visible, we must be |
michael@0 | 1218 | // in the phone UI. |
michael@0 | 1219 | if (forwardButton.getVisibility() != View.VISIBLE) { |
michael@0 | 1220 | return; |
michael@0 | 1221 | } |
michael@0 | 1222 | |
michael@0 | 1223 | final boolean showing = (animation == ForwardButtonAnimation.SHOW); |
michael@0 | 1224 | |
michael@0 | 1225 | // if the forward button's margin is non-zero, this means it has already |
michael@0 | 1226 | // been animated to be visible¸ and vice-versa. |
michael@0 | 1227 | MarginLayoutParams fwdParams = (MarginLayoutParams) forwardButton.getLayoutParams(); |
michael@0 | 1228 | if ((fwdParams.leftMargin > defaultForwardMargin && showing) || |
michael@0 | 1229 | (fwdParams.leftMargin == defaultForwardMargin && !showing)) { |
michael@0 | 1230 | return; |
michael@0 | 1231 | } |
michael@0 | 1232 | |
michael@0 | 1233 | // We want the forward button to show immediately when switching tabs |
michael@0 | 1234 | final PropertyAnimator forwardAnim = |
michael@0 | 1235 | new PropertyAnimator(isSwitchingTabs ? 10 : FORWARD_ANIMATION_DURATION); |
michael@0 | 1236 | final int width = forwardButton.getWidth() / 2; |
michael@0 | 1237 | |
michael@0 | 1238 | forwardAnim.addPropertyAnimationListener(new PropertyAnimator.PropertyAnimationListener() { |
michael@0 | 1239 | @Override |
michael@0 | 1240 | public void onPropertyAnimationStart() { |
michael@0 | 1241 | if (!showing) { |
michael@0 | 1242 | // Set the margin before the transition when hiding the forward button. We |
michael@0 | 1243 | // have to do this so that the favicon isn't clipped during the transition |
michael@0 | 1244 | MarginLayoutParams layoutParams = |
michael@0 | 1245 | (MarginLayoutParams) urlDisplayLayout.getLayoutParams(); |
michael@0 | 1246 | layoutParams.leftMargin = 0; |
michael@0 | 1247 | |
michael@0 | 1248 | // Do the same on the URL edit container |
michael@0 | 1249 | layoutParams = (MarginLayoutParams) urlEditLayout.getLayoutParams(); |
michael@0 | 1250 | layoutParams.leftMargin = 0; |
michael@0 | 1251 | |
michael@0 | 1252 | requestLayout(); |
michael@0 | 1253 | // Note, we already translated the favicon, site security, and text field |
michael@0 | 1254 | // in prepareForwardAnimation, so they should appear to have not moved at |
michael@0 | 1255 | // all at this point. |
michael@0 | 1256 | } |
michael@0 | 1257 | } |
michael@0 | 1258 | |
michael@0 | 1259 | @Override |
michael@0 | 1260 | public void onPropertyAnimationEnd() { |
michael@0 | 1261 | if (showing) { |
michael@0 | 1262 | MarginLayoutParams layoutParams = |
michael@0 | 1263 | (MarginLayoutParams) urlDisplayLayout.getLayoutParams(); |
michael@0 | 1264 | layoutParams.leftMargin = urlBarViewOffset; |
michael@0 | 1265 | |
michael@0 | 1266 | layoutParams = (MarginLayoutParams) urlEditLayout.getLayoutParams(); |
michael@0 | 1267 | layoutParams.leftMargin = urlBarViewOffset; |
michael@0 | 1268 | } |
michael@0 | 1269 | |
michael@0 | 1270 | urlDisplayLayout.finishForwardAnimation(); |
michael@0 | 1271 | |
michael@0 | 1272 | MarginLayoutParams layoutParams = (MarginLayoutParams) forwardButton.getLayoutParams(); |
michael@0 | 1273 | layoutParams.leftMargin = defaultForwardMargin + (showing ? width : 0); |
michael@0 | 1274 | ViewHelper.setTranslationX(forwardButton, 0); |
michael@0 | 1275 | |
michael@0 | 1276 | requestLayout(); |
michael@0 | 1277 | } |
michael@0 | 1278 | }); |
michael@0 | 1279 | |
michael@0 | 1280 | prepareForwardAnimation(forwardAnim, animation, width); |
michael@0 | 1281 | forwardAnim.start(); |
michael@0 | 1282 | } |
michael@0 | 1283 | |
michael@0 | 1284 | public void updateForwardButton(Tab tab) { |
michael@0 | 1285 | final boolean enabled = canDoForward(tab); |
michael@0 | 1286 | if (forwardButton.isEnabled() == enabled) |
michael@0 | 1287 | return; |
michael@0 | 1288 | |
michael@0 | 1289 | // Save the state on the forward button so that we can skip animations |
michael@0 | 1290 | // when there's nothing to change |
michael@0 | 1291 | setButtonEnabled(forwardButton, enabled); |
michael@0 | 1292 | animateForwardButton(enabled ? ForwardButtonAnimation.SHOW : ForwardButtonAnimation.HIDE); |
michael@0 | 1293 | } |
michael@0 | 1294 | |
michael@0 | 1295 | private void prepareForwardAnimation(PropertyAnimator anim, ForwardButtonAnimation animation, int width) { |
michael@0 | 1296 | if (animation == ForwardButtonAnimation.HIDE) { |
michael@0 | 1297 | anim.attach(forwardButton, |
michael@0 | 1298 | PropertyAnimator.Property.TRANSLATION_X, |
michael@0 | 1299 | -width); |
michael@0 | 1300 | anim.attach(forwardButton, |
michael@0 | 1301 | PropertyAnimator.Property.ALPHA, |
michael@0 | 1302 | 0); |
michael@0 | 1303 | |
michael@0 | 1304 | } else { |
michael@0 | 1305 | anim.attach(forwardButton, |
michael@0 | 1306 | PropertyAnimator.Property.TRANSLATION_X, |
michael@0 | 1307 | width); |
michael@0 | 1308 | anim.attach(forwardButton, |
michael@0 | 1309 | PropertyAnimator.Property.ALPHA, |
michael@0 | 1310 | 1); |
michael@0 | 1311 | } |
michael@0 | 1312 | |
michael@0 | 1313 | urlDisplayLayout.prepareForwardAnimation(anim, animation, width); |
michael@0 | 1314 | } |
michael@0 | 1315 | |
michael@0 | 1316 | @Override |
michael@0 | 1317 | public boolean addActionItem(View actionItem) { |
michael@0 | 1318 | actionItemBar.addView(actionItem); |
michael@0 | 1319 | return true; |
michael@0 | 1320 | } |
michael@0 | 1321 | |
michael@0 | 1322 | @Override |
michael@0 | 1323 | public void removeActionItem(View actionItem) { |
michael@0 | 1324 | actionItemBar.removeView(actionItem); |
michael@0 | 1325 | } |
michael@0 | 1326 | |
michael@0 | 1327 | @Override |
michael@0 | 1328 | public void setPrivateMode(boolean isPrivate) { |
michael@0 | 1329 | super.setPrivateMode(isPrivate); |
michael@0 | 1330 | |
michael@0 | 1331 | tabsButton.setPrivateMode(isPrivate); |
michael@0 | 1332 | menuButton.setPrivateMode(isPrivate); |
michael@0 | 1333 | menuIcon.setPrivateMode(isPrivate); |
michael@0 | 1334 | urlEditLayout.setPrivateMode(isPrivate); |
michael@0 | 1335 | |
michael@0 | 1336 | if (backButton instanceof BackButton) { |
michael@0 | 1337 | ((BackButton) backButton).setPrivateMode(isPrivate); |
michael@0 | 1338 | } |
michael@0 | 1339 | |
michael@0 | 1340 | if (forwardButton instanceof ForwardButton) { |
michael@0 | 1341 | ((ForwardButton) forwardButton).setPrivateMode(isPrivate); |
michael@0 | 1342 | } |
michael@0 | 1343 | } |
michael@0 | 1344 | |
michael@0 | 1345 | public void show() { |
michael@0 | 1346 | setVisibility(View.VISIBLE); |
michael@0 | 1347 | } |
michael@0 | 1348 | |
michael@0 | 1349 | public void hide() { |
michael@0 | 1350 | setVisibility(View.GONE); |
michael@0 | 1351 | } |
michael@0 | 1352 | |
michael@0 | 1353 | public View getDoorHangerAnchor() { |
michael@0 | 1354 | return urlDisplayLayout.getDoorHangerAnchor(); |
michael@0 | 1355 | } |
michael@0 | 1356 | |
michael@0 | 1357 | public void onDestroy() { |
michael@0 | 1358 | Tabs.unregisterOnTabsChangedListener(this); |
michael@0 | 1359 | |
michael@0 | 1360 | unregisterEventListener("Reader:Click"); |
michael@0 | 1361 | unregisterEventListener("Reader:LongClick"); |
michael@0 | 1362 | } |
michael@0 | 1363 | |
michael@0 | 1364 | public boolean openOptionsMenu() { |
michael@0 | 1365 | if (!hasSoftMenuButton) { |
michael@0 | 1366 | return false; |
michael@0 | 1367 | } |
michael@0 | 1368 | |
michael@0 | 1369 | // Initialize the popup. |
michael@0 | 1370 | if (menuPopup == null) { |
michael@0 | 1371 | View panel = activity.getMenuPanel(); |
michael@0 | 1372 | menuPopup = new MenuPopup(activity); |
michael@0 | 1373 | menuPopup.setPanelView(panel); |
michael@0 | 1374 | |
michael@0 | 1375 | menuPopup.setOnDismissListener(new PopupWindow.OnDismissListener() { |
michael@0 | 1376 | @Override |
michael@0 | 1377 | public void onDismiss() { |
michael@0 | 1378 | activity.onOptionsMenuClosed(null); |
michael@0 | 1379 | } |
michael@0 | 1380 | }); |
michael@0 | 1381 | } |
michael@0 | 1382 | |
michael@0 | 1383 | GeckoAppShell.getGeckoInterface().invalidateOptionsMenu(); |
michael@0 | 1384 | if (!menuPopup.isShowing()) { |
michael@0 | 1385 | menuPopup.showAsDropDown(menuButton); |
michael@0 | 1386 | } |
michael@0 | 1387 | |
michael@0 | 1388 | return true; |
michael@0 | 1389 | } |
michael@0 | 1390 | |
michael@0 | 1391 | public boolean closeOptionsMenu() { |
michael@0 | 1392 | if (!hasSoftMenuButton) { |
michael@0 | 1393 | return false; |
michael@0 | 1394 | } |
michael@0 | 1395 | |
michael@0 | 1396 | if (menuPopup != null && menuPopup.isShowing()) { |
michael@0 | 1397 | menuPopup.dismiss(); |
michael@0 | 1398 | } |
michael@0 | 1399 | |
michael@0 | 1400 | return true; |
michael@0 | 1401 | } |
michael@0 | 1402 | |
michael@0 | 1403 | private void registerEventListener(String event) { |
michael@0 | 1404 | GeckoAppShell.getEventDispatcher().registerEventListener(event, this); |
michael@0 | 1405 | } |
michael@0 | 1406 | |
michael@0 | 1407 | private void unregisterEventListener(String event) { |
michael@0 | 1408 | GeckoAppShell.getEventDispatcher().unregisterEventListener(event, this); |
michael@0 | 1409 | } |
michael@0 | 1410 | |
michael@0 | 1411 | @Override |
michael@0 | 1412 | public void handleMessage(String event, JSONObject message) { |
michael@0 | 1413 | Log.d(LOGTAG, "handleMessage: " + event); |
michael@0 | 1414 | if (event.equals("Reader:Click")) { |
michael@0 | 1415 | Tab tab = Tabs.getInstance().getSelectedTab(); |
michael@0 | 1416 | if (tab != null) { |
michael@0 | 1417 | tab.toggleReaderMode(); |
michael@0 | 1418 | } |
michael@0 | 1419 | } else if (event.equals("Reader:LongClick")) { |
michael@0 | 1420 | Tab tab = Tabs.getInstance().getSelectedTab(); |
michael@0 | 1421 | if (tab != null) { |
michael@0 | 1422 | tab.addToReadingList(); |
michael@0 | 1423 | } |
michael@0 | 1424 | } |
michael@0 | 1425 | } |
michael@0 | 1426 | |
michael@0 | 1427 | @Override |
michael@0 | 1428 | public void onLightweightThemeChanged() { |
michael@0 | 1429 | Drawable drawable = theme.getDrawable(this); |
michael@0 | 1430 | if (drawable == null) |
michael@0 | 1431 | return; |
michael@0 | 1432 | |
michael@0 | 1433 | StateListDrawable stateList = new StateListDrawable(); |
michael@0 | 1434 | stateList.addState(PRIVATE_STATE_SET, getColorDrawable(R.color.background_private)); |
michael@0 | 1435 | stateList.addState(EMPTY_STATE_SET, drawable); |
michael@0 | 1436 | |
michael@0 | 1437 | setBackgroundDrawable(stateList); |
michael@0 | 1438 | |
michael@0 | 1439 | if (editCancel != null) { |
michael@0 | 1440 | editCancel.onLightweightThemeChanged(); |
michael@0 | 1441 | } |
michael@0 | 1442 | } |
michael@0 | 1443 | |
michael@0 | 1444 | @Override |
michael@0 | 1445 | public void onLightweightThemeReset() { |
michael@0 | 1446 | setBackgroundResource(R.drawable.url_bar_bg); |
michael@0 | 1447 | if (editCancel != null) { |
michael@0 | 1448 | editCancel.onLightweightThemeReset(); |
michael@0 | 1449 | } |
michael@0 | 1450 | } |
michael@0 | 1451 | } |