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