]> source.dussan.org Git - vaadin-framework.git/commitdiff
Fix for #6841 - Tree no longer scrolls horizontally on selection.
authorJonatan Kronqvist <jonatan.kronqvist@itmill.com>
Mon, 2 May 2011 08:17:50 +0000 (08:17 +0000)
committerJonatan Kronqvist <jonatan.kronqvist@itmill.com>
Mon, 2 May 2011 08:17:50 +0000 (08:17 +0000)
svn changeset:18573/svn branch:6.6

src/com/vaadin/terminal/gwt/client/ui/FocusElementPanel.java [new file with mode: 0644]
src/com/vaadin/terminal/gwt/client/ui/VTree.java

diff --git a/src/com/vaadin/terminal/gwt/client/ui/FocusElementPanel.java b/src/com/vaadin/terminal/gwt/client/ui/FocusElementPanel.java
new file mode 100644 (file)
index 0000000..fe4b483
--- /dev/null
@@ -0,0 +1,82 @@
+package com.vaadin.terminal.gwt.client.ui;
+
+import com.google.gwt.dom.client.DivElement;
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.Position;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.client.ui.impl.FocusImpl;
+import com.vaadin.terminal.gwt.client.BrowserInfo;
+
+/**
+ * A panel that contains an always visible 0x0 size element that holds the focus
+ * for all browsers but IE6.
+ */
+public class FocusElementPanel extends SimpleFocusablePanel {
+
+    private DivElement focusElement;
+
+    public FocusElementPanel() {
+        focusElement = Document.get().createDivElement();
+    }
+
+    @Override
+    public void setWidget(Widget w) {
+        super.setWidget(w);
+        if (!BrowserInfo.get().isIE6()) {
+            if (focusElement.getParentElement() == null) {
+                Style style = focusElement.getStyle();
+                style.setPosition(Position.FIXED);
+                style.setTop(0, Unit.PX);
+                style.setLeft(0, Unit.PX);
+                getElement().appendChild(focusElement);
+                /* Sink from focusElement too as focus and blur don't bubble */
+                DOM.sinkEvents(
+                        (com.google.gwt.user.client.Element) focusElement
+                                .cast(), Event.FOCUSEVENTS);
+                // revert to original, not focusable
+                getElement().setPropertyObject("tabIndex", null);
+            } else {
+                moveFocusElementAfterWidget();
+            }
+        }
+    }
+
+    /**
+     * Helper to keep focus element always in domChild[1]. Aids testing.
+     */
+    private void moveFocusElementAfterWidget() {
+        getElement().insertAfter(focusElement, getWidget().getElement());
+    }
+
+    @Override
+    public void setFocus(boolean focus) {
+        if (BrowserInfo.get().isIE6()) {
+            super.setFocus(focus);
+        } else {
+            if (focus) {
+                FocusImpl.getFocusImplForPanel().focus(
+                        (Element) focusElement.cast());
+            } else {
+                FocusImpl.getFocusImplForPanel().blur(
+                        (Element) focusElement.cast());
+            }
+        }
+    }
+
+    @Override
+    public void setTabIndex(int tabIndex) {
+        if (BrowserInfo.get().isIE6()) {
+            super.setTabIndex(tabIndex);
+        } else {
+            getElement().setTabIndex(-1);
+            if (focusElement != null) {
+                focusElement.setTabIndex(tabIndex);
+            }
+        }
+    }
+}
index 0ee86da0a0cc34c079b09ff34cd35ac9eacb7c0a..53ca56aca9918de4f9d8f463fef4e184924a0197 100644 (file)
@@ -56,7 +56,7 @@ import com.vaadin.terminal.gwt.client.ui.dd.VerticalDropLocation;
 /**
  * 
  */
-public class VTree extends SimpleFocusablePanel implements Paintable,
+public class VTree extends FocusElementPanel implements Paintable,
         VHasDropHandler, FocusHandler, BlurHandler, KeyPressHandler,
         KeyDownHandler, SubPartAware, ActionOwner {
 
@@ -152,6 +152,13 @@ public class VTree extends SimpleFocusablePanel implements Paintable,
          * selection patch in IE
          */
         sinkEvents(Event.ONMOUSEDOWN | Event.ONMOUSEUP | Event.ONKEYUP);
+
+        /*
+         * Re-set the tab index to make sure that the FocusElementPanel's
+         * (super) focus element gets the tab index and not the element
+         * containing the tree.
+         */
+        setTabIndex(0);
     }
 
     /*
@@ -628,6 +635,10 @@ public class VTree extends SimpleFocusablePanel implements Paintable,
             }
         }
 
+        private boolean isIE6OrOpera() {
+            return BrowserInfo.get().isIE6() || BrowserInfo.get().isOpera();
+        }
+
         /**
          * Handles mouse selection
          * 
@@ -643,6 +654,15 @@ public class VTree extends SimpleFocusablePanel implements Paintable,
             // always when clicking an item, focus it
             setFocusedNode(this, false);
 
+            if (!isIE6OrOpera()) {
+                /*
+                 * Ensure that the tree's focus element also gains focus
+                 * (TreeNodes focus is faked using FocusElementPanel in browsers
+                 * other than IE6 and Opera).
+                 */
+                focus();
+            }
+
             ScheduledCommand command = new ScheduledCommand() {
                 public void execute() {
 
@@ -810,10 +830,14 @@ public class VTree extends SimpleFocusablePanel implements Paintable,
              * previously modified field may contain dirty variables.
              */
             if (!treeHasFocus) {
-                if (focusedNode == null) {
-                    getNodeByKey(key).setFocused(true);
+                if (isIE6OrOpera()) {
+                    if (focusedNode == null) {
+                        getNodeByKey(key).setFocused(true);
+                    } else {
+                        focusedNode.setFocused(true);
+                    }
                 } else {
-                    focusedNode.setFocused(true);
+                    focus();
                 }
             }
             final MouseEventDetails details = new MouseEventDetails(evt);
@@ -870,11 +894,13 @@ public class VTree extends SimpleFocusablePanel implements Paintable,
             DOM.appendChild(nodeCaptionDiv, wrapper);
             DOM.appendChild(wrapper, nodeCaptionSpan);
 
-            /*
-             * Focus the caption div of the node to get keyboard navigation to
-             * work without scrolling up or down when focusing a node.
-             */
-            nodeCaptionDiv.setTabIndex(-1);
+            if (isIE6OrOpera()) {
+                /*
+                 * Focus the caption div of the node to get keyboard navigation
+                 * to work without scrolling up or down when focusing a node.
+                 */
+                nodeCaptionDiv.setTabIndex(-1);
+            }
 
             childNodeContainer = new FlowPanel();
             childNodeContainer.setStyleName(CLASSNAME + "-children");
@@ -1167,7 +1193,9 @@ public class VTree extends SimpleFocusablePanel implements Paintable,
                     ie6compatnode.addClassName(CLASSNAME_FOCUSED);
                 }
                 this.focused = focused;
-                nodeCaptionDiv.focus();
+                if (isIE6OrOpera()) {
+                    nodeCaptionDiv.focus();
+                }
                 treeHasFocus = true;
             } else if (this.focused && !focused) {
                 nodeCaptionDiv.removeClassName(CLASSNAME_FOCUSED);
@@ -1776,9 +1804,10 @@ public class VTree extends SimpleFocusablePanel implements Paintable,
                             focusedNode);
                     setFocusedNode(focusedNode.getParentNode());
                 } else {
-                    setSelected(focusedNode, false);
+                    TreeNode oldFocusedNode = focusedNode;
                     setFocusedNode(focusedNode.getParentNode());
                     setSelected(focusedNode, true);
+                    setSelected(oldFocusedNode, false);
                 }
             }
             return true;
@@ -1796,9 +1825,10 @@ public class VTree extends SimpleFocusablePanel implements Paintable,
                     setFocusedNode(focusedNode.getChildren().get(0));
                     setSelected(focusedNode, true);
                 } else {
-                    setSelected(focusedNode, false);
+                    TreeNode oldFocusedNode = focusedNode;
                     setFocusedNode(focusedNode.getChildren().get(0));
                     setSelected(focusedNode, true);
+                    setSelected(oldFocusedNode, false);
                 }
             }
             return true;