001/*
002 *  Copyright 2012 GWT-Bootstrap
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package com.github.gwtbootstrap.client.ui;
017
018import java.util.List;
019
020import com.github.gwtbootstrap.client.ui.base.HasAlternateSize;
021import com.github.gwtbootstrap.client.ui.base.HasId;
022import com.github.gwtbootstrap.client.ui.base.HasSize;
023import com.github.gwtbootstrap.client.ui.base.HasStyle;
024import com.github.gwtbootstrap.client.ui.base.IsResponsive;
025import com.github.gwtbootstrap.client.ui.base.IsSearchQuery;
026import com.github.gwtbootstrap.client.ui.base.ResponsiveHelper;
027import com.github.gwtbootstrap.client.ui.base.SearchQueryStyleHelper;
028import com.github.gwtbootstrap.client.ui.base.SizeHelper;
029import com.github.gwtbootstrap.client.ui.base.Style;
030import com.github.gwtbootstrap.client.ui.base.StyleHelper;
031import com.github.gwtbootstrap.client.ui.constants.AlternateSize;
032import com.github.gwtbootstrap.client.ui.constants.Constants;
033import com.github.gwtbootstrap.client.ui.constants.ControlGroupType;
034import com.github.gwtbootstrap.client.ui.constants.Device;
035import com.google.gwt.dom.client.Element;
036import com.google.gwt.editor.client.EditorError;
037import com.google.gwt.editor.client.HasEditorErrors;
038import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
039import com.google.gwt.user.client.ui.Widget;
040
041/**
042 * A ListBox for Bootstrap form.
043 * 
044 * @since 2.0.4.0
045 * 
046 * @author ohashi keisuke
047 * 
048 */
049public class ListBox extends com.google.gwt.user.client.ui.ListBox implements HasSize, HasAlternateSize, IsSearchQuery, HasId , IsResponsive , HasStyle, HasEditorErrors<String>{
050
051        /** Widget for control decoration on <code>EditorError</code>s */
052        private Widget controlGroup;// could be a ControlGroup widget
053        /** Widget where <code>EditorError</code>s messages will be placed */
054        private Widget errorLabel;// could be a HelpInline widget
055        
056        {
057                setStyleName("");
058        }
059
060        /**
061         * Creates an empty list box in single selection mode.
062         */
063        public ListBox() {
064                super();
065        }
066
067        /**
068         * Creates an empty list box. The preferred way to enable multiple
069         * selections is to use this constructor rather than
070         * {@link #setMultipleSelect(boolean)}.
071         * 
072         * @param isMultipleSelect
073         *            specifies if multiple selection is enabled
074         */
075        public ListBox(boolean isMultipleSelect) {
076                super(isMultipleSelect);
077        }
078
079        /**
080         * This constructor may be used by subclasses to explicitly use an existing
081         * element. This element must be a &lt;select&gt; element.
082         * 
083         * @param element
084         *            the element to be used
085         */
086        protected ListBox(Element element) {
087                super(element);
088        }
089
090        /**
091         * {@inheritDoc}
092         */
093        @Override
094        public void setAlternateSize(AlternateSize size) {
095                StyleHelper.changeStyle(this, size, AlternateSize.class);
096        }
097
098        /**
099         * {@inheritDoc}
100         */
101        @Override
102        public void setSize(int size) {
103                SizeHelper.setSize(this, size);
104        }
105
106        /**
107         * Get Selected Value.
108         * <p>
109         * If set multiple,return first selected value.
110         * @return Selected Value.(If there is nothing selected item,return null)
111         */
112        public String getValue() {
113
114                if(getSelectedIndex() == -1) {
115                        return null;
116                }
117
118                return getValue(getSelectedIndex());
119        }
120
121        /**
122         * {@inheritDoc}
123         */
124        @Override
125        public void setSearchQuery(boolean searchQuery) {
126                SearchQueryStyleHelper.setSearchQuery(this, searchQuery);
127        }
128
129        /**
130         * {@inheritDoc}
131         */
132        @Override
133        public boolean isSearchQuery() {
134                return SearchQueryStyleHelper.isSearchQuery(this);
135        }
136
137        /**
138         * {@inheritDoc}
139         */
140        @Override
141        public String getId() {
142                return getElement().getId();
143        }
144
145        /**
146         * {@inheritDoc}
147         */
148        @Override
149        public void setId(String id) {
150                getElement().setId(id);
151        }
152
153        /**
154         * {@inheritDoc}
155         */
156        @Override
157        public void setEnabled(boolean enabled) {
158                super.setEnabled(enabled);
159                if(enabled) {
160                        removeStyleName(Constants.DISABLED);
161                } else {
162                        addStyleName(Constants.DISABLED);
163                }
164        }
165
166        /**
167         * Selects item which has the given value. If value
168         * is not found, nothing is done.
169         * @param value to be selected (<code>null</code>-safe)
170         */
171        public void setSelectedValue(String value) {
172                if (value == null) {
173                        value = "";
174                }
175                for(int i = 0; i < getItemCount(); i++) {
176                        if (getValue(i).equals(value)) {
177                                setSelectedIndex(i);
178                                return;
179                        }
180                }
181        }
182        
183
184        /**
185         * {@inheritDoc}
186         */
187        @Override
188        public void setShowOn(Device device) {
189                ResponsiveHelper.setShowOn(this, device);
190        }
191
192        /**
193         * {@inheritDoc}
194         */
195        @Override
196        public void setHideOn(Device device) {
197                ResponsiveHelper.setHideOn(this, device);
198                
199        }
200
201        /**
202         * {@inheritDoc}
203         */
204        @Override
205        public void setStyle(Style style) {
206                StyleHelper.setStyle(this, style);
207        }
208
209        /**
210         * {@inheritDoc}
211         */
212        @Override
213        public void addStyle(Style style) {
214                StyleHelper.addStyle(this, style);
215        }
216
217        /**
218         * {@inheritDoc}
219         */
220        @Override
221        public void removeStyle(Style style) {
222                StyleHelper.removeStyle(this, style);
223                
224        }
225        
226        /**
227         * 
228         * @see com.google.gwt.editor.client.HasEditorErrors#showErrors(java.util.List)
229         */
230        @Override
231        public void showErrors(List<EditorError> errors) {
232                Widget decoratedWidget = controlGroup != null? controlGroup : this;
233                if(errors != null && !errors.isEmpty()) {
234                        StyleHelper.addStyle(decoratedWidget, ControlGroupType.ERROR);
235                        SafeHtmlBuilder sb = new SafeHtmlBuilder();
236                        for (EditorError error : errors) {
237                                if(error.getEditor() == this) {
238                                        error.setConsumed(true);
239                                        sb.appendEscaped(error.getMessage());
240                                        sb.appendHtmlConstant("<br />");
241                                }
242                        }
243                        setErrorLabelText(sb.toSafeHtml().asString());
244                } else {
245                        StyleHelper.removeStyle(decoratedWidget, ControlGroupType.ERROR);
246                        setErrorLabelText("");
247                }
248        }
249
250        /**
251         * The widget that will be decorated on <code>EditorError</code>s will be added de <code>ControlGroupType.ERROR</code> style.
252         * It can be a ControlGroup or any widget.
253         * @param controlGroup
254         */
255        public void setControlGroup(Widget controlGroup) {
256                this.controlGroup = controlGroup;
257        }
258        /**
259         * Widget where <code>EditorError</code>s messages will be placed.
260         * It can be a HelpBlock or any other widget.
261         * @param errorLabel
262         */
263        public void setErrorLabel(Widget errorLabel) {
264                this.errorLabel = errorLabel;
265        }
266
267        /**
268         * Sets the content of the <code>EditorError</code>s messages inside de <code>errorLabel</code>.
269         * This implementation uses {@link Element#setInnerHTML(String)} to set the content.
270         * @param errorMessage
271         */
272        protected void setErrorLabelText(String errorMessage) {
273                if(errorLabel != null) {
274                        errorLabel.getElement().setInnerHTML(errorMessage);
275                }
276        }
277}