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.client.ui; 021 022import com.google.gwt.dom.client.Document; 023import com.google.gwt.dom.client.Element; 024import com.google.gwt.user.client.ui.HasWidgets; 025import com.google.gwt.user.client.ui.Widget; 026import gwt.material.design.client.base.AbstractButton; 027import gwt.material.design.client.base.HasActive; 028import gwt.material.design.client.base.HasProgress; 029import gwt.material.design.client.base.mixin.ProgressMixin; 030import gwt.material.design.client.constants.CssName; 031import gwt.material.design.client.constants.Display; 032import gwt.material.design.client.constants.ProgressType; 033import gwt.material.design.client.constants.WavesType; 034import gwt.material.design.client.ui.MaterialCollapsible.HasCollapsibleParent; 035 036//@formatter:off 037 038/** 039 * Collapsible element to define every items 040 * 041 * @author kevzlou7979 042 * @author Ben Dol 043 * @see <a href="http://gwtmaterialdesign.github.io/gwt-material-demo/#collapsible">Material Collapsibles</a> 044 * @see <a href="https://material.io/guidelines/components/expansion-panels.html#expansion-panels-behavior">Material Design Specification</a> 045 */ 046//@formatter:on 047public class MaterialCollapsibleItem extends AbstractButton implements HasWidgets, HasCollapsibleParent, 048 HasProgress, HasActive { 049 050 private boolean active; 051 private MaterialCollapsible parent; 052 private MaterialCollapsibleBody body; 053 private MaterialCollapsibleHeader header; 054 055 private ProgressMixin<MaterialCollapsibleItem> progressMixin; 056 057 /** 058 * Creates an empty collapsible item. 059 */ 060 public MaterialCollapsibleItem() { 061 super(); 062 } 063 064 /** 065 * Adds MaterialCollapsible contents. 066 */ 067 public MaterialCollapsibleItem(final Widget... widgets) { 068 this(); 069 for (Widget w : widgets) { 070 add(w); 071 } 072 } 073 074 @Override 075 protected Element createElement() { 076 return Document.get().createLIElement(); 077 } 078 079 @Override 080 public void add(Widget child) { 081 if (child instanceof MaterialCollapsibleBody) { 082 body = (MaterialCollapsibleBody) child; 083 } else if (child instanceof MaterialCollapsibleHeader) { 084 header = (MaterialCollapsibleHeader) child; 085 } 086 super.add(child); 087 } 088 089 @Override 090 public boolean remove(Widget w) { 091 if (w instanceof HasCollapsibleParent) { 092 ((HasCollapsibleParent) w).setParent(null); 093 } 094 095 if (w.equals(body)) { 096 body = null; 097 } else if (w.equals(header)) { 098 header = null; 099 } 100 return super.remove(w); 101 } 102 103 /** 104 * Expand the body panel. 105 */ 106 public void expand() { 107 if (body != null) { 108 setActive(true); 109 } 110 } 111 112 /** 113 * Collapse the cody panel. 114 */ 115 public void collapse() { 116 if (body != null) { 117 setActive(false); 118 } 119 } 120 121 @Override 122 public void showProgress(ProgressType type) { 123 getProgressMixin().showProgress(type); 124 } 125 126 @Override 127 public void setPercent(double percent) { 128 getProgressMixin().setPercent(percent); 129 } 130 131 @Override 132 public void hideProgress() { 133 getProgressMixin().hideProgress(); 134 } 135 136 @Override 137 public MaterialProgress getProgress() { 138 return getProgressMixin().getProgress(); 139 } 140 141 /** 142 * Make this item active. 143 */ 144 @Override 145 public void setActive(boolean active) { 146 this.active = active; 147 removeStyleName(CssName.ACTIVE); 148 if (header != null) { 149 header.removeStyleName(CssName.ACTIVE); 150 } 151 if (active) { 152 if (parent != null) { 153 parent.clearActive(); 154 } 155 addStyleName(CssName.ACTIVE); 156 157 if (header != null) { 158 header.addStyleName(CssName.ACTIVE); 159 } 160 } 161 162 if (body != null) { 163 body.setDisplay(active ? Display.BLOCK : Display.NONE); 164 } 165 } 166 167 @Override 168 public boolean isActive() { 169 return active; 170 } 171 172 public void setParent(MaterialCollapsible parent) { 173 this.parent = parent; 174 175 for (Widget child : this) { 176 if (child instanceof HasCollapsibleParent) { 177 ((HasCollapsibleParent) child).setParent(parent); 178 } 179 } 180 } 181 182 @Override 183 public void setWaves(WavesType waves) { 184 super.setWaves(waves); 185 186 // Waves change to inline block. 187 // We need to retain 'block' display 188 setDisplay(Display.BLOCK); 189 } 190 191 public MaterialCollapsibleBody getBody() { 192 return body; 193 } 194 195 public MaterialCollapsibleHeader getHeader() { 196 return header; 197 } 198 199 protected ProgressMixin<MaterialCollapsibleItem> getProgressMixin() { 200 if (progressMixin == null) { 201 progressMixin = new ProgressMixin<>(this); 202 } 203 return progressMixin; 204 } 205}