001package gwt.material.design.addins.client.tree;
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.core.client.GWT;
024import com.google.gwt.dom.client.Document;
025import com.google.gwt.event.logical.shared.*;
026import com.google.gwt.event.shared.HandlerRegistration;
027import com.google.gwt.user.client.ui.Widget;
028import gwt.material.design.addins.client.MaterialAddins;
029import gwt.material.design.client.MaterialDesignBase;
030import gwt.material.design.client.base.MaterialWidget;
031
032//@formatter:off
033
034/**
035 * MaterialTree is a component that wraps all the tree items that provide lists of
036 * event handlers like open/close and selection event.
037 *
038 * <h3>XML Namespace Declaration</h3>
039 * <pre>
040 * {@code
041 * xmlns:ma='urn:import:gwt.material.design.addins.client'
042 * }
043 * </pre>
044 *
045 * <h3>UiBinder Usage:</h3>
046 * <pre>
047 * {@code
048 * <ma:tree.MaterialTree>
049 *     <ma:tree.MaterialTreeItem text="Folder 1" iconType="FOLDER" />
050 *     <ma:tree.MaterialTreeItem text="Folder 2" iconType="FOLDER">
051 *         &lt;-- Image support -->
052 *         <ma:tree.MaterialTreeItem text="Item 2.1" resource="{res.batman.png}" />
053 *         <ma:tree.MaterialTreeItem text="Item 2.2" resource="{res.superman.png}" />
054 *         <ma:tree.MaterialTreeItem text="Item 2.3" resource="{res.spiderman.png}" />
055 *     </ma:tree.MaterialTreeItem>
056 *     <ma:tree.MaterialTreeItem text="Folder 3" iconType="FOLDER" />
057 * </ma:tree.MaterialTree>
058 * }
059 * </pre>
060 *
061 * @author kevzlou7979
062 * @see <a href="http://gwtmaterialdesign.github.io/gwt-material-demo/#treeview">Tree View</a>
063 */
064// @formatter:on
065public class MaterialTree extends MaterialWidget implements HasCloseHandlers<MaterialTreeItem>, HasOpenHandlers<MaterialTreeItem>, HasSelectionHandlers<MaterialTreeItem> {
066
067
068    static {
069        if(MaterialAddins.isDebug()) {
070            MaterialDesignBase.injectCss(MaterialTreeDebugClientBundle.INSTANCE.treeCssDebug());
071        } else {
072            MaterialDesignBase.injectCss(MaterialTreeClientBundle.INSTANCE.treeCss());
073        }
074    }
075
076    private MaterialTreeItem selectedTree;
077
078    public MaterialTree() {
079        super(Document.get().createDivElement(), "tree");
080    }
081
082    protected void initSelectionEvent() {
083        // Add selection event
084        addSelectionHandler(new SelectionHandler<MaterialTreeItem>() {
085            @Override
086            public void onSelection(SelectionEvent<MaterialTreeItem> event) {
087                for(Widget item : getChildren()){
088                    if(item instanceof MaterialTreeItem){
089                        clearItemSelectedStyles((MaterialTreeItem) item);
090                    }
091                }
092                MaterialTreeItem treeItem = event.getSelectedItem();
093                treeItem.addStyleName("selected");
094                setSelectedTree(treeItem);
095            }
096        });
097    }
098
099    @Override
100    public void add(Widget child) {
101        if(child instanceof MaterialTreeItem){
102            super.add(child);
103        }else{
104            GWT.log("Material Tree must contain on Material Tree Items");
105        }
106    }
107
108
109    @Override
110    protected void onLoad() {
111        super.onLoad();
112        for(Widget w : getChildren()){
113            if(w instanceof MaterialTreeItem){
114                initTree((MaterialTreeItem) w);
115            }
116        }
117    }
118
119    // Recursive function to set the parent of tree item
120    public void initTree(MaterialTreeItem item) {
121        item.setTree(this);
122        for(MaterialTreeItem treeItem : item.getTreeItems()){
123            initTree(treeItem);
124        }
125        initSelectionEvent();
126    }
127
128    protected void clearItemSelectedStyles(MaterialTreeItem item) {
129        item.removeStyleName("selected");
130        for(MaterialTreeItem treeItem : item.getTreeItems()){
131            clearItemSelectedStyles(treeItem);
132        }
133    }
134
135    @Override
136    public HandlerRegistration addCloseHandler(final CloseHandler<MaterialTreeItem> handler) {
137        return addHandler(new CloseHandler<MaterialTreeItem>() {
138            @Override
139            public void onClose(CloseEvent<MaterialTreeItem> event) {
140                if(isEnabled()){
141                    handler.onClose(event);
142                }
143            }
144        }, CloseEvent.getType());
145    }
146
147    @Override
148    public HandlerRegistration addOpenHandler(final OpenHandler<MaterialTreeItem> handler) {
149        return addHandler(new OpenHandler<MaterialTreeItem>() {
150            @Override
151            public void onOpen(OpenEvent<MaterialTreeItem> event) {
152                if(isEnabled()){
153                    handler.onOpen(event);
154                }
155            }
156        }, OpenEvent.getType());
157    }
158
159    @Override
160    public HandlerRegistration addSelectionHandler(final SelectionHandler<MaterialTreeItem> handler) {
161        return addHandler(new SelectionHandler<MaterialTreeItem>() {
162            @Override
163            public void onSelection(SelectionEvent<MaterialTreeItem> event) {
164                if(isEnabled()){
165                    handler.onSelection(event);
166                }
167            }
168        }, SelectionEvent.getType());
169    }
170
171    public MaterialTreeItem getSelectedTree() {
172        return selectedTree;
173    }
174
175    public void setSelectedTree(MaterialTreeItem selectedTree) {
176        this.selectedTree = selectedTree;
177    }
178
179
180    /**
181     * Expand all tree item's content
182     */
183    public void expand() {
184        for(Widget w : getChildren()){
185            if(w instanceof MaterialTreeItem){
186                expandItems((MaterialTreeItem) w);
187            }
188        }
189    }
190
191    /**
192     * Recursive function to expand each tree item
193     * @param item
194     */
195    protected void expandItems(MaterialTreeItem item) {
196        item.expand();
197        item.setHide(true);
198        for(MaterialTreeItem t : item.getTreeItems()){
199            expandItems(t);
200        }
201    }
202
203    /**
204     * Collapse all tree item's content
205     */
206    public void collapse() {
207        for(Widget w : getChildren()){
208            if(w instanceof MaterialTreeItem){
209                collapseItems((MaterialTreeItem)w);
210            }
211        }
212    }
213
214    /**
215     * Recursive function to collapse each tree item
216     * @param item
217     */
218    protected void collapseItems(MaterialTreeItem item) {
219        item.collapse();
220        item.setHide(false);
221        for(MaterialTreeItem t : item.getTreeItems()){
222            collapseItems(t);
223        }
224    }
225}
226