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.contextmenu;
029
030import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle;
031
032import com.google.gwt.event.dom.client.ClickEvent;
033import com.google.gwt.event.dom.client.ClickHandler;
034import com.google.gwt.event.dom.client.HasClickHandlers;
035import com.google.gwt.event.dom.client.HasMouseOutHandlers;
036import com.google.gwt.event.dom.client.HasMouseOverHandlers;
037import com.google.gwt.event.dom.client.MouseOutEvent;
038import com.google.gwt.event.dom.client.MouseOutHandler;
039import com.google.gwt.event.dom.client.MouseOverEvent;
040import com.google.gwt.event.dom.client.MouseOverHandler;
041import com.google.gwt.event.shared.HandlerRegistration;
042import com.google.gwt.user.client.ui.Composite;
043import com.google.gwt.user.client.ui.Widget;
044
045/**
046 * A abstract implementation for a context menu item.<p>
047 *
048 * @since version 8.0.0
049 */
050public abstract class A_CmsContextMenuItem extends Composite
051implements ClickHandler, MouseOutHandler, MouseOverHandler, HasClickHandlers, HasMouseOutHandlers,
052HasMouseOverHandlers {
053
054    /** Signals if the item should be disabled. */
055    private boolean m_active;
056
057    /** The handler registration for the click handler. */
058    private HandlerRegistration m_clickRegistration;
059
060    /** The handler registration for the click handler. */
061    private HandlerRegistration m_mouseOutRegistration;
062
063    /** The handler registration for the click handler. */
064    private HandlerRegistration m_mouseOverRegistration;
065
066    /** The parent menu of this menu item. */
067    private CmsContextMenu m_parentMenu;
068
069    /** The optional sub menu of this menu item. */
070    private CmsContextMenu m_subMenu;
071
072    /** The text for the menu item. */
073    private String m_text;
074
075    /**
076     * Constructor.<p>
077     *
078     * @param text the text for the menu item
079     */
080    protected A_CmsContextMenuItem(String text) {
081
082        m_active = true;
083        m_text = text;
084    }
085
086    /**
087     * @see com.google.gwt.event.dom.client.HasClickHandlers#addClickHandler(com.google.gwt.event.dom.client.ClickHandler)
088     */
089    public HandlerRegistration addClickHandler(ClickHandler handler) {
090
091        m_clickRegistration = addDomHandler(handler, ClickEvent.getType());
092        return m_clickRegistration;
093    }
094
095    /**
096     * @see com.google.gwt.event.dom.client.HasMouseOutHandlers#addMouseOutHandler(com.google.gwt.event.dom.client.MouseOutHandler)
097     */
098    public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) {
099
100        m_mouseOutRegistration = addDomHandler(handler, MouseOutEvent.getType());
101        return m_mouseOutRegistration;
102    }
103
104    /**
105     * @see com.google.gwt.event.dom.client.HasMouseOverHandlers#addMouseOverHandler(com.google.gwt.event.dom.client.MouseOverHandler)
106     */
107    public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) {
108
109        m_mouseOverRegistration = addDomHandler(handler, MouseOverEvent.getType());
110        return m_mouseOverRegistration;
111    }
112
113    /**
114     * Deselects an item.<p>
115     */
116    public void deselectItem() {
117
118        getElement().removeClassName(I_CmsLayoutBundle.INSTANCE.contextmenuCss().selected());
119        m_parentMenu.setSelectedItem(null);
120    }
121
122    /**
123     * Returns the parent menu of this menu item.<p>
124     *
125     * @return the parent menu
126     */
127    public CmsContextMenu getParentMenu() {
128
129        return m_parentMenu;
130    }
131
132    /**
133     * Returns the sub menu of this menu item.<p>
134     *
135     * @return the sub menu
136     */
137    public CmsContextMenu getSubMenu() {
138
139        return m_subMenu;
140    }
141
142    /**
143     * Returns the text of this menu item.<p>
144     *
145     * @return the text
146     */
147    public String getText() {
148
149        return m_text;
150    }
151
152    /**
153     * Returns <code>true</code> if this menu item has a sub menu, <code>false</code> otherwise.<p>
154     *
155     * @return <code>true</code> if this menu item has a sub menu
156     */
157    public boolean hasSubmenu() {
158
159        if (m_subMenu != null) {
160            return true;
161        }
162        return false;
163    }
164
165    /**
166     * Returns <code>true</code> if the item is active <code>false</code> otherwise.<p>
167     *
168     * @return <code>true</code> if the item is active <code>false</code> otherwise
169     */
170    public boolean isActive() {
171
172        return m_active;
173    }
174
175    /**
176     * The action that is executed on click depends on the concrete implementation of a menu item.
177     * So the onClick Method has to be implemented in the sub class.<p>
178     *
179     * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent)
180     */
181    public abstract void onClick(ClickEvent event);
182
183    /**
184     * @see com.google.gwt.event.dom.client.MouseOutHandler#onMouseOut(com.google.gwt.event.dom.client.MouseOutEvent)
185     */
186    public final void onMouseOut(MouseOutEvent event) {
187
188        onHoverOut(event);
189    }
190
191    /**
192     * @see com.google.gwt.event.dom.client.MouseOverHandler#onMouseOver(com.google.gwt.event.dom.client.MouseOverEvent)
193     */
194    public final void onMouseOver(final MouseOverEvent event) {
195
196        onHoverIn(event);
197    }
198
199    /**
200     * Selects a item.<p>
201     */
202    public void selectItem() {
203
204        getElement().addClassName(I_CmsLayoutBundle.INSTANCE.contextmenuCss().selected());
205        m_parentMenu.setSelectedItem(this);
206    }
207
208    /**
209     * Makes the menu item active or inactive.<p>
210     *
211     * If the item is inactive all handlers are removed.<p>
212     *
213     * @param active <code>true</code> if the item should be active, <code>false</code> otherwise
214     * @param reason the reason for de-activation
215     */
216    public void setActive(boolean active, String reason) {
217
218        if (!active) {
219            m_clickRegistration.removeHandler();
220            m_mouseOutRegistration.removeHandler();
221            m_mouseOverRegistration.removeHandler();
222            getElement().addClassName(I_CmsLayoutBundle.INSTANCE.contextmenuCss().disabled());
223            getElement().setAttribute("title", reason);
224        } else {
225            addMouseOutHandler(this);
226            addMouseOverHandler(this);
227            addClickHandler(this);
228            getElement().removeClassName(I_CmsLayoutBundle.INSTANCE.contextmenuCss().disabled());
229        }
230        m_active = active;
231    }
232
233    /**
234     * Sets the text of the menu item.<p>
235     *
236     * @param text the text to set
237     */
238    public void setText(String text) {
239
240        m_text = text;
241    }
242
243    /**
244     * @see com.google.gwt.user.client.ui.Composite#initWidget(com.google.gwt.user.client.ui.Widget)
245     */
246    @Override
247    protected void initWidget(Widget widget) {
248
249        super.initWidget(widget);
250        addMouseOutHandler(this);
251        addMouseOverHandler(this);
252        addClickHandler(this);
253    }
254
255    /**
256     * Implements the hover over action for a item.<p>
257     *
258     * First closes all sub menus that are not required anymore.
259     * And then reopens the necessary sub menus and activates the selected item.<p>
260     *
261     * @param event the mouse over event
262     */
263    protected void onHoverIn(MouseOverEvent event) {
264
265        if ((getParentMenu().getSelectedItem() != null)
266            && (getParentMenu().getSelectedItem() != this)
267            && getParentMenu().getSelectedItem().hasSubmenu()) {
268
269            getParentMenu().getSelectedItem().getSubMenu().onClose();
270            getParentMenu().getSelectedItem().deselectItem();
271        }
272        if (hasSubmenu()) {
273            getSubMenu().openPopup(this);
274        }
275        selectItem();
276    }
277
278    /**
279     * Implements the hover out action for a item.<p>
280     *
281     * If a menu item has no sub menu it will be deselected.<p>
282     *
283     * @param event the mouse out event
284     */
285    protected void onHoverOut(MouseOutEvent event) {
286
287        if (!hasSubmenu()) {
288            deselectItem();
289        }
290    }
291
292    /**
293     * Sets the parent menu of this menu item.<p>
294     *
295     * @param parentMenu the parent menu to set
296     */
297    protected void setParentMenu(CmsContextMenu parentMenu) {
298
299        m_parentMenu = parentMenu;
300    }
301
302    /**
303     * Sets the sub menu for the menu item.<p>
304     *
305     * @param subMenu the sub menu to set
306     */
307    protected void setSubMenu(CmsContextMenu subMenu) {
308
309        m_subMenu = subMenu;
310        subMenu.setParentItem(this);
311
312    }
313}