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.Element; 025import com.google.gwt.dom.client.NodeList; 026import com.google.gwt.dom.client.Style.Unit; 027import com.google.gwt.event.dom.client.ChangeEvent; 028import com.google.gwt.event.dom.client.ChangeHandler; 029import com.google.gwt.event.dom.client.HasChangeHandlers; 030import com.google.gwt.event.shared.HandlerRegistration; 031import gwt.material.design.client.base.MaterialWidget; 032import gwt.material.design.client.base.HasError; 033import gwt.material.design.client.base.mixin.ErrorMixin; 034import gwt.material.design.client.constants.InputType; 035import gwt.material.design.client.ui.html.Paragraph; 036import gwt.material.design.client.ui.html.Span; 037 038//@formatter:off 039 040/** 041 * Material Range - a slider that initialize the minimum and maximum values. 042 * 043 * <h3>UiBinder Usage:</h3> 044 * <pre> 045 *{@code<m:MaterialRange value="2" min="20" max="50" value="25"/>} 046 * </pre> 047 * 048 * @author kevzlou7979 049 * @author Ben Dol 050 * @see <a href="http://gwt-material-demo.herokuapp.com/#forms">Material Range</a> 051 */ 052//@formatter:on 053public class MaterialRange extends MaterialWidget implements HasChangeHandlers, HasError { 054 055 private Paragraph paragraph = new Paragraph(); 056 private MaterialInput input = new MaterialInput(); 057 private Span thumb = new Span(); 058 059 private static String VALUE = "value"; 060 private static String MAX = "max"; 061 private static String MIN = "min"; 062 private static String INPUT = "INPUT"; 063 private MaterialLabel lblError = new MaterialLabel(); 064 065 // cache the embedded range input element 066 private Element rangeElement = null; 067 068 private final ErrorMixin<MaterialRange, MaterialLabel> errorMixin = new ErrorMixin<>(this, lblError, null); 069 070 /** 071 * Creates a range 072 */ 073 public MaterialRange() { 074 super(Document.get().createElement("form")); 075 getElement().setAttribute("action", "#"); 076 lblError.setVisible(false); 077 paragraph.setStyleName("range-field"); 078 079 input.setType(InputType.RANGE); 080 paragraph.add(input); 081 082 thumb.getElement().setClassName("thumb"); 083 Span value = new Span(); 084 value.getElement().setClassName("value"); 085 thumb.add(value); 086 087 paragraph.add(thumb); 088 add(paragraph); 089 090 lblError.getElement().getStyle().setMarginTop(-10, Unit.PX); 091 add(lblError); 092 } 093 094 /** 095 * Creates a range with specified values 096 * @param min - start min value 097 * @param max - end max value 098 * @param value - default range value 099 */ 100 public MaterialRange(Integer min, Integer max, Integer value) { 101 this(); 102 setMin(min); 103 setMax(max); 104 setValue(value); 105 } 106 107 public void reset() { 108 setValue(getMin()); 109 clearErrorOrSuccess(); 110 } 111 112 /** 113 * Try to identify the embedded range elements input field (see ui xml) 114 * @return The found element or null if none found. 115 */ 116 protected Element getRangeElement() { 117 if (rangeElement == null) { 118 NodeList<Element> elements = this.getElement().getElementsByTagName(INPUT); 119 if (elements != null && elements.getLength() > 0) { 120 rangeElement = elements.getItem(0); 121 } 122 } 123 return rangeElement; 124 } 125 126 /** 127 * Retrieve the Integer value from the given Attribute of the range element 128 * @param attribute The name of the attribute on the range element 129 * @return The Integer vaulue read from the given attribute or null 130 */ 131 protected Integer getIntFromRangeElement(String attribute) { 132 Element ele = getRangeElement(); 133 if(ele != null) { 134 return ele.getPropertyInt(attribute); 135 } 136 return null; 137 } 138 139 /** 140 * Set the given Integer value to the attribute of the range element. 141 */ 142 protected void setIntToRangeElement(String attribute,Integer val) { 143 Element ele = getRangeElement(); 144 if(ele != null) { 145 ele.setPropertyInt(attribute,val); 146 } 147 } 148 149 /** 150 * Read the current value 151 * @return The Integer value or null 152 */ 153 public Integer getValue() { 154 return getIntFromRangeElement(VALUE); 155 } 156 157 /** 158 * Write the current value 159 * @param value value must be >= min and <= max 160 */ 161 public void setValue(Integer value) { 162 if (value == null)return; 163 if (value < getMin())return; 164 if (value > getMax())return; 165 setIntToRangeElement(VALUE,value); 166 } 167 168 /** 169 * Read the min value 170 * @return The Integer or null 171 */ 172 public Integer getMin() { 173 return getIntFromRangeElement(MIN); 174 } 175 176 /** 177 * Write the current min value 178 * @param min value must be < max 179 */ 180 public void setMin(Integer min) { 181 setIntToRangeElement(MIN,min); 182 } 183 184 /** 185 * Read the max value 186 * @return The Integer or null 187 */ 188 public Integer getMax() { 189 return getIntFromRangeElement(MAX); 190 } 191 192 /** 193 * Write the current max value 194 * @param max value must be > min 195 */ 196 public void setMax(Integer max) { 197 setIntToRangeElement(MAX,max); 198 } 199 200 /** 201 * Register the ChangeHandler to become notified if the user changes the slider. 202 * The Handler is called when the user releases the mouse only at the end of the slide 203 * operation. 204 */ 205 @Override 206 public HandlerRegistration addChangeHandler(final ChangeHandler handler) { 207 return addDomHandler(new ChangeHandler() { 208 @Override 209 public void onChange(ChangeEvent event) { 210 if(isEnabled()){ 211 handler.onChange(event); 212 } 213 } 214 }, ChangeEvent.getType()); 215 } 216 217 @Override 218 public void setError(String error) { 219 errorMixin.setError(error); 220 } 221 222 @Override 223 public void setSuccess(String success) { 224 errorMixin.setSuccess(success); 225 } 226 227 @Override 228 public void setHelperText(String helperText) { 229 errorMixin.setHelperText(helperText); 230 } 231 232 @Override 233 public void clearErrorOrSuccess() { 234 errorMixin.clearErrorOrSuccess(); 235 } 236}