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}