Bug 577925 - F6 doesn't work when message summary view is shown (operate on collapsed); r=asuth,a=Standard8
authorJim Porter <squibblyflabbetydoo@gmail.com>
Sun, 24 Jul 2011 03:23:41 -0500
changeset 8369 9c7f4200754d15645795987dc45345d616be9643
parent 8368 271501c7d9a22bcaa71db5787d6e5d1c9a3de8d5
child 8370 f0dd4c316c5a24b47f87286cacac212c3d421542
push idunknown
push userunknown
push dateunknown
reviewersasuth, Standard8
bugs577925
Bug 577925 - F6 doesn't work when message summary view is shown (operate on collapsed); r=asuth,a=Standard8
mail/base/content/mail3PaneWindowCommands.js
mail/test/mozmill/folder-display/test-pane-focus.js
--- a/mail/base/content/mail3PaneWindowCommands.js
+++ b/mail/base/content/mail3PaneWindowCommands.js
@@ -996,26 +996,35 @@ function FocusRingUpdate_Mail()
     // since we just changed the pane with focus we need to update the toolbar to reflect this
     // XXX TODO
     // can we optimize
     // and just update cmd_delete and button_delete?
     UpdateMailToolbar("focus");
   }
 }
 
+/**
+ * Determine which pane currently has focus (one of the folder pane, thread
+ * pane, message pane, or multimessage pane).
+ *
+ * @return the focused pane
+ */
 function WhichPaneHasFocus()
 {
   if (top.document.commandDispatcher.focusedWindow == GetMessagePaneFrame())
     return GetMessagePane();
 
-  var currentNode = top.document.commandDispatcher.focusedElement;
+  var panes = [document.getElementById(id) for each (id in [
+    "threadTree", "folderTree", "messagepanebox", "multimessage"
+  ])];
+
+  var currentNode = top.document.activeElement;
+
   while (currentNode) {
-    if (currentNode === document.getElementById('threadTree') ||
-        currentNode === document.getElementById("folderTree") ||
-        currentNode === document.getElementById("messagepanebox"))
+    if (panes.indexOf(currentNode) != -1)
       return currentNode;
 
     currentNode = currentNode.parentNode;
   }
   return null;
 }
 
 function RestoreFocusAfterHdrButton()
@@ -1117,48 +1126,71 @@ function SetFocusThreadPaneIfNotOnMessag
   var focusedElement = WhichPaneHasFocus();
 
   if((focusedElement != GetThreadTree()) &&
      (focusedElement != GetMessagePane()))
      SetFocusThreadPane();
 }
 
 // 3pane related commands.  Need to go in own file.  Putting here for the moment.
+
+/**
+ * Cycle through the various panes in the 3pane window (in reverse if the shift
+ * key is being held down).
+ *
+ * @param event the event that triggered us
+ */
 function SwitchPaneFocus(event)
 {
-  var folderTree = document.getElementById("folderTree");
-  var threadTree = GetThreadTree();
-  var messagePane = GetMessagePane();
+  let messagePane = GetMessagePane();
+
+  // First, build an array of panes to cycle through based on our current state.
+  // This will usually be something like [threadPane, messagePane, folderPane].
+  let panes = [GetThreadTree()];
 
-  var folderPaneCollapsed = document.getElementById("folderPaneBox").collapsed;
+  if (!IsMessagePaneCollapsed()) {
+    if (gMessageDisplay.singleMessageDisplay)
+      panes.push(messagePane);
+    else
+      panes.push(document.getElementById("multimessage"));
+  }
 
-  var focusedElement = WhichPaneHasFocus();
-  if (focusedElement == null)       // focus not on one of the main three panes (probably toolbar)
-    focusedElement = threadTree;    // treat as if on thread tree
+  if (gFolderDisplay.folderPaneVisible)
+    panes.push(document.getElementById("folderTree"));
+
+  // Find our focused element in the array. If focus is not on one of the main
+  // panes (it's probably on the toolbar), then act as if it's on the thread
+  // tree.
+  let focusedElement = WhichPaneHasFocus();
+  let focusedElementIndex = panes.indexOf(focusedElement);
+  if (focusedElementIndex == -1)
+    focusedElementIndex = 0;
 
   if (event && event.shiftKey)
   {
-    // Reverse traversal: Message -> Thread -> Folder -> Message
-    if (focusedElement == threadTree && !folderPaneCollapsed)
-      folderTree.focus();
-    else if (focusedElement != messagePane && !IsMessagePaneCollapsed())
-      SetFocusMessagePane();
-    else
-      threadTree.focus();
+    focusedElementIndex--;
+    if (focusedElementIndex == -1)
+      focusedElementIndex = panes.length-1;
   }
   else
   {
-    // Forward traversal: Folder -> Thread -> Message -> Folder
-    if (focusedElement == threadTree && !IsMessagePaneCollapsed())
-      SetFocusMessagePane();
-    else if (focusedElement != folderTree && !folderPaneCollapsed)
-      folderTree.focus();
-    else
-      threadTree.focus();
+    focusedElementIndex++;
+    if (focusedElementIndex == panes.length)
+      focusedElementIndex = 0;
   }
+
+  let newElem = panes[focusedElementIndex];
+
+  // We need to handle the message pane specially, since focusing it isn't as
+  // simple as just calling focus(). See SetFocusMessagePane below for more
+  // details.
+  if (newElem == messagePane)
+    SetFocusMessagePane();
+  else
+    newElem.focus();
 }
 
 function SetFocusThreadPane()
 {
     var threadTree = GetThreadTree();
     threadTree.focus();
 }
 
new file mode 100644
--- /dev/null
+++ b/mail/test/mozmill/folder-display/test-pane-focus.js
@@ -0,0 +1,107 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ *   Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Thunderbird Mail Client.
+ *
+ * The Initial Developer of the Original Code is
+ * the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Jim Porter <squibblyflabbetydoo@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/*
+ * Test that cycling through the focus of the 3pane's panes works correctly.
+ */
+var MODULE_NAME = "test-pane-focus";
+
+var RELATIVE_ROOT = "../shared-modules";
+var MODULE_REQUIRES = ["folder-display-helpers"];
+
+var folder;
+
+function setupModule(module) {
+  let fdh = collector.getModule("folder-display-helpers");
+  fdh.installInto(module);
+
+  folder = create_folder("PaneFocus");
+  make_new_sets_in_folder(folder, [{count: 3}]);
+}
+
+/**
+ * Check that it's possible to cycle through the 3pane's panes forward and
+ * backward.
+ *
+ * @param multimessage true if the multimessage pane should be active
+ */
+function check_pane_cycling(multimessage) {
+  let folderPane = mc.e("folderTree");
+  let threadPane = mc.e("threadTree");
+  let messagePane = mc.e(multimessage ? "multimessage" : "messagepanebox");
+
+  folderPane.focus();
+
+  mc.keypress(null, "VK_F6", {});
+  assert_equals(threadPane, mc.window.WhichPaneHasFocus());
+  mc.keypress(null, "VK_F6", {});
+  assert_equals(messagePane, mc.window.WhichPaneHasFocus());
+  mc.keypress(null, "VK_F6", {});
+  assert_equals(folderPane, mc.window.WhichPaneHasFocus());
+
+  mc.keypress(null, "VK_F6", {shiftKey: true});
+  assert_equals(messagePane, mc.window.WhichPaneHasFocus());
+  mc.keypress(null, "VK_F6", {shiftKey: true});
+  assert_equals(threadPane, mc.window.WhichPaneHasFocus());
+  mc.keypress(null, "VK_F6", {shiftKey: true});
+  assert_equals(folderPane, mc.window.WhichPaneHasFocus());
+}
+
+function test_no_messages_selected() {
+  be_in_folder(folder);
+
+  // Select nothing
+  select_none();
+  check_pane_cycling(false);
+}
+
+function test_one_message_selected() {
+  be_in_folder(folder);
+
+  // Select a message
+  select_click_row(0);
+  check_pane_cycling(false);
+}
+
+function test_n_messages_selected() {
+  be_in_folder(folder);
+
+  // Select a thread
+  select_click_row(0);
+  select_shift_click_row(2);
+  check_pane_cycling(true);
+}