/* * Copyright 2012 The Solmix Project * * This 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 software 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. * * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.gnu.org/licenses/ * or see the FSF site: http://www.fsf.org. */ package org.solmix.sgt.client.pagebar; import com.google.gwt.user.client.Timer; import com.smartgwt.client.types.Alignment; import com.smartgwt.client.types.VerticalAlignment; import com.smartgwt.client.util.Page; import com.smartgwt.client.widgets.Canvas; import com.smartgwt.client.widgets.Label; import com.smartgwt.client.widgets.events.DrawEvent; import com.smartgwt.client.widgets.events.DrawHandler; import com.smartgwt.client.widgets.events.ResizedEvent; import com.smartgwt.client.widgets.events.ResizedHandler; import com.smartgwt.client.widgets.layout.HLayout; import com.smartgwt.client.widgets.layout.VLayout; /** * Class that supports masking an entire {@link Canvas} and adds the possibility to display a message during masking and * a loading image * * @author Mihai Ile (mihai007) * */ public class ModalWindow { /** * The canvas to be masked */ private final Canvas canvas; /** * Parent for modal layer */ private HLayout parent; /** * The modal layer */ private VLayout modal; /** * The reference to the transparent layer inside the modal HStack */ private Canvas transparent; /** * The exact time when show was called on this modal */ private long showStartedTime; /** * The loading icon, by default "{@link Page#getSkinImgDir()}/loading.gif" */ private String loadingIcon = null; /** * The color, by default white */ private String messageBoxBgColor = "#fff"; /** * Holds the default opacity for the background masking color */ private int opacity = 30; /** * Holds the default color for the masking */ private String maskingColor = "#555"; /** * Creates a new {@link ModalWindow} given the canvas to be masked (an {@link Canvas#addChild(Canvas)} will be * called to add the masking layer above the given canvas) * * @param canvas the canvas to be masked */ public ModalWindow(Canvas canvas) { this.canvas = canvas; createModalPanel(); } /** * Creates a new {@link ModalWindow} given the canvas to be masked (an {@link Canvas#addChild(Canvas)} will be * called to add the masking layer above the given canvas) * * @param canvas the canvas to be masked * @param opacity the opacity used for modal * @param maskingColor the color used for modal */ public ModalWindow(Canvas canvas, int opacity, String maskingColor) { this.canvas = canvas; this.opacity = opacity; this.maskingColor = maskingColor; createModalPanel(); } /** * Mask the {@link Canvas} with a transparent color * * @param showLoading whether to show a box with a loading indicator above the background */ public void show(boolean showLoading) { showStartedTime = System.currentTimeMillis(); insertModalIntoCanvas(); clearLabel(); if (showLoading) { modal.addMember(createLabel("", showLoading)); } parent.show(); } /** * Mask the {@link Canvas} with a transparent color and display a message above it * * @param message the message to display above the background * @param showLoading whether to show a box with a loading indicator above the background */ public void show(String message, boolean showLoading) { showStartedTime = System.currentTimeMillis(); insertModalIntoCanvas(); clearLabel(); if (showLoading || !message.equals("")) { modal.addMember(createLabel(message, showLoading)); } parent.show(); } /** * Hide the masking layer from the {@link Canvas} */ public void hide() { long showEndTime = System.currentTimeMillis(); // don't hide if is showed for less than 1s, avoid flickering int delay = 1000; if (showEndTime - showStartedTime < delay) { new Timer() { public void run() { _hide(); } }.schedule((int) (delay - (showEndTime - showStartedTime))); } else { _hide(); } } private void _hide() { parent.hide(); } private void insertModalIntoCanvas() { if (!canvas.contains(parent)) { canvas.addChild(parent); canvas.addResizedHandler(new ResizedHandler() { public void onResized(ResizedEvent event) { parent.setWidth(canvas.getWidth()); parent.setHeight(canvas.getHeight()); } }); } } private void clearLabel() { Canvas[] children = modal.getChildren(); for (Canvas canvas : children) { if (canvas instanceof Label) { Label label = (Label) canvas; modal.removeChild(label); label.destroy(); } } } private void createModalPanel() { parent = new HLayout(); parent.setDefaultLayoutAlign(VerticalAlignment.CENTER); parent.hide(); // we need a handler to ensure we always cover the entire canvas parent.addDrawHandler(new DrawHandler() { public void onDraw(DrawEvent event) { parent.setWidth(canvas.getVisibleWidth()); parent.setHeight(canvas.getVisibleHeight()); } }); transparent = new Canvas(); transparent.setWidth100(); transparent.setHeight100(); transparent.setBackgroundColor(maskingColor); transparent.setOpacity(opacity); parent.addChild(transparent); modal = new VLayout(); modal.setDefaultLayoutAlign(Alignment.CENTER); modal.setHeight(25); // this is for label height modal.setZIndex(transparent.getZIndex() + 2); parent.addMember(modal); insertModalIntoCanvas(); } private Label createLabel(String message, boolean showLoading) { final Label label = new Label(); label.setWrap(false); label.setPadding(5); label.setWidth(1); label.setHeight(1); label.setContents(message); label.setBackgroundColor(messageBoxBgColor); label.setBorder("1px solid #999"); label.setShowShadow(true); label.setShadowSoftness(0); label.setShadowOffset(10); label.addDrawHandler(new DrawHandler() { public void onDraw(DrawEvent event) { int visibleWidth = label.getVisibleWidth(); label.setWidth(visibleWidth); label.setMargin(10); } }); label.setAlign(Alignment.CENTER); if (showLoading) { if (loadingIcon != null) { // icon provided by user label.setIcon(loadingIcon); } else { // show default icon from used skin String icon = Page.getSkinImgDir() + "loading.gif"; label.setIcon(icon); } if (message.equals("")) { // no spacing, just show the loading icon // centered label.setIconSpacing(0); } } label.setZIndex(modal.getZIndex() + 2); return label; } /** * Destroy the {@link ModalWindow} freeing up resources */ public void destroy() { parent.destroy(); } /** * Optional icon to be used instead of the default one. * <P> * Specify as the partial URL to an image, relative to the imgDir (by default "public/images/") of this component * * @param loadingIcon icon URL of new image icon. Default value is <blockquote> " {@link Page#getSkinImgDir()} * /loading.gif " */ public void setLoadingIcon(String loadingIcon) { this.loadingIcon = loadingIcon; } /** * The background color for the message/loading box. You can set this property to an RGB value (e.g. #22AAFF) or a * named color (e.g. red) from a list of browser supported color names. * * @param backgroundColor new background color to set to the message/loading box. Default value is "#fff" */ public void setBackgroundColor(String backgroundColor) { this.messageBoxBgColor = backgroundColor; } }