001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.gwt.client.ui;
029
030import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle;
031import org.opencms.gwt.client.util.CmsFadeAnimation;
032
033import com.google.gwt.animation.client.Animation;
034import com.google.gwt.core.client.GWT;
035import com.google.gwt.dom.client.Element;
036import com.google.gwt.dom.client.Style.Visibility;
037import com.google.gwt.uibinder.client.UiBinder;
038import com.google.gwt.uibinder.client.UiField;
039import com.google.gwt.user.client.Command;
040import com.google.gwt.user.client.ui.Composite;
041import com.google.gwt.user.client.ui.FlowPanel;
042import com.google.gwt.user.client.ui.Widget;
043
044/**
045 * The toolbar notification widget.<p>
046 *
047 * @since 8.0.0
048 */
049public class CmsNotificationWidget extends Composite implements I_CmsNotificationWidget {
050
051    /**
052     * @see com.google.gwt.uibinder.client.UiBinder
053     */
054    protected interface I_CmsNotificationWidgetUiBinder extends UiBinder<Widget, CmsNotificationWidget> {
055        // GWT interface, nothing to do here
056    }
057
058    /** The ui-binder instance for this class. */
059    private static I_CmsNotificationWidgetUiBinder uiBinder = GWT.create(I_CmsNotificationWidgetUiBinder.class);
060
061    /** The message. */
062    @UiField
063    FlowPanel m_messages;
064
065    /** The current animation. */
066    private Animation m_animation;
067
068    /**
069     * Constructor.<p>
070     */
071    public CmsNotificationWidget() {
072
073        initWidget(uiBinder.createAndBindUi(this));
074        restore();
075        CmsNotification.get().setWidget(this);
076    }
077
078    /**
079     * @see org.opencms.gwt.client.ui.I_CmsNotificationWidget#addMessage(org.opencms.gwt.client.ui.CmsNotificationMessage)
080     */
081    public void addMessage(CmsNotificationMessage message) {
082
083        clearAnimation();
084        if (m_messages.getWidgetCount() == 0) {
085            animateShow();
086        }
087        m_messages.add(message);
088        if (message.isBlockingMode()) {
089            setBlocking(true);
090        }
091        if (message.isBusyMode()) {
092            setBusy(true);
093        }
094    }
095
096    /**
097     * @see org.opencms.gwt.client.ui.I_CmsNotificationWidget#clearMessages()
098     */
099    public void clearMessages() {
100
101        animateHide();
102    }
103
104    /**
105     * @see org.opencms.gwt.client.ui.I_CmsNotificationWidget#removeMessage(org.opencms.gwt.client.ui.CmsNotificationMessage)
106     */
107    public void removeMessage(CmsNotificationMessage message) {
108
109        clearAnimation();
110        if ((m_messages.getWidgetCount() == 1) && (m_messages.getWidgetIndex(message) != -1)) {
111            animateHide();
112        } else {
113            m_messages.remove(message);
114            setBlocking(requiresBlocking());
115            setBusy(requiresBusy());
116        }
117    }
118
119    /**
120     * Clears the messages once the hide animation is completed.<p>
121     */
122    protected void onHideComplete() {
123
124        m_animation = null;
125        m_messages.clear();
126        setBlocking(false);
127        setBusy(false);
128        restore();
129    }
130
131    /**
132     * Called once the show animation is completed.<p>
133     */
134    protected void onShowComplete() {
135
136        m_animation = null;
137    }
138
139    /**
140     * Animates hiding the messages.<p>
141     */
142    private void animateHide() {
143
144        m_animation = CmsFadeAnimation.fadeOut(getElement(), new Command() {
145
146            /**
147             * @see com.google.gwt.user.client.Command#execute()
148             */
149            public void execute() {
150
151                onHideComplete();
152            }
153        }, 200);
154    }
155
156    /**
157     * Animates showing the messages.<p>
158     */
159    private void animateShow() {
160
161        // ensure to display the notification above everything else
162        Element parent = getElement().getParentElement();
163        if (parent != null) {
164            parent.getStyle().setZIndex(I_CmsLayoutBundle.INSTANCE.constants().css().zIndexDND());
165        }
166        getElement().getStyle().clearVisibility();
167        m_animation = CmsFadeAnimation.fadeIn(getElement(), new Command() {
168
169            /**
170             * @see com.google.gwt.user.client.Command#execute()
171             */
172            public void execute() {
173
174                onShowComplete();
175            }
176        }, 200);
177    }
178
179    /**
180     * Cancels the current animation.<p>
181     */
182    private void clearAnimation() {
183
184        if (m_animation != null) {
185            m_animation.cancel();
186            m_animation = null;
187        }
188    }
189
190    /**
191     * Checks if any message requires a blocking overlay.<p>
192     *
193     * @return <code>true</code> if the blocking overlay is required
194     */
195    private boolean requiresBlocking() {
196
197        for (Widget message : m_messages) {
198            if (((CmsNotificationMessage)message).isBlockingMode()) {
199                return true;
200            }
201        }
202        return false;
203    }
204
205    /**
206     * Checks if any message requires the busy icon.<p>
207     *
208     * @return <code>true</code> if the busy icon is required
209     */
210    private boolean requiresBusy() {
211
212        for (Widget message : m_messages) {
213            if (((CmsNotificationMessage)message).isBusyMode()) {
214                return true;
215            }
216        }
217        return false;
218    }
219
220    /**
221     * Restores the initial state.<p>
222     */
223    private void restore() {
224
225        Element parent = getElement().getParentElement();
226        if (parent != null) {
227            parent.getStyle().clearZIndex();
228        }
229        getElement().getStyle().setVisibility(Visibility.HIDDEN);
230    }
231
232    /**
233     * Toggles the blocking overlay.<p>
234     *
235     * @param blocking <code>true</code> to show the blocking overlay
236     */
237    private void setBlocking(boolean blocking) {
238
239        if (blocking) {
240            getElement().addClassName(I_CmsLayoutBundle.INSTANCE.notificationCss().blocking());
241        } else {
242            getElement().removeClassName(I_CmsLayoutBundle.INSTANCE.notificationCss().blocking());
243        }
244    }
245
246    /**
247     * Toggles the busy icon.<p>
248     *
249     * @param busy <code>true</code> to show the busy icon
250     */
251    private void setBusy(boolean busy) {
252
253        if (busy) {
254            getElement().addClassName(I_CmsLayoutBundle.INSTANCE.notificationCss().busy());
255        } else {
256            getElement().removeClassName(I_CmsLayoutBundle.INSTANCE.notificationCss().busy());
257        }
258    }
259}