001/* 002 * #%L 003 * GwtMaterial 004 * %% 005 * Copyright (C) 2015 - 2017 GwtMaterialDesign 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package gwt.material.design.addins.client.stepper; 021 022import com.google.gwt.dom.client.Document; 023import com.google.gwt.event.dom.client.ClickHandler; 024import com.google.gwt.event.logical.shared.HasSelectionHandlers; 025import com.google.gwt.event.logical.shared.SelectionEvent; 026import com.google.gwt.event.logical.shared.SelectionHandler; 027import com.google.gwt.event.shared.HandlerRegistration; 028import com.google.gwt.safehtml.shared.SafeHtmlUtils; 029import com.google.gwt.user.client.ui.Widget; 030import gwt.material.design.addins.client.base.constants.AddinsCssName; 031import gwt.material.design.addins.client.stepper.constants.State; 032import gwt.material.design.client.base.*; 033import gwt.material.design.client.base.mixin.ActiveMixin; 034import gwt.material.design.client.constants.Axis; 035import gwt.material.design.client.constants.CssName; 036import gwt.material.design.client.constants.IconType; 037import gwt.material.design.client.ui.MaterialIcon; 038import gwt.material.design.client.ui.html.Div; 039 040//@formatter:off 041 042/** 043 * Material Step is a child element of Material Stepper, sometimes called Stepper Item, used to indicate the active 044 * inactive items on the Stepper Component. 045 * <p> 046 * <h3>XML Namespace Declaration</h3> 047 * <pre> 048 * {@code 049 * xmlns:ma='urn:import:gwt.material.design.addins.client' 050 * } 051 * </pre> 052 * <p> 053 * <h3>UiBinder Usage:</h3> 054 * <pre> 055 * {@code 056 * <ma:stepper.MaterialStep step="1" title="Name of Step 1"> 057 * <m:MaterialPanel width="100%" height="300px" backgroundColor="grey lighten-2"/> 058 * <m:MaterialButton ui:field="btnContinue1" text="Continue to Step 2" grid="l4" marginTop="12" backgroundColor="blue" textColor="white" waves="DEFAULT"/> 059 * <m:MaterialButton ui:field="btnPrev1" text="Cancel" grid="l4" marginTop="12" type="FLAT" waves="DEFAULT"/> 060 * </ma:stepper.MaterialStep> 061 * } 062 * </pre> 063 * 064 * @author kevzlou7979 065 * @see <a href="http://gwtmaterialdesign.github.io/gwt-material-demo/#steppers">Material Steppers</a> 066 * @see <a href="https://material.io/guidelines/components/steppers.html">Material Design Specification</a> 067 */ 068// @formatter:on 069public class MaterialStep extends MaterialWidget implements HasActive, HasTitle, HasError, HasAxis, 070 HasSelectionHandlers<MaterialStep> { 071 072 private int step; 073 private String title; 074 private String description = ""; 075 private Div conCircle = new Div(); 076 private Div conBody = new Div(); 077 private Div divCircle = new Div(); 078 private Div divLine = new Div(); 079 private Div divTitle = new Div(); 080 private Div divDescription = new Div(); 081 private Div divBody = new Div(); 082 private MaterialIcon iconError = new MaterialIcon(IconType.REPORT_PROBLEM); 083 private MaterialIcon iconSuccess = new MaterialIcon(IconType.CHECK_CIRCLE); 084 private ActiveMixin<MaterialStep> activeMixin; 085 private Axis axis = Axis.VERTICAL; 086 private State state; 087 088 public MaterialStep() { 089 super(Document.get().createDivElement(), AddinsCssName.STEP); 090 091 super.add(conCircle); 092 conCircle.add(divCircle); 093 conCircle.add(divLine); 094 095 super.add(conBody); 096 conBody.add(divTitle); 097 conBody.add(divBody); 098 099 divCircle.setStyleName(CssName.CIRCLE); 100 divLine.setStyleName(AddinsCssName.LINE); 101 divTitle.setStyleName(CssName.TITLE); 102 divBody.setStyleName(AddinsCssName.BODY); 103 } 104 105 public MaterialStep(String title, String description) { 106 this(); 107 setTitle(title); 108 setDescription(description); 109 } 110 111 public MaterialStep(String title, String description, Integer step) { 112 this(title, description); 113 setStep(step); 114 } 115 116 @Override 117 protected void onLoad() { 118 super.onLoad(); 119 120 ClickHandler handler = event -> { 121 if (isEnabled() && isVisible()) { 122 SelectionEvent.fire(MaterialStep.this, MaterialStep.this); 123 } 124 }; 125 registerHandler(conCircle.addClickHandler(handler)); 126 registerHandler(divTitle.addClickHandler(handler)); 127 registerHandler(divDescription.addClickHandler(handler)); 128 } 129 130 @Override 131 public void add(Widget child) { 132 divBody.add(child); 133 } 134 135 public int getStep() { 136 return step; 137 } 138 139 public void setStep(int step) { 140 this.step = step; 141 divCircle.getElement().setInnerSafeHtml(SafeHtmlUtils.fromString(String.valueOf(step))); 142 } 143 144 @Override 145 public void setTitle(String title) { 146 this.title = title; 147 divTitle.getElement().setInnerSafeHtml(SafeHtmlUtils.fromString(title)); 148 } 149 150 public String getTitle() { 151 return title; 152 } 153 154 @Override 155 public void setDescription(String description) { 156 this.description = description; 157 divDescription.setStyleName(AddinsCssName.DESCRIPTION); 158 divDescription.getElement().setInnerSafeHtml(SafeHtmlUtils.fromString(description)); 159 conBody.insert(divDescription, 1); 160 } 161 162 public String getDescription() { 163 return description; 164 } 165 166 @Override 167 public void setActive(boolean active) { 168 getActiveMixin().setActive(active); 169 } 170 171 @Override 172 public boolean isActive() { 173 return getActiveMixin().isActive(); 174 } 175 176 @Override 177 public void setError(String error) { 178 removeStyleName(AddinsCssName.SUCCESS); 179 addStyleName(AddinsCssName.ERROR); 180 applyIconStatus(iconError, error); 181 state = State.ERROR; 182 } 183 184 @Override 185 public void setSuccess(String success) { 186 removeStyleName(AddinsCssName.ERROR); 187 addStyleName(AddinsCssName.SUCCESS); 188 applyIconStatus(iconSuccess, success); 189 state = State.SUCCESS; 190 } 191 192 @Override 193 public void setHelperText(String helperText) { 194 setDescription(helperText); 195 } 196 197 public State getState() { 198 return state; 199 } 200 201 @Override 202 public void clearErrorOrSuccess() { 203 iconError.removeFromParent(); 204 iconSuccess.removeFromParent(); 205 conCircle.insert(divCircle, 0); 206 removeStyleName(AddinsCssName.ERROR); 207 removeStyleName(AddinsCssName.SUCCESS); 208 } 209 210 protected void applyIconStatus(MaterialIcon icon, String description) { 211 iconError.removeFromParent(); 212 iconSuccess.removeFromParent(); 213 divCircle.removeFromParent(); 214 conCircle.insert(icon, 0); 215 if (description != null) { 216 divDescription.getElement().setInnerSafeHtml(SafeHtmlUtils.fromString(description)); 217 } 218 } 219 220 public Div getDivBody() { 221 return divBody; 222 } 223 224 public Div getConCircle() { 225 return conCircle; 226 } 227 228 public Div getConBody() { 229 return conBody; 230 } 231 232 public Div getDivCircle() { 233 return divCircle; 234 } 235 236 public Div getDivLine() { 237 return divLine; 238 } 239 240 public Div getDivTitle() { 241 return divTitle; 242 } 243 244 public Div getDivDescription() { 245 return divDescription; 246 } 247 248 @Override 249 public void setAxis(Axis axis) { 250 if (axis == null) { 251 axis = Axis.VERTICAL; 252 } 253 this.axis = axis; 254 switch (axis) { 255 case HORIZONTAL: 256 conCircle.add(divTitle); 257 conCircle.add(divLine); 258 conCircle.add(divDescription); 259 break; 260 case VERTICAL: 261 conBody.insert(divTitle, 0); 262 conBody.insert(divDescription, 1); 263 conCircle.add(divLine); 264 265 break; 266 } 267 } 268 269 @Override 270 public Axis getAxis() { 271 return axis; 272 } 273 274 public MaterialIcon getIconError() { 275 return iconError; 276 } 277 278 public MaterialIcon getIconSuccess() { 279 return iconSuccess; 280 } 281 282 protected ActiveMixin<MaterialStep> getActiveMixin() { 283 if (activeMixin == null) { 284 activeMixin = new ActiveMixin<>(this); 285 } 286 return activeMixin; 287 } 288 289 @Override 290 public HandlerRegistration addSelectionHandler(final SelectionHandler<MaterialStep> handler) { 291 return this.addHandler(new SelectionHandler<MaterialStep>() { 292 @Override 293 public void onSelection(SelectionEvent<MaterialStep> event) { 294 if (isEnabled()) { 295 handler.onSelection(event); 296 } 297 } 298 }, SelectionEvent.getType()); 299 } 300}