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.I_CmsButton.ButtonColor;
031import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle;
032import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle;
033import org.opencms.gwt.client.util.CmsDomUtil;
034
035import com.google.gwt.user.client.DOM;
036import com.google.gwt.user.client.Event;
037import com.google.gwt.user.client.ui.HasHorizontalAlignment;
038import com.google.gwt.user.client.ui.PushButton;
039
040/**
041 * Push button class.<p>
042 *
043 * Uses CSS classes cmsState and dependent from 'button.css', make sure it is injected.<p>
044 *
045 * @since 8.0.0
046 */
047public class CmsPushButton extends PushButton implements HasHorizontalAlignment {
048
049    /** The current horizontal alignment. */
050    private HorizontalAlignmentConstant m_align;
051
052    /** Stores the button style. */
053    private ButtonStyle m_buttonStyle;
054
055    /** Stores the button color. */
056    private I_CmsButton.ButtonColor m_color;
057
058    /** The disabled reason. */
059    private String m_disabledReason;
060
061    /** The down face image class. */
062    private String m_downImageClass;
063
064    /** The hide from tab navigation flag. */
065    private boolean m_hideFromTabNav;
066
067    /** The image class. */
068    private String m_imageClass;
069
070    /** Flag to indicate the button was reenalbled. Set until the next mouse up, over or out event. */
071    private boolean m_isReenabled;
072
073    /** The button size. */
074    private I_CmsButton.Size m_size;
075
076    /** The button text. */
077    private String m_text;
078
079    /** The title. */
080    private String m_title;
081
082    /** Use minimum width flag. */
083    private boolean m_useMinWidth;
084
085    /**
086     * The constructor.<p>
087     */
088    public CmsPushButton() {
089
090        m_align = HasHorizontalAlignment.ALIGN_RIGHT;
091        setStyleName(I_CmsLayoutBundle.INSTANCE.buttonCss().cmsState());
092        setButtonStyle(ButtonStyle.TEXT, ButtonColor.BLUE);
093        addStyleName(I_CmsLayoutBundle.INSTANCE.buttonCss().cmsPushButton());
094        setSize(I_CmsButton.Size.medium);
095    }
096
097    /**
098     * The constructor. Setting the button icon.<p>
099     *
100     * @param imageClass the class for the image
101     */
102    public CmsPushButton(String imageClass) {
103
104        this();
105        setImageClass(imageClass);
106    }
107
108    /**
109     * The constructor. Setting different icons for the up and down face of the button.<p>
110     *
111     * @param imageClass the class for the up face image
112     * @param downImageClass the class for the down face image
113     */
114    public CmsPushButton(String imageClass, String downImageClass) {
115
116        this(imageClass);
117        setDownImageClass(downImageClass);
118    }
119
120    /**
121     * Clears the hover state of the button.<p>
122     * Use when opening modal popups to ensure the button is not left in hovered state.<p>
123     */
124    public void clearHoverState() {
125
126        setEnabled(!isEnabled());
127        setEnabled(!isEnabled());
128    }
129
130    /**
131     * Disables the button and changes the button title attribute to the disabled reason.<p>
132     *
133     * @param disabledReason the disabled reason
134     */
135    public void disable(String disabledReason) {
136
137        setDown(false);
138        setEnabled(false);
139        m_disabledReason = disabledReason;
140        super.setTitle(disabledReason);
141    }
142
143    /**
144     * Enables the button, switching the button title attribute from the disabled reason to the original title.<p>
145     */
146    public void enable() {
147
148        m_isReenabled = true;
149        setEnabled(true);
150        m_disabledReason = null;
151        super.setTitle(m_title);
152    }
153
154    /**
155     * Returns the disabled reason.<p>
156     *
157     * @return the disabled reason
158     */
159    public String getDisabledReason() {
160
161        return m_disabledReason;
162    }
163
164    /**
165     * Returns the image class of the down face.<p>
166     *
167     * @return the image class of the down face
168     */
169    public String getDownImageClass() {
170
171        return m_downImageClass;
172    }
173
174    /**
175     * This is the alignment of the text in reference to the image, possible values are left or right.<p>
176     *
177     * @see com.google.gwt.user.client.ui.HasHorizontalAlignment#getHorizontalAlignment()
178     */
179    public HorizontalAlignmentConstant getHorizontalAlignment() {
180
181        return m_align;
182    }
183
184    /**
185     * Returns the master image class.<p>
186     *
187     * @return the master image class
188     */
189    public String getImageClass() {
190
191        return m_imageClass;
192    }
193
194    /**
195     * Returns the size.<p>
196     *
197     * @return the size
198     */
199    public I_CmsButton.Size getSize() {
200
201        return m_size;
202    }
203
204    /**
205     * Returns the text.<p>
206     *
207     * @return the text
208     */
209    @Override
210    public String getText() {
211
212        return m_text;
213    }
214
215    /**
216     * Returns the title.<p>
217     *
218     * @return the title
219     */
220    @Override
221    public String getTitle() {
222
223        return m_title;
224    }
225
226    /**
227     * @see com.google.gwt.user.client.ui.CustomButton#isDown()
228     */
229    @Override
230    public boolean isDown() {
231
232        return super.isDown();
233    }
234
235    /**
236     * Checks if the button is constraint to a minimal width.<p>
237     *
238     * @return <code>true</code> if the button is constraint to a minimal width
239     */
240    public boolean isUseMinWidth() {
241
242        return m_useMinWidth;
243    }
244
245    /**
246     * @see com.google.gwt.user.client.ui.CustomButton#onBrowserEvent(com.google.gwt.user.client.Event)
247     */
248    @Override
249    public void onBrowserEvent(Event event) {
250
251        // if the button is enabled while the mouse-pointer is within the button element,
252        // the mouse-over element will not get triggered again
253        // this may prevent correct handling of the click event
254        if (isEnabled() && m_isReenabled) {
255            int type = DOM.eventGetType(event);
256            switch (type) {
257                case Event.ONMOUSEUP:
258                    m_isReenabled = false;
259                    CmsDomUtil.ensureMouseOver(getElement());
260                    break;
261                case Event.ONMOUSEOVER:
262                case Event.ONMOUSEOUT:
263                    m_isReenabled = false;
264                    break;
265                default:
266            }
267        }
268
269        super.onBrowserEvent(event);
270    }
271
272    /**
273     * Sets the button style.<p>
274     *
275     * @param style the style to set
276     * @param color the color to set
277     */
278    public void setButtonStyle(I_CmsButton.ButtonStyle style, I_CmsButton.ButtonColor color) {
279
280        if (m_buttonStyle != null) {
281            for (String styleName : m_buttonStyle.getAdditionalClasses()) {
282                removeStyleName(styleName);
283            }
284        }
285        if (style == ButtonStyle.TRANSPARENT) {
286            setSize(null);
287        }
288        addStyleName(style.getCssClassName());
289        m_buttonStyle = style;
290
291        if (m_color != null) {
292            removeStyleName(m_color.getClassName());
293        }
294        if (color != null) {
295            addStyleName(color.getClassName());
296        }
297        m_color = color;
298    }
299
300    /**
301     * @see com.google.gwt.user.client.ui.CustomButton#setDown(boolean)
302     */
303    @Override
304    public void setDown(boolean down) {
305
306        super.setDown(down);
307    }
308
309    /**
310     * Sets the down face text and image.<p>
311     *
312     * @param text the down face text to set, set to <code>null</code> to not show any
313     * @param imageClass the down face image class to use, set to <code>null</code> to not show any
314     */
315    public void setDownFace(String text, String imageClass) {
316
317        m_downImageClass = imageClass;
318        getDownFace().setHTML(getFaceHtml(text, imageClass));
319    }
320
321    /**
322     * Sets the image class for the down face.<p>
323     *
324     * @param downImageClass the image class to set
325     */
326    public void setDownImageClass(String downImageClass) {
327
328        setDownFace(m_text, downImageClass);
329    }
330
331    /**
332     * Sets the hide from tab navigation flag.<p>
333     * If <code>true</code> the button will not be accessible by tab navigation.<p>
334     *
335     * @param hideFromTabNav the hide from tab navigation flag
336     */
337    public void setHideFromTabNav(boolean hideFromTabNav) {
338
339        m_hideFromTabNav = hideFromTabNav;
340        setTabIndex(-1);
341    }
342
343    /**
344     * This is the alignment of the text in reference to the image, possible values are left or right.<p>
345     *
346     * @see com.google.gwt.user.client.ui.HasHorizontalAlignment#setHorizontalAlignment(com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant)
347     */
348    public void setHorizontalAlignment(HorizontalAlignmentConstant align) {
349
350        if (align.equals(HasHorizontalAlignment.ALIGN_CENTER)) {
351            // ignore center alignment
352            return;
353        }
354        m_align = align;
355    }
356
357    /**
358     * Sets the master image class.<p>
359     *
360     * @param imageClass the master image class to set
361     */
362    public void setImageClass(String imageClass) {
363
364        setUpFace(m_text, imageClass);
365    }
366
367    /**
368     * Sets the size.<p>
369     *
370     * @param size the size to set
371     */
372    public void setSize(I_CmsButton.Size size) {
373
374        if (m_size != null) {
375            removeStyleName(m_size.getCssClassName());
376        }
377        if (size != null) {
378            addStyleName(size.getCssClassName());
379        }
380        m_size = size;
381    }
382
383    /**
384     * Sets the text.<p>
385     *
386     * @param text the text to set
387     */
388    @Override
389    public void setText(String text) {
390
391        setUpFace(text, m_imageClass);
392        setTitle(text);
393    }
394
395    /**
396     * @see com.google.gwt.user.client.ui.UIObject#setTitle(java.lang.String)
397     */
398    @Override
399    public void setTitle(String title) {
400
401        super.setTitle(title);
402        m_title = title;
403    }
404
405    /**
406     * Sets the up face text and image.<p>
407     *
408     * @param text the up face text to set, set to <code>null</code> to not show any
409     * @param imageClass the up face image class to use, set to <code>null</code> to not show any
410     */
411    public void setUpFace(String text, String imageClass) {
412
413        m_text = text;
414        m_imageClass = imageClass;
415        getUpFace().setHTML(getFaceHtml(text, imageClass));
416    }
417
418    /**
419     * Tells the button to use a minimal width.<p>
420     *
421     * @param useMinWidth <code>true</code> to use a minimal width
422     */
423    public void setUseMinWidth(boolean useMinWidth) {
424
425        if (useMinWidth != m_useMinWidth) {
426            if (useMinWidth) {
427                addStyleName(I_CmsLayoutBundle.INSTANCE.buttonCss().cmsMinWidth());
428            } else {
429                removeStyleName(I_CmsLayoutBundle.INSTANCE.buttonCss().cmsMinWidth());
430            }
431            m_useMinWidth = useMinWidth;
432        }
433    }
434
435    /**
436     * Convenience method to assemble the HTML to use for a button face.<p>
437     *
438     * @param text text the up face text to set, set to <code>null</code> to not show any
439     * @param imageClass the up face image class to use, set to <code>null</code> to not show any
440     *
441     * @return the HTML
442     */
443    protected String getFaceHtml(String text, String imageClass) {
444
445        return CmsDomUtil.createFaceHtml(text, imageClass, m_align);
446    }
447
448    /**
449     * @see com.google.gwt.user.client.ui.CustomButton#onAttach()
450     */
451    @Override
452    protected void onAttach() {
453
454        super.onAttach();
455        if (m_hideFromTabNav) {
456            setTabIndex(-1);
457        }
458    }
459}