001package gwt.material.design.client.ui; 002 003/* 004 * #%L 005 * GwtMaterial 006 * %% 007 * Copyright (C) 2015 GwtMaterialDesign 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 com.google.gwt.dom.client.Document; 024import com.google.gwt.dom.client.Style.Unit; 025import com.google.gwt.event.dom.client.ClickEvent; 026import com.google.gwt.event.dom.client.ClickHandler; 027import com.google.gwt.event.dom.client.HasClickHandlers; 028import com.google.gwt.event.logical.shared.ValueChangeEvent; 029import com.google.gwt.event.logical.shared.ValueChangeHandler; 030import com.google.gwt.event.shared.HandlerRegistration; 031import com.google.gwt.user.client.ui.HasValue; 032import gwt.material.design.client.base.HasError; 033import gwt.material.design.client.base.MaterialWidget; 034import gwt.material.design.client.base.mixin.ErrorMixin; 035import gwt.material.design.client.constants.InputType; 036import gwt.material.design.client.ui.html.Label; 037import gwt.material.design.client.ui.html.Span; 038 039//@formatter:off 040 041/** 042 * Material Switch or other call it toggle - used for an alternative for checkbox 043 * 044 * <h3>UiBinder Usage:</h3> 045 * <pre> 046 *{@code<m:MaterialSwitch value="true"/> 047 *<m:MaterialSwitch value="true" disabled="true"/> 048 * } 049 * </pre> 050 * 051 * @author kevzlou7979 052 * @see <a href="http://gwtmaterialdesign.github.io/gwt-material-demo/#!forms">Material Switch</a> 053 */ 054//@formatter:on 055public class MaterialSwitch extends MaterialWidget implements HasValue<Boolean>, HasClickHandlers, HasError { 056 057 private MaterialInput input = new MaterialInput(); 058 private Span span = new Span(); 059 private Label label = new Label(); 060 private MaterialLabel lblError = new MaterialLabel(); 061 private Span onLabel = new Span(); 062 private Span offLabel = new Span(); 063 064 private final ErrorMixin<MaterialSwitch, MaterialLabel> errorMixin = new ErrorMixin<>(this, lblError, null); 065 066 /** 067 * Creates a switch element 068 */ 069 public MaterialSwitch() { 070 super(Document.get().createDivElement(), "switch"); 071 span.setStyleName("lever"); 072 input.setType(InputType.CHECKBOX); 073 074 addClickHandler(new ClickHandler() { 075 @Override 076 public void onClick(ClickEvent event) { 077 setValue(!getValue()); 078 } 079 }); 080 } 081 082 /** 083 * Creates a material switch with default value. 084 */ 085 public MaterialSwitch(boolean value) { 086 this(); 087 setValue(value); 088 } 089 090 @Override 091 protected void onLoad() { 092 super.onLoad(); 093 if(offLabel.getText() != null && !offLabel.getText().isEmpty()) { 094 label.add(offLabel); 095 } 096 label.add(input); 097 label.add(span); 098 add(label); 099 add(lblError); 100 lblError.getElement().getStyle().setMarginTop(16, Unit.PX); 101 102 if(onLabel.getText() != null && !onLabel.getText().isEmpty()) { 103 label.add(onLabel); 104 } 105 106 // register click handler here in order to have it at first position 107 // and therefore it will deal with clicks as first and setup the value 108 // right before others get notified. 109 addClickHandler(new ClickHandler() { 110 @Override 111 public void onClick(ClickEvent event) { 112 event.preventDefault(); 113 event.stopPropagation(); 114 } 115 }); 116 } 117 118 @Override 119 public void setEnabled(boolean enabled) { 120 super.setEnabled(enabled); 121 span.setEnabled(enabled); 122 input.setEnabled(enabled); 123 } 124 125 /** 126 * Set the value of switch component. 127 */ 128 @Override 129 public void setValue(Boolean value, boolean fireEvents) { 130 boolean oldValue = getValue(); 131 if(value) { 132 input.getElement().setAttribute("checked", "true"); 133 } else { 134 input.getElement().removeAttribute("checked"); 135 } 136 137 if(fireEvents && oldValue != value) { 138 ValueChangeEvent.fire(this, getValue()); 139 } 140 } 141 142 @Override 143 public void setValue(Boolean value) { 144 setValue(value, true); 145 } 146 147 /** 148 * Gets the value of switch component. 149 */ 150 @Override 151 public Boolean getValue() { 152 return input.getElement().hasAttribute("checked"); 153 } 154 155 @Override 156 public HandlerRegistration addValueChangeHandler(final ValueChangeHandler<Boolean> handler) { 157 return addHandler(new ValueChangeHandler<Boolean>() { 158 @Override 159 public void onValueChange(ValueChangeEvent<Boolean> event) { 160 if(isEnabled()){ 161 handler.onValueChange(event); 162 } 163 } 164 }, ValueChangeEvent.getType()); 165 } 166 167 /** 168 * @return the input 169 */ 170 public MaterialInput getInput() { 171 return input; 172 } 173 174 /** 175 * @param input the input to set 176 */ 177 public void setInput(MaterialInput input) { 178 this.input = input; 179 } 180 181 /** 182 * @return the span 183 */ 184 public Span getSpan() { 185 return span; 186 } 187 188 /** 189 * @param span the span to set 190 */ 191 public void setSpan(Span span) { 192 this.span = span; 193 } 194 195 /** 196 * @return the label 197 */ 198 @Deprecated 199 public Label getLabel() { 200 return label; 201 } 202 203 /** 204 * @param label the label to set 205 */ 206 @Deprecated 207 public void setLabel(Label label) { 208 this.label = label; 209 } 210 211 @Override 212 public HandlerRegistration addClickHandler(final ClickHandler handler) { 213 return addDomHandler(new ClickHandler() { 214 @Override 215 public void onClick(ClickEvent event) { 216 if(isEnabled()) { 217 handler.onClick(event); 218 } 219 } 220 }, ClickEvent.getType()); 221 } 222 223 @Override 224 public void setError(String error) { 225 errorMixin.setError(error); 226 } 227 228 @Override 229 public void setSuccess(String success) { 230 errorMixin.setSuccess(success); 231 } 232 233 @Override 234 public void setHelperText(String helperText) { 235 errorMixin.setHelperText(helperText); 236 } 237 238 @Override 239 public void clearErrorOrSuccess() { 240 errorMixin.clearErrorOrSuccess(); 241 } 242 243 /** 244 * Set the On State Label of the switch component 245 */ 246 public void setOnLabel(String label) { 247 onLabel.setText(label); 248 } 249 250 /** 251 * Set the Off State Label of the switch component 252 */ 253 public void setOffLabel(String label) { 254 offLabel.setText(label); 255 } 256}