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.ade.sitemap.client.hoverbar;
029
030import org.opencms.ade.sitemap.client.control.CmsSitemapController;
031import org.opencms.ade.sitemap.client.ui.css.I_CmsImageBundle;
032import org.opencms.ade.sitemap.shared.CmsClientSitemapEntry;
033import org.opencms.gwt.client.ui.A_CmsHoverHandler;
034import org.opencms.gwt.client.ui.CmsListItemWidget;
035import org.opencms.gwt.client.ui.CmsPushButton;
036import org.opencms.gwt.client.ui.tree.CmsTreeItem;
037import org.opencms.util.CmsUUID;
038
039import java.util.Collection;
040import java.util.Iterator;
041
042import com.google.gwt.event.dom.client.MouseOutEvent;
043import com.google.gwt.event.dom.client.MouseOverEvent;
044import com.google.gwt.event.shared.HandlerRegistration;
045import com.google.gwt.event.shared.SimpleEventBus;
046import com.google.gwt.user.client.rpc.AsyncCallback;
047import com.google.gwt.user.client.ui.FlowPanel;
048import com.google.gwt.user.client.ui.Widget;
049
050/**
051 * Sitemap tree item hover-bar.<p>
052 *
053 * @since 8.0.0
054 */
055public final class CmsSitemapHoverbar extends FlowPanel {
056
057    /** The sitemap controller. */
058    private CmsSitemapController m_controller;
059
060    /** Flag if hover bar buttons are enabled. */
061    private boolean m_enabled;
062
063    /** The sitemap entry id. */
064    private CmsUUID m_entryId;
065
066    /** The event bus. */
067    private SimpleEventBus m_eventBus;
068
069    /** Flag indicating if the hoverbar is currently hovered, the mouse cursor is over the bar. */
070    private boolean m_hovered;
071
072    /** Flag to indicate the the hoverbar visibility is locked. */
073    private boolean m_locked;
074
075    /** The entry site path, only used for gallery tree items. */
076    private String m_sitePath;
077
078    /** Flag which controls whether the hover bar should always be visible. */
079    private boolean m_alwaysVisible;
080
081    /**
082     * Constructor.<p>
083     *
084     * @param controller the controller
085     * @param entryId sitemap entry id
086     * @param moveable <code>true</code> if in galleries view
087     * @param contextmenu flag to control whether the context menu should be shown
088     * @param contextMenuProvider provides items for the context menu
089     */
090    private CmsSitemapHoverbar(
091        CmsSitemapController controller,
092        CmsUUID entryId,
093        boolean moveable,
094        boolean contextmenu,
095        I_CmsContextMenuItemProvider contextMenuProvider) {
096
097        m_controller = controller;
098        m_entryId = entryId;
099        m_eventBus = new SimpleEventBus();
100        m_enabled = true;
101        setStyleName(I_CmsImageBundle.INSTANCE.buttonCss().hoverbar());
102        if (contextmenu) {
103            add(new CmsHoverbarContextMenuButton(this, contextMenuProvider));
104        }
105        if (controller.isEditable() && moveable) {
106
107            add(new CmsHoverbarMoveButton(this));
108
109        }
110    }
111
112    /**
113     * Constructor to be used for gallery tree items.<p>
114     *
115     * @param controller the controller
116     * @param entryId sitemap entry id
117     * @param sitePath the entry site path
118     * @param contextmenu flag to control whether the context menu should be shown
119     */
120    private CmsSitemapHoverbar(CmsSitemapController controller, CmsUUID entryId, String sitePath, boolean contextmenu) {
121
122        this(controller, entryId, false, contextmenu, null);
123        m_sitePath = sitePath;
124    }
125
126    /**
127     * Constructor.<p>
128     *
129     * @param controller the controller
130     * @param buttons the buttons to add to the hover bar
131     */
132    private CmsSitemapHoverbar(CmsSitemapController controller, Collection<Widget> buttons) {
133
134        m_controller = controller;
135        m_eventBus = new SimpleEventBus();
136        m_enabled = true;
137        setStyleName(I_CmsImageBundle.INSTANCE.buttonCss().hoverbar());
138        for (Widget button : buttons) {
139            add(button);
140        }
141    }
142
143    /**
144     * Installs a hover bar for the given item widget.<p>
145     *
146     * @param controller the controller
147     * @param treeItem the item to hover
148     * @param entryId the entry id
149     */
150    public static void installOn(CmsSitemapController controller, CmsTreeItem treeItem, CmsUUID entryId) {
151
152        CmsSitemapHoverbar hoverbar = new CmsSitemapHoverbar(controller, entryId, true, true, null);
153        installHoverbar(hoverbar, treeItem.getListItemWidget());
154    }
155
156    /**
157     * Installs a hover bar for the given item widget.<p>
158     *
159     * @param controller the controller
160     * @param treeItem the item to hover
161     * @param entryId the entry id
162     * @param movable true if the item should be movable
163     * @param contextmenu true if the item should have a context menu
164     * @param menuItemProvider provides items for the context menu
165     *
166     * @return the installed hover bar
167     */
168    public static CmsSitemapHoverbar installOn(
169        CmsSitemapController controller,
170        CmsTreeItem treeItem,
171        CmsUUID entryId,
172        boolean movable,
173        boolean contextmenu,
174        I_CmsContextMenuItemProvider menuItemProvider) {
175
176        CmsSitemapHoverbar hoverbar = new CmsSitemapHoverbar(
177            controller,
178            entryId,
179            movable,
180            contextmenu,
181            menuItemProvider);
182        installHoverbar(hoverbar, treeItem.getListItemWidget());
183        return hoverbar;
184    }
185
186    /**
187     * Installs a hover bar for the given item widget.<p>
188     *
189     * @param controller the controller
190     * @param treeItem the item to hover
191     * @param entryId the entry id
192     * @param menuItemProvider the context menu item provider
193     */
194    public static void installOn(
195        CmsSitemapController controller,
196        CmsTreeItem treeItem,
197        CmsUUID entryId,
198        I_CmsContextMenuItemProvider menuItemProvider) {
199
200        CmsSitemapHoverbar hoverbar = new CmsSitemapHoverbar(controller, entryId, true, true, menuItemProvider);
201        installHoverbar(hoverbar, treeItem.getListItemWidget());
202    }
203
204    /**
205     * Installs a hover bar for the given item widget.<p>
206     *
207     * @param controller the controller
208     * @param treeItem the item to hover
209     * @param entryId the entry id
210     * @param sitePath the entry site path
211     * @param contextmenu flag to control whether the context menu should be shown
212     */
213    public static void installOn(
214        CmsSitemapController controller,
215        CmsTreeItem treeItem,
216        CmsUUID entryId,
217        String sitePath,
218        boolean contextmenu) {
219
220        CmsSitemapHoverbar hoverbar = new CmsSitemapHoverbar(controller, entryId, sitePath, contextmenu);
221        installHoverbar(hoverbar, treeItem.getListItemWidget());
222    }
223
224    /**
225     * Installs a hover bar for the given item widget.<p>
226     *
227     * @param controller the controller
228     * @param treeItem the item to hover
229     * @param buttons the buttons
230     *
231     * @return the hover bar instance
232     */
233    public static CmsSitemapHoverbar installOn(
234        CmsSitemapController controller,
235        CmsTreeItem treeItem,
236        Collection<Widget> buttons) {
237
238        CmsSitemapHoverbar hoverbar = new CmsSitemapHoverbar(controller, buttons);
239        installHoverbar(hoverbar, treeItem.getListItemWidget());
240        return hoverbar;
241    }
242
243    /**
244     * Installs the given hover bar.<p>
245     *
246     * @param hoverbar the hover bar
247     * @param widget the list item widget
248     */
249    private static void installHoverbar(final CmsSitemapHoverbar hoverbar, CmsListItemWidget widget) {
250
251        hoverbar.setVisible(false);
252        widget.getContentPanel().add(hoverbar);
253        A_CmsHoverHandler handler = new A_CmsHoverHandler() {
254
255            /**
256             * @see org.opencms.gwt.client.ui.A_CmsHoverHandler#onHoverIn(com.google.gwt.event.dom.client.MouseOverEvent)
257             */
258            @Override
259            protected void onHoverIn(MouseOverEvent event) {
260
261                hoverbar.setHovered(true);
262                if (hoverbar.isVisible()) {
263                    // prevent show when not needed
264                    return;
265                }
266                hoverbar.show();
267            }
268
269            /**
270             * @see org.opencms.gwt.client.ui.A_CmsHoverHandler#onHoverOut(com.google.gwt.event.dom.client.MouseOutEvent)
271             */
272            @Override
273            protected void onHoverOut(MouseOutEvent event) {
274
275                hoverbar.setHovered(false);
276                if (!hoverbar.isLocked()) {
277                    hoverbar.hide();
278                }
279            }
280        };
281        widget.addMouseOutHandler(handler);
282        widget.addMouseOverHandler(handler);
283    }
284
285    /**
286     * Adds a new detach event handler.<p>
287     *
288     * @param handler the handler to add
289     *
290     * @return the handler registration
291     */
292    public HandlerRegistration addHideHandler(I_CmsHoverbarHideHandler handler) {
293
294        return m_eventBus.addHandlerToSource(CmsHoverbarHideEvent.getType(), this, handler);
295    }
296
297    /**
298     * Adds a new attach event handler.<p>
299     *
300     * @param handler the handler to add
301     *
302     * @return the handler registration
303     */
304    public HandlerRegistration addShowHandler(I_CmsHoverbarShowHandler handler) {
305
306        return m_eventBus.addHandlerToSource(CmsHoverbarShowEvent.getType(), this, handler);
307    }
308
309    /**
310     * Returns the controller.<p>
311     *
312     * @return the controller
313     */
314    public CmsSitemapController getController() {
315
316        return m_controller;
317    }
318
319    /**
320     * Returns the sitemap entry.<p>
321     *
322     * @return the sitemap entry
323     */
324    public CmsClientSitemapEntry getEntry() {
325
326        return m_controller.getEntryById(m_entryId);
327    }
328
329    /**
330     * Gets the entry id.<p>
331     *
332     * @return the entry id
333     */
334    public CmsUUID getId() {
335
336        return m_entryId;
337    }
338
339    /**
340     * Detaches the hover bar.<p>
341     */
342    public void hide() {
343
344        m_locked = false;
345        if (!m_alwaysVisible) {
346            setVisible(false);
347        }
348        m_eventBus.fireEventFromSource(new CmsHoverbarHideEvent(), this);
349        // CmsDebugLog.getInstance().printLine("detached");
350    }
351
352    /**
353     * Returns if the bar is hovered.<p>
354     *
355     * @return <code>true</code> if hovered
356     */
357    public boolean isHovered() {
358
359        return m_hovered;
360    }
361
362    /**
363     * Makes the hoverbar permanently visible.<p>
364     */
365    public void setAlwaysVisible() {
366
367        m_alwaysVisible = true;
368        setVisible(true);
369    }
370
371    /**
372     * Sets the buttons of the hoverbar enabled.<p>
373     *
374     * @param enable if <code>true</code> the buttons will be enabled
375     * @param disableMessage message for disabling buttons
376     */
377    public void setEnabled(boolean enable, String disableMessage) {
378
379        if (m_enabled && !enable) {
380            Iterator<Widget> it = iterator();
381            while (it.hasNext()) {
382                Widget w = it.next();
383                if (w instanceof CmsPushButton) {
384                    ((CmsPushButton)w).disable(disableMessage);
385                }
386            }
387        } else if (!m_enabled && enable) {
388            Iterator<Widget> it = iterator();
389            while (it.hasNext()) {
390                Widget w = it.next();
391                if (w instanceof CmsPushButton) {
392                    ((CmsPushButton)w).enable();
393                }
394            }
395        }
396    }
397
398    /**
399     * Locks the hoverbar visibility.<p>
400     *
401     * @param locked <code>true</code> to lock the hoverbar visibility
402     */
403    public void setLocked(boolean locked) {
404
405        m_locked = locked;
406    }
407
408    /**
409     * Returns if the hoverbar visibility is locked.<p>
410     *
411     * @return <code>true</code> if the hoverbar visibility is locked
412     */
413    protected boolean isLocked() {
414
415        return m_locked;
416    }
417
418    /**
419     * Loads the sitemap entry.<p>
420     *
421     * @param callback executed when the entry is loaded
422     */
423    protected void loadEntry(AsyncCallback<CmsClientSitemapEntry> callback) {
424
425        CmsClientSitemapEntry entry = getEntry();
426        if ((entry == null) && (m_sitePath != null)) {
427            m_controller.loadPath(m_sitePath, true, callback);
428        } else {
429            callback.onSuccess(entry);
430        }
431    }
432
433    /**
434     * Sets the hovered state.<p>
435     *
436     * @param hovered <code>true</code> if hovered
437     */
438    protected void setHovered(boolean hovered) {
439
440        m_hovered = hovered;
441    }
442
443    /**
444     * Shows the hoverbar firing the appropriate event.<p>
445     */
446    protected void show() {
447
448        setVisible(true);
449        m_eventBus.fireEventFromSource(new CmsHoverbarShowEvent(), this);
450    }
451
452}