aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VEmbedded.java168
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VPanel.java43
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTextField.java12
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VView.java14
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VWindow.java9
-rw-r--r--src/com/vaadin/ui/AbsoluteLayout.java19
-rw-r--r--src/com/vaadin/ui/Embedded.java69
-rw-r--r--src/com/vaadin/ui/Panel.java39
-rw-r--r--src/com/vaadin/ui/Window.java28
9 files changed, 336 insertions, 65 deletions
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VEmbedded.java b/src/com/vaadin/terminal/gwt/client/ui/VEmbedded.java
index f1d61029d4..a0f7cc649c 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VEmbedded.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VEmbedded.java
@@ -1,4 +1,4 @@
-/*
+/*
@ITMillApache2LicenseForJavaFiles@
*/
@@ -137,35 +137,9 @@ public class VEmbedded extends HTML implements Paintable {
} else if (uidl.hasAttribute("mimetype")) {
final String mime = uidl.getStringAttribute("mimetype");
if (mime.equals("application/x-shockwave-flash")) {
- addStyleName(CLASSNAME + "-flash");
- String html = "<object "
- + "type=\"application/x-shockwave-flash\" "
- + "width=\"" + width + "\" height=\"" + height + "\">";
+ // Handle embedding of Flash
+ setHTML(createFlashEmbed(uidl));
- Map<String, String> parameters = getParameters(uidl);
- if (parameters.get("movie") == null) {
- parameters.put("movie", getSrc(uidl, client));
- }
-
- // Add the parameters to the Object
- for (String name : parameters.keySet()) {
- html += "<param name=\"" + escapeAttribute(name)
- + "\" value=\""
- + escapeAttribute(parameters.get(name)) + "\"/>";
- }
-
- html += "<embed src=\"" + getSrc(uidl, client) + "\" width=\""
- + width + "\" height=\"" + height + "\" "
- + "type=\"application/x-shockwave-flash\" ";
-
- // Add the parameters to the Embed
- for (String name : parameters.keySet()) {
- html += escapeAttribute(name) + "=\""
- + escapeAttribute(parameters.get(name)) + "\" ";
- }
-
- html += "></embed></object>";
- setHTML(html);
} else if (mime.equals("image/svg+xml")) {
addStyleName(CLASSNAME + "-svg");
String data;
@@ -185,6 +159,26 @@ public class VEmbedded extends HTML implements Paintable {
if (height != null) {
obj.getStyle().setProperty("height", "100%");
}
+ if (uidl.hasAttribute("classid")) {
+ obj.setAttribute("classid",
+ uidl.getStringAttribute(escapeAttribute("classid")));
+ }
+ if (uidl.hasAttribute("codebase")) {
+ obj.setAttribute("codebase", uidl
+ .getStringAttribute(escapeAttribute("codebase")));
+ }
+ if (uidl.hasAttribute("codetype")) {
+ obj.setAttribute("codetype", uidl
+ .getStringAttribute(escapeAttribute("codetype")));
+ }
+ if (uidl.hasAttribute("archive")) {
+ obj.setAttribute("archive",
+ uidl.getStringAttribute(escapeAttribute("archive")));
+ }
+ if (uidl.hasAttribute("standby")) {
+ obj.setAttribute("standby",
+ uidl.getStringAttribute(escapeAttribute("standby")));
+ }
getElement().appendChild(obj);
} else {
@@ -197,7 +191,123 @@ public class VEmbedded extends HTML implements Paintable {
if (clearBrowserElement) {
browserElement = null;
}
+ }
+
+ /**
+ * Creates the Object and Embed tags for the Flash plugin so it works
+ * cross-browser
+ *
+ * @param uidl
+ * The UIDL
+ * @return Tags concatenated into a string
+ */
+ private String createFlashEmbed(UIDL uidl) {
+ addStyleName(CLASSNAME + "-flash");
+
+ /*
+ * To ensure cross-browser compatibility we are using the twice-cooked
+ * method to embed flash i.e. we add a OBJECT tag for IE ActiveX and
+ * inside it a EMBED for all other browsers.
+ */
+
+ StringBuilder html = new StringBuilder();
+
+ // Start the object tag
+ html.append("<object ");
+
+ /*
+ * Add classid required for ActiveX to recognize the flash. This is a
+ * predefined value which ActiveX recognizes and must be the given
+ * value. More info can be found on
+ * http://kb2.adobe.com/cps/415/tn_4150.html. Allow user to override
+ * this by setting his own classid.
+ */
+ if (uidl.hasAttribute("classid")) {
+ html.append("classid=\""
+ + escapeAttribute(uidl.getStringAttribute("classid"))
+ + "\" ");
+ } else {
+ html.append("classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" ");
+ }
+
+ /*
+ * Add codebase required for ActiveX and must be exactly this according
+ * to http://kb2.adobe.com/cps/415/tn_4150.html to work with the above
+ * given classid. Again, see more info on
+ * http://kb2.adobe.com/cps/415/tn_4150.html. Limiting Flash version to
+ * 6.0.0.0 and above. Allow user to override this by setting his own
+ * codebase
+ */
+ if (uidl.hasAttribute("codebase")) {
+ html.append("codebase=\""
+ + escapeAttribute(uidl.getStringAttribute("codebase"))
+ + "\" ");
+ } else {
+ html.append("codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0\" ");
+ }
+
+ // Add width and height
+ html.append("width=\"" + width + "\" ");
+ html.append("height=\"" + height + "\" ");
+ html.append("type=\"application/x-shockwave-flash\" ");
+
+ // Codetype
+ if (uidl.hasAttribute("codetype")) {
+ html.append("codetype=\"" + uidl.getStringAttribute("codetype")
+ + "\" ");
+ }
+
+ // Standby
+ if (uidl.hasAttribute("standby")) {
+ html.append("standby=\"" + uidl.getStringAttribute("standby")
+ + "\" ");
+ }
+
+ // Archive
+ if (uidl.hasAttribute("archive")) {
+ html.append("archive=\"" + uidl.getStringAttribute("archive")
+ + "\" ");
+ }
+
+ // End object tag
+ html.append(">");
+
+ // Ensure we have an movie parameter
+ Map<String, String> parameters = getParameters(uidl);
+ if (parameters.get("movie") == null) {
+ parameters.put("movie", getSrc(uidl, client));
+ }
+
+ // Add parameters to OBJECT
+ for (String name : parameters.keySet()) {
+ html.append("<param ");
+ html.append("name=\"" + escapeAttribute(name) + "\" ");
+ html.append("value=\"" + escapeAttribute(parameters.get(name))
+ + "\" ");
+ html.append("/>");
+ }
+
+ // Build inner EMBED tag
+ html.append("<embed ");
+ html.append("src=\"" + getSrc(uidl, client) + "\" ");
+ html.append("width=\"" + width + "\" ");
+ html.append("height=\"" + height + "\" ");
+ html.append("type=\"application/x-shockwave-flash\" ");
+
+ // Add the parameters to the Embed
+ for (String name : parameters.keySet()) {
+ html.append(escapeAttribute(name));
+ html.append("=");
+ html.append("\"" + escapeAttribute(parameters.get(name)) + "\"");
+ }
+
+ // End embed tag
+ html.append("></embed>");
+
+ // End object tag
+ html.append("</object>");
+ return html.toString();
}
/**
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VPanel.java b/src/com/vaadin/terminal/gwt/client/ui/VPanel.java
index 586e04ed10..692b8a4858 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VPanel.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VPanel.java
@@ -1,4 +1,4 @@
-/*
+/*
@ITMillApache2LicenseForJavaFiles@
*/
@@ -21,6 +21,7 @@ import com.google.gwt.user.client.ui.Widget;
import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.Container;
+import com.vaadin.terminal.gwt.client.Focusable;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.RenderInformation;
import com.vaadin.terminal.gwt.client.RenderSpace;
@@ -29,7 +30,7 @@ import com.vaadin.terminal.gwt.client.Util;
import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHandlerOwner;
public class VPanel extends SimplePanel implements Container,
- ShortcutActionHandlerOwner {
+ ShortcutActionHandlerOwner, Focusable {
public static final String CLICK_EVENT_IDENTIFIER = "click";
public static final String CLASSNAME = "v-panel";
@@ -103,7 +104,16 @@ public class VPanel extends SimplePanel implements Container,
bottomDecoration.setClassName(CLASSNAME + "-deco");
getElement().appendChild(captionWrap);
+
+ /*
+ * Make contentNode focusable only by using the setFocus() method. This
+ * behaviour can be changed by invoking setTabIndex() in the serverside
+ * implementation
+ */
+ contentNode.setTabIndex(-1);
+
getElement().appendChild(contentNode);
+
getElement().appendChild(bottomDecoration);
setStyleName(CLASSNAME);
DOM.sinkEvents(getElement(), Event.ONKEYDOWN);
@@ -117,6 +127,30 @@ public class VPanel extends SimplePanel implements Container,
}, TouchStartEvent.getType());
}
+ /**
+ * Sets the keyboard focus on the Panel
+ *
+ * @param focus
+ * Should the panel have focus or not.
+ */
+ public void setFocus(boolean focus) {
+ if (focus) {
+ getContainerElement().focus();
+ } else {
+ getContainerElement().blur();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.terminal.gwt.client.Focusable#focus()
+ */
+ public void focus() {
+ setFocus(true);
+
+ }
+
@Override
protected Element getContainerElement() {
return contentNode;
@@ -236,6 +270,11 @@ public class VPanel extends SimplePanel implements Container,
// scrollTop
runHacks(false);
+ // And apply tab index
+ if (uidl.hasVariable("tabindex")) {
+ contentNode.setTabIndex(uidl.getIntVariable("tabindex"));
+ }
+
rendering = false;
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTextField.java b/src/com/vaadin/terminal/gwt/client/ui/VTextField.java
index 49d18f0867..edf4261988 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VTextField.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VTextField.java
@@ -145,12 +145,14 @@ public class VTextField extends TextBoxBase implements Paintable, Field,
@Override
public void run() {
- updateCursorPosition();
- boolean textChanged = communicateTextValueToServer();
- if (textChanged) {
- client.sendPendingVariableChanges();
+ if (isAttached()) {
+ updateCursorPosition();
+ boolean textChanged = communicateTextValueToServer();
+ if (textChanged) {
+ client.sendPendingVariableChanges();
+ }
+ scheduled = false;
}
- scheduled = false;
}
};
private boolean scheduled = false;
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VView.java b/src/com/vaadin/terminal/gwt/client/ui/VView.java
index ea43deba9d..5d7cc18945 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VView.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VView.java
@@ -43,7 +43,7 @@ import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHan
*
*/
public class VView extends SimplePanel implements Container, ResizeHandler,
- Window.ClosingHandler, ShortcutActionHandlerOwner {
+ Window.ClosingHandler, ShortcutActionHandlerOwner, Focusable {
private static final String CLASSNAME = "v-view";
@@ -110,6 +110,10 @@ public class VView extends SimplePanel implements Container, ResizeHandler,
public VView() {
super();
setStyleName(CLASSNAME);
+
+ // Allow focusing the view by using the focus() method, the view
+ // should not be in the document focus flow
+ getElement().setTabIndex(-1);
}
/**
@@ -691,9 +695,9 @@ public class VView extends SimplePanel implements Container, ResizeHandler,
DOM.setStyleAttribute(fElem, "position", "absolute");
DOM.setStyleAttribute(fElem, "opacity", "0.1");
DOM.appendChild(getElement(), fElem);
- Util.focus(fElem);
+ fElem.focus();
} else {
- Util.focus(getElement());
+ getElement().focus();
}
parentFrame = getParentFrame();
@@ -703,4 +707,8 @@ public class VView extends SimplePanel implements Container, ResizeHandler,
return actionHandler;
}
+ public void focus() {
+ getElement().focus();
+ }
+
}
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java
index 8e03ca89d7..395d6f6ea0 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VWindow.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VWindow.java
@@ -1,4 +1,4 @@
-/*
+/*
@ITMillApache2LicenseForJavaFiles@
*/
@@ -35,6 +35,7 @@ import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.BrowserInfo;
import com.vaadin.terminal.gwt.client.Container;
import com.vaadin.terminal.gwt.client.EventId;
+import com.vaadin.terminal.gwt.client.Focusable;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.RenderSpace;
import com.vaadin.terminal.gwt.client.UIDL;
@@ -50,7 +51,7 @@ import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHan
*/
public class VWindow extends VOverlay implements Container,
ShortcutActionHandlerOwner, ScrollHandler, KeyDownHandler,
- FocusHandler, BlurHandler, BeforeShortcutActionListener {
+ FocusHandler, BlurHandler, BeforeShortcutActionListener, Focusable {
/**
* Minimum allowed height of a window. This refers to the content area, not
@@ -1307,4 +1308,8 @@ public class VWindow extends VOverlay implements Container,
// blur/focus )
}
+ public void focus() {
+ contentPanel.focus();
+ }
+
}
diff --git a/src/com/vaadin/ui/AbsoluteLayout.java b/src/com/vaadin/ui/AbsoluteLayout.java
index 3b0239af7b..c7a1583d28 100644
--- a/src/com/vaadin/ui/AbsoluteLayout.java
+++ b/src/com/vaadin/ui/AbsoluteLayout.java
@@ -122,8 +122,23 @@ public class AbsoluteLayout extends AbstractLayout implements
* The css position string
*/
public void addComponent(Component c, String cssPosition) {
- addComponent(c);
- getPosition(c).setCSSString(cssPosition);
+ /*
+ * Create position instance and add it to componentToCoordinates map. We
+ * need to do this before we call addComponent so the attachListeners
+ * can access this position. #6368
+ */
+ ComponentPosition position = new ComponentPosition();
+ position.setCSSString(cssPosition);
+ componentToCoordinates.put(c, position);
+
+ try {
+ addComponent(c);
+
+ } catch (IllegalArgumentException e) {
+ // Remove component coordinates if adding fails
+ componentToCoordinates.remove(c);
+ throw e;
+ }
}
/**
diff --git a/src/com/vaadin/ui/Embedded.java b/src/com/vaadin/ui/Embedded.java
index 85d67ae105..55991eafb2 100644
--- a/src/com/vaadin/ui/Embedded.java
+++ b/src/com/vaadin/ui/Embedded.java
@@ -1,4 +1,4 @@
-/*
+/*
@ITMillApache2LicenseForJavaFiles@
*/
@@ -205,8 +205,9 @@ public class Embedded extends AbstractComponent {
}
/**
- * Gets the codebase, the root-path used to access resources with relative
- * paths.
+ * This attribute specifies the base path used to resolve relative URIs
+ * specified by the classid, data, and archive attributes. When absent, its
+ * default value is the base URI of the current document.
*
* @return the code base.
*/
@@ -233,20 +234,22 @@ public class Embedded extends AbstractComponent {
}
/**
- * Gets the standby text displayed when the object is loading.
+ * This attribute specifies a message that a user agent may render while
+ * loading the object's implementation and data.
*
- * @return the standby text.
+ * @return The text displayed when loading
*/
public String getStandby() {
return standby;
}
/**
- * Sets the codebase, the root-path used to access resources with relative
- * paths.
+ * This attribute specifies the base path used to resolve relative URIs
+ * specified by the classid, data, and archive attributes. When absent, its
+ * default value is the base URI of the current document.
*
* @param codebase
- * the codebase to set.
+ * The base path
*/
public void setCodebase(String codebase) {
if (codebase != this.codebase
@@ -257,7 +260,11 @@ public class Embedded extends AbstractComponent {
}
/**
- * Sets the codetype, the MIME-Type of the code.
+ * This attribute specifies the content type of data expected when
+ * downloading the object specified by classid. This attribute is optional
+ * but recommended when classid is specified since it allows the user agent
+ * to avoid loading information for unsupported content types. When absent,
+ * it defaults to the value of the type attribute.
*
* @param codetype
* the codetype to set.
@@ -296,10 +303,11 @@ public class Embedded extends AbstractComponent {
}
/**
- * Sets the standby, the text to display while loading the object.
+ * This attribute specifies a message that a user agent may render while
+ * loading the object's implementation and data.
*
* @param standby
- * the standby to set.
+ * The text to display while loading
*/
public void setStandby(String standby) {
if (standby != this.standby
@@ -310,16 +318,18 @@ public class Embedded extends AbstractComponent {
}
/**
- * Gets the classId attribute.
+ * This attribute may be used to specify the location of an object's
+ * implementation via a URI.
*
- * @return the class id.
+ * @return the classid.
*/
public String getClassId() {
return classId;
}
/**
- * Sets the classId attribute.
+ * This attribute may be used to specify the location of an object's
+ * implementation via a URI.
*
* @param classId
* the classId to set.
@@ -410,19 +420,31 @@ public class Embedded extends AbstractComponent {
}
/**
- * Gets the archive attribute.
+ * This attribute may be used to specify a space-separated list of URIs for
+ * archives containing resources relevant to the object, which may include
+ * the resources specified by the classid and data attributes. Preloading
+ * archives will generally result in reduced load times for objects.
+ * Archives specified as relative URIs should be interpreted relative to the
+ * codebase attribute.
*
- * @return the archive attribute.
+ * @return Space-separated list of URIs with resources relevant to the
+ * object
*/
public String getArchive() {
return archive;
}
/**
- * Sets the archive attribute.
+ * This attribute may be used to specify a space-separated list of URIs for
+ * archives containing resources relevant to the object, which may include
+ * the resources specified by the classid and data attributes. Preloading
+ * archives will generally result in reduced load times for objects.
+ * Archives specified as relative URIs should be interpreted relative to the
+ * codebase attribute.
*
* @param archive
- * the archive string to set.
+ * Space-separated list of URIs with resources relevant to the
+ * object
*/
public void setArchive(String archive) {
if (archive != this.archive
@@ -458,6 +480,12 @@ public class Embedded extends AbstractComponent {
removeListener(CLICK_EVENT, ClickEvent.class, listener);
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.vaadin.ui.AbstractComponent#changeVariables(java.lang.Object,
+ * java.util.Map)
+ */
@SuppressWarnings("unchecked")
@Override
public void changeVariables(Object source, Map<String, Object> variables) {
@@ -468,6 +496,11 @@ public class Embedded extends AbstractComponent {
}
+ /**
+ * Notifies click-listeners that a mouse click event has occurred.
+ *
+ * @param parameters
+ */
private void fireClick(Map<String, Object> parameters) {
MouseEventDetails mouseDetails = MouseEventDetails
.deSerialize((String) parameters.get("mouseDetails"));
diff --git a/src/com/vaadin/ui/Panel.java b/src/com/vaadin/ui/Panel.java
index 4d00cddfdd..7ffa11a325 100644
--- a/src/com/vaadin/ui/Panel.java
+++ b/src/com/vaadin/ui/Panel.java
@@ -1,4 +1,4 @@
-/*
+/*
@ITMillApache2LicenseForJavaFiles@
*/
@@ -17,6 +17,7 @@ import com.vaadin.terminal.PaintTarget;
import com.vaadin.terminal.Scrollable;
import com.vaadin.terminal.gwt.client.MouseEventDetails;
import com.vaadin.terminal.gwt.client.ui.VPanel;
+import com.vaadin.ui.Component.Focusable;
import com.vaadin.ui.themes.Reindeer;
import com.vaadin.ui.themes.Runo;
@@ -32,7 +33,7 @@ import com.vaadin.ui.themes.Runo;
@ClientWidget(VPanel.class)
public class Panel extends AbstractComponentContainer implements Scrollable,
ComponentContainer.ComponentAttachListener,
- ComponentContainer.ComponentDetachListener, Action.Notifier {
+ ComponentContainer.ComponentDetachListener, Action.Notifier, Focusable {
private static final String CLICK_EVENT = VPanel.CLICK_EVENT_IDENTIFIER;
@@ -75,6 +76,13 @@ public class Panel extends AbstractComponentContainer implements Scrollable,
protected ActionManager actionManager;
/**
+ * By default the Panel is not in the normal document focus flow and can
+ * only be focused by using the focus()-method. Change this to 0 if you want
+ * to have the Panel in the normal focus flow.
+ */
+ private int tabIndex = -1;
+
+ /**
* Creates a new empty panel. A VerticalLayout is used as content.
*/
public Panel() {
@@ -234,6 +242,8 @@ public class Panel extends AbstractComponentContainer implements Scrollable,
public void paintContent(PaintTarget target) throws PaintException {
content.paint(target);
+ target.addVariable(this, "tabindex", getTabIndex());
+
if (isScrollable()) {
target.addVariable(this, "scrollLeft", getScrollLeft());
target.addVariable(this, "scrollTop", getScrollTop());
@@ -582,4 +592,29 @@ public class Panel extends AbstractComponentContainer implements Scrollable,
fireEvent(new ClickEvent(this, mouseDetails));
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getTabIndex() {
+ return tabIndex;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setTabIndex(int tabIndex) {
+ this.tabIndex = tabIndex;
+ requestRepaint();
+ }
+
+ /**
+ * Moves keyboard focus to the component. {@see Focusable#focus()}
+ *
+ */
+ @Override
+ public void focus() {
+ super.focus();
+ }
+
}
diff --git a/src/com/vaadin/ui/Window.java b/src/com/vaadin/ui/Window.java
index b31255cb26..5c2769c756 100644
--- a/src/com/vaadin/ui/Window.java
+++ b/src/com/vaadin/ui/Window.java
@@ -1,4 +1,4 @@
-/*
+/*
@ITMillApache2LicenseForJavaFiles@
*/
@@ -1120,6 +1120,10 @@ public class Window extends Panel implements URIHandler, ParameterHandler,
if (parent == null) {
fireClose();
} else {
+
+ // focus is restored to the parent window
+ parent.focus();
+
// subwindow is removed from parent
parent.removeWindow(this);
}
@@ -2089,7 +2093,7 @@ public class Window extends Panel implements URIHandler, ParameterHandler,
* <code>
* // within the window using helper
* subWindow.setCloseShortcut(KeyCode.ESCAPE, null);
- *
+ *
* // or globally
* getWindow().addAction(new Window.CloseShortcut(subWindow, KeyCode.ESCAPE));
* </code>
@@ -2180,4 +2184,24 @@ public class Window extends Panel implements URIHandler, ParameterHandler,
removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener);
}
+ /**
+ * {@inheritDoc}
+ *
+ * If the window is a sub-window focusing will cause the sub-window to be
+ * brought on top of other sub-windows on gain keyboard focus.
+ */
+ @Override
+ public void focus() {
+ if (getParent() != null) {
+ /*
+ * When focusing a sub-window it basically means it should be
+ * brought to the front. Instead of just moving the keyboard focus
+ * we focus the window and bring it top-most.
+ */
+ bringToFront();
+ } else {
+ super.focus();
+ }
+ }
+
}