001package org.gwtbootstrap3.extras.select.client.ui;
002
003/*
004 * #%L
005 * GwtBootstrap3
006 * %%
007 * Copyright (C) 2013 - 2016 GwtBootstrap3
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 * 
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 * 
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.CONTENT;
024import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.DIVIDER;
025import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.HIDDEN;
026import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.ICON;
027import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.SUBTEXT;
028import static org.gwtbootstrap3.extras.select.client.ui.SelectOptions.TOKENS;
029
030import org.gwtbootstrap3.client.ui.base.AbstractTextWidget;
031import org.gwtbootstrap3.client.ui.base.mixin.AttributeMixin;
032import org.gwtbootstrap3.client.ui.base.mixin.EnabledMixin;
033import org.gwtbootstrap3.client.ui.constants.IconType;
034
035import com.google.gwt.dom.client.Document;
036import com.google.gwt.dom.client.OptionElement;
037import com.google.gwt.user.client.TakesValue;
038import com.google.gwt.user.client.ui.HasEnabled;
039import com.google.gwt.user.client.ui.HasName;
040
041/**
042 * Select option widget.
043 *
044 * @author Xiaodong Sun
045 */
046public class Option extends AbstractTextWidget implements HasName, TakesValue<String>, HasEnabled {
047
048    private final AttributeMixin<Option> attrMixin = new AttributeMixin<>(this);
049    private final EnabledMixin<Option> enabledMixin = new EnabledMixin<>(this);
050
051    private static final String NAME = "name";
052    private static final String VALUE = "value";
053
054    public Option() {
055        super(Document.get().createOptionElement());
056    }
057
058    /**
059     * Returns the {@link OptionElement}.
060     *
061     * @return the {@link OptionElement}.
062     */
063    public OptionElement getSelectElement() {
064        return getElement().cast();
065    }
066
067    /**
068     * Returns <code>true</code> if the option is selected.
069     *
070     * @return <code>true</code> if the option is selected
071     */
072    public boolean isSelected() {
073        return isDivider() ? false : getSelectElement().isSelected();
074    }
075
076    /**
077     * Selects/deselects the option.
078     *
079     * @param selected
080     */
081    public void setSelected(boolean selected) {
082        getSelectElement().setSelected(isDivider() ? false : selected);
083    }
084
085    @Override
086    public void setName(final String name) {
087        if (name != null)
088            attrMixin.setAttribute(NAME, name);
089        else
090            attrMixin.removeAttribute(NAME);
091    }
092
093    @Override
094    public String getName() {
095        String name = attrMixin.getAttribute(NAME);
096        return name.isEmpty() ? null : name;
097    }
098
099    @Override
100    public void setValue(final String value) {
101        if (value != null)
102            attrMixin.setAttribute(VALUE, value);
103        else
104            attrMixin.removeAttribute(VALUE);
105    }
106
107    /**
108     * Returns the value of the option. If no value, fall-back
109     * to the displayed option text.
110     */
111    @Override
112    public String getValue() {
113        String value = attrMixin.getAttribute(VALUE);
114        return value.isEmpty() ? getText() : value;
115    }
116
117    @Override
118    public boolean isEnabled() {
119        return enabledMixin.isEnabled();
120    }
121
122    @Override
123    public void setEnabled(final boolean enabled) {
124        enabledMixin.setEnabled(enabled);
125    }
126
127    /**
128     * Adds key words to improve the searchability.
129     *
130     * @param tokens
131     */
132    public void setTokens(final String tokens) {
133        if (tokens != null)
134            attrMixin.setAttribute(TOKENS, tokens);
135        else
136            attrMixin.removeAttribute(TOKENS);
137    }
138
139    /**
140     * Returns the search key words.
141     *
142     * @return
143     */
144    public String getTokens() {
145        String tokens = attrMixin.getAttribute(TOKENS);
146        return tokens.isEmpty() ? null : tokens;
147    }
148
149    /**
150     * Turns the option into a divider.
151     *
152     * @param divider
153     */
154    public void setDivider(final boolean divider) {
155        if (divider)
156            attrMixin.setAttribute(DIVIDER, Boolean.toString(true));
157        else
158            attrMixin.removeAttribute(DIVIDER);
159    }
160
161    /**
162     * Returns <code>true</code> if the option is a divider.
163     *
164     * @return <code>true</code> if the option is a divider
165     */
166    public boolean isDivider() {
167        return Boolean.parseBoolean(attrMixin.getAttribute(DIVIDER));
168    }
169
170    /**
171     * Set the specified sub-text to the option.
172     *
173     * @param subtext
174     */
175    public void setSubtext(final String subtext) {
176        if (subtext != null)
177            attrMixin.setAttribute(SUBTEXT, subtext);
178        else
179            attrMixin.removeAttribute(SUBTEXT);
180    }
181
182    /**
183     * Returns the sub-text of the option.
184     *
185     * @return
186     */
187    public String getSubtext() {
188        String subtext = attrMixin.getAttribute(SUBTEXT);
189        return subtext.isEmpty() ? null : subtext;
190    }
191
192    /**
193     * Add an icon to the option.
194     *
195     * @param iconType
196     */
197    public void setIcon(final IconType iconType) {
198        if (iconType != null)
199            attrMixin.setAttribute(ICON, iconType.getCssName());
200        else
201            attrMixin.removeAttribute(ICON);
202    }
203
204    /**
205     * Returns the icon of the option; may be <code>null</code>.
206     *
207     * @return
208     */
209    public IconType getIcon() {
210        return IconType.fromStyleName(attrMixin.getAttribute(ICON));
211    }
212
213    /**
214     * Inserts custom HTML into the option.
215     *
216     * @param content
217     */
218    public void setContent(final String content) {
219        if (content != null)
220            attrMixin.setAttribute(CONTENT, content);
221        else
222            attrMixin.removeAttribute(CONTENT);
223    }
224
225    /**
226     * Returns the custom HTML content; may be <code>null</code>.
227     *
228     * @return the custom HTML content
229     */
230    public String getContent() {
231        String content = attrMixin.getAttribute(CONTENT);
232        return content.isEmpty() ? null : content;
233    }
234
235    /**
236     * Hides the option if set to <code>true</code>.<br>
237     * <br>
238     * Defaults to <code>false</code>.
239     *
240     * @param hidden
241     */
242    public void setHidden(final boolean hidden) {
243        if (hidden)
244            attrMixin.setAttribute(HIDDEN, Boolean.toString(true));
245        else
246            attrMixin.removeAttribute(HIDDEN);
247    }
248
249    /**
250     * Returns <code>true</code> if the option is hidden.
251     *
252     * @return <code>true</code> if the option is hidden
253     */
254    public boolean isHidden() {
255        return Boolean.parseBoolean(attrMixin.getAttribute(HIDDEN));
256    }
257}