diff -r 000000000000 -r 6474c204b198 mobile/android/base/DynamicToolbar.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mobile/android/base/DynamicToolbar.java Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,167 @@ +package org.mozilla.gecko; + +import java.util.EnumSet; + +import org.mozilla.gecko.PrefsHelper.PrefHandlerBase; +import org.mozilla.gecko.gfx.LayerView; +import org.mozilla.gecko.util.ThreadUtils; + +import android.os.Bundle; + +public class DynamicToolbar { + private static final String STATE_ENABLED = "dynamic_toolbar"; + private static final String CHROME_PREF = "browser.chrome.dynamictoolbar"; + + // DynamicToolbar is enabled iff prefEnabled is true *and* accessibilityEnabled is false, + // so it is disabled by default on startup. We do not enable it until we explicitly get + // the pref from Gecko telling us to turn it on. + private volatile boolean prefEnabled; + private boolean accessibilityEnabled; + + private final int prefObserverId; + private final EnumSet pinFlags = EnumSet.noneOf(PinReason.class); + private LayerView layerView; + private OnEnabledChangedListener enabledChangedListener; + + public enum PinReason { + RELAYOUT, + ACTION_MODE + } + + public enum VisibilityTransition { + IMMEDIATE, + ANIMATE + } + + /** + * Listener for changes to the dynamic toolbar's enabled state. + */ + public interface OnEnabledChangedListener { + /** + * This callback is executed on the UI thread. + */ + public void onEnabledChanged(boolean enabled); + } + + public DynamicToolbar() { + // Listen to the dynamic toolbar pref + prefObserverId = PrefsHelper.getPref(CHROME_PREF, new PrefHandler()); + } + + public void destroy() { + PrefsHelper.removeObserver(prefObserverId); + } + + public void setLayerView(LayerView layerView) { + ThreadUtils.assertOnUiThread(); + + this.layerView = layerView; + } + + public void setEnabledChangedListener(OnEnabledChangedListener listener) { + ThreadUtils.assertOnUiThread(); + + enabledChangedListener = listener; + } + + public void onSaveInstanceState(Bundle outState) { + ThreadUtils.assertOnUiThread(); + + outState.putBoolean(STATE_ENABLED, prefEnabled); + } + + public void onRestoreInstanceState(Bundle savedInstanceState) { + ThreadUtils.assertOnUiThread(); + + if (savedInstanceState != null) { + prefEnabled = savedInstanceState.getBoolean(STATE_ENABLED); + } + } + + public boolean isEnabled() { + ThreadUtils.assertOnUiThread(); + + return prefEnabled && !accessibilityEnabled; + } + + public void setAccessibilityEnabled(boolean enabled) { + ThreadUtils.assertOnUiThread(); + + if (accessibilityEnabled == enabled) { + return; + } + + // Disable the dynamic toolbar when accessibility features are enabled, + // and re-read the preference when they're disabled. + accessibilityEnabled = enabled; + if (prefEnabled) { + triggerEnabledListener(); + } + } + + public void setVisible(boolean visible, VisibilityTransition transition) { + ThreadUtils.assertOnUiThread(); + + if (layerView == null) { + return; + } + + final boolean immediate = transition.equals(VisibilityTransition.IMMEDIATE); + if (visible) { + layerView.getLayerMarginsAnimator().showMargins(immediate); + } else { + layerView.getLayerMarginsAnimator().hideMargins(immediate); + } + } + + public void setPinned(boolean pinned, PinReason reason) { + ThreadUtils.assertOnUiThread(); + + if (layerView == null) { + return; + } + + if (pinned) { + pinFlags.add(reason); + } else { + pinFlags.remove(reason); + } + + layerView.getLayerMarginsAnimator().setMarginsPinned(!pinFlags.isEmpty()); + } + + private void triggerEnabledListener() { + if (enabledChangedListener != null) { + enabledChangedListener.onEnabledChanged(isEnabled()); + } + } + + private class PrefHandler extends PrefHandlerBase { + @Override + public void prefValue(String pref, boolean value) { + if (value == prefEnabled) { + return; + } + + prefEnabled = value; + + ThreadUtils.postToUiThread(new Runnable() { + @Override + public void run() { + // If accessibility is enabled, the dynamic toolbar is + // forced to be off. + if (!accessibilityEnabled) { + triggerEnabledListener(); + } + } + }); + } + + @Override + public boolean isObserver() { + // We want to be notified of changes to be able to switch mode + // without restarting. + return true; + } + } +} \ No newline at end of file