001 package org.gwtbootstrap3.client.ui;
002
003 /*
004 * #%L
005 * GwtBootstrap3
006 * %%
007 * Copyright (C) 2013 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
023 import org.gwtbootstrap3.client.ui.base.HasActive;
024 import org.gwtbootstrap3.client.ui.base.HasIcon;
025 import org.gwtbootstrap3.client.ui.base.HasIconPosition;
026 import org.gwtbootstrap3.client.ui.base.HasSize;
027 import org.gwtbootstrap3.client.ui.base.HasType;
028 import org.gwtbootstrap3.client.ui.base.helper.StyleHelper;
029 import org.gwtbootstrap3.client.ui.base.mixin.ActiveMixin;
030 import org.gwtbootstrap3.client.ui.constants.ButtonSize;
031 import org.gwtbootstrap3.client.ui.constants.ButtonType;
032 import org.gwtbootstrap3.client.ui.constants.IconFlip;
033 import org.gwtbootstrap3.client.ui.constants.IconPosition;
034 import org.gwtbootstrap3.client.ui.constants.IconRotate;
035 import org.gwtbootstrap3.client.ui.constants.IconSize;
036 import org.gwtbootstrap3.client.ui.constants.IconType;
037 import org.gwtbootstrap3.client.ui.constants.Styles;
038
039 import com.google.gwt.dom.client.Document;
040 import com.google.gwt.dom.client.InputElement;
041 import com.google.gwt.event.dom.client.ClickEvent;
042 import com.google.gwt.event.dom.client.ClickHandler;
043 import com.google.gwt.event.logical.shared.ValueChangeEvent;
044 import com.google.gwt.i18n.client.HasDirection.Direction;
045 import com.google.gwt.i18n.shared.DirectionEstimator;
046 import com.google.gwt.safehtml.shared.SafeHtml;
047 import com.google.gwt.user.client.DOM;
048 import com.google.gwt.user.client.Event;
049
050 /**
051 * Button representing a checkbox used within a {@link ButtonGroup} that has
052 * toggle set to {@code Toogle.BUTTONS}.
053 * <p/>
054 * If you are looking for a classic checkbox see {@link CheckBox}.
055 *
056 * @author Sven Jacobs
057 */
058 public class CheckBoxButton extends CheckBox implements HasActive,
059 HasType<ButtonType>, HasSize<ButtonSize>, HasIcon, HasIconPosition {
060
061 private final ActiveMixin<CheckBoxButton> activeMixin = new ActiveMixin<CheckBoxButton>(this);
062
063 private IconPosition iconPosition = IconPosition.LEFT;
064 private Icon icon;
065
066 /**
067 * Creates a check box button with the specified text label.
068 *
069 * @param label
070 * the check box's label
071 */
072 public CheckBoxButton(SafeHtml label) {
073 this(label.asString(), true);
074 }
075
076 /**
077 * Creates a check box button with the specified text label.
078 *
079 * @param label
080 * the check box's label
081 * @param dir
082 * the text's direction. Note that {@code DEFAULT} means
083 * direction should be inherited from the widget's parent
084 * element.
085 */
086 public CheckBoxButton(SafeHtml label, Direction dir) {
087 this();
088 setHTML(label, dir);
089 }
090
091 /**
092 * Creates a check box button with the specified text label.
093 *
094 * @param label
095 * the check box's label
096 * @param directionEstimator
097 * A DirectionEstimator object used for automatic direction
098 * adjustment. For convenience,
099 * {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used.
100 */
101 public CheckBoxButton(SafeHtml label, DirectionEstimator directionEstimator) {
102 this();
103 setDirectionEstimator(directionEstimator);
104 setHTML(label.asString());
105 }
106
107 /**
108 * Creates a check box button with the specified text label.
109 *
110 * @param label
111 * the check box's label
112 */
113 public CheckBoxButton(String label) {
114 this();
115 setText(label);
116 }
117
118 /**
119 * Creates a check box button with the specified text label.
120 *
121 * @param label
122 * the check box's label
123 * @param dir
124 * the text's direction. Note that {@code DEFAULT} means
125 * direction should be inherited from the widget's parent
126 * element.
127 */
128 public CheckBoxButton(String label, Direction dir) {
129 this();
130 setText(label, dir);
131 }
132
133 /**
134 * Creates a label with the specified text and a default direction
135 * estimator.
136 *
137 * @param label
138 * the check box's label
139 * @param directionEstimator
140 * A DirectionEstimator object used for automatic direction
141 * adjustment. For convenience,
142 * {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used.
143 */
144 public CheckBoxButton(String label, DirectionEstimator directionEstimator) {
145 this();
146 setDirectionEstimator(directionEstimator);
147 setText(label);
148 }
149
150 /**
151 * Creates a check box button with the specified text label.
152 *
153 * @param label
154 * the check box's label
155 * @param asHTML
156 * <code>true</code> to treat the specified label as html
157 */
158 public CheckBoxButton(String label, boolean asHTML) {
159 this();
160 if (asHTML) {
161 setHTML(label);
162 } else {
163 setText(label);
164 }
165 }
166
167 public CheckBoxButton() {
168 this(Document.get().createCheckInputElement());
169 }
170
171 protected CheckBoxButton(InputElement element) {
172 super(DOM.createLabel(), element);
173
174 setStyleName(Styles.BTN);
175 setType(ButtonType.DEFAULT);
176
177 getElement().appendChild(inputElem);
178 getElement().appendChild(Document.get().createTextNode(" "));
179 getElement().appendChild(labelElem);
180 getElement().appendChild(Document.get().createTextNode(" "));
181 }
182
183 @Override
184 protected void ensureDomEventHandlers() {
185 // Use a ClickHandler since Bootstrap's jQuery does not trigger native
186 // change events:
187 // http://learn.jquery.com/events/triggering-event-handlers/
188 addClickHandler(new ClickHandler() {
189
190 @Override
191 public void onClick(ClickEvent event) {
192 ValueChangeEvent.fire(CheckBoxButton.this, getValue());
193 }
194
195 });
196 }
197
198 @Override
199 public void sinkEvents(int eventBitsToAdd) {
200 // Sink on the actual element because that's what gets clicked
201 if (isOrWasAttached()) {
202 Event.sinkEvents(getElement(),
203 eventBitsToAdd | Event.getEventsSunk(getElement()));
204 } else {
205 super.sinkEvents(eventBitsToAdd);
206 }
207 }
208
209 @Override
210 public void setSize(ButtonSize size) {
211 StyleHelper.addUniqueEnumStyleName(this, ButtonSize.class, size);
212 }
213
214 @Override
215 public ButtonSize getSize() {
216 return ButtonSize.fromStyleName(getStyleName());
217 }
218
219 @Override
220 public void setType(ButtonType type) {
221 StyleHelper.addUniqueEnumStyleName(this, ButtonType.class, type);
222 }
223
224 @Override
225 public ButtonType getType() {
226 return ButtonType.fromStyleName(getStyleName());
227 }
228
229 @Override
230 public void setActive(boolean active) {
231 setValue(active);
232 activeMixin.setActive(active);
233 }
234
235 @Override
236 public boolean isActive() {
237 return activeMixin.isActive();
238 }
239
240 @Override
241 public void setIconPosition(IconPosition iconPosition) {
242 this.iconPosition = iconPosition;
243 render();
244 }
245
246 @Override
247 public IconPosition getIconPosition() {
248 return iconPosition;
249 }
250
251 @Override
252 public void setIcon(IconType iconType) {
253 getActualIcon().setType(iconType);
254 }
255
256 @Override
257 public IconType getIcon() {
258 return getActualIcon().getType();
259 }
260
261 @Override
262 public void setIconSize(IconSize iconSize) {
263 getActualIcon().setSize(iconSize);
264 }
265
266 @Override
267 public IconSize getIconSize() {
268 return getActualIcon().getSize();
269 }
270
271 @Override
272 public void setIconFlip(IconFlip iconFlip) {
273 getActualIcon().setFlip(iconFlip);
274 }
275
276 @Override
277 public IconFlip getIconFlip() {
278 return getActualIcon().getFlip();
279 }
280
281 @Override
282 public void setIconRotate(IconRotate iconRotate) {
283 getActualIcon().setRotate(iconRotate);
284 }
285
286 @Override
287 public IconRotate getIconRotate() {
288 return getActualIcon().getRotate();
289 }
290
291 @Override
292 public void setIconBordered(boolean iconBordered) {
293 getActualIcon().setBorder(iconBordered);
294 }
295
296 @Override
297 public boolean isIconBordered() {
298 return getActualIcon().isBorder();
299 }
300
301 @Override
302 public void setIconMuted(boolean iconMuted) {
303 getActualIcon().setMuted(iconMuted);
304 }
305
306 @Override
307 public boolean isIconMuted() {
308 return getActualIcon().isMuted();
309 }
310
311 @Override
312 public void setIconLight(boolean iconLight) {
313 getActualIcon().setLight(iconLight);
314 }
315
316 @Override
317 public boolean isIconLight() {
318 return getActualIcon().isLight();
319 }
320
321 @Override
322 public void setIconSpin(boolean iconSpin) {
323 getActualIcon().setSpin(iconSpin);
324 }
325
326 @Override
327 public boolean isIconSpin() {
328 return getActualIcon().isSpin();
329 }
330
331 @Override
332 public void setIconFixedWidth(boolean iconFixedWidth) {
333 getActualIcon().setFixedWidth(iconFixedWidth);
334 }
335
336 @Override
337 public boolean isIconFixedWidth() {
338 return getActualIcon().isFixedWidth();
339 }
340
341 private Icon getActualIcon() {
342 if (icon == null) {
343 icon = new Icon();
344 render();
345 }
346 return icon;
347 }
348
349 private void render() {
350 if (iconPosition == IconPosition.LEFT) {
351 getElement().insertAfter(icon.getElement(), inputElem);
352 } else {
353 getElement().insertAfter(icon.getElement(), null);
354 }
355 }
356
357 }