001 package org.gwtbootstrap3.extras.toggleswitch.client.ui.base;
002
003 /*
004 * #%L
005 * GwtBootstrap3
006 * %%
007 * Copyright (C) 2013 - 2015 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 com.google.gwt.dom.client.Element;
024 import com.google.gwt.editor.client.IsEditor;
025 import com.google.gwt.editor.client.LeafValueEditor;
026 import com.google.gwt.editor.client.adapters.TakesValueEditor;
027 import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
028 import com.google.gwt.event.logical.shared.ValueChangeEvent;
029 import com.google.gwt.event.logical.shared.ValueChangeHandler;
030 import com.google.gwt.event.shared.HandlerRegistration;
031 import com.google.gwt.user.client.ui.*;
032
033 import org.gwtbootstrap3.client.ui.Icon;
034 import org.gwtbootstrap3.client.ui.base.HasId;
035 import org.gwtbootstrap3.client.ui.base.HasResponsiveness;
036 import org.gwtbootstrap3.client.ui.base.HasSize;
037 import org.gwtbootstrap3.client.ui.base.helper.StyleHelper;
038 import org.gwtbootstrap3.client.ui.base.mixin.AttributeMixin;
039 import org.gwtbootstrap3.client.ui.base.mixin.IdMixin;
040 import org.gwtbootstrap3.client.ui.constants.DeviceSize;
041 import org.gwtbootstrap3.client.ui.constants.IconSize;
042 import org.gwtbootstrap3.client.ui.constants.IconType;
043 import org.gwtbootstrap3.extras.toggleswitch.client.ui.base.constants.ColorType;
044 import org.gwtbootstrap3.extras.toggleswitch.client.ui.base.constants.SizeType;
045
046 /**
047 * Original source from http://www.bootstrap-switch.org/
048 * @author Grant Slender
049 */
050 public class ToggleSwitchBase extends Widget implements HasSize<SizeType>, HasValue<Boolean>, HasValueChangeHandlers<Boolean>,
051 HasEnabled, HasVisibility, HasId, HasName, HasResponsiveness, IsEditor<LeafValueEditor<Boolean>> {
052
053 private final SimpleCheckBox checkBox;
054 private SizeType size = SizeType.REGULAR;
055 private ColorType onColor = ColorType.DEFAULT;
056 private ColorType offColor = ColorType.PRIMARY;
057 private final IdMixin<ToggleSwitchBase> idMixin = new IdMixin<ToggleSwitchBase>(this);
058 private final AttributeMixin<ToggleSwitchBase> attributeMixin = new AttributeMixin<ToggleSwitchBase>(this);
059 private LeafValueEditor<Boolean> editor;
060
061 protected ToggleSwitchBase(SimpleCheckBox checkBox) {
062 this.checkBox = checkBox;
063 // remove the gwt styles
064 checkBox.setStyleName("");
065 setElement((Element) checkBox.getElement());
066 }
067
068 @Override
069 protected void onLoad() {
070 super.onLoad();
071 switchInit(getElement());
072 }
073
074 @Override
075 protected void onUnload() {
076 super.onUnload();
077 switchDestroy(getElement());
078 }
079
080 @Override
081 public void setVisibleOn(final DeviceSize deviceSize) {
082 StyleHelper.setVisibleOn(this, deviceSize);
083 }
084
085 @Override
086 public void setHiddenOn(final DeviceSize deviceSize) {
087 StyleHelper.setHiddenOn(this, deviceSize);
088 }
089
090 @Override
091 public void setId(final String id) {
092 idMixin.setId(id);
093 }
094
095 @Override
096 public String getId() {
097 return idMixin.getId();
098 }
099
100 @Override
101 public void setName(String name) {
102 checkBox.setName(name);
103 }
104
105 @Override
106 public String getName() {
107 return checkBox.getName();
108 }
109
110 @Override
111 public boolean isEnabled() {
112 return !getBooleanAttribute(Option.DISABLED);
113 }
114
115 @Override
116 public void setEnabled(final boolean enabled) {
117 updateSwitch(Option.DISABLED, !enabled);
118 }
119
120 @Override
121 public SizeType getSize() {
122 return size;
123 }
124
125 @Override
126 public void setSize(final SizeType size) {
127 this.size = size;
128 updateSwitch(Option.SIZE, size.getType());
129 }
130
131 public ColorType getOnColor() {
132 return onColor;
133 }
134
135 public void setOnColor(final ColorType onColor) {
136 this.onColor = onColor;
137 updateSwitch(Option.ON_COLOR, onColor.getType());
138 }
139
140 public ColorType getOffColor() {
141 return offColor;
142 }
143
144 public void setOffColor(final ColorType offColor) {
145 this.offColor = offColor;
146 updateSwitch(Option.OFF_COLOR, offColor.getType());
147 }
148
149 public boolean isAnimate() {
150 return getBooleanAttribute(Option.ANIMATE);
151 }
152
153 public void setAnimate(final boolean animate) {
154 updateSwitch(Option.ANIMATE, animate);
155 }
156
157 public String getOnText() {
158 return getStringAttribute(Option.ON_TEXT);
159 }
160
161 public void setOnText(final String onText) {
162 updateSwitch(Option.ON_TEXT, onText);
163 }
164
165 public void setOnIcon(final IconType iconType) {
166 String text = createIconHtml(iconType);
167 setOnText(text);
168 }
169
170 public String getOffText() {
171 return getStringAttribute(Option.OFF_TEXT);
172 }
173
174 public void setOffText(final String offText) {
175 updateSwitch(Option.OFF_TEXT, offText);
176 }
177
178 public void setOffIcon(final IconType iconType) {
179 String text = createIconHtml(iconType);
180 setOffText(text);
181 }
182
183 public String getLabelText() {
184 return getStringAttribute(Option.LABEL_TEXT);
185 }
186
187 public void setLabelText(final String labelText) {
188 updateSwitch(Option.LABEL_TEXT, labelText);
189 }
190
191 @Override
192 public HandlerRegistration addValueChangeHandler(final ValueChangeHandler<Boolean> handler) {
193 return addHandler(handler, ValueChangeEvent.getType());
194 }
195
196 @Override
197 public Boolean getValue() {
198 if (isAttached()) {
199 return switchState(getElement());
200 }
201 return checkBox.getValue();
202 }
203
204 @Override
205 public void setValue(final Boolean value) {
206 setValue(value, false);
207 }
208
209 @Override
210 public void setValue(final Boolean value, final boolean fireEvents) {
211 Boolean oldValue = getValue();
212 if (isAttached()) {
213 switchState(getElement(), value, true);
214 } else {
215 checkBox.setValue(value);
216 }
217 if (fireEvents) {
218 ValueChangeEvent.fireIfNotEqual(ToggleSwitchBase.this, oldValue, value);
219 }
220 }
221
222 public void onChange(final boolean value) {
223 ValueChangeEvent.fire(this, value);
224 }
225
226 @Override
227 public LeafValueEditor<Boolean> asEditor() {
228 if (editor == null) {
229 editor = TakesValueEditor.of(this);
230 }
231 return editor;
232 }
233
234 public boolean isReadOnly() {
235 return getBooleanAttribute(Option.READONLY);
236 }
237
238 public void setReadOnly(boolean readOnly) {
239 updateSwitch(Option.READONLY, readOnly);
240 }
241
242 public boolean isIndeterminate() {
243 return getBooleanAttribute(Option.INDETERMINATE);
244 }
245
246 /**
247 * Indeterminate state.
248 */
249 public void setIndeterminate(boolean indeterminate) {
250 updateSwitch(Option.INDETERMINATE, indeterminate);
251 }
252
253 public boolean isInverse() {
254 return getBooleanAttribute(Option.INVERSE);
255 }
256
257 /**
258 * Inverse switch direction.
259 */
260 public void setInverse(boolean inverse) {
261 updateSwitch(Option.INVERSE, inverse);
262 }
263
264 public boolean isRadioAllOff() {
265 return getBooleanAttribute(Option.RADIO_ALL_OFF);
266 }
267
268 /**
269 * Allow this radio button to be unchecked by the user.
270 */
271 public void setRadioAllOff(boolean radioAllOff) {
272 updateSwitch(Option.RADIO_ALL_OFF, radioAllOff);
273 }
274
275 /**
276 * Sets the handle's width.
277 * @param labelWidth - set to "auto" (default) for automatic sizing, integer otherwise
278 */
279 public void setHandleWidth(String handleWidth) {
280 updateSwitch(Option.HANDLE_WIDTH, handleWidth);
281 }
282
283 /**
284 * Sets the label's width (the space between handles).
285 * @param labelWidth - set to "auto" (default) for automatic sizing, integer otherwise
286 */
287 public void setLabelWidth(String labelWidth) {
288 updateSwitch(Option.LABEL_WIDTH, labelWidth);
289 }
290
291 private String createIconHtml(IconType iconType) {
292 // Fix incorrect handle width when using icons
293 setHandleWidth("30");
294 final Icon icon = new Icon(iconType);
295 icon.setSize(IconSize.LARGE);
296 return icon.getElement().getString();
297 }
298
299 private void updateSwitch(Option option, String value) {
300 if (isAttached()) {
301 switchCmd(getElement(), option.getCommand(), value);
302 } else {
303 attributeMixin.setAttribute(option.getAttribute(), value);
304 }
305 }
306
307 private void updateSwitch(Option option, boolean value) {
308 if (isAttached()) {
309 switchCmd(getElement(), option.getCommand(), value);
310 } else {
311 attributeMixin.setAttribute(option.getAttribute(), Boolean.toString(value));
312 }
313 }
314
315 private String getStringAttribute(Option option) {
316 if (isAttached()) {
317 return getCommandStringValue(getElement(), option.getCommand());
318 } else {
319 return attributeMixin.getAttribute(option.getAttribute());
320 }
321 }
322
323 private boolean getBooleanAttribute(Option option) {
324 if (isAttached()) {
325 return getCommandBooleanValue(getElement(), option.getCommand());
326 } else {
327 String value = attributeMixin.getAttribute(option.getAttribute());
328 if (value != null && !value.isEmpty()) {
329 return Boolean.valueOf(value);
330 } else {
331 return false;
332 }
333 }
334 }
335
336 private native void switchInit(Element e) /*-{
337 $wnd.jQuery(e).bootstrapSwitch();
338
339 var me = this;
340 $wnd.jQuery(e).on('switchChange.bootstrapSwitch', function (em, state) {
341 me.@org.gwtbootstrap3.extras.toggleswitch.client.ui.base.ToggleSwitchBase::onChange(Z)(state);
342 });
343 }-*/;
344
345 private native void switchDestroy(Element e) /*-{
346 $wnd.jQuery(e).off('switchChange.bootstrapSwitch');
347 $wnd.jQuery(e).bootstrapSwitch('destroy');
348 }-*/;
349
350 private native void switchCmd(Element e, String cmd, String value) /*-{
351 $wnd.jQuery(e).bootstrapSwitch(cmd, value);
352 }-*/;
353
354 private native void switchCmd(Element e, String cmd, boolean value) /*-{
355 $wnd.jQuery(e).bootstrapSwitch(cmd, value);
356 }-*/;
357
358 private native String getCommandStringValue(Element e, String cmd) /*-{
359 return $wnd.jQuery(e).bootstrapSwitch(cmd);
360 }-*/;
361
362 private native boolean getCommandBooleanValue(Element e, String cmd) /*-{
363 return $wnd.jQuery(e).bootstrapSwitch(cmd);
364 }-*/;
365
366 private native void switchState(Element e, boolean value, boolean skip) /*-{
367 $wnd.jQuery(e).bootstrapSwitch('state', value, skip);
368 }-*/;
369
370 private native boolean switchState(Element e) /*-{
371 return $wnd.jQuery(e).bootstrapSwitch('state');
372 }-*/;
373 }