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.ade.contenteditor.client.css.I_CmsLayoutBundle;
032import org.opencms.gwt.client.ui.input.CmsSelectBox;
033
034import java.util.Map;
035import java.util.Map.Entry;
036
037import com.google.gwt.dom.client.Element;
038import com.google.gwt.event.dom.client.FocusEvent;
039import com.google.gwt.event.dom.client.FocusHandler;
040import com.google.gwt.event.logical.shared.ValueChangeEvent;
041import com.google.gwt.event.logical.shared.ValueChangeHandler;
042import com.google.gwt.event.shared.HandlerRegistration;
043import com.google.gwt.user.client.ui.Composite;
044
045/**
046 * An option of a select type widget.<p>
047 *
048 * Regarding widget configuration, see <code>{@link org.opencms.acacia.client.widgets.CmsSelectConfigurationParser}</code>.<p>
049 */
050public class CmsSelectWidget extends Composite implements I_CmsEditWidget, I_CmsHasDisplayDirection {
051
052    /** The global select box. */
053    protected CmsSelectBox m_selectBox = new CmsSelectBox();
054
055    /** Value of the activation. */
056    private boolean m_active = true;
057
058    /** THe default value. */
059    private String m_defaultValue;
060
061    /** The last value set through the setValue method. This is not necessarily the current widget value. */
062    private String m_externalValue;
063
064    private boolean m_allowUnknown;
065
066    /**
067     * Constructs an CmsComboWidget with the in XSD schema declared configuration.<p>
068     * @param config The configuration string given from OpenCms XSD.
069     */
070    public CmsSelectWidget(String config, boolean allowUnknown) {
071
072        parseConfiguration(config);
073
074        // Place the check above the box using a vertical panel.
075        m_selectBox.addStyleName(I_CmsWidgetsLayoutBundle.INSTANCE.widgetCss().selectBoxPanel());
076        m_allowUnknown = allowUnknown;
077        m_selectBox.setPopupResize(false);
078        // add some styles to parts of the selectbox.
079        m_selectBox.getOpener().addStyleName(I_CmsWidgetsLayoutBundle.INSTANCE.widgetCss().selectBoxSelected());
080        m_selectBox.getSelectorPopup().addStyleName(I_CmsLayoutBundle.INSTANCE.globalWidgetCss().selectBoxPopup());
081        m_selectBox.addValueChangeHandler(new ValueChangeHandler<String>() {
082
083            public void onValueChange(ValueChangeEvent<String> event) {
084
085                fireChangeEvent();
086
087            }
088
089        });
090
091        // All composites must call initWidget() in their constructors.
092        initWidget(m_selectBox);
093
094    }
095
096    /**
097     * @see com.google.gwt.event.dom.client.HasFocusHandlers#addFocusHandler(com.google.gwt.event.dom.client.FocusHandler)
098     */
099    public HandlerRegistration addFocusHandler(FocusHandler handler) {
100
101        return addDomHandler(handler, FocusEvent.getType());
102    }
103
104    /**
105     * @see com.google.gwt.event.logical.shared.HasValueChangeHandlers#addValueChangeHandler(com.google.gwt.event.logical.shared.ValueChangeHandler)
106     */
107    public HandlerRegistration addValueChangeHandler(ValueChangeHandler<String> handler) {
108
109        return addHandler(handler, ValueChangeEvent.getType());
110    }
111
112    /**
113     * Represents a value change event.<p>
114     *
115     */
116    public void fireChangeEvent() {
117
118        ValueChangeEvent.fire(this, m_selectBox.getFormValueAsString());
119
120    }
121
122    /**
123     * @see org.opencms.acacia.client.widgets.I_CmsHasDisplayDirection#getDisplayingDirection()
124     */
125    public Direction getDisplayingDirection() {
126
127        return m_selectBox.displayingAbove() ? Direction.above : Direction.below;
128    }
129
130    /**
131     * @see com.google.gwt.user.client.ui.HasValue#getValue()
132     */
133    public String getValue() {
134
135        return m_selectBox.getFormValueAsString();
136    }
137
138    /**
139     * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#isActive()
140     */
141    public boolean isActive() {
142
143        return m_active;
144    }
145
146    /**
147     * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#onAttachWidget()
148     */
149    public void onAttachWidget() {
150
151        super.onAttach();
152    }
153
154    /**
155     * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#owns(com.google.gwt.dom.client.Element)
156     */
157    public boolean owns(Element element) {
158
159        // TODO implement this in case we want the delete behavior for optional fields
160        return false;
161
162    }
163
164    /**
165     * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#setActive(boolean)
166     */
167    public void setActive(boolean active) {
168
169        // check if value change. If not do nothing.
170        if (m_active == active) {
171            if (active && !m_selectBox.getFormValueAsString().equals(m_externalValue)) {
172                // in case the previously set external value does not match the internal select box value fire change event
173                // this is needed in case the external value didn't match any select option,
174                // in this case the select box will display the first available value so fire the change to reflect that
175                fireChangeEvent();
176            }
177            return;
178        }
179        // set new value.
180        m_active = active;
181        // set the new value to the selectbox.
182        m_selectBox.setEnabled(active);
183        // fire change event if necessary.
184        if (active) {
185            fireChangeEvent();
186        }
187
188    }
189
190    /**
191     * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#setName(java.lang.String)
192     */
193    public void setName(String name) {
194
195        // no input field so nothing to do
196
197    }
198
199    /**
200     * @see com.google.gwt.user.client.ui.HasValue#setValue(java.lang.Object)
201     */
202    public void setValue(String value) {
203
204        setValue(value, false);
205
206    }
207
208    /**
209     * @see com.google.gwt.user.client.ui.HasValue#setValue(java.lang.Object, boolean)
210     */
211    public void setValue(String value, boolean fireEvents) {
212
213        Map<String, String> items = m_selectBox.getItems();
214        if (m_allowUnknown) {
215            m_selectBox.setFormValue(value, false);
216        } else if (items.containsKey(value)) {
217            m_selectBox.selectValue(value);
218            m_externalValue = value;
219        } else {
220            m_selectBox.selectValue(m_defaultValue);
221        }
222        if (fireEvents) {
223            fireChangeEvent();
224        }
225
226    }
227
228    /**
229     * @see org.opencms.acacia.client.widgets.I_CmsEditWidget#shouldSetDefaultWhenDisabled()
230     */
231    public boolean shouldSetDefaultWhenDisabled() {
232
233        return true;
234    }
235
236    /**
237     * Helper class for parsing the configuration of the select-box. <p>
238     *
239     * @param config the configuration string
240     * */
241    private void parseConfiguration(String config) {
242
243        CmsSelectConfigurationParser parser = new CmsSelectConfigurationParser(config);
244        // set the help info first!!
245        for (Entry<String, String> helpEntry : parser.getHelpTexts().entrySet()) {
246            m_selectBox.setTitle(helpEntry.getKey(), helpEntry.getValue());
247        }
248        //set value and option to the combo box.
249        m_selectBox.setItems(parser.getOptions());
250        //if one entrance is declared for default.
251        if (parser.getDefaultValue() != null) {
252            //set the declared value selected.
253            m_selectBox.selectValue(parser.getDefaultValue());
254            m_defaultValue = parser.getDefaultValue();
255        }
256        fireChangeEvent();
257    }
258
259}