Bug 804575 - Implement a way of keeping the debugger panes always visible, r=past
authorVictor Porof <vporof@mozilla.com>
Fri, 26 Oct 2012 23:28:54 +0300
changeset 111511 3f97424506bda958ed64e704fbc03fe054a0fc45
parent 111510 0eecbc50194c809f81f83804917c9a21581cecd3
child 111512 275f82501a03e545668d0a14e87075818121a664
push id23752
push userryanvm@gmail.com
push dateSat, 27 Oct 2012 01:22:44 +0000
treeherdermozilla-central@f9acc2e4d4e3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspast
bugs804575
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 804575 - Implement a way of keeping the debugger panes always visible, r=past
browser/app/profile/firefox.js
browser/devtools/debugger/debugger-controller.js
browser/devtools/debugger/debugger-panes.js
browser/devtools/debugger/debugger-toolbar.js
browser/devtools/debugger/debugger-view.js
browser/devtools/debugger/debugger.xul
browser/devtools/debugger/test/browser_dbg_pane-collapse.js
browser/devtools/debugger/test/browser_dbg_pause-exceptions.js
browser/locales/en-US/chrome/browser/devtools/debugger.dtd
browser/themes/gnomestripe/devtools/debugger.css
browser/themes/pinstripe/devtools/debugger.css
browser/themes/winstripe/devtools/debugger.css
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1030,19 +1030,18 @@ pref("devtools.debugger.remote-autoconne
 pref("devtools.debugger.remote-connection-retries", 3);
 pref("devtools.debugger.remote-timeout", 20000);
 
 // The default Debugger UI settings
 pref("devtools.debugger.ui.height", 250);
 pref("devtools.debugger.ui.remote-win.width", 900);
 pref("devtools.debugger.ui.remote-win.height", 400);
 pref("devtools.debugger.ui.stackframes-width", 200);
-pref("devtools.debugger.ui.stackframes-pane-visible", true);
 pref("devtools.debugger.ui.variables-width", 300);
-pref("devtools.debugger.ui.variables-pane-visible", true);
+pref("devtools.debugger.ui.panes-visible-on-startup", false);
 pref("devtools.debugger.ui.non-enum-visible", true);
 
 // Enable the style inspector
 pref("devtools.styleinspector.enabled", true);
 
 // Enable the Tilt inspector
 pref("devtools.tilt.enabled", true);
 pref("devtools.tilt.intro_transition", true);
--- a/browser/devtools/debugger/debugger-controller.js
+++ b/browser/devtools/debugger/debugger-controller.js
@@ -1193,19 +1193,18 @@ XPCOMUtils.defineLazyGetter(L10N, "strin
   return Services.strings.createBundle(DBG_STRINGS_URI);
 });
 
 XPCOMUtils.defineLazyGetter(L10N, "ellipsis", function() {
   return Services.prefs.getComplexValue("intl.ellipsis", Ci.nsIPrefLocalizedString).data;
 });
 
 const STACKFRAMES_WIDTH = "devtools.debugger.ui.stackframes-width";
-const STACKFRAMES_VISIBLE = "devtools.debugger.ui.stackframes-pane-visible";
 const VARIABLES_WIDTH = "devtools.debugger.ui.variables-width";
-const VARIABLES_PANE_VISIBLE = "devtools.debugger.ui.variables-pane-visible";
+const PANES_VISIBLE_ON_STARTUP = "devtools.debugger.ui.panes-visible-on-startup";
 const NON_ENUM_VISIBLE = "devtools.debugger.ui.non-enum-visible";
 const REMOTE_AUTO_CONNECT = "devtools.debugger.remote-autoconnect";
 const REMOTE_HOST = "devtools.debugger.remote-host";
 const REMOTE_PORT = "devtools.debugger.remote-port";
 const REMOTE_CONNECTION_RETRIES = "devtools.debugger.remote-connection-retries";
 const REMOTE_TIMEOUT = "devtools.debugger.remote-timeout";
 
 /**
@@ -1228,36 +1227,16 @@ let Prefs = {
    * @param number value
    */
   set stackframesWidth(value) {
     Services.prefs.setIntPref(STACKFRAMES_WIDTH, value);
     this._stackframesWidth = value;
   },
 
   /**
-   * Gets the preferred stackframes pane visibility state.
-   * @return boolean
-   */
-  get stackframesPaneVisible() {
-    if (this._stackframesVisible === undefined) {
-      this._stackframesVisible = Services.prefs.getBoolPref(STACKFRAMES_VISIBLE);
-    }
-    return this._stackframesVisible;
-  },
-
-  /**
-   * Sets the preferred stackframes pane visibility state.
-   * @param boolean value
-   */
-  set stackframesPaneVisible(value) {
-    Services.prefs.setBoolPref(STACKFRAMES_VISIBLE, value);
-    this._stackframesVisible = value;
-  },
-
-  /**
    * Gets the preferred variables pane width.
    * @return number
    */
   get variablesWidth() {
     if (this._variablesWidth === undefined) {
       this._variablesWidth = Services.prefs.getIntPref(VARIABLES_WIDTH);
     }
     return this._variablesWidth;
@@ -1268,36 +1247,16 @@ let Prefs = {
    * @param number value
    */
   set variablesWidth(value) {
     Services.prefs.setIntPref(VARIABLES_WIDTH, value);
     this._variablesWidth = value;
   },
 
   /**
-   * Gets the preferred variables pane visibility state.
-   * @return boolean
-   */
-  get variablesPaneVisible() {
-    if (this._variablesVisible === undefined) {
-      this._variablesVisible = Services.prefs.getBoolPref(VARIABLES_PANE_VISIBLE);
-    }
-    return this._variablesVisible;
-  },
-
-  /**
-   * Sets the preferred variables pane visibility state.
-   * @param boolean value
-   */
-  set variablesPaneVisible(value) {
-    Services.prefs.setBoolPref(VARIABLES_PANE_VISIBLE, value);
-    this._variablesVisible = value;
-  },
-
-  /**
    * Gets a flag specifying if the debugger should automatically connect to
    * the default host and port number.
    * @return boolean
    */
   get remoteAutoConnect() {
     if (this._autoConnect === undefined) {
       this._autoConnect = Services.prefs.getBoolPref(REMOTE_AUTO_CONNECT);
     }
@@ -1310,16 +1269,36 @@ let Prefs = {
    * @param boolean value
    */
   set remoteAutoConnect(value) {
     Services.prefs.setBoolPref(REMOTE_AUTO_CONNECT, value);
     this._autoConnect = value;
   },
 
   /**
+   * Gets the preferred panes visibility state on startup.
+   * @return boolean
+   */
+  get panesVisibleOnStartup() {
+    if (this._panesVisible === undefined) {
+      this._panesVisible = Services.prefs.getBoolPref(PANES_VISIBLE_ON_STARTUP);
+    }
+    return this._panesVisible;
+  },
+
+  /**
+   * Sets the preferred panes visibility state on startup.
+   * @param boolean value
+   */
+  set panesVisibleOnStartup(value) {
+    Services.prefs.setBoolPref(PANES_VISIBLE_ON_STARTUP, value);
+    this._panesVisible = value;
+  },
+
+  /**
    * Gets a flag specifying if the debugger should show non-enumerable
    * properties and variables in the scope view.
    * @return boolean
    */
   get nonEnumVisible() {
     if (this._nonEnumVisible === undefined) {
       this._nonEnumVisible = Services.prefs.getBoolPref(NON_ENUM_VISIBLE);
     }
--- a/browser/devtools/debugger/debugger-panes.js
+++ b/browser/devtools/debugger/debugger-panes.js
@@ -52,17 +52,17 @@ create({ constructor: StackFramesView, p
    *        The frame depth specified by the debugger.
    * @param object aOptions [optional]
    *        Additional options or flags supported by this operation:
    *          - attachment: any kind of primitive/object to attach
    */
   addFrame:
   function DVSF_addFrame(aFrameName, aFrameDetails, aDepth, aOptions = {}) {
     // Stackframes are UI elements which benefit from visible panes.
-    DebuggerView.showPanesIfPreffered();
+    DebuggerView.showPanesSoon();
 
     // Append a stackframe item to this container.
     let stackframeItem = this.push(aFrameName, aFrameDetails, {
       forced: true,
       unsorted: true,
       relaxed: true,
       attachment: aOptions.attachment
     });
--- a/browser/devtools/debugger/debugger-toolbar.js
+++ b/browser/devtools/debugger/debugger-toolbar.js
@@ -129,18 +129,17 @@ ToolbarView.prototype = {
   },
 
   /**
    * Listener handling the toggle button click event.
    */
   _onTogglePanesPressed: function DVT__onTogglePanesPressed() {
     DebuggerView.togglePanes({
       visible: DebuggerView.panesHidden,
-      animated: true,
-      silent: true
+      animated: true
     });
   },
 
   /**
    * Listener handling the pause/resume button click event.
    */
   _onResumePressed: function DVT__onResumePressed() {
     if (DebuggerController.activeThread.paused) {
@@ -192,39 +191,43 @@ ToolbarView.prototype = {
   _stepOutTooltip: ""
 };
 
 /**
  * Functions handling the options UI.
  */
 function OptionsView() {
   dumpn("OptionsView was instantiated");
-  this._togglePOE = this._togglePOE.bind(this);
+  this._togglePauseOnExceptions = this._togglePauseOnExceptions.bind(this);
+  this._toggleShowPanesOnStartup = this._toggleShowPanesOnStartup.bind(this);
   this._toggleShowNonEnum = this._toggleShowNonEnum.bind(this);
 }
 
 OptionsView.prototype = {
   /**
    * Initialization function, called when the debugger is started.
    */
   initialize: function DVO_initialize() {
     dumpn("Initializing the OptionsView");
     this._button = document.getElementById("debugger-options");
-    this._poeItem = document.getElementById("pause-on-exceptions");
+    this._pauseOnExceptionsItem = document.getElementById("pause-on-exceptions");
+    this._showPanesOnStartupItem = document.getElementById("show-panes-on-startup");
     this._showNonEnumItem = document.getElementById("show-nonenum");
 
-    this._poeItem.setAttribute("checked", "false");
+    this._pauseOnExceptionsItem.setAttribute("checked", "false");
+    this._showPanesOnStartupItem.setAttribute("checked", Prefs.panesVisibleOnStartup);
     this._showNonEnumItem.setAttribute("checked", Prefs.nonEnumVisible);
   },
 
   /**
    * Destruction function, called when the debugger is closed.
    */
   destroy: function DVO_destroy() {
     dumpn("Destroying the OptionsView");
+    // Nothing to do here yet.
   },
 
   /**
    * Listener handling the 'gear menu' popup showing event.
    */
   _onPopupShowing: function DVO__onPopupShowing() {
     this._button.setAttribute("open", "true");
   },
@@ -232,33 +235,42 @@ OptionsView.prototype = {
   /**
    * Listener handling the 'gear menu' popup hiding event.
    */
   _onPopupHiding: function DVO__onPopupHiding() {
     this._button.removeAttribute("open");
   },
 
   /**
-   * Listener handling the 'pause on exceptions' checkbox click event.
+   * Listener handling the 'pause on exceptions' menuitem command.
    */
-  _togglePOE: function DVO__togglePOE() {
+  _togglePauseOnExceptions: function DVO__togglePauseOnExceptions() {
     DebuggerController.activeThread.pauseOnExceptions(
-      this._poeItem.getAttribute("checked") == "true");
+      this._pauseOnExceptionsItem.getAttribute("checked") == "true");
   },
 
   /**
-   * Listener handling the 'show non-enumerables' checkbox click event.
+   * Listener handling the 'show panes on startup' menuitem command.
+   */
+  _toggleShowPanesOnStartup: function DVO__toggleShowPanesOnStartup() {
+    Prefs.panesVisibleOnStartup =
+      this._showPanesOnStartupItem.getAttribute("checked") == "true";
+  },
+
+  /**
+   * Listener handling the 'show non-enumerables' menuitem command.
    */
   _toggleShowNonEnum: function DVO__toggleShowNonEnum() {
     DebuggerView.Variables.nonEnumVisible = Prefs.nonEnumVisible =
       this._showNonEnumItem.getAttribute("checked") == "true";
   },
 
   _button: null,
-  _poeItem: null,
+  _pauseOnExceptionsItem: null,
+  _showPanesOnStartupItem: null,
   _showNonEnumItem: null
 };
 
 /**
  * Functions handling the chrome globals UI.
  */
 function ChromeGlobalsView() {
   dumpn("ChromeGlobalsView was instantiated");
--- a/browser/devtools/debugger/debugger-view.js
+++ b/browser/devtools/debugger/debugger-view.js
@@ -76,17 +76,20 @@ let DebuggerView = {
     dumpn("Initializing the DebuggerView panes");
 
     this._togglePanesButton = document.getElementById("toggle-panes");
     this._stackframesAndBreakpoints = document.getElementById("stackframes+breakpoints");
     this._variables = document.getElementById("variables");
 
     this._stackframesAndBreakpoints.setAttribute("width", Prefs.stackframesWidth);
     this._variables.setAttribute("width", Prefs.variablesWidth);
-    this.togglePanes({ visible: false, animated: false, silent: true });
+    this.togglePanes({
+      visible: Prefs.panesVisibleOnStartup,
+      animated: false
+    });
   },
 
   /**
    * Destroys the UI for all the displayed panes.
    */
   _destroyPanes: function DV__initializePanes() {
     dumpn("Destroying the DebuggerView panes");
 
@@ -313,135 +316,76 @@ let DebuggerView = {
     return this.editor.getText(start, end);
   },
 
   /**
    * Gets the visibility state of the panes.
    * @return boolean
    */
   get panesHidden()
-    this.stackframesAndBreakpointsHidden && this.variablesHidden,
-
-  /**
-   * Gets the visibility state of the stackframes and breakpoints pane.
-   * @return boolean
-   */
-  get stackframesAndBreakpointsHidden()
-    !!this._togglePanesButton.getAttribute("stackframesAndBreakpointsHidden"),
-
-  /**
-   * Gets the visibility state of the varialbes pane.
-   * @return boolean
-   */
-  get variablesHidden()
-    !!this._togglePanesButton.getAttribute("variablesHidden"),
+    this._togglePanesButton.hasAttribute("panesHidden"),
 
   /**
    * Sets all the panes hidden or visible.
    *
    * @param object aFlags [optional]
    *        An object containing some of the following boolean properties:
    *        - visible: true if the pane should be shown, false for hidden
    *        - animated: true to display an animation on toggle
-   *        - silent: true to not update any designated prefs
    */
   togglePanes: function DV__togglePanes(aFlags = {}) {
-    this._toggleStackframesAndBreakpointsPane(aFlags);
-    this._toggleVariablesPane(aFlags);
-  },
-
-  /**
-   * Shows the stackframes, breakpoints and variable panes if currently hidden
-   * and the preferences dictate otherwise.
-   */
-  showPanesIfPreffered: function DV_showPanesIfPreffered() {
-    let self = this;
-
-    // Try to keep animations as smooth as possible, so wait a few cycles.
-    window.setTimeout(function() {
-      let target;
+    // Avoid useless toggles.
+    if (aFlags.visible == !this.panesHidden) {
+      return;
+    }
 
-      if (Prefs.stackframesPaneVisible && self.stackframesAndBreakpointsHidden) {
-        self._toggleStackframesAndBreakpointsPane({
-          visible: true,
-          animated: true,
-          silent: true
-        });
-        target = self._stackframesAndBreakpoints;
-      }
-      if (Prefs.variablesPaneVisible && self.variablesHidden) {
-        self._toggleVariablesPane({
-          visible: true,
-          animated: true,
-          silent: true
-        });
-        target = self._variables;
-      }
+    if (aFlags.visible) {
+      this._stackframesAndBreakpoints.style.marginLeft = "0";
+      this._variables.style.marginRight = "0";
+      this._togglePanesButton.removeAttribute("panesHidden");
+      this._togglePanesButton.setAttribute("tooltiptext", L10N.getStr("collapsePanes"));
+    } else {
+      let marginL = ~~(this._stackframesAndBreakpoints.getAttribute("width")) + 1;
+      let marginR = ~~(this._variables.getAttribute("width")) + 1;
+      this._stackframesAndBreakpoints.style.marginLeft = -marginL + "px";
+      this._variables.style.marginRight = -marginR + "px";
+      this._togglePanesButton.setAttribute("panesHidden", "true");
+      this._togglePanesButton.setAttribute("tooltiptext", L10N.getStr("expandPanes"));
+    }
+
+    if (aFlags.animated) {
+      this._stackframesAndBreakpoints.setAttribute("animated", "");
+      this._variables.setAttribute("animated", "");
+
       // Displaying the panes may have the effect of triggering scrollbars to
       // appear in the source editor, which would render the currently
       // highlighted line to appear behind them in some cases.
-      if (target) {
-        target.addEventListener("transitionend", function onEvent() {
-          target.removeEventListener("transitionend", onEvent, false);
-          self.updateEditor();
-        }, false);
-      }
-    }, PANES_APPEARANCE_DELAY);
-  },
+      let self = this;
 
-  /**
-   * Sets the stackframes and breakpoints (left) pane hidden or visible.
-   * @see DebuggerView.togglePanes
-   */
-  _toggleStackframesAndBreakpointsPane:
-  function DV__toggleStackframesAndBreakpointsPane(aFlags) {
-    if (aFlags.animated) {
-      this._stackframesAndBreakpoints.setAttribute("animated", "");
+      window.addEventListener("transitionend", function onEvent() {
+        window.removeEventListener("transitionend", onEvent, false);
+        self.updateEditor();
+      }, false);
     } else {
       this._stackframesAndBreakpoints.removeAttribute("animated");
-    }
-    if (aFlags.visible) {
-      this._stackframesAndBreakpoints.style.marginLeft = "0";
-      this._togglePanesButton.removeAttribute("stackframesAndBreakpointsHidden");
-      this._togglePanesButton.setAttribute("tooltiptext", L10N.getStr("collapsePanes"));
-    } else {
-      let margin = parseInt(this._stackframesAndBreakpoints.getAttribute("width")) + 1;
-      this._stackframesAndBreakpoints.style.marginLeft = -margin + "px";
-      this._togglePanesButton.setAttribute("stackframesAndBreakpointsHidden", "true");
-      this._togglePanesButton.setAttribute("tooltiptext", L10N.getStr("expandPanes"));
-    }
-    if (!aFlags.silent) {
-      Prefs.stackframesPaneVisible = !!aFlags.visible;
+      this._variables.removeAttribute("animated");
     }
   },
 
   /**
-   * Sets the variables (right) pane hidden or visible.
-   * @see DebuggerView.togglePanes
+   * Sets all the panes visible after a short period of time.
    */
-  _toggleVariablesPane:
-  function DV__toggleVariablesPane(aFlags) {
-    if (aFlags.animated) {
-      this._variables.setAttribute("animated", "");
-    } else {
-      this._variables.removeAttribute("animated");
-    }
-    if (aFlags.visible) {
-      this._variables.style.marginRight = "0";
-      this._togglePanesButton.removeAttribute("variablesHidden");
-      this._togglePanesButton.setAttribute("tooltiptext", L10N.getStr("collapsePanes"));
-    } else {
-      let margin = parseInt(this._variables.getAttribute("width")) + 1;
-      this._variables.style.marginRight = -margin + "px";
-      this._togglePanesButton.setAttribute("variablesHidden", "true");
-      this._togglePanesButton.setAttribute("tooltiptext", L10N.getStr("expandPanes"));
-    }
-    if (!aFlags.silent) {
-      Prefs.variablesPaneVisible = !!aFlags.visible;
-    }
+  showPanesSoon: function DV__showPanesSoon() {
+    // Try to keep animations as smooth as possible, so wait a few cycles.
+    window.setTimeout(function() {
+      DebuggerView.togglePanes({
+        visible: true,
+        animated: true
+      });
+    }, PANES_APPEARANCE_DELAY);
   },
 
   /**
    * Handles any initialization on a tab navigation event issued by the client.
    */
   _handleTabNavigation: function DV__handleTabNavigation() {
     dumpn("Handling tab navigation in the DebuggerView");
 
--- a/browser/devtools/debugger/debugger.xul
+++ b/browser/devtools/debugger/debugger.xul
@@ -37,17 +37,19 @@
              oncommand="DebuggerView.Filtering._doFileSearch()"/>
     <command id="lineSearchCommand"
              oncommand="DebuggerView.Filtering._doLineSearch()"/>
     <command id="tokenSearchCommand"
              oncommand="DebuggerView.Filtering._doTokenSearch()"/>
     <command id="globalSearchCommand"
              oncommand="DebuggerView.Filtering._doGlobalSearch()"/>
     <command id="togglePauseOnExceptions"
-             oncommand="DebuggerView.Options._togglePOE()"/>
+             oncommand="DebuggerView.Options._togglePauseOnExceptions()"/>
+    <command id="toggleShowPanesOnStartup"
+             oncommand="DebuggerView.Options._toggleShowPanesOnStartup()"/>
     <command id="toggleShowNonEnum"
              oncommand="DebuggerView.Options._toggleShowNonEnum()"/>
   </commandset>
 
   <popupset id="debuggerPopupset">
     <menupopup id="sourceEditorContextMenu"
                onpopupshowing="goUpdateSourceEditorMenuItems()">
       <menuitem id="se-cMenu-copy"/>
@@ -63,16 +65,21 @@
                position="before_end"
                onpopupshowing="DebuggerView.Options._onPopupShowing()"
                onpopuphiding="DebuggerView.Options._onPopupHiding()">
       <menuitem id="pause-on-exceptions"
                 type="checkbox"
                 label="&debuggerUI.pauseExceptions;"
                 accesskey="&debuggerUI.pauseExceptions.key;"
                 command="togglePauseOnExceptions"/>
+      <menuitem id="show-panes-on-startup"
+                type="checkbox"
+                label="&debuggerUI.showPanesOnInit;"
+                accesskey="&debuggerUI.showPanesOnInit.key;"
+                command="toggleShowPanesOnStartup"/>
       <menuitem id="show-nonenum"
                 type="checkbox"
                 label="&debuggerUI.showNonEnums;"
                 accesskey="&debuggerUI.showNonEnums.key;"
                 command="toggleShowNonEnum"/>
     </menupopup>
   </popupset>
 
--- a/browser/devtools/debugger/test/browser_dbg_pane-collapse.js
+++ b/browser/devtools/debugger/test/browser_dbg_pane-collapse.js
@@ -16,144 +16,182 @@ function test() {
     gTab = aTab;
     gDebuggee = aDebuggee;
     gPane = aPane;
     gDebugger = gPane.contentWindow;
     gView = gDebugger.DebuggerView;
 
     testPanesState();
 
-    gView._toggleStackframesAndBreakpointsPane({ visible: true });
-    gView._toggleVariablesPane({ visible: true });
+    gView.togglePanes({ visible: true, animated: false });
     testPaneCollapse1();
     testPaneCollapse2();
-
-    closeDebuggerAndFinish();
+    testPanesStartupPref(closeDebuggerAndFinish);
   });
 }
 
 function testPanesState() {
   let togglePanesButton =
     gDebugger.document.getElementById("toggle-panes");
 
-  ok(togglePanesButton.getAttribute("stackframesAndBreakpointsHidden"),
-    "The stackframes and breakpoints pane should initially be invisible.");
-  is(gDebugger.Prefs.stackframesPaneVisible, true,
-    "The stackframes and breakpoints pane should initially be preffed as visible.");
-
-  ok(togglePanesButton.getAttribute("variablesHidden"),
-    "The stackframes and breakpoints pane should initially be invisible.");
-  is(gDebugger.Prefs.variablesPaneVisible, true,
-    "The stackframes and breakpoints pane should initially be preffed as visible.");
+  ok(togglePanesButton.getAttribute("panesHidden"),
+    "The debugger view panes should initially be hidden.");
+  is(gDebugger.Prefs.panesVisibleOnStartup, false,
+    "The debugger view panes should initially be preffed as hidden.");
+  isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
+    "The options menu item should not be checked.");
 }
 
 function testPaneCollapse1() {
   let stackframesAndBrekpoints =
     gDebugger.document.getElementById("stackframes+breakpoints");
   let togglePanesButton =
     gDebugger.document.getElementById("toggle-panes");
 
   let width = parseInt(stackframesAndBrekpoints.getAttribute("width"));
   is(width, gDebugger.Prefs.stackframesWidth,
     "The stackframes and breakpoints pane has an incorrect width.");
   is(stackframesAndBrekpoints.style.marginLeft, "0px",
     "The stackframes and breakpoints pane has an incorrect left margin.");
   ok(!stackframesAndBrekpoints.hasAttribute("animated"),
     "The stackframes and breakpoints pane has an incorrect animated attribute.");
-  ok(!togglePanesButton.getAttribute("stackframesAndBreakpointsHidden"),
+  ok(!togglePanesButton.getAttribute("panesHidden"),
     "The stackframes and breakpoints pane should at this point be visible.");
 
-  is(gDebugger.Prefs.stackframesPaneVisible, true,
-    "The stackframes and breakpoints pane should at this point be visible.");
+  gView.togglePanes({ visible: false, animated: true });
 
-  gView._toggleStackframesAndBreakpointsPane({ visible: false, animated: true });
-
-  is(gDebugger.Prefs.stackframesPaneVisible, false,
-    "The stackframes and breakpoints pane should be hidden after collapsing.");
+  is(gDebugger.Prefs.panesVisibleOnStartup, false,
+    "The debugger view panes should still initially be preffed as hidden.");
+  isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
+    "The options menu item should still not be checked.");
 
   let margin = -(width + 1) + "px";
   is(width, gDebugger.Prefs.stackframesWidth,
     "The stackframes and breakpoints pane has an incorrect width after collapsing.");
   is(stackframesAndBrekpoints.style.marginLeft, margin,
     "The stackframes and breakpoints pane has an incorrect left margin after collapsing.");
   ok(stackframesAndBrekpoints.hasAttribute("animated"),
     "The stackframes and breakpoints pane has an incorrect attribute after an animated collapsing.");
-  ok(togglePanesButton.hasAttribute("stackframesAndBreakpointsHidden"),
+  ok(togglePanesButton.hasAttribute("panesHidden"),
     "The stackframes and breakpoints pane should not be visible after collapsing.");
 
-  is(gDebugger.Prefs.stackframesPaneVisible, false,
-    "The stackframes and breakpoints pane should be hidden before uncollapsing.");
+  gView.togglePanes({ visible: true, animated: false });
 
-  gView._toggleStackframesAndBreakpointsPane({ visible: true, animated: false });
-
-  is(gDebugger.Prefs.stackframesPaneVisible, true,
-    "The stackframes and breakpoints pane should be visible after uncollapsing.");
+  is(gDebugger.Prefs.panesVisibleOnStartup, false,
+    "The debugger view panes should still initially be preffed as hidden.");
+  isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
+    "The options menu item should still not be checked.");
 
   is(width, gDebugger.Prefs.stackframesWidth,
     "The stackframes and breakpoints pane has an incorrect width after uncollapsing.");
   is(stackframesAndBrekpoints.style.marginLeft, "0px",
     "The stackframes and breakpoints pane has an incorrect left margin after uncollapsing.");
   ok(!stackframesAndBrekpoints.hasAttribute("animated"),
     "The stackframes and breakpoints pane has an incorrect attribute after an unanimated uncollapsing.");
-  ok(!togglePanesButton.getAttribute("stackframesAndBreakpointsHidden"),
+  ok(!togglePanesButton.getAttribute("panesHidden"),
     "The stackframes and breakpoints pane should be visible again after uncollapsing.");
 }
 
 function testPaneCollapse2() {
   let variables =
     gDebugger.document.getElementById("variables");
   let togglePanesButton =
     gDebugger.document.getElementById("toggle-panes");
 
   let width = parseInt(variables.getAttribute("width"));
   is(width, gDebugger.Prefs.variablesWidth,
     "The variables pane has an incorrect width.");
   is(variables.style.marginRight, "0px",
     "The variables pane has an incorrect right margin.");
   ok(!variables.hasAttribute("animated"),
     "The variables pane has an incorrect animated attribute.");
-  ok(!togglePanesButton.getAttribute("variablesHidden"),
+  ok(!togglePanesButton.getAttribute("panesHidden"),
     "The variables pane should at this point be visible.");
 
-  is(gDebugger.Prefs.variablesPaneVisible, true,
-    "The variables pane should at this point be visible.");
+  gView.togglePanes({ visible: false, animated: true });
 
-  gView._toggleVariablesPane({ visible: false, animated: true });
-
-  is(gDebugger.Prefs.variablesPaneVisible, false,
-    "The variables pane should be hidden after collapsing.");
+  is(gDebugger.Prefs.panesVisibleOnStartup, false,
+    "The debugger view panes should still initially be preffed as hidden.");
+  isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
+    "The options menu item should still not be checked.");
 
   let margin = -(width + 1) + "px";
   is(width, gDebugger.Prefs.variablesWidth,
     "The variables pane has an incorrect width after collapsing.");
   is(variables.style.marginRight, margin,
     "The variables pane has an incorrect right margin after collapsing.");
   ok(variables.hasAttribute("animated"),
     "The variables pane has an incorrect attribute after an animated collapsing.");
-  ok(togglePanesButton.hasAttribute("variablesHidden"),
+  ok(togglePanesButton.hasAttribute("panesHidden"),
     "The variables pane should not be visible after collapsing.");
 
-  is(gDebugger.Prefs.variablesPaneVisible, false,
-    "The variables pane should be hidden before uncollapsing.");
+  gView.togglePanes({ visible: true, animated: false });
 
-  gView._toggleVariablesPane({ visible: true, animated: false });
-
-  is(gDebugger.Prefs.variablesPaneVisible, true,
-    "The variables pane should be visible after uncollapsing.");
+  is(gDebugger.Prefs.panesVisibleOnStartup, false,
+    "The debugger view panes should still initially be preffed as hidden.");
+  isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
+    "The options menu item should still not be checked.");
 
   is(width, gDebugger.Prefs.variablesWidth,
     "The variables pane has an incorrect width after uncollapsing.");
   is(variables.style.marginRight, "0px",
     "The variables pane has an incorrect right margin after uncollapsing.");
   ok(!variables.hasAttribute("animated"),
     "The variables pane has an incorrect attribute after an unanimated uncollapsing.");
-  ok(!togglePanesButton.getAttribute("variablesHidden"),
+  ok(!togglePanesButton.getAttribute("panesHidden"),
     "The variables pane should be visible again after uncollapsing.");
 }
 
+function testPanesStartupPref(aCallback) {
+  let stackframesAndBrekpoints =
+    gDebugger.document.getElementById("stackframes+breakpoints");
+  let variables =
+    gDebugger.document.getElementById("variables");
+  let togglePanesButton =
+    gDebugger.document.getElementById("toggle-panes");
+
+  is(gDebugger.Prefs.panesVisibleOnStartup, false,
+    "The debugger view panes should still initially be preffed as hidden.");
+
+  ok(!togglePanesButton.getAttribute("panesHidden"),
+    "The debugger panes should at this point be visible.");
+  is(gDebugger.Prefs.panesVisibleOnStartup, false,
+    "The debugger view panes should initially be preffed as hidden.");
+  isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
+    "The options menu item should still not be checked.");
+
+  gDebugger.DebuggerView.Options._showPanesOnStartupItem.setAttribute("checked", "true");
+  gDebugger.DebuggerView.Options._toggleShowPanesOnStartup();
+
+  executeSoon(function() {
+    ok(!togglePanesButton.getAttribute("panesHidden"),
+      "The debugger panes should at this point be visible.");
+    is(gDebugger.Prefs.panesVisibleOnStartup, true,
+      "The debugger view panes should now be preffed as visible.");
+    is(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
+      "The options menu item should now be checked.");
+
+    gDebugger.DebuggerView.Options._showPanesOnStartupItem.setAttribute("checked", "false");
+    gDebugger.DebuggerView.Options._toggleShowPanesOnStartup();
+
+    executeSoon(function() {
+      ok(!togglePanesButton.getAttribute("panesHidden"),
+        "The debugger panes should at this point be visible.");
+      is(gDebugger.Prefs.panesVisibleOnStartup, false,
+        "The debugger view panes should now be preffed as hidden.");
+      isnot(gDebugger.DebuggerView.Options._showPanesOnStartupItem.getAttribute("checked"), "true",
+        "The options menu item should now be unchecked.");
+
+      executeSoon(function() {
+        aCallback();
+      });
+    });
+  });
+}
+
 registerCleanupFunction(function() {
   removeTab(gTab);
   gPane = null;
   gTab = null;
   gDebuggee = null;
   gDebugger = null;
   gView = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_pause-exceptions.js
+++ b/browser/devtools/debugger/test/browser_dbg_pause-exceptions.js
@@ -35,18 +35,18 @@ function testWithFrame()
         return;
       }
       is(gCount, 2, "A. Second Debugger:FetchedVariables event received.");
       gDebugger.removeEventListener("Debugger:FetchedVariables", testA, false);
 
       is(gDebugger.DebuggerController.activeThread.state, "paused",
         "Should be paused now.");
 
-      gDebugger.DebuggerView.Options._poeItem.setAttribute("checked", "true");
-      gDebugger.DebuggerView.Options._togglePOE();
+      gDebugger.DebuggerView.Options._pauseOnExceptionsItem.setAttribute("checked", "true");
+      gDebugger.DebuggerView.Options._togglePauseOnExceptions();
 
       gCount = 0;
       gPane.contentWindow.gClient.addOneTimeListener("resumed", function() {
         gDebugger.addEventListener("Debugger:FetchedVariables", function testB() {
           // We expect 2 Debugger:FetchedVariables events, one from the global object
           // scope and the regular one.
           if (++gCount < 2) {
             is(gCount, 1, "B. First Debugger:FetchedVariables event received.");
--- a/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
+++ b/browser/locales/en-US/chrome/browser/devtools/debugger.dtd
@@ -39,16 +39,21 @@
   -  the button that opens up an options context menu for the debugger UI. -->
 <!ENTITY debuggerUI.optsButton.tooltip  "Debugger Options">
 
 <!-- LOCALIZATION NOTE (debuggerUI.pauseExceptions): This is the label for the
   -  checkbox that toggles pausing on exceptions. -->
 <!ENTITY debuggerUI.pauseExceptions     "Pause on exceptions">
 <!ENTITY debuggerUI.pauseExceptions.key "E">
 
+<!-- LOCALIZATION NOTE (debuggerUI.showPanesOnInit): This is the label for the
+  -  checkbox that toggles visibility of panes when opening the debugger. -->
+<!ENTITY debuggerUI.showPanesOnInit     "Show panes on startup">
+<!ENTITY debuggerUI.showPanesOnInit.key "S">
+
 <!-- LOCALIZATION NOTE (debuggerUI.showNonEnums): This is the label for the
   -  checkbox that toggles visibility of hidden (non-enumerable) variables and
   -  properties in stack views. -->
 <!ENTITY debuggerUI.showNonEnums        "Show hidden properties">
 <!ENTITY debuggerUI.showNonEnums.key    "P">
 
 <!-- LOCALIZATION NOTE (debuggerUI.searchPanelTitle): This is the text that
   -  appears in the filter panel popup as a description. -->
--- a/browser/themes/gnomestripe/devtools/debugger.css
+++ b/browser/themes/gnomestripe/devtools/debugger.css
@@ -397,17 +397,17 @@
 #toggle-panes {
   background: none;
   box-shadow: none;
   border: none;
   list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
 
-#toggle-panes:not([stackframesAndBreakpointsHidden]):not([variablesHidden]) {
+#toggle-panes:not([panesHidden]) {
   list-style-image: url("chrome://browser/skin/devtools/debugger-collapse.png");
 }
 
 #toggle-panes:active {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 #resume {
--- a/browser/themes/pinstripe/devtools/debugger.css
+++ b/browser/themes/pinstripe/devtools/debugger.css
@@ -397,17 +397,17 @@
 #toggle-panes {
   background: none;
   box-shadow: none;
   border: none;
   list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
 
-#toggle-panes:not([stackframesAndBreakpointsHidden]):not([variablesHidden]) {
+#toggle-panes:not([panesHidden]) {
   list-style-image: url("chrome://browser/skin/devtools/debugger-collapse.png");
 }
 
 #toggle-panes:active {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 #resume {
--- a/browser/themes/winstripe/devtools/debugger.css
+++ b/browser/themes/winstripe/devtools/debugger.css
@@ -408,17 +408,17 @@
 #toggle-panes {
   background: none;
   box-shadow: none;
   border: none;
   list-style-image: url("chrome://browser/skin/devtools/debugger-expand.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px);
 }
 
-#toggle-panes:not([stackframesAndBreakpointsHidden]):not([variablesHidden]) {
+#toggle-panes:not([panesHidden]) {
   list-style-image: url("chrome://browser/skin/devtools/debugger-collapse.png");
 }
 
 #toggle-panes:hover {
   -moz-image-region: rect(0px, 32px, 16px, 16px);
 }
 
 #toggle-panes:hover:active {