--- /dev/null
+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);
+ }
+ }
+ }
+}
/**
*
*/
-public class VTree extends SimpleFocusablePanel implements Paintable,
+public class VTree extends FocusElementPanel implements Paintable,
VHasDropHandler, FocusHandler, BlurHandler, KeyPressHandler,
KeyDownHandler, SubPartAware, ActionOwner {
* 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);
}
/*
}
}
+ private boolean isIE6OrOpera() {
+ return BrowserInfo.get().isIE6() || BrowserInfo.get().isOpera();
+ }
+
/**
* Handles mouse selection
*
// 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() {
* 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);
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");
ie6compatnode.addClassName(CLASSNAME_FOCUSED);
}
this.focused = focused;
- nodeCaptionDiv.focus();
+ if (isIE6OrOpera()) {
+ nodeCaptionDiv.focus();
+ }
treeHasFocus = true;
} else if (this.focused && !focused) {
nodeCaptionDiv.removeClassName(CLASSNAME_FOCUSED);
focusedNode);
setFocusedNode(focusedNode.getParentNode());
} else {
- setSelected(focusedNode, false);
+ TreeNode oldFocusedNode = focusedNode;
setFocusedNode(focusedNode.getParentNode());
setSelected(focusedNode, true);
+ setSelected(oldFocusedNode, false);
}
}
return true;
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;