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.input;
029
030import org.opencms.gwt.client.I_CmsHasInit;
031import org.opencms.gwt.client.ui.CmsToggleButton;
032import org.opencms.gwt.client.ui.I_CmsAutoHider;
033import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle;
034import org.opencms.gwt.client.ui.css.I_CmsInputCss;
035import org.opencms.gwt.client.ui.css.I_CmsInputLayoutBundle;
036import org.opencms.gwt.client.ui.input.form.CmsWidgetFactoryRegistry;
037import org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory;
038
039import java.util.Map;
040
041import com.google.common.base.Optional;
042import com.google.gwt.event.dom.client.ClickEvent;
043import com.google.gwt.event.dom.client.ClickHandler;
044import com.google.gwt.event.dom.client.HasClickHandlers;
045import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
046import com.google.gwt.event.logical.shared.ValueChangeEvent;
047import com.google.gwt.event.logical.shared.ValueChangeHandler;
048import com.google.gwt.event.shared.HandlerRegistration;
049import com.google.gwt.user.client.ui.Composite;
050import com.google.gwt.user.client.ui.FlowPanel;
051import com.google.gwt.user.client.ui.HasHorizontalAlignment;
052
053/**
054 * This class represents a labeled checkbox which is not represented as an INPUT element in
055 * the DOM, but is displayed as an image.<p>
056 *
057 * It can be checked/unchecked and enabled/disabled, which means 4 combinations in total.
058 * So you need to supply 4 images, one for each of the combinations.<p>
059 *
060 * @since 8.0.0
061 */
062public class CmsCheckBox extends Composite
063implements HasClickHandlers, I_CmsFormWidget, I_CmsHasInit, HasHorizontalAlignment, HasValueChangeHandlers<Boolean> {
064
065    /** Type string for this widget. */
066    public static final String WIDGET_TYPE = "checkbox";
067
068    /** CSS bundle for this widget. */
069    private static final I_CmsInputCss CSS = I_CmsInputLayoutBundle.INSTANCE.inputCss();
070
071    /** The current horizontal alignment. */
072    private HorizontalAlignmentConstant m_align;
073
074    /** Toggle button which actually displays the checkbox. */
075    private final CmsToggleButton m_button;
076
077    /** The error display for this widget. */
078    private final CmsErrorWidget m_error;
079
080    /** Internal root widget to which all other components of this widget are attached. */
081    private final FlowPanel m_root;
082
083    /** The internal value of this checkbox. */
084    private String m_value;
085
086    /**
087     * Default constructor which creates a checkbox without a label.<p>
088     */
089    public CmsCheckBox() {
090
091        this(null);
092    }
093
094    /**
095     * Public constructor for a checkbox.<p>
096     *
097     * The label text passed will be displayed to the right of the checkbox. If
098     * it is null, no label is displayed.<p>
099     *
100     * @param labelText the label text
101     */
102    public CmsCheckBox(String labelText) {
103
104        m_button = new CmsToggleButton();
105        m_button.setUseMinWidth(false);
106        m_button.setButtonStyle(ButtonStyle.TRANSPARENT, null);
107        m_button.setImageClass(CSS.checkBoxImage());
108        if (labelText != null) {
109            m_button.setText(labelText);
110        }
111        setHorizontalAlignment(ALIGN_RIGHT);
112
113        m_root = new FlowPanel();
114        m_error = new CmsErrorWidget();
115        m_root.add(m_button);
116        m_root.add(m_error);
117
118        initWidget(m_root);
119        addStyleName(CSS.checkBox());
120        addStyleName(CSS.inlineBlock());
121        m_button.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
122
123            public void onValueChange(ValueChangeEvent<Boolean> changeEvent) {
124
125                ValueChangeEvent.fire(CmsCheckBox.this, changeEvent.getValue());
126            }
127        });
128    }
129
130    /**
131     * Initializes this class.<p>
132     */
133    public static void initClass() {
134
135        // registers a factory for creating new instances of this widget
136        CmsWidgetFactoryRegistry.instance().registerFactory(WIDGET_TYPE, new I_CmsFormWidgetFactory() {
137
138            /**
139             * @see org.opencms.gwt.client.ui.input.form.I_CmsFormWidgetFactory#createWidget(java.util.Map, com.google.common.base.Optional)
140             */
141            public I_CmsFormWidget createWidget(Map<String, String> widgetParams, Optional<String> defaultValue) {
142
143                return new CmsCheckBox(widgetParams.get("label"));
144            }
145        });
146    }
147
148    /**
149     * Adds a click handler to the checkbox.<p>
150     *
151     * @see com.google.gwt.event.dom.client.HasClickHandlers#addClickHandler(com.google.gwt.event.dom.client.ClickHandler)
152     */
153    public HandlerRegistration addClickHandler(ClickHandler handler) {
154
155        return addDomHandler(handler, ClickEvent.getType());
156    }
157
158    /**
159     * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler)
160     */
161    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<Boolean> handler) {
162
163        return addHandler(handler, ValueChangeEvent.getType());
164    }
165
166    /**
167     * Disables the checkbox and changes the checkbox title attribute to the disabled reason.<p>
168     *
169     * @param disabledReason the disabled reason
170     */
171    public void disable(String disabledReason) {
172
173        m_button.disable(disabledReason);
174    }
175
176    /**
177     * Enables the checkbox, switching the checkbox title attribute from the disabled reason to the original title.<p>
178     */
179    public void enable() {
180
181        m_button.enable();
182    }
183
184    /**
185     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getApparentValue()
186     */
187    public String getApparentValue() {
188
189        return getFormValueAsString();
190    }
191
192    /**
193     * Gets the toggle button used internally.<p>
194     *
195     * @return the toggle button
196     */
197    public CmsToggleButton getButton() {
198
199        return m_button;
200    }
201
202    /**
203     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFieldType()
204     */
205    public FieldType getFieldType() {
206
207        return I_CmsFormWidget.FieldType.BOOLEAN;
208    }
209
210    /**
211     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFormValue()
212     */
213    public Boolean getFormValue() {
214
215        return isChecked() ? Boolean.TRUE : Boolean.FALSE;
216    }
217
218    /**
219     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#getFormValueAsString()
220     */
221    public String getFormValueAsString() {
222
223        return "" + isChecked();
224    }
225
226    /**
227     * This is the alignment of the text in reference to the checkbox, possible values are left or right.<p>
228     *
229     * @see com.google.gwt.user.client.ui.HasHorizontalAlignment#getHorizontalAlignment()
230     */
231    public HorizontalAlignmentConstant getHorizontalAlignment() {
232
233        return m_align;
234    }
235
236    /**
237     * Returns the internal value of this Checkbox.<p>
238     *
239     * @return the internal value of this Checkbox
240     */
241    public String getInternalValue() {
242
243        return m_value;
244    }
245
246    /**
247     * Returns the text.<p>
248     *
249     * @return the text as String
250     */
251    public String getText() {
252
253        return m_button.getText();
254
255    }
256
257    /**
258     * Returns true if the checkbox is checked.<p>
259     *
260     * @return true if the checkbox is checked
261     */
262    public boolean isChecked() {
263
264        return m_button.isDown();
265    }
266
267    /**
268     * Returns true if the checkbox is enabled.<p>
269     *
270     * @return true if the checkbox is enabled
271     */
272    public boolean isEnabled() {
273
274        return m_button.isEnabled();
275    }
276
277    /**
278     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#reset()
279     */
280    public void reset() {
281
282        setChecked(false);
283    }
284
285    /**
286     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setAutoHideParent(org.opencms.gwt.client.ui.I_CmsAutoHider)
287     */
288    public void setAutoHideParent(I_CmsAutoHider autoHideParent) {
289
290        // do nothing
291    }
292
293    /**
294     * Checks or unchecks the checkbox.<p>
295     *
296     * @param checked if true, check the checkbox else uncheck it
297     */
298    public void setChecked(boolean checked) {
299
300        m_button.setDown(checked);
301    }
302
303    /**
304     * Toggles between display:inline-block and display:block.<p>
305     *
306     * @param inline <code>true</code> to display inline-block
307     */
308    public void setDisplayInline(boolean inline) {
309
310        if (inline) {
311            addStyleName(CSS.inlineBlock());
312        } else {
313            removeStyleName(CSS.inlineBlock());
314        }
315    }
316
317    /**
318     * Enables or disables the checkbox.<p>
319     *
320     * @param enabled if true, enable the checkbox, else disable it
321     */
322    public void setEnabled(boolean enabled) {
323
324        m_button.setEnabled(enabled);
325    }
326
327    /**
328     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setErrorMessage(java.lang.String)
329     */
330    public void setErrorMessage(String errorMessage) {
331
332        m_error.setText(errorMessage);
333    }
334
335    /**
336     * Sets the value of the widget.<p>
337     *
338     * @param value the new value
339     */
340    public void setFormValue(Object value) {
341
342        if (value instanceof Boolean) {
343            Boolean boolValue = (Boolean)value;
344            setChecked(boolValue.booleanValue());
345        }
346    }
347
348    /**
349     * @see org.opencms.gwt.client.ui.input.I_CmsFormWidget#setFormValueAsString(java.lang.String)
350     */
351    public void setFormValueAsString(String value) {
352
353        setChecked(Boolean.parseBoolean(value) || "checked".equalsIgnoreCase(value));
354    }
355
356    /**
357     * This is the alignment of the text in reference to the checkbox, possible values are left or right.<p>
358     *
359     * @see com.google.gwt.user.client.ui.HasHorizontalAlignment#setHorizontalAlignment(com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant)
360     */
361    public void setHorizontalAlignment(HorizontalAlignmentConstant align) {
362
363        if (align.equals(HasHorizontalAlignment.ALIGN_CENTER)) {
364            // ignore center alignment
365            return;
366        }
367        m_button.setHorizontalAlignment(align);
368        m_align = align;
369    }
370
371    /**
372     * Sets the internal value of this Checkbox.<p>
373     *
374     *  @param value the new internal value
375     */
376    public void setInternalValue(String value) {
377
378        m_value = value;
379    }
380
381    /**
382     * Sets the text.<p>
383     *
384     * @param text the text to set
385     */
386    public void setText(String text) {
387
388        m_button.setText(text);
389    }
390
391    /**
392     * Helper method for firing a 'value changed' event.<p>
393     */
394    protected void fireValueChangedEvent() {
395
396        ValueChangeEvent.fire(this, getFormValue());
397    }
398}