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.tree; 021 022import com.google.gwt.dom.client.Document; 023import com.google.gwt.event.logical.shared.*; 024import com.google.gwt.event.shared.HandlerRegistration; 025import com.google.gwt.user.client.ui.Widget; 026import gwt.material.design.addins.client.MaterialAddins; 027import gwt.material.design.addins.client.base.constants.AddinsCssName; 028import gwt.material.design.client.MaterialDesignBase; 029import gwt.material.design.client.base.MaterialWidget; 030 031//@formatter:off 032 033/** 034 * MaterialTree is a component that wraps all the tree items that provide lists of 035 * event handlers like open/close and selection event. 036 * <p> 037 * <h3>XML Namespace Declaration</h3> 038 * <pre> 039 * {@code 040 * xmlns:ma='urn:import:gwt.material.design.addins.client' 041 * } 042 * </pre> 043 * <p> 044 * <h3>UiBinder Usage:</h3> 045 * <pre> 046 * {@code 047 * <ma:tree.MaterialTree> 048 * <ma:tree.MaterialTreeItem text="Folder 1" iconType="FOLDER" /> 049 * <ma:tree.MaterialTreeItem text="Folder 2" iconType="FOLDER"> 050 * <-- Image support --> 051 * <ma:tree.MaterialTreeItem text="Item 2.1" resource="{res.batman.png}" /> 052 * <ma:tree.MaterialTreeItem text="Item 2.2" resource="{res.superman.png}" /> 053 * <ma:tree.MaterialTreeItem text="Item 2.3" resource="{res.spiderman.png}" /> 054 * </ma:tree.MaterialTreeItem> 055 * <ma:tree.MaterialTreeItem text="Folder 3" iconType="FOLDER" /> 056 * </ma:tree.MaterialTree> 057 * } 058 * </pre> 059 * 060 * @author kevzlou7979 061 * @author Ben Dol 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>, 066 HasOpenHandlers<MaterialTreeItem>, HasSelectionHandlers<MaterialTreeItem> { 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 selectedItem; 077 078 public MaterialTree() { 079 super(Document.get().createDivElement(), AddinsCssName.TREE); 080 } 081 082 @Override 083 protected void onLoad() { 084 super.onLoad(); 085 086 // Ensure all children know we are the root. 087 for (Widget child : getChildren()) { 088 if (child instanceof MaterialTreeItem) { 089 ((MaterialTreeItem) child).setTree(this); 090 } 091 } 092 093 // Add selection event 094 registerHandler(addSelectionHandler(event -> { 095 for (Widget item : getChildren()) { 096 if (item instanceof MaterialTreeItem) { 097 clearSelectedStyles((MaterialTreeItem) item); 098 } 099 } 100 MaterialTreeItem treeItem = event.getSelectedItem(); 101 treeItem.addStyleName(AddinsCssName.SELECTED); 102 setSelectedItem(treeItem); 103 })); 104 } 105 106 @Override 107 protected void add(Widget child, com.google.gwt.user.client.Element container) { 108 if (child instanceof MaterialTreeItem) { 109 super.add(child, container); 110 ((MaterialTreeItem) child).setTree(this); 111 } else { 112 throw new IllegalArgumentException("MaterialTree can only contain MaterialTreeItem"); 113 } 114 } 115 116 @Override 117 protected void insert(Widget child, com.google.gwt.user.client.Element container, int beforeIndex, boolean domInsert) { 118 if (child instanceof MaterialTreeItem) { 119 super.insert(child, container, beforeIndex, domInsert); 120 ((MaterialTreeItem) child).setTree(this); 121 } else { 122 throw new IllegalArgumentException("MaterialTree can only contain MaterialTreeItem"); 123 } 124 } 125 126 protected void clearSelectedStyles(MaterialTreeItem item) { 127 item.removeStyleName(AddinsCssName.SELECTED); 128 129 for (MaterialTreeItem treeItem : item.getTreeItems()) { 130 clearSelectedStyles(treeItem); 131 } 132 } 133 134 public MaterialTreeItem getSelectedItem() { 135 return selectedItem; 136 } 137 138 public void setSelectedItem(MaterialTreeItem selectedItem) { 139 this.selectedItem = selectedItem; 140 } 141 142 /** 143 * Expand all tree item's content 144 */ 145 public void expand() { 146 for (Widget w : getChildren()) { 147 if (w instanceof MaterialTreeItem) { 148 expandItems((MaterialTreeItem) w); 149 } 150 } 151 } 152 153 /** 154 * Recursive function to expand each tree item. 155 */ 156 protected void expandItems(MaterialTreeItem item) { 157 item.expand(); 158 item.setHide(true); 159 item.getTreeItems().forEach(this::expandItems); 160 } 161 162 /** 163 * Collapse all tree item's content 164 */ 165 public void collapse() { 166 for (Widget w : getChildren()) { 167 if (w instanceof MaterialTreeItem) { 168 collapseItems((MaterialTreeItem) w); 169 } 170 } 171 } 172 173 /** 174 * Deselect selected tree item 175 */ 176 public void deselectSelectedItem() { 177 // Check whether tree has selected item 178 if (selectedItem != null) { 179 clearSelectedStyles(selectedItem); 180 setSelectedItem(null); 181 SelectionEvent.fire(this, null); 182 } 183 } 184 185 /** 186 * Recursive function to collapse each tree item. 187 */ 188 protected void collapseItems(MaterialTreeItem item) { 189 item.collapse(); 190 item.setHide(false); 191 192 item.getTreeItems().forEach(this::collapseItems); 193 } 194 195 @Override 196 public HandlerRegistration addCloseHandler(final CloseHandler<MaterialTreeItem> handler) { 197 return addHandler(new CloseHandler<MaterialTreeItem>() { 198 @Override 199 public void onClose(CloseEvent<MaterialTreeItem> event) { 200 if (isEnabled()) { 201 handler.onClose(event); 202 } 203 } 204 }, CloseEvent.getType()); 205 } 206 207 @Override 208 public HandlerRegistration addOpenHandler(final OpenHandler<MaterialTreeItem> handler) { 209 return addHandler(new OpenHandler<MaterialTreeItem>() { 210 @Override 211 public void onOpen(OpenEvent<MaterialTreeItem> event) { 212 if (isEnabled()) { 213 handler.onOpen(event); 214 } 215 } 216 }, OpenEvent.getType()); 217 } 218 219 @Override 220 public HandlerRegistration addSelectionHandler(final SelectionHandler<MaterialTreeItem> handler) { 221 return addHandler(new SelectionHandler<MaterialTreeItem>() { 222 @Override 223 public void onSelection(SelectionEvent<MaterialTreeItem> event) { 224 if (isEnabled()) { 225 handler.onSelection(event); 226 } 227 } 228 }, SelectionEvent.getType()); 229 } 230}