1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mobile/android/base/DynamicToolbar.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,167 @@ 1.4 +package org.mozilla.gecko; 1.5 + 1.6 +import java.util.EnumSet; 1.7 + 1.8 +import org.mozilla.gecko.PrefsHelper.PrefHandlerBase; 1.9 +import org.mozilla.gecko.gfx.LayerView; 1.10 +import org.mozilla.gecko.util.ThreadUtils; 1.11 + 1.12 +import android.os.Bundle; 1.13 + 1.14 +public class DynamicToolbar { 1.15 + private static final String STATE_ENABLED = "dynamic_toolbar"; 1.16 + private static final String CHROME_PREF = "browser.chrome.dynamictoolbar"; 1.17 + 1.18 + // DynamicToolbar is enabled iff prefEnabled is true *and* accessibilityEnabled is false, 1.19 + // so it is disabled by default on startup. We do not enable it until we explicitly get 1.20 + // the pref from Gecko telling us to turn it on. 1.21 + private volatile boolean prefEnabled; 1.22 + private boolean accessibilityEnabled; 1.23 + 1.24 + private final int prefObserverId; 1.25 + private final EnumSet<PinReason> pinFlags = EnumSet.noneOf(PinReason.class); 1.26 + private LayerView layerView; 1.27 + private OnEnabledChangedListener enabledChangedListener; 1.28 + 1.29 + public enum PinReason { 1.30 + RELAYOUT, 1.31 + ACTION_MODE 1.32 + } 1.33 + 1.34 + public enum VisibilityTransition { 1.35 + IMMEDIATE, 1.36 + ANIMATE 1.37 + } 1.38 + 1.39 + /** 1.40 + * Listener for changes to the dynamic toolbar's enabled state. 1.41 + */ 1.42 + public interface OnEnabledChangedListener { 1.43 + /** 1.44 + * This callback is executed on the UI thread. 1.45 + */ 1.46 + public void onEnabledChanged(boolean enabled); 1.47 + } 1.48 + 1.49 + public DynamicToolbar() { 1.50 + // Listen to the dynamic toolbar pref 1.51 + prefObserverId = PrefsHelper.getPref(CHROME_PREF, new PrefHandler()); 1.52 + } 1.53 + 1.54 + public void destroy() { 1.55 + PrefsHelper.removeObserver(prefObserverId); 1.56 + } 1.57 + 1.58 + public void setLayerView(LayerView layerView) { 1.59 + ThreadUtils.assertOnUiThread(); 1.60 + 1.61 + this.layerView = layerView; 1.62 + } 1.63 + 1.64 + public void setEnabledChangedListener(OnEnabledChangedListener listener) { 1.65 + ThreadUtils.assertOnUiThread(); 1.66 + 1.67 + enabledChangedListener = listener; 1.68 + } 1.69 + 1.70 + public void onSaveInstanceState(Bundle outState) { 1.71 + ThreadUtils.assertOnUiThread(); 1.72 + 1.73 + outState.putBoolean(STATE_ENABLED, prefEnabled); 1.74 + } 1.75 + 1.76 + public void onRestoreInstanceState(Bundle savedInstanceState) { 1.77 + ThreadUtils.assertOnUiThread(); 1.78 + 1.79 + if (savedInstanceState != null) { 1.80 + prefEnabled = savedInstanceState.getBoolean(STATE_ENABLED); 1.81 + } 1.82 + } 1.83 + 1.84 + public boolean isEnabled() { 1.85 + ThreadUtils.assertOnUiThread(); 1.86 + 1.87 + return prefEnabled && !accessibilityEnabled; 1.88 + } 1.89 + 1.90 + public void setAccessibilityEnabled(boolean enabled) { 1.91 + ThreadUtils.assertOnUiThread(); 1.92 + 1.93 + if (accessibilityEnabled == enabled) { 1.94 + return; 1.95 + } 1.96 + 1.97 + // Disable the dynamic toolbar when accessibility features are enabled, 1.98 + // and re-read the preference when they're disabled. 1.99 + accessibilityEnabled = enabled; 1.100 + if (prefEnabled) { 1.101 + triggerEnabledListener(); 1.102 + } 1.103 + } 1.104 + 1.105 + public void setVisible(boolean visible, VisibilityTransition transition) { 1.106 + ThreadUtils.assertOnUiThread(); 1.107 + 1.108 + if (layerView == null) { 1.109 + return; 1.110 + } 1.111 + 1.112 + final boolean immediate = transition.equals(VisibilityTransition.IMMEDIATE); 1.113 + if (visible) { 1.114 + layerView.getLayerMarginsAnimator().showMargins(immediate); 1.115 + } else { 1.116 + layerView.getLayerMarginsAnimator().hideMargins(immediate); 1.117 + } 1.118 + } 1.119 + 1.120 + public void setPinned(boolean pinned, PinReason reason) { 1.121 + ThreadUtils.assertOnUiThread(); 1.122 + 1.123 + if (layerView == null) { 1.124 + return; 1.125 + } 1.126 + 1.127 + if (pinned) { 1.128 + pinFlags.add(reason); 1.129 + } else { 1.130 + pinFlags.remove(reason); 1.131 + } 1.132 + 1.133 + layerView.getLayerMarginsAnimator().setMarginsPinned(!pinFlags.isEmpty()); 1.134 + } 1.135 + 1.136 + private void triggerEnabledListener() { 1.137 + if (enabledChangedListener != null) { 1.138 + enabledChangedListener.onEnabledChanged(isEnabled()); 1.139 + } 1.140 + } 1.141 + 1.142 + private class PrefHandler extends PrefHandlerBase { 1.143 + @Override 1.144 + public void prefValue(String pref, boolean value) { 1.145 + if (value == prefEnabled) { 1.146 + return; 1.147 + } 1.148 + 1.149 + prefEnabled = value; 1.150 + 1.151 + ThreadUtils.postToUiThread(new Runnable() { 1.152 + @Override 1.153 + public void run() { 1.154 + // If accessibility is enabled, the dynamic toolbar is 1.155 + // forced to be off. 1.156 + if (!accessibilityEnabled) { 1.157 + triggerEnabledListener(); 1.158 + } 1.159 + } 1.160 + }); 1.161 + } 1.162 + 1.163 + @Override 1.164 + public boolean isObserver() { 1.165 + // We want to be notified of changes to be able to switch mode 1.166 + // without restarting. 1.167 + return true; 1.168 + } 1.169 + } 1.170 +} 1.171 \ No newline at end of file