123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- /*
- * Copyright 2000-2016 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
- package com.vaadin.ui;
-
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Map;
- import java.util.Objects;
- import java.util.Set;
-
- import com.vaadin.data.Binder;
- import com.vaadin.data.HasDataProvider;
- import com.vaadin.data.SelectionModel;
- import com.vaadin.data.provider.DataGenerator;
- import com.vaadin.data.provider.DataProvider;
- import com.vaadin.data.provider.HierarchicalDataProvider;
- import com.vaadin.event.CollapseEvent;
- import com.vaadin.event.CollapseEvent.CollapseListener;
- import com.vaadin.event.ExpandEvent;
- import com.vaadin.event.ExpandEvent.ExpandListener;
- import com.vaadin.event.selection.SelectionListener;
- import com.vaadin.server.Resource;
- import com.vaadin.shared.Registration;
- import com.vaadin.shared.ui.grid.HeightMode;
- import com.vaadin.shared.ui.tree.TreeRendererState;
- import com.vaadin.ui.Grid.SelectionMode;
- import com.vaadin.ui.renderers.AbstractRenderer;
-
- import elemental.json.JsonObject;
-
- /**
- * Tree component. A Tree can be used to select an item from a hierarchical set
- * of items.
- *
- * @author Vaadin Ltd
- * @since 8.1
- *
- * @param <T>
- * the data type
- */
- public class Tree<T> extends Composite implements HasDataProvider<T> {
-
- /**
- * String renderer that handles icon resources and stores their identifiers
- * into data objects.
- *
- * @since 8.1
- */
- public final class TreeRenderer extends AbstractRenderer<T, String>
- implements DataGenerator<T> {
-
- /**
- * Constructs a new TreeRenderer.
- */
- protected TreeRenderer() {
- super(String.class);
- }
-
- private Map<T, String> resourceKeyMap = new HashMap<>();
- private int counter = 0;
-
- @Override
- public void generateData(T item, JsonObject jsonObject) {
- Resource resource = iconProvider.apply(item);
- if (resource == null) {
- destroyData(item);
- return;
- }
-
- if (!resourceKeyMap.containsKey(item)) {
- resourceKeyMap.put(item, "icon" + (counter++));
- }
- setResource(resourceKeyMap.get(item), resource);
- jsonObject.put("itemIcon", resourceKeyMap.get(item));
- }
-
- @Override
- public void destroyData(T item) {
- if (resourceKeyMap.containsKey(item)) {
- setResource(resourceKeyMap.get(item), null);
- resourceKeyMap.remove(item);
- }
- }
-
- @Override
- public void destroyAllData() {
- Set<T> keys = new HashSet<>(resourceKeyMap.keySet());
- for (T key : keys) {
- destroyData(key);
- }
- }
-
- @Override
- protected TreeRendererState getState() {
- return (TreeRendererState) super.getState();
- }
-
- @Override
- protected TreeRendererState getState(boolean markAsDirty) {
- return (TreeRendererState) super.getState(markAsDirty);
- }
- }
-
- private TreeGrid<T> treeGrid = new TreeGrid<>();
- private ItemCaptionGenerator<T> captionGenerator = String::valueOf;
- private IconGenerator<T> iconProvider = t -> null;
-
- /**
- * Constructs a new Tree Component.
- */
- public Tree() {
- setCompositionRoot(treeGrid);
- TreeRenderer renderer = new TreeRenderer();
- treeGrid.getDataCommunicator().addDataGenerator(renderer);
- treeGrid.addColumn(i -> captionGenerator.apply(i), renderer)
- .setId("column");
- treeGrid.setHierarchyColumn("column");
- while (treeGrid.getHeaderRowCount() > 0) {
- treeGrid.removeHeaderRow(0);
- }
- treeGrid.setPrimaryStyleName("v-newtree");
-
- setWidth("100%");
- setHeightUndefined();
- treeGrid.setHeightMode(HeightMode.UNDEFINED);
-
- treeGrid.addExpandListener(e -> fireExpandEvent(e.getExpandedItem(),
- e.isUserOriginated()));
- treeGrid.addCollapseListener(e -> fireCollapseEvent(
- e.getCollapsedItem(), e.isUserOriginated()));
- }
-
- /**
- * Constructs a new Tree Component.
- *
- * @param caption
- * the caption for component
- */
- public Tree(String caption) {
- this();
-
- setCaption(caption);
- }
-
- @Override
- public HierarchicalDataProvider<T, ?> getDataProvider() {
- return treeGrid.getDataProvider();
- }
-
- @Override
- public void setDataProvider(DataProvider<T, ?> dataProvider) {
- treeGrid.setDataProvider(dataProvider);
- }
-
- /**
- * Adds an ExpandListener to this Tree.
- *
- * @see ExpandEvent
- *
- * @param listener
- * the listener to add
- * @return a registration for the listener
- */
- public Registration addExpandListener(ExpandListener<T> listener) {
- return addListener(ExpandEvent.class, listener,
- ExpandListener.EXPAND_METHOD);
- }
-
- /**
- * Adds a CollapseListener to this Tree.
- *
- * @see CollapseEvent
- *
- * @param listener
- * the listener to add
- * @return a registration for the listener
- */
- public Registration addCollapseListener(CollapseListener<T> listener) {
- return addListener(CollapseEvent.class, listener,
- CollapseListener.COLLAPSE_METHOD);
- }
-
- /**
- * Fires an expand event with given item.
- *
- * @param item
- * the expanded item
- * @param userOriginated
- * whether the expand was triggered by a user interaction or the
- * server
- */
- protected void fireExpandEvent(T item, boolean userOriginated) {
- fireEvent(new ExpandEvent<>(this, item, userOriginated));
- }
-
- /**
- * Fires a collapse event with given item.
- *
- * @param item
- * the collapsed item
- * @param userOriginated
- * whether the collapse was triggered by a user interaction or
- * the server
- */
- protected void fireCollapseEvent(T item, boolean userOriginated) {
- fireEvent(new CollapseEvent<>(this, item, userOriginated));
- }
-
- /**
- * Expands the given item.
- * <p>
- * If the item is currently expanded, does nothing. If the item does not
- * have any children, does nothing.
- *
- * @param item
- * the item to expand
- */
- public void expand(T item) {
- treeGrid.expand(item);
- }
-
- /**
- * Collapses the given item.
- * <p>
- * If the item is already collapsed, does nothing.
- *
- * @param item
- * the item to collapse
- */
- public void collapse(T item) {
- treeGrid.collapse(item);
- }
-
- /**
- * This method is a shorthand that delegates to the currently set selection
- * model.
- *
- * @see #getSelectionModel()
- *
- * @return set of selected items
- */
- public Set<T> getSelectedItems() {
- return treeGrid.getSelectedItems();
- }
-
- /**
- * This method is a shorthand that delegates to the currently set selection
- * model.
- *
- * @param item
- * item to select
- *
- * @see SelectionModel#select(Object)
- * @see #getSelectionModel()
- */
- public void select(T item) {
- treeGrid.select(item);
- }
-
- /**
- * This method is a shorthand that delegates to the currently set selection
- * model.
- *
- * @param item
- * item to deselect
- *
- * @see SelectionModel#deselect(Object)
- * @see #getSelectionModel()
- */
- public void deselect(T item) {
- treeGrid.deselect(item);
- }
-
- /**
- * Adds a selection listener to the current selection model.
- * <p>
- * <strong>NOTE:</strong> If selection mode is switched with
- * {@link setSelectionMode(SelectionMode)}, then this listener is not
- * triggered anymore when selection changes!
- *
- * @param listener
- * the listener to add
- * @return a registration handle to remove the listener
- *
- * @throws UnsupportedOperationException
- * if selection has been disabled with
- * {@link SelectionMode.NONE}
- */
- public Registration addSelectionListener(SelectionListener<T> listener) {
- return treeGrid.addSelectionListener(listener);
- }
-
- /**
- * Use this tree as a single select in {@link Binder}. Throws
- * {@link IllegalStateException} if the tree is not using
- * {@link SelectionMode#SINGLE}.
- *
- * @return the single select wrapper that can be used in binder
- */
- public SingleSelect<T> asSingleSelect() {
- return treeGrid.asSingleSelect();
- }
-
- /**
- * Returns the selection model for this Tree.
- *
- * @return the selection model, not <code>null</code>
- */
- public SelectionModel<T> getSelectionModel() {
- return treeGrid.getSelectionModel();
- }
-
- @Override
- public void setItems(Collection<T> items) {
- treeGrid.setItems(items);
- }
-
- /**
- * Sets the item caption generator that is used to produce the strings shown
- * as the text for each item. By default, {@link String#valueOf(Object)} is
- * used.
- *
- * @param captionGenerator
- * the item caption provider to use, not <code>null</code>
- */
- public void setItemCaptionGenerator(
- ItemCaptionGenerator<T> captionGenerator) {
- Objects.requireNonNull(captionGenerator,
- "Caption generator must not be null");
- this.captionGenerator = captionGenerator;
- treeGrid.getDataCommunicator().reset();
- }
-
- /**
- * Sets the item icon generator that is used to produce custom icons for
- * items. The generator can return <code>null</code> for items with no icon.
- *
- * @see IconGenerator
- *
- * @param iconGenerator
- * the item icon generator to set, not <code>null</code>
- * @throws NullPointerException
- * if {@code itemIconGenerator} is {@code null}
- */
- public void setItemIconGenerator(IconGenerator<T> iconGenerator) {
- Objects.requireNonNull(iconGenerator,
- "Item icon generator must not be null");
- this.iconProvider = iconGenerator;
- treeGrid.getDataCommunicator().reset();
- }
-
- }
|