import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
+import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.vaadin.client.ui.aria.AriaHelper;
import com.vaadin.client.ui.window.WindowMoveEvent;
import com.vaadin.client.ui.window.WindowMoveHandler;
+import com.vaadin.client.ui.window.WindowOrderEvent;
+import com.vaadin.client.ui.window.WindowOrderHandler;
import com.vaadin.shared.Connector;
import com.vaadin.shared.EventId;
import com.vaadin.shared.ui.window.WindowMode;
public class VWindow extends VOverlay implements ShortcutActionHandlerOwner,
ScrollHandler, KeyDownHandler, FocusHandler, BlurHandler, Focusable {
- private static ArrayList<VWindow> windowOrder = new ArrayList<VWindow>();
+ private static List<VWindow> windowOrder = new ArrayList<VWindow>();
+
+ private static final HandlerManager WINDOW_ORDER_HANDLER = new HandlerManager(
+ VWindow.class);
private static boolean orderingDefered;
}
public void bringToFront() {
- int curIndex = windowOrder.indexOf(this);
+ bringToFront(true);
+ }
+
+ private void bringToFront(boolean notifyListeners) {
+ int curIndex = getWindowOrder();
if (curIndex + 1 < windowOrder.size()) {
windowOrder.remove(this);
windowOrder.add(this);
for (; curIndex < windowOrder.size(); curIndex++) {
- windowOrder.get(curIndex).setWindowOrder(curIndex);
+ VWindow window = windowOrder.get(curIndex);
+ window.setWindowOrder(curIndex);
}
}
+ if (notifyListeners) {
+ fireOrderEvent();
+ }
+ }
+
+ static void fireOrderEvent() {
+ fireOrderEvent(windowOrder);
+ }
+
+ private void doFireOrderEvent() {
+ List<VWindow> list = new ArrayList<VWindow>();
+ list.add(this);
+ fireOrderEvent(list);
+ }
+
+ private static void fireOrderEvent(List<VWindow> windows) {
+ WINDOW_ORDER_HANDLER.fireEvent(
+ new WindowOrderEvent(new ArrayList<VWindow>(windows)));
}
/**
}
private static VWindow getTopmostWindow() {
- if (windowOrder.size() > 0) {
+ if (!windowOrder.isEmpty()) {
return windowOrder.get(windowOrder.size() - 1);
}
return null;
windowOrder.add(this);
setPopupPosition(order * STACKING_OFFSET_PIXELS,
order * STACKING_OFFSET_PIXELS);
-
+ doFireOrderEvent();
}
private void setWindowOrder(int order) {
setZIndex(order + Z_INDEX);
}
+ /**
+ * Returns window position in list of opened and shown windows.
+ *
+ * @since 7.7.12
+ */
+ public final int getWindowOrder() {
+ return windowOrder.indexOf(this);
+ }
+
@Override
protected void setZIndex(int zIndex) {
super.setZIndex(zIndex);
Roles.getDialogRole().setAriaLabelledbyProperty(getElement(),
Id.of(headerText));
- // Handlers to Prevent tab to leave the window
+ // Handlers to Prevent tab to leave the window (by circulating focus)
// and backspace to cause browser navigation
topEventBlocker = new NativePreviewHandler() {
@Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
+ if (!getElement()
+ .isOrHasChild(WidgetUtil.getFocusedElement())) {
+ return;
+ }
NativeEvent nativeEvent = event.getNativeEvent();
if (nativeEvent.getEventTarget().cast() == topTabStop
&& nativeEvent.getKeyCode() == KeyCodes.KEY_TAB
&& nativeEvent.getShiftKey()) {
nativeEvent.preventDefault();
+ FocusUtil.focusOnLastFocusableElement(
+ VWindow.this.getElement());
}
if (nativeEvent.getEventTarget().cast() == topTabStop
&& nativeEvent.getKeyCode() == KeyCodes.KEY_BACKSPACE) {
bottomEventBlocker = new NativePreviewHandler() {
@Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
+ if (!getElement()
+ .isOrHasChild(WidgetUtil.getFocusedElement())) {
+ return;
+ }
NativeEvent nativeEvent = event.getNativeEvent();
if (nativeEvent.getEventTarget().cast() == bottomTabStop
&& nativeEvent.getKeyCode() == KeyCodes.KEY_TAB
&& !nativeEvent.getShiftKey()) {
nativeEvent.preventDefault();
+ FocusUtil.focusOnFirstFocusableElement(
+ VWindow.this.getElement());
}
if (nativeEvent.getEventTarget().cast() == bottomTabStop
&& nativeEvent.getKeyCode() == KeyCodes.KEY_BACKSPACE) {
@Override
public int compare(VWindow o1, VWindow o2) {
- /*
- * Order by modality, then by bringtofront sequence.
- */
+ /*
+ * Order by modality, then by bringtofront sequence.
+ */
if (o1.vaadinModality && !o2.vaadinModality) {
return 1;
- } else if (!o1.vaadinModality && o2.vaadinModality) {
+ }
+ if (!o1.vaadinModality && o2.vaadinModality) {
return -1;
- } else if (o1.bringToFrontSequence > o2.bringToFrontSequence) {
+ }
+ if (o1.bringToFrontSequence > o2.bringToFrontSequence) {
return 1;
- } else if (o1.bringToFrontSequence < o2.bringToFrontSequence) {
+ }
+ if (o1.bringToFrontSequence < o2.bringToFrontSequence) {
return -1;
- } else {
- return 0;
}
+ return 0;
}
});
- for (int i = 0; i < array.length; i++) {
- VWindow w = array[i];
+ for (VWindow w : array) {
if (w.bringToFrontSequence != -1 || w.vaadinModality) {
- w.bringToFront();
+ w.bringToFront(false);
w.bringToFrontSequence = -1;
}
}
private static void focusTopmostModalWindow() {
VWindow topmost = getTopmostWindow();
- if ((topmost != null) && (topmost.vaadinModality)) {
+ if (topmost != null && topmost.vaadinModality) {
topmost.focus();
}
+ fireOrderEvent();
}
@Override
}
super.hide();
- int curIndex = windowOrder.indexOf(this);
+ int curIndex = getWindowOrder();
// Remove window from windowOrder to avoid references being left
// hanging.
windowOrder.remove(curIndex);
// Update the z-indices of any remaining windows
+ List<VWindow> update = new ArrayList<VWindow>(
+ windowOrder.size() - curIndex + 1);
+ update.add(this);
while (curIndex < windowOrder.size()) {
- windowOrder.get(curIndex).setWindowOrder(curIndex++);
+ VWindow window = windowOrder.get(curIndex);
+ window.setWindowOrder(curIndex++);
+ update.add(window);
}
focusTopmostModalWindow();
+ fireOrderEvent(update);
}
private void fixIE8FocusCaptureIssue() {
}
private void showModalityCurtain() {
- getModalityCurtain().getStyle()
- .setZIndex(windowOrder.indexOf(this) + Z_INDEX);
+ getModalityCurtain().getStyle().setZIndex(getWindowOrder() + Z_INDEX);
if (isShowing()) {
getOverlayContainer().insertBefore(getModalityCurtain(),
// Override PopupPanel which sets the width to the contents
getElement().getStyle().setProperty("width", width);
// Update v-has-width in case undefined window is resized
- setStyleName("v-has-width", width != null && width.length() > 0);
+ setStyleName("v-has-width", width != null && !width.isEmpty());
}
@Override
// Override PopupPanel which sets the height to the contents
getElement().getStyle().setProperty("height", height);
// Update v-has-height in case undefined window is resized
- setStyleName("v-has-height", height != null && height.length() > 0);
+ setStyleName("v-has-height", height != null && !height.isEmpty());
}
private void onDragEvent(Event event) {
return addHandler(handler, WindowMoveEvent.getType());
}
+ /**
+ * Adds a Handler for window order change event.
+ *
+ * @since 7.7.12
+ *
+ * @return registration object to deregister the handler
+ */
+ public static HandlerRegistration addWindowOrderHandler(
+ WindowOrderHandler handler) {
+ return WINDOW_ORDER_HANDLER.addHandler(WindowOrderEvent.getType(),
+ handler);
+ }
+
/**
* Checks if a modal window is currently open.
- *
+ *
* @return <code>true</code> if a modal window is open, <code>false</code>
* otherwise.
*/
return Document.get().getBody()
.hasClassName(MODAL_WINDOW_OPEN_CLASSNAME);
}
-
}
--- /dev/null
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.client.ui.window;
+
+import java.util.ArrayList;
+
+import com.google.gwt.event.shared.GwtEvent;
+import com.vaadin.client.ui.VWindow;
+
+/**
+ * Event for window order position updates.
+ *
+ * @since 7.7.12
+ *
+ * @author Vaadin Ltd
+ */
+public class WindowOrderEvent extends GwtEvent<WindowOrderHandler> {
+
+ private static final Type<WindowOrderHandler> TYPE = new Type<WindowOrderHandler>();
+
+ private final ArrayList<VWindow> windows;
+
+ /**
+ * Creates a new event with the given order.
+ *
+ * @param windows
+ * The new order position for the VWindow
+ */
+ public WindowOrderEvent(ArrayList<VWindow> windows) {
+ this.windows = windows;
+ }
+
+ @Override
+ public Type<WindowOrderHandler> getAssociatedType() {
+ return TYPE;
+ }
+
+ /**
+ * Returns windows in order.
+ *
+ * @return windows in the specific order
+ */
+ public VWindow[] getWindows() {
+ return windows.toArray(new VWindow[windows.size()]);
+ }
+
+ @Override
+ protected void dispatch(WindowOrderHandler handler) {
+ handler.onWindowOrderChange(this);
+ }
+
+ /**
+ * Gets the type of the event.
+ *
+ * @return the type of the event
+ */
+ public static Type<WindowOrderHandler> getType() {
+ return TYPE;
+ }
+
+}