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.acacia.client.widgets;
029
030import org.opencms.acacia.client.css.I_CmsWidgetsLayoutBundle;
031import org.opencms.gwt.client.ui.CmsScrollPanel;
032import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle;
033import org.opencms.gwt.client.ui.input.CmsRadioButton;
034import org.opencms.gwt.client.ui.input.CmsRadioButtonGroup;
035import org.opencms.gwt.client.util.CmsClientStringUtil;
036import org.opencms.gwt.client.util.CmsDomUtil;
037
038import java.util.LinkedList;
039import java.util.List;
040import java.util.Map;
041
042import com.google.gwt.core.client.GWT;
043import com.google.gwt.dom.client.Element;
044import com.google.gwt.event.dom.client.ClickEvent;
045import com.google.gwt.event.dom.client.ClickHandler;
046import com.google.gwt.event.dom.client.FocusEvent;
047import com.google.gwt.event.dom.client.FocusHandler;
048import com.google.gwt.event.logical.shared.ValueChangeEvent;
049import com.google.gwt.event.logical.shared.ValueChangeHandler;
050import com.google.gwt.event.shared.HandlerRegistration;
051import com.google.gwt.user.client.ui.Composite;
052import com.google.gwt.user.client.ui.FlowPanel;
053
054/**
055 * Provides a widget for a standard HTML form for a group of radio buttons.<p>
056 *
057 * Regarding widget configuration, see <code>{@link org.opencms.acacia.client.widgets.CmsSelectConfigurationParser}</code>.<p>
058 * */
059public class CmsRadioSelectWidget extends Composite implements I_CmsEditWidget {
060
061    /** Default value of rows to be shown. */
062    private static final int DEFAULT_ROWS_SHOWN = 10;
063
064    /** The main panel of this widget. */
065    FlowPanel m_panel = new FlowPanel();
066
067    /** The scroll panel around the radio buttons. */
068    CmsScrollPanel m_scrollPanel = GWT.create(CmsScrollPanel.class);
069
070    /** Value of the activation. */
071    private boolean m_active = true;
072
073    /** The default radio button set in xsd. */
074    private CmsRadioButton m_defaultRadioButton;
075
076    /** Value of the radio group. */
077    private CmsRadioButtonGroup m_group;
078
079    /** List of all radio button. */
080    private List<CmsRadioButton> m_radioButtons;
081
082    /** The parameter set from configuration.*/
083    private int m_rowsToShow = DEFAULT_ROWS_SHOWN;
084
085    /**
086     * Constructs an OptionalTextBox with the given caption on the check.<p>
087     * @param config the configuration string.
088     */
089    public CmsRadioSelectWidget(String config) {
090
091        // generate a list of all radio button.
092        m_group = new CmsRadioButtonGroup();
093        // move the list to the array of all radio button.
094        m_radioButtons = parseConfiguration(config);
095        // add separate style to the panel.
096        m_scrollPanel.addStyleName(I_CmsWidgetsLayoutBundle.INSTANCE.widgetCss().radioButtonPanel());
097        FocusHandler focusHandler = new FocusHandler() {
098
099            public void onFocus(FocusEvent event) {
100
101                CmsDomUtil.fireFocusEvent(CmsRadioSelectWidget.this);
102            }
103        };
104        // iterate about all radio button.
105        for (CmsRadioButton radiobutton : m_radioButtons) {
106            // add a separate style each radio button.
107            radiobutton.addStyleName(I_CmsWidgetsLayoutBundle.INSTANCE.widgetCss().radioButtonlabel());
108            radiobutton.getRadioButton().addFocusHandler(focusHandler);
109            // add the radio button to the panel.
110            m_panel.add(radiobutton);
111        }
112        m_scrollPanel.add(m_panel);
113        m_scrollPanel.setResizable(false);
114        int lineHeight = CmsClientStringUtil.parseInt(I_CmsLayoutBundle.INSTANCE.constants().css().lineHeightBig());
115        if (lineHeight <= 0) {
116            lineHeight = 17;
117        }
118        int height = (m_rowsToShow * lineHeight);
119        if (m_radioButtons.size() < m_rowsToShow) {
120            height = (m_radioButtons.size() * lineHeight);
121        }
122        // account for padding
123        height += 8;
124        m_scrollPanel.setDefaultHeight(height);
125        m_scrollPanel.setHeight(height + "px");
126        initWidget(m_scrollPanel);
127    }
128
129    /**
130     * @see com.google.gwt.event.dom.client.HasFocusHandlers#addFocusHandler(com.google.gwt.event.dom.client.FocusHandler)
131     */
132    public HandlerRegistration addFocusHandler(FocusHandler handler) {
133
134        return addDomHandler(handler, FocusEvent.getType());
135    }
136
137    /**
138     * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler)
139     */
140    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) {
141
142        return addHandler(handler, ValueChangeEvent.getType());
143    }
144
145    /**
146     * Represents a value change event.<p>
147     *
148     */
149    public void fireChangeEvent() {
150
151        String result = "";
152        // check if there is a radio button selected.
153        if (m_group.getSelectedButton() != null) {
154            // set the name of the selected radio button.
155            result = m_group.getSelectedButton().getName();
156        }
157
158        ValueChangeEvent.fire(this, result);
159    }
160
161    /**
162     * @see com.google.gwt.user.client.ui.HasValue#getValue()
163     */
164    public String getValue() {
165
166        return m_group.getSelectedButton().getName();
167    }
168
169    /**
170     * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#isActive()
171     */
172    public boolean isActive() {
173
174        return m_active;
175    }
176
177    /**
178     * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#onAttachWidget()
179     */
180    public void onAttachWidget() {
181
182        super.onAttach();
183    }
184
185    /**
186     * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#owns(com.google.gwt.dom.client.Element)
187     */
188    public boolean owns(Element element) {
189
190        // TODO implement this in case we want the delete behavior for optional fields
191        return false;
192
193    }
194
195    /**
196     * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#setActive(boolean)
197     */
198    public void setActive(boolean active) {
199
200        // check if the value has changed. If there is no change do nothing.
201        if (m_active == active) {
202            // if the value is initial activated set the default value.
203            if (active) {
204                fireChangeEvent();
205            }
206            return;
207        }
208        // set the new value.
209        m_active = active;
210        // Iterate about all radio button.
211        for (CmsRadioButton radiobutton : m_radioButtons) {
212            // set the radio button active / inactive.
213            radiobutton.setEnabled(active);
214            // if this widget is set inactive.
215            if (active) {
216                // select the default value if set.
217                if (m_defaultRadioButton != null) {
218                    m_defaultRadioButton.setChecked(active);
219                    fireChangeEvent();
220                }
221            }
222        }
223        // fire value change event.
224        if (active) {
225            fireChangeEvent();
226        }
227
228    }
229
230    /**
231     * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#setName(java.lang.String)
232     */
233    public void setName(String name) {
234
235        // no input field so nothing to do
236
237    }
238
239    /**
240     * @see com.google.gwt.user.client.ui.HasValue#setValue(java.lang.Object)
241     */
242    public void setValue(String value) {
243
244        setValue(value, false);
245
246    }
247
248    /**
249     * @see com.google.gwt.user.client.ui.HasValue#setValue(java.lang.Object, boolean)
250     */
251    public void setValue(String value, boolean fireEvents) {
252
253        // iterate about all the radio button.
254        for (CmsRadioButton radiobutton : m_radioButtons) {
255            // if the value is the name of a radio button active it.
256            if (radiobutton.getName().equals(value)) {
257                m_group.selectButton(radiobutton);
258            }
259            // fire change event.
260            if (fireEvents) {
261                fireChangeEvent();
262            }
263        }
264
265    }
266
267    /**
268     * Helper class for parsing the configuration in to a list of Radiobuttons. <p>
269     *
270     * @param config the configuration string.
271     * @return List of CmsRadioButtons
272     * */
273    private List<CmsRadioButton> parseConfiguration(String config) {
274
275        // generate an empty list off radio button.
276        List<CmsRadioButton> result = new LinkedList<CmsRadioButton>();
277
278        CmsSelectConfigurationParser parser = new CmsSelectConfigurationParser(config);
279        for (Map.Entry<String, String> entry : parser.getOptions().entrySet()) {
280            // create a new radio button with the given name and label.
281            CmsRadioButton radiobutton = new CmsRadioButton(entry.getKey(), entry.getValue());
282            // add click handler.
283            radiobutton.addClickHandler(new ClickHandler() {
284
285                public void onClick(ClickEvent event) {
286
287                    fireChangeEvent();
288                }
289            });
290            // add this radio button to the group
291            radiobutton.setGroup(m_group);
292            // check if this value is default set.
293            if (entry.getKey().equals(parser.getDefaultValue())) {
294                radiobutton.setChecked(true);
295                m_defaultRadioButton = radiobutton;
296            }
297            // add this radio button to the list.
298            result.add(radiobutton);
299        }
300        return result;
301    }
302}