org.opencms.gwt.client.ui.CmsPopup Maven / Gradle / Ivy
Show all versions of opencms-gwt Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH (http://www.alkacon.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* For further information about Alkacon Software, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.gwt.client.ui;
import org.opencms.gwt.client.Messages;
import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle;
import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle;
import org.opencms.gwt.client.util.CmsFadeAnimation;
import org.opencms.util.CmsStringUtil;
import java.util.Iterator;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.EventTarget;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.WidgetCollection;
/**
* Provides a pop up dialog base.
*
* @since 8.0.0
*/
public class CmsPopup extends PopupPanel implements I_CmsAutoHider {
/**
* The dialog button panel.
*/
private class ButtonPanel extends FlowPanel {
/**
* Default constructor.
*/
protected ButtonPanel() {
// nothing to do
}
/**
* Making function visible.
*
* @see com.google.gwt.user.client.ui.Widget#onAttach()
*/
@Override
protected void onAttach() {
super.onAttach();
}
/**
* Making function visible.
*
* @see com.google.gwt.user.client.ui.Widget#onDetach()
*/
@Override
protected void onDetach() {
super.onDetach();
}
}
/**
* The dialog caption.
*/
private class Caption extends HTML {
/**
* Default constructor.
*/
protected Caption() {
// nothing to do
}
/**
* Making function visible.
*
* @see com.google.gwt.user.client.ui.Widget#onAttach()
*/
@Override
protected void onAttach() {
super.onAttach();
}
/**
* Making function visible.
*
* @see com.google.gwt.user.client.ui.Widget#onDetach()
*/
@Override
protected void onDetach() {
super.onDetach();
}
}
/**
* The dialog close button.
*/
private class CloseButton extends CmsPushButton {
/**
* Default constructor.
*/
protected CloseButton() {
// nothing to do
}
/**
* Making function visible.
*
* @see com.google.gwt.user.client.ui.Widget#onAttach()
*/
@Override
protected void onAttach() {
super.onAttach();
}
/**
* Making function visible.
*
* @see com.google.gwt.user.client.ui.Widget#onDetach()
*/
@Override
protected void onDetach() {
super.onDetach();
}
}
/**
* The dialog mouse handler.
*/
private class MouseHandler implements MouseDownHandler, MouseUpHandler, MouseMoveHandler {
/**
* Default constructor.
*/
protected MouseHandler() {
// nothing to do
}
/**
* @see com.google.gwt.event.dom.client.MouseDownHandler#onMouseDown(com.google.gwt.event.dom.client.MouseDownEvent)
*/
public void onMouseDown(MouseDownEvent event) {
beginDragging(event);
}
/**
* @see com.google.gwt.event.dom.client.MouseMoveHandler#onMouseMove(com.google.gwt.event.dom.client.MouseMoveEvent)
*/
public void onMouseMove(MouseMoveEvent event) {
continueDragging(event);
}
/**
* @see com.google.gwt.event.dom.client.MouseUpHandler#onMouseUp(com.google.gwt.event.dom.client.MouseUpEvent)
*/
public void onMouseUp(MouseUpEvent event) {
endDragging(event);
}
}
/** The default width of this dialog. */
private static final int DEFAULT_WIDTH = 300;
/** The close command. */
protected Command m_closeCommand;
/** Flag which indicates whether the notification widget has already been installed. */
protected boolean m_notificationWidgetInstalled;
/** The window width. */
protected int m_windowWidth;
/** The panel holding the dialog's buttons. */
private ButtonPanel m_buttonPanel;
/** The dialog caption. */
private Caption m_caption;
/** Flag indicating if the dialog should catch all notifications while visible. */
private boolean m_catchNotifications;
/** The child widgets. */
private WidgetCollection m_children;
/** Body offset left. */
private int m_clientLeft;
/** Body offset top. */
private int m_clientTop;
/** The panel for the close button. */
private CloseButton m_close;
/** The dialog closing handler registration used for organizing notifications. */
private HandlerRegistration m_closingHandlerRegistration;
/** The popup container element. */
private Element m_containerElement;
/** The content height correction, used when explicitly setting the dialog height. */
private int m_contentHeightCorrection = 6;
/** Flag if dragging. */
private boolean m_dragging;
/** Drag starting x position. */
private int m_dragStartX;
/** Drag starting y position. */
private int m_dragStartY;
/** The main widget of this dialog containing all others. */
private Element m_main;
/** The own notification widget. */
private A_CmsNotificationWidget m_ownNotificationWidget;
/** The parent notification widget. */
private I_CmsNotificationWidget m_parentNotificationWidget;
/** The resize handler registration .*/
private HandlerRegistration m_resizeHandlerRegistration;
/** Signals whether a animation should be used to show the popup or not. */
private boolean m_useAnimation = true;
/** The content width, -1 indicating the value was not set. */
private int m_width = -1;
/**
* Constructor.
*/
public CmsPopup() {
this(DEFAULT_WIDTH);
}
/**
* Constructor setting the width of the dialog.
*
* @param width the width to set
*/
public CmsPopup(int width) {
super(false, true);
// super(autoHide, modal);
m_containerElement = super.getContainerElement();
setStyleName(I_CmsLayoutBundle.INSTANCE.dialogCss().popup());
m_containerElement.setClassName(I_CmsLayoutBundle.INSTANCE.dialogCss().popupContent());
setGlassStyleName(I_CmsLayoutBundle.INSTANCE.dialogCss().popupOverlay());
Element dragOverlay = DOM.createDiv();
dragOverlay.setClassName(I_CmsLayoutBundle.INSTANCE.dialogCss().dragOverlay());
getElement().insertFirst(dragOverlay);
m_caption = new Caption();
m_caption.setStyleName(I_CmsLayoutBundle.INSTANCE.dialogCss().caption());
// Add the caption to the top of the popup-panel. We need to
// logically adopt the caption so we can catch mouse events.
DOM.appendChild(m_containerElement, m_caption.getElement());
adopt(m_caption);
m_children = new WidgetCollection(this);
m_main = DOM.createDiv();
m_main.addClassName(I_CmsLayoutBundle.INSTANCE.dialogCss().popupMainContent());
m_main.addClassName(I_CmsLayoutBundle.INSTANCE.dialogCss().contentPadding());
DOM.appendChild(m_containerElement, m_main);
m_buttonPanel = new ButtonPanel();
m_buttonPanel.setStyleName(I_CmsLayoutBundle.INSTANCE.dialogCss().hideButtonPanel());
// Add the caption to the top of the popup-panel. We need to
// logically adopt the caption so we can catch mouse events.
DOM.appendChild(m_containerElement, m_buttonPanel.getElement());
adopt(m_buttonPanel);
MouseHandler mouseHandler = new MouseHandler();
addDomHandler(mouseHandler, MouseDownEvent.getType());
addDomHandler(mouseHandler, MouseUpEvent.getType());
addDomHandler(mouseHandler, MouseMoveEvent.getType());
setWidth(width);
getElement().addClassName(I_CmsLayoutBundle.INSTANCE.dialogCss().hideCaption());
}
/**
* Constructor setting the dialog caption.
*
* @param caption the caption to set
*/
public CmsPopup(String caption) {
this();
setCaption(caption);
}
/**
* Constructor setting caption and width.
*
* @param caption the caption to set
* @param width the width to set
*/
public CmsPopup(String caption, int width) {
this(width);
setCaption(caption);
}
/**
* The constructor.
*
* @param title the title and heading of the dialog
* @param content the content widget
*/
public CmsPopup(String title, Widget content) {
this(title);
setMainContent(content);
}
/**
* Wraps the given Widget with a cornered border, padding and margin.
*
* @param w the widget to wrap
*
* @return a new widget that wraps the given one
*/
public static Widget wrapWithBorderPadding(Widget w) {
w.addStyleName(I_CmsLayoutBundle.INSTANCE.dialogCss().borderPadding());
w.addStyleName(I_CmsLayoutBundle.INSTANCE.generalCss().cornerAll());
SimplePanel panel = new SimplePanel();
panel.add(w);
return panel;
}
/**
* Adds the given child widget.
*
* @param w the widget
*/
@Override
public void add(Widget w) {
add(w, m_main);
}
/**
* Adds a button widget to the button panel.
*
* @param button the button widget
*/
public void addButton(Widget button) {
addButton(button, 0);
}
/**
* Adds a button widget to the button panel before the given position.
*
* @param button the button widget
* @param position the position to insert the button
*/
public void addButton(Widget button, int position) {
m_buttonPanel.insert(button, position);
m_buttonPanel.setStyleName(I_CmsLayoutBundle.INSTANCE.dialogCss().popupButtonPanel());
}
/**
* Adds a close "button" to the top of the popup.
*
* @param cmd the command that should be executed when the close button is clicked
*/
public void addDialogClose(final Command cmd) {
m_closeCommand = cmd;
if (m_close == null) {
m_close = new CloseButton();
m_close.setTitle(Messages.get().key(Messages.GUI_CLOSE_0));
m_close.addStyleName(I_CmsLayoutBundle.INSTANCE.dialogCss().closePopup());
m_close.setImageClass(I_CmsLayoutBundle.INSTANCE.dialogCss().closePopupImage());
m_close.setButtonStyle(ButtonStyle.TRANSPARENT, null);
m_close.addClickHandler(new ClickHandler() {
/**
* @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent)
*/
public void onClick(ClickEvent event) {
boolean cancelled = false;
try {
if (m_closeCommand != null) {
m_closeCommand.execute();
}
} catch (CmsCancelCloseException e) {
cancelled = true;
} finally {
if (!cancelled) {
hide();
}
}
}
});
DOM.appendChild(m_containerElement, m_close.getElement());
adopt(m_close);
}
}
/**
* Replaces current notification widget by an overlay.
*/
public void catchNotifications() {
m_catchNotifications = true;
if (isShowing()) {
installNotificationWidget();
}
if (m_closingHandlerRegistration == null) {
// when closing the dialog
m_closingHandlerRegistration = addCloseHandler(new CloseHandler() {
/**
* @see CloseHandler#onClose(CloseEvent)
*/
public void onClose(CloseEvent event) {
clearNotifications();
}
});
}
}
/**
* @see com.google.gwt.user.client.ui.PopupPanel#center()
*/
@Override
public void center() {
show();
if (Position.FIXED.getCssName().equals(getElement().getStyle().getPosition())) {
// keep position fixed, as may have been set to absolute
setPositionFixed();
int left = (Window.getClientWidth() - getOffsetWidth()) >> 1;
int top = (Window.getClientHeight() - getOffsetHeight()) >> 1;
setPopupPosition(Math.max(left, 0), Math.max(top, 0));
} else {
super.center();
}
}
/**
* Shows the dialog and centers it horizontally, but positions it at a fixed vertical position.
*
* @param top the top position
*/
public void centerHorizontally(int top) {
if (Position.FIXED.getCssName().equals(getElement().getStyle().getPosition())) {
show();
// keep position fixed, as may have been set to absolute
setPositionFixed();
int left = (Window.getClientWidth() - getOffsetWidth()) >> 1;
setPopupPosition(Math.max(left, 0), Math.max(top, 0));
} else {
show();
int left = (Window.getClientWidth() - getOffsetWidth()) >> 1;
setPopupPosition(Math.max(Window.getScrollLeft() + left, 0), Math.max(Window.getScrollTop() + top, 0));
}
}
/**
* @see com.google.gwt.user.client.ui.Panel#clear()
*/
@Override
public void clear() {
for (Widget w : this) {
// Orphan.
try {
orphan(w);
} finally {
// Physical detach.
Element elem = w.getElement();
elem.removeFromParent();
}
}
m_children = new WidgetCollection(this);
}
/**
* Returns the maximum available height inside the popup.
*
* @param fixedContentHeight fixed content height to deduct from the available height
*
* @return the maximum available height
*/
public int getAvailableHeight(int fixedContentHeight) {
if (m_buttonPanel.isVisible()) {
fixedContentHeight += m_buttonPanel.getOffsetHeight();
}
return Window.getClientHeight() - 150 - fixedContentHeight;
}
/**
* Returns the dialog caption text.
*
* @return the dialog caption
*/
public String getCaption() {
return m_caption.getText();
}
/**
* Returns the child widget with the given index.
*
* @param index the index
*
* @return the child widget
*/
public Widget getWidget(int index) {
return getChildren().get(index);
}
/**
* Returns the number of child widgets.
*
* @return the number of child widgets
*/
public int getWidgetCount() {
return getChildren().size();
}
/**
* Returns the index of the given widget.
*
* @param child the child widget
*
* @return the index of the child widget
*/
public int getWidgetIndex(IsWidget child) {
return getWidgetIndex(asWidgetOrNull(child));
}
/**
* Returns the index of the given child widget.
*
* @param child the child widget
*
* @return the index
*/
public int getWidgetIndex(Widget child) {
return getChildren().indexOf(child);
}
/**
* Returns the dialog content width, -1 if not set.
*
* @return the dialog content width
*/
public int getWidth() {
return m_width;
}
/**
* Returns true
if a caption is set for this popup false
otherwise.
*
* @return true
if a caption is set for this popup false
otherwise
*/
public boolean hasCaption() {
return CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_caption.getText());
}
/**
* @see com.google.gwt.user.client.ui.PopupPanel#hide()
*/
@Override
public void hide() {
if (m_resizeHandlerRegistration != null) {
m_resizeHandlerRegistration.removeHandler();
m_resizeHandlerRegistration = null;
}
super.hide();
}
/**
* Inserts a child widget before the given index.
*
* @param w the child widget
* @param beforeIndex the index
*
* @throws IndexOutOfBoundsException if the index is out of bounds
*/
public void insert(Widget w, int beforeIndex) throws IndexOutOfBoundsException {
insert(w, m_main, beforeIndex, true);
}
/**
* Inserts a widget as the first widget in the popup.
*
* @param widget the widget to insert
*/
public void insertFront(Widget widget) {
insert(widget, 0);
}
/**
* @see com.google.gwt.user.client.ui.SimplePanel#iterator()
*/
@Override
public Iterator iterator() {
return getChildren().iterator();
}
/**
* @see com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt.user.client.Event)
*/
@Override
public void onBrowserEvent(Event event) {
// If we're not yet dragging, only trigger mouse events if the event occurs
// in the caption wrapper
switch (event.getTypeInt()) {
case Event.ONMOUSEDOWN:
case Event.ONMOUSEUP:
case Event.ONMOUSEMOVE:
case Event.ONMOUSEOVER:
case Event.ONMOUSEOUT:
if (!m_dragging && !isCaptionEvent(event)) {
return;
}
break;
default:
}
super.onBrowserEvent(event);
}
/**
* Removes a child widget.
*
* @param index the index of the widget to remove
*
* @return true
if the there was a widget at the given index to remove
*/
public boolean remove(int index) {
Widget w = getWidget(index);
if (w != null) {
return remove(getWidget(index));
}
return false;
}
/**
* @see com.google.gwt.user.client.ui.SimplePanel#remove(com.google.gwt.user.client.ui.Widget)
*/
@Override
public boolean remove(Widget w) {
// Validate.
if (w.getParent() != this) {
return false;
}
// Orphan.
try {
orphan(w);
} finally {
// Physical detach.
Element elem = w.getElement();
elem.removeFromParent();
// Logical detach.
getChildren().remove(w);
}
return true;
}
/**
* Removes all buttons.
*/
public void removeAllButtons() {
m_buttonPanel.clear();
}
/**
* Removes the given button widget from the button panel.
*
* @param button the button widget to remove
*/
public void removeButton(Widget button) {
m_buttonPanel.remove(button);
if (m_buttonPanel.getWidgetCount() == 0) {
m_buttonPanel.setStyleName(I_CmsLayoutBundle.INSTANCE.dialogCss().hideButtonPanel());
}
}
/**
* Removes the padding from the popup's content.
*/
public void removePadding() {
m_main.removeClassName(I_CmsLayoutBundle.INSTANCE.dialogCss().contentPadding());
m_contentHeightCorrection = -6;
}
/**
* Sets the popup's content background.
*
* @param color the color to set
*/
public void setBackgroundColor(String color) {
m_main.getStyle().setBackgroundColor(color);
}
/**
* Sets the captions text.
*
* @param caption the text to set
*/
public void setCaption(String caption) {
if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(caption)) {
getElement().removeClassName(I_CmsLayoutBundle.INSTANCE.dialogCss().hideCaption());
m_caption.setText(caption);
} else {
getElement().addClassName(I_CmsLayoutBundle.INSTANCE.dialogCss().hideCaption());
}
}
/**
* Sets the height for the popup content.
*
* @param height the height in pixels
*/
public void setHeight(int height) {
if (height <= 0) {
m_containerElement.getStyle().clearWidth();
m_main.getStyle().clearHeight();
} else {
int contentHeight = height - 6;
if (hasCaption()) {
contentHeight = contentHeight - 36;
}
if (hasButtons()) {
contentHeight = contentHeight - 34;
}
contentHeight = contentHeight - m_contentHeightCorrection;
m_main.getStyle().setHeight(contentHeight, Unit.PX);
}
}
/**
* @see com.google.gwt.user.client.ui.PopupPanel#setHeight(java.lang.String)
*/
@Override
@Deprecated
public void setHeight(String height) {
throw new UnsupportedOperationException();
}
/**
* Replaces the content from the main widget.
*
* @param w the widget that should replace the main content
*/
public void setMainContent(Widget w) {
clear();
add(w);
}
/**
* @see com.google.gwt.user.client.ui.UIObject#setSize(java.lang.String, java.lang.String)
*/
@Override
@Deprecated
public void setPixelSize(int width, int height) {
throw new UnsupportedOperationException();
}
/**
* Sets the popup's dialog position to 'fixed'.
*/
public void setPositionFixed() {
getElement().getStyle().setPosition(Position.FIXED);
}
/**
* @see com.google.gwt.user.client.ui.UIObject#setSize(java.lang.String, java.lang.String)
*/
@Override
@Deprecated
public void setSize(String width, String height) {
throw new UnsupportedOperationException();
}
/**
* Sets an additional CSS class to the main content element.
*
* @param cssClassName the CSS class to set
*/
public void setSpecialBackgroundClass(String cssClassName) {
m_main.addClassName(cssClassName);
}
/**
* Sets the use animation flag.
*
* @param use true
if the animation should be used, default is true
*/
public void setUseAnimation(boolean use) {
m_useAnimation = use;
}
/**
* Unsupported operation.
*
* @see com.google.gwt.user.client.ui.PopupPanel#setWidget(com.google.gwt.user.client.ui.Widget)
*/
@Override
@Deprecated
public void setWidget(Widget w) {
throw new UnsupportedOperationException();
}
/**
* Sets the width for the popup content.
*
* @param width the width in pixels
*/
public void setWidth(int width) {
if (width <= 0) {
m_containerElement.getStyle().clearWidth();
m_width = -1;
} else {
m_containerElement.getStyle().setWidth(width, Unit.PX);
m_width = width;
}
}
/**
* @see com.google.gwt.user.client.ui.PopupPanel#setWidth(java.lang.String)
*/
@Override
@Deprecated
public void setWidth(String width) {
throw new UnsupportedOperationException();
}
/**
* @see com.google.gwt.user.client.ui.PopupPanel#show()
*/
@Override
public void show() {
boolean fixed = Position.FIXED.getCssName().equals(getElement().getStyle().getPosition());
boolean wasAlreadyShowing = isShowing();
super.show();
if (fixed) {
// keep position fixed as it may have been set to absolute
setPositionFixed();
}
if (m_useAnimation && !wasAlreadyShowing) {
CmsFadeAnimation.fadeIn(getElement(), null, 250);
}
if (m_resizeHandlerRegistration == null) {
m_resizeHandlerRegistration = Window.addResizeHandler(new ResizeHandler() {
public void onResize(ResizeEvent event) {
m_windowWidth = event.getWidth();
}
});
}
if (m_catchNotifications) {
catchNotifications();
}
}
/**
* Adds a new child widget to the panel, attaching its Element to the
* specified container Element.
*
* @param child the child widget to be added
* @param container the element within which the child will be contained
*/
protected void add(Widget child, Element container) {
// Detach new child.
child.removeFromParent();
// Logical attach.
getChildren().add(child);
// Physical attach.
DOM.appendChild(container, child.getElement());
// Adopt.
adopt(child);
}
/**
* Adjusts beforeIndex to account for the possibility that the given widget is
* already a child of this panel.
*
* @param child the widget that might be an existing child
* @param beforeIndex the index at which it will be added to this panel
* @return the modified index
*/
protected int adjustIndex(Widget child, int beforeIndex) {
checkIndexBoundsForInsertion(beforeIndex);
// Check to see if this widget is already a direct child.
if (child.getParent() == this) {
// If the Widget's previous position was left of the desired new position
// shift the desired position left to reflect the removal
int idx = getWidgetIndex(child);
if (idx < beforeIndex) {
beforeIndex--;
}
}
return beforeIndex;
}
/**
* Called on mouse down in the caption area, begins the dragging loop by
* turning on event capture.
*
* @see DOM#setCapture
* @see #continueDragging
* @param event the mouse down event that triggered dragging
*/
protected void beginDragging(MouseDownEvent event) {
m_dragging = true;
m_windowWidth = Window.getClientWidth();
m_clientLeft = Document.get().getBodyOffsetLeft();
m_clientTop = Document.get().getBodyOffsetTop();
DOM.setCapture(getElement());
m_dragStartX = event.getX();
m_dragStartY = event.getY();
addStyleName(I_CmsLayoutBundle.INSTANCE.dialogCss().dragging());
}
/**
* Checks that index
is in the range [0, getWidgetCount()), which
* is the valid range on accessible indexes.
*
* @param index the index being accessed
*/
protected void checkIndexBoundsForAccess(int index) {
if ((index < 0) || (index >= getWidgetCount())) {
throw new IndexOutOfBoundsException();
}
}
/**
* Checks that index
is in the range [0, getWidgetCount()], which
* is the valid range for indexes on an insertion.
*
* @param index the index where insertion will occur
*/
protected void checkIndexBoundsForInsertion(int index) {
if ((index < 0) || (index > getWidgetCount())) {
throw new IndexOutOfBoundsException();
}
}
/**
* Called on mouse move in the caption area, continues dragging if it was
* started by {@link #beginDragging}.
*
* @see #beginDragging
* @see #endDragging
* @param event the mouse move event that continues dragging
*/
protected void continueDragging(MouseMoveEvent event) {
if (m_dragging) {
int absX = event.getX() + getAbsoluteLeft();
int absY = event.getY() + getAbsoluteTop();
// if the mouse is off the screen to the left, right, or top, don't
// move the dialog box. This would let users lose dialog boxes, which
// would be bad for modal popups.
if ((absX < m_clientLeft) || (absX >= m_windowWidth) || (absY < m_clientTop)) {
return;
}
setPopupPosition(absX - m_dragStartX, absY - m_dragStartY);
}
}
/**
* Creates a new notification widget for this dialog.
*
* @return the notification widget for this dialog
*/
protected A_CmsNotificationWidget createDialogNotificationWidget() {
return new CmsDialogNotificationWidget();
}
/**
* @see com.google.gwt.user.client.ui.Panel#doAttachChildren()
*/
@Override
protected void doAttachChildren() {
try {
super.doAttachChildren();
} finally {
// See comment in doDetachChildren for an explanation of this call
m_caption.onAttach();
m_buttonPanel.onAttach();
if (m_close != null) {
m_close.onAttach();
}
}
}
/**
* @see com.google.gwt.user.client.ui.Panel#doDetachChildren()
*/
@Override
protected void doDetachChildren() {
try {
super.doDetachChildren();
} finally {
// We need to detach the caption specifically because it is not part of the
// iterator of Widgets that the {@link SimplePanel} super class returns.
// This is similar to a {@link ComplexPanel}, but we do not want to expose
// the caption widget, as its just an internal implementation.
m_caption.onDetach();
m_buttonPanel.onDetach();
if (m_close != null) {
m_close.onDetach();
}
}
}
/**
* Called on mouse up in the caption area, ends dragging by ending event
* capture.
*
* @param event the mouse up event that ended dragging
*
* @see DOM#releaseCapture
* @see #beginDragging
* @see #endDragging
*/
protected void endDragging(MouseUpEvent event) {
m_dragging = false;
DOM.releaseCapture(getElement());
removeStyleName(I_CmsLayoutBundle.INSTANCE.dialogCss().dragging());
}
/**
* Gets the list of children contained in this panel.
*
* @return a collection of child widgets
*/
protected WidgetCollection getChildren() {
return m_children;
}
/**
* @see com.google.gwt.user.client.ui.PopupPanel#getContainerElement()
*/
@SuppressWarnings("deprecation")
@Override
protected com.google.gwt.user.client.Element getContainerElement() {
if (m_containerElement == null) {
m_containerElement = super.getContainerElement();
}
return (com.google.gwt.user.client.Element)m_containerElement;
}
/**
* Insert a new child Widget into this Panel at a specified index, attaching
* its Element to the specified container Element. The child Element will
* either be attached to the container at the same index, or simply appended
* to the container, depending on the value of domInsert
.
*
* @param child the child Widget to be added
* @param container the Element within which child
will be
* contained
* @param beforeIndex the index before which child
will be
* inserted
* @param domInsert if true
, insert child
into
* container
at beforeIndex
; otherwise
* append child
to the end of container
.
*/
protected void insert(Widget child, Element container, int beforeIndex, boolean domInsert) {
// Validate index; adjust if the widget is already a child of this panel.
beforeIndex = adjustIndex(child, beforeIndex);
// Detach new child.
child.removeFromParent();
// Logical attach.
getChildren().insert(child, beforeIndex);
// Physical attach.
if (domInsert) {
DOM.insertChild(container, child.getElement(), beforeIndex);
} else {
DOM.appendChild(container, child.getElement());
}
// Adopt.
adopt(child);
}
/**
* Sets the notification widget.
*/
protected void installNotificationWidget() {
if (m_notificationWidgetInstalled) {
return;
}
// remember current notification widget
m_parentNotificationWidget = CmsNotification.get().getWidget();
// create our own notification overlay
if (m_ownNotificationWidget == null) {
m_ownNotificationWidget = createDialogNotificationWidget();
}
add(m_ownNotificationWidget);
CmsNotification.get().setWidget(m_ownNotificationWidget);
m_notificationWidgetInstalled = true;
}
/**
* Override to work around the glass overlay still showing after dialog hide.
*
* @see com.google.gwt.user.client.ui.Widget#onDetach()
*/
@Override
protected void onDetach() {
super.onDetach();
if (getGlassElement() != null) {
getGlassElement().removeFromParent();
}
}
/**
* @see com.google.gwt.user.client.ui.PopupPanel#onPreviewNativeEvent(com.google.gwt.user.client.Event.NativePreviewEvent)
*/
@Override
protected void onPreviewNativeEvent(NativePreviewEvent event) {
// We need to preventDefault() on mouseDown events (outside of the
// DialogBox content) to keep text from being selected when it
// is dragged.
NativeEvent nativeEvent = event.getNativeEvent();
if (!event.isCanceled() && (event.getTypeInt() == Event.ONMOUSEDOWN) && isCaptionEvent(nativeEvent)) {
nativeEvent.preventDefault();
}
super.onPreviewNativeEvent(event);
}
/**
* Appends the arrow element to the popup's dialog.
*
* @param arrow the arrow element to add
*/
protected void showArrow(Element arrow) {
getElement().appendChild(arrow);
}
/**
* Resets the notification to the parent notification widget and detaches the own notification widget.
*/
void clearNotifications() {
if (m_parentNotificationWidget != null) {
// restore the previous notification widget
CmsNotification.get().setWidget(m_parentNotificationWidget);
}
if (m_ownNotificationWidget != null) {
// remove the overlay notification widget
remove(m_ownNotificationWidget);
}
}
/**
* Returns true
if this popup has buttons false
otherwise.
*
* @return true
if this popup has buttons false
otherwise
*/
private boolean hasButtons() {
return m_buttonPanel.getWidgetCount() != 0;
}
/**
* Checks if the target of the given event is the caption or a child of the caption.
*
* @param event the event to check
*
* @return true
if the target of the given event is the caption false
otherwise
*/
private boolean isCaptionEvent(NativeEvent event) {
EventTarget target = event.getEventTarget();
if (com.google.gwt.dom.client.Element.is(target)) {
return m_caption.getElement().isOrHasChild(com.google.gwt.dom.client.Element.as(target));
}
return false;
}
}