You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Tree.java 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. /*
  2. * Copyright 2000-2016 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.ui;
  17. import java.lang.reflect.Method;
  18. import java.util.Collection;
  19. import java.util.HashMap;
  20. import java.util.HashSet;
  21. import java.util.Map;
  22. import java.util.Objects;
  23. import java.util.Set;
  24. import com.vaadin.data.Binder;
  25. import com.vaadin.data.HasHierarchicalDataProvider;
  26. import com.vaadin.data.SelectionModel;
  27. import com.vaadin.data.TreeData;
  28. import com.vaadin.data.provider.DataGenerator;
  29. import com.vaadin.data.provider.DataProvider;
  30. import com.vaadin.data.provider.HierarchicalDataProvider;
  31. import com.vaadin.data.provider.TreeDataProvider;
  32. import com.vaadin.event.CollapseEvent;
  33. import com.vaadin.event.CollapseEvent.CollapseListener;
  34. import com.vaadin.event.ConnectorEvent;
  35. import com.vaadin.event.ContextClickEvent;
  36. import com.vaadin.event.ExpandEvent;
  37. import com.vaadin.event.ExpandEvent.ExpandListener;
  38. import com.vaadin.event.SerializableEventListener;
  39. import com.vaadin.event.selection.SelectionListener;
  40. import com.vaadin.server.ErrorMessage;
  41. import com.vaadin.server.Resource;
  42. import com.vaadin.shared.EventId;
  43. import com.vaadin.shared.MouseEventDetails;
  44. import com.vaadin.shared.Registration;
  45. import com.vaadin.shared.ui.ContentMode;
  46. import com.vaadin.shared.ui.grid.HeightMode;
  47. import com.vaadin.shared.ui.tree.TreeMultiSelectionModelState;
  48. import com.vaadin.shared.ui.tree.TreeRendererState;
  49. import com.vaadin.ui.Grid.SelectionMode;
  50. import com.vaadin.ui.components.grid.MultiSelectionModelImpl;
  51. import com.vaadin.ui.renderers.AbstractRenderer;
  52. import com.vaadin.util.ReflectTools;
  53. import elemental.json.JsonObject;
  54. /**
  55. * Tree component. A Tree can be used to select an item from a hierarchical set
  56. * of items.
  57. *
  58. * @author Vaadin Ltd
  59. * @since 8.1
  60. *
  61. * @param <T>
  62. * the data type
  63. */
  64. public class Tree<T> extends Composite
  65. implements HasHierarchicalDataProvider<T> {
  66. @Deprecated
  67. private static final Method ITEM_CLICK_METHOD = ReflectTools
  68. .findMethod(ItemClickListener.class, "itemClick", ItemClick.class);
  69. private Registration contextClickRegistration = null;
  70. /**
  71. * A listener for item click events.
  72. *
  73. * @param <T>
  74. * the tree item type
  75. *
  76. * @see ItemClick
  77. * @see Registration
  78. * @since 8.1
  79. */
  80. @FunctionalInterface
  81. public interface ItemClickListener<T> extends SerializableEventListener {
  82. /**
  83. * Invoked when this listener receives a item click event from a Tree to
  84. * which it has been added.
  85. *
  86. * @param event
  87. * the received event, not {@code null}
  88. */
  89. public void itemClick(Tree.ItemClick<T> event);
  90. }
  91. /**
  92. * Tree item click event.
  93. *
  94. * @param <T>
  95. * the data type of tree
  96. * @since 8.1
  97. */
  98. public static class ItemClick<T> extends ConnectorEvent {
  99. private final T item;
  100. private final MouseEventDetails mouseEventDetails;
  101. /**
  102. * Constructs a new item click.
  103. *
  104. * @param source
  105. * the tree component
  106. * @param item
  107. * the clicked item
  108. * @param mouseEventDetails
  109. * information about the original mouse event (mouse button
  110. * clicked, coordinates if available etc.)
  111. */
  112. protected ItemClick(Tree<T> source, T item,
  113. MouseEventDetails mouseEventDetails) {
  114. super(source);
  115. this.item = item;
  116. this.mouseEventDetails = mouseEventDetails;
  117. }
  118. /**
  119. * Returns the clicked item.
  120. *
  121. * @return the clicked item
  122. */
  123. public T getItem() {
  124. return item;
  125. }
  126. @SuppressWarnings("unchecked")
  127. @Override
  128. public Tree<T> getSource() {
  129. return (Tree<T>) super.getSource();
  130. }
  131. /**
  132. * Returns the mouse event details.
  133. *
  134. * @return the mouse event details
  135. */
  136. public MouseEventDetails getMouseEventDetails() {
  137. return mouseEventDetails;
  138. }
  139. }
  140. /**
  141. * String renderer that handles icon resources and stores their identifiers
  142. * into data objects.
  143. *
  144. * @since 8.1
  145. */
  146. public final class TreeRenderer extends AbstractRenderer<T, String>
  147. implements DataGenerator<T> {
  148. /**
  149. * Constructs a new TreeRenderer.
  150. */
  151. protected TreeRenderer() {
  152. super(String.class);
  153. }
  154. private Map<T, String> resourceKeyMap = new HashMap<>();
  155. private int counter = 0;
  156. @Override
  157. public void generateData(T item, JsonObject jsonObject) {
  158. Resource resource = iconProvider.apply(item);
  159. if (resource == null) {
  160. destroyData(item);
  161. return;
  162. }
  163. if (!resourceKeyMap.containsKey(item)) {
  164. resourceKeyMap.put(item, "icon" + (counter++));
  165. }
  166. setResource(resourceKeyMap.get(item), resource);
  167. jsonObject.put("itemIcon", resourceKeyMap.get(item));
  168. }
  169. @Override
  170. public void destroyData(T item) {
  171. if (resourceKeyMap.containsKey(item)) {
  172. setResource(resourceKeyMap.get(item), null);
  173. resourceKeyMap.remove(item);
  174. }
  175. }
  176. @Override
  177. public void destroyAllData() {
  178. Set<T> keys = new HashSet<>(resourceKeyMap.keySet());
  179. for (T key : keys) {
  180. destroyData(key);
  181. }
  182. }
  183. @Override
  184. protected TreeRendererState getState() {
  185. return (TreeRendererState) super.getState();
  186. }
  187. @Override
  188. protected TreeRendererState getState(boolean markAsDirty) {
  189. return (TreeRendererState) super.getState(markAsDirty);
  190. }
  191. }
  192. /**
  193. * Custom MultiSelectionModel for Tree. TreeMultiSelectionModel does not
  194. * show selection column.
  195. *
  196. * @param <T>
  197. * the tree item type
  198. *
  199. * @since 8.1
  200. */
  201. public final static class TreeMultiSelectionModel<T>
  202. extends MultiSelectionModelImpl<T> {
  203. @Override
  204. protected TreeMultiSelectionModelState getState() {
  205. return (TreeMultiSelectionModelState) super.getState();
  206. }
  207. @Override
  208. protected TreeMultiSelectionModelState getState(boolean markAsDirty) {
  209. return (TreeMultiSelectionModelState) super.getState(markAsDirty);
  210. }
  211. }
  212. private TreeGrid<T> treeGrid = new TreeGrid<>();
  213. private ItemCaptionGenerator<T> captionGenerator = String::valueOf;
  214. private IconGenerator<T> iconProvider = t -> null;
  215. private final TreeRenderer renderer;
  216. /**
  217. * Constructs a new Tree Component.
  218. */
  219. public Tree() {
  220. setCompositionRoot(treeGrid);
  221. renderer = new TreeRenderer();
  222. treeGrid.getDataCommunicator().addDataGenerator(renderer);
  223. treeGrid.addColumn(i -> captionGenerator.apply(i), renderer)
  224. .setId("column");
  225. treeGrid.setHierarchyColumn("column");
  226. while (treeGrid.getHeaderRowCount() > 0) {
  227. treeGrid.removeHeaderRow(0);
  228. }
  229. treeGrid.setPrimaryStyleName("v-tree8");
  230. treeGrid.setRowHeight(28);
  231. setWidth("100%");
  232. treeGrid.setHeightUndefined();
  233. treeGrid.setHeightMode(HeightMode.UNDEFINED);
  234. treeGrid.addExpandListener(e -> fireExpandEvent(e.getExpandedItem(),
  235. e.isUserOriginated()));
  236. treeGrid.addCollapseListener(e -> fireCollapseEvent(
  237. e.getCollapsedItem(), e.isUserOriginated()));
  238. treeGrid.addItemClickListener(e -> fireEvent(
  239. new ItemClick<>(this, e.getItem(), e.getMouseEventDetails())));
  240. }
  241. /**
  242. * Constructs a new Tree Component with given caption.
  243. *
  244. * @param caption
  245. * the caption for component
  246. */
  247. public Tree(String caption) {
  248. this();
  249. setCaption(caption);
  250. }
  251. /**
  252. * Constructs a new Tree Component with given caption and {@code TreeData}.
  253. *
  254. * @param caption
  255. * the caption for component
  256. * @param treeData
  257. * the tree data for component
  258. */
  259. public Tree(String caption, TreeData<T> treeData) {
  260. this(caption, new TreeDataProvider<>(treeData));
  261. }
  262. /**
  263. * Constructs a new Tree Component with given caption and
  264. * {@code HierarchicalDataProvider}.
  265. *
  266. * @param caption
  267. * the caption for component
  268. * @param dataProvider
  269. * the hierarchical data provider for component
  270. */
  271. public Tree(String caption, HierarchicalDataProvider<T, ?> dataProvider) {
  272. this(caption);
  273. treeGrid.setDataProvider(dataProvider);
  274. }
  275. /**
  276. * Constructs a new Tree Component with given
  277. * {@code HierarchicalDataProvider}.
  278. *
  279. * @param dataProvider
  280. * the hierarchical data provider for component
  281. */
  282. public Tree(HierarchicalDataProvider<T, ?> dataProvider) {
  283. this(null, dataProvider);
  284. }
  285. @Override
  286. public HierarchicalDataProvider<T, ?> getDataProvider() {
  287. return treeGrid.getDataProvider();
  288. }
  289. @Override
  290. public void setDataProvider(DataProvider<T, ?> dataProvider) {
  291. treeGrid.setDataProvider(dataProvider);
  292. }
  293. /**
  294. * Adds an ExpandListener to this Tree.
  295. *
  296. * @see ExpandEvent
  297. *
  298. * @param listener
  299. * the listener to add
  300. * @return a registration for the listener
  301. */
  302. public Registration addExpandListener(ExpandListener<T> listener) {
  303. return addListener(ExpandEvent.class, listener,
  304. ExpandListener.EXPAND_METHOD);
  305. }
  306. /**
  307. * Adds a CollapseListener to this Tree.
  308. *
  309. * @see CollapseEvent
  310. *
  311. * @param listener
  312. * the listener to add
  313. * @return a registration for the listener
  314. */
  315. public Registration addCollapseListener(CollapseListener<T> listener) {
  316. return addListener(CollapseEvent.class, listener,
  317. CollapseListener.COLLAPSE_METHOD);
  318. }
  319. /**
  320. * Fires an expand event with given item.
  321. *
  322. * @param item
  323. * the expanded item
  324. * @param userOriginated
  325. * whether the expand was triggered by a user interaction or the
  326. * server
  327. */
  328. protected void fireExpandEvent(T item, boolean userOriginated) {
  329. fireEvent(new ExpandEvent<>(this, item, userOriginated));
  330. }
  331. /**
  332. * Fires a collapse event with given item.
  333. *
  334. * @param item
  335. * the collapsed item
  336. * @param userOriginated
  337. * whether the collapse was triggered by a user interaction or
  338. * the server
  339. */
  340. protected void fireCollapseEvent(T item, boolean userOriginated) {
  341. fireEvent(new CollapseEvent<>(this, item, userOriginated));
  342. }
  343. /**
  344. * Expands the given items.
  345. * <p>
  346. * If an item is currently expanded, does nothing. If an item does not have
  347. * any children, does nothing.
  348. *
  349. * @param items
  350. * the items to expand
  351. */
  352. public void expand(T... items) {
  353. treeGrid.expand(items);
  354. }
  355. /**
  356. * Expands the given items.
  357. * <p>
  358. * If an item is currently expanded, does nothing. If an item does not have
  359. * any children, does nothing.
  360. *
  361. * @param items
  362. * the items to expand
  363. */
  364. public void expand(Collection<T> items) {
  365. treeGrid.expand(items);
  366. }
  367. /**
  368. * Collapse the given items.
  369. * <p>
  370. * For items that are already collapsed, does nothing.
  371. *
  372. * @param items
  373. * the collection of items to collapse
  374. */
  375. public void collapse(T... items) {
  376. treeGrid.collapse(items);
  377. }
  378. /**
  379. * Collapse the given items.
  380. * <p>
  381. * For items that are already collapsed, does nothing.
  382. *
  383. * @param items
  384. * the collection of items to collapse
  385. */
  386. public void collapse(Collection<T> items) {
  387. treeGrid.collapse(items);
  388. }
  389. /**
  390. * Returns whether a given item is expanded or collapsed.
  391. *
  392. * @param item
  393. * the item to check
  394. * @return true if the item is expanded, false if collapsed
  395. */
  396. public boolean isExpanded(T item) {
  397. return treeGrid.isExpanded(item);
  398. }
  399. /**
  400. * This method is a shorthand that delegates to the currently set selection
  401. * model.
  402. *
  403. * @see #getSelectionModel()
  404. *
  405. * @return set of selected items
  406. */
  407. public Set<T> getSelectedItems() {
  408. return treeGrid.getSelectedItems();
  409. }
  410. /**
  411. * This method is a shorthand that delegates to the currently set selection
  412. * model.
  413. *
  414. * @param item
  415. * item to select
  416. *
  417. * @see SelectionModel#select(Object)
  418. * @see #getSelectionModel()
  419. */
  420. public void select(T item) {
  421. treeGrid.select(item);
  422. }
  423. /**
  424. * This method is a shorthand that delegates to the currently set selection
  425. * model.
  426. *
  427. * @param item
  428. * item to deselect
  429. *
  430. * @see SelectionModel#deselect(Object)
  431. * @see #getSelectionModel()
  432. */
  433. public void deselect(T item) {
  434. treeGrid.deselect(item);
  435. }
  436. /**
  437. * Adds a selection listener to the current selection model.
  438. * <p>
  439. * <strong>NOTE:</strong> If selection mode is switched with
  440. * {@link #setSelectionMode(SelectionMode)}, then this listener is not
  441. * triggered anymore when selection changes!
  442. *
  443. * @param listener
  444. * the listener to add
  445. * @return a registration handle to remove the listener
  446. *
  447. * @throws UnsupportedOperationException
  448. * if selection has been disabled with
  449. * {@link SelectionMode#NONE}
  450. */
  451. public Registration addSelectionListener(SelectionListener<T> listener) {
  452. return treeGrid.addSelectionListener(listener);
  453. }
  454. /**
  455. * Use this tree as a single select in {@link Binder}. Throws
  456. * {@link IllegalStateException} if the tree is not using
  457. * {@link SelectionMode#SINGLE}.
  458. *
  459. * @return the single select wrapper that can be used in binder
  460. */
  461. public SingleSelect<T> asSingleSelect() {
  462. return treeGrid.asSingleSelect();
  463. }
  464. /**
  465. * Returns the selection model for this Tree.
  466. *
  467. * @return the selection model, not <code>null</code>
  468. */
  469. public SelectionModel<T> getSelectionModel() {
  470. return treeGrid.getSelectionModel();
  471. }
  472. /**
  473. * Sets the item caption generator that is used to produce the strings shown
  474. * as the text for each item. By default, {@link String#valueOf(Object)} is
  475. * used.
  476. *
  477. * @param captionGenerator
  478. * the item caption provider to use, not <code>null</code>
  479. */
  480. public void setItemCaptionGenerator(
  481. ItemCaptionGenerator<T> captionGenerator) {
  482. Objects.requireNonNull(captionGenerator,
  483. "Caption generator must not be null");
  484. this.captionGenerator = captionGenerator;
  485. treeGrid.getDataCommunicator().reset();
  486. }
  487. /**
  488. * Sets the item icon generator that is used to produce custom icons for
  489. * items. The generator can return <code>null</code> for items with no icon.
  490. *
  491. * @see IconGenerator
  492. *
  493. * @param iconGenerator
  494. * the item icon generator to set, not <code>null</code>
  495. * @throws NullPointerException
  496. * if {@code itemIconGenerator} is {@code null}
  497. */
  498. public void setItemIconGenerator(IconGenerator<T> iconGenerator) {
  499. Objects.requireNonNull(iconGenerator,
  500. "Item icon generator must not be null");
  501. this.iconProvider = iconGenerator;
  502. treeGrid.getDataCommunicator().reset();
  503. }
  504. /**
  505. * Sets the item collapse allowed provider for this Tree. The provider
  506. * should return {@code true} for any item that the user can collapse.
  507. * <p>
  508. * <strong>Note:</strong> This callback will be accessed often when sending
  509. * data to the client. The callback should not do any costly operations.
  510. *
  511. * @param provider
  512. * the item collapse allowed provider, not {@code null}
  513. */
  514. public void setItemCollapseAllowedProvider(
  515. ItemCollapseAllowedProvider<T> provider) {
  516. treeGrid.setItemCollapseAllowedProvider(provider);
  517. }
  518. /**
  519. * Sets the style generator that is used for generating class names for
  520. * items in this tree. Returning null from the generator results in no
  521. * custom style name being set.
  522. *
  523. * @see StyleGenerator
  524. *
  525. * @param styleGenerator
  526. * the item style generator to set, not {@code null}
  527. * @throws NullPointerException
  528. * if {@code styleGenerator} is {@code null}
  529. */
  530. public void setStyleGenerator(StyleGenerator<T> styleGenerator) {
  531. treeGrid.setStyleGenerator(styleGenerator);
  532. }
  533. /**
  534. * Gets the item caption generator.
  535. *
  536. * @return the item caption generator
  537. */
  538. public ItemCaptionGenerator<T> getItemCaptionGenerator() {
  539. return captionGenerator;
  540. }
  541. /**
  542. * Gets the item icon generator.
  543. *
  544. * @see IconGenerator
  545. *
  546. * @return the item icon generator
  547. */
  548. public IconGenerator<T> getItemIconGenerator() {
  549. return iconProvider;
  550. }
  551. /**
  552. * Gets the item collapse allowed provider.
  553. *
  554. * @return the item collapse allowed provider
  555. */
  556. public ItemCollapseAllowedProvider<T> getItemCollapseAllowedProvider() {
  557. return treeGrid.getItemCollapseAllowedProvider();
  558. }
  559. /**
  560. * Gets the style generator.
  561. *
  562. * @see StyleGenerator
  563. *
  564. * @return the item style generator
  565. */
  566. public StyleGenerator<T> getStyleGenerator() {
  567. return treeGrid.getStyleGenerator();
  568. }
  569. /**
  570. * Adds an item click listener. The listener is called when an item of this
  571. * {@code Tree} is clicked.
  572. *
  573. * @param listener
  574. * the item click listener, not null
  575. * @return a registration for the listener
  576. * @see #addContextClickListener
  577. */
  578. public Registration addItemClickListener(ItemClickListener<T> listener) {
  579. return addListener(ItemClick.class, listener, ITEM_CLICK_METHOD);
  580. }
  581. /**
  582. * Sets the tree's selection mode.
  583. * <p>
  584. * The built-in selection modes are:
  585. * <ul>
  586. * <li>{@link SelectionMode#SINGLE} <b>the default model</b></li>
  587. * <li>{@link SelectionMode#MULTI}</li>
  588. * <li>{@link SelectionMode#NONE} preventing selection</li>
  589. * </ul>
  590. *
  591. * @param selectionMode
  592. * the selection mode to switch to, not {@code null}
  593. * @return the used selection model
  594. *
  595. * @see SelectionMode
  596. */
  597. public SelectionModel<T> setSelectionMode(SelectionMode selectionMode) {
  598. Objects.requireNonNull(selectionMode,
  599. "Can not set selection mode to null");
  600. switch (selectionMode) {
  601. case MULTI:
  602. TreeMultiSelectionModel<T> model = new TreeMultiSelectionModel<>();
  603. treeGrid.setSelectionModel(model);
  604. return model;
  605. default:
  606. return treeGrid.setSelectionMode(selectionMode);
  607. }
  608. }
  609. @Override
  610. public void setCaption(String caption) {
  611. treeGrid.setCaption(caption);
  612. }
  613. @Override
  614. public String getCaption() {
  615. return treeGrid.getCaption();
  616. }
  617. @Override
  618. public void setIcon(Resource icon) {
  619. treeGrid.setIcon(icon);
  620. }
  621. @Override
  622. public Resource getIcon() {
  623. return treeGrid.getIcon();
  624. }
  625. @Override
  626. public String getStyleName() {
  627. return treeGrid.getStyleName();
  628. }
  629. @Override
  630. public void setStyleName(String style) {
  631. treeGrid.setStyleName(style);
  632. }
  633. @Override
  634. public void setStyleName(String style, boolean add) {
  635. treeGrid.setStyleName(style, add);
  636. }
  637. @Override
  638. public void addStyleName(String style) {
  639. treeGrid.addStyleName(style);
  640. }
  641. @Override
  642. public void removeStyleName(String style) {
  643. treeGrid.removeStyleName(style);
  644. }
  645. @Override
  646. public String getPrimaryStyleName() {
  647. return treeGrid.getPrimaryStyleName();
  648. }
  649. @Override
  650. public void setPrimaryStyleName(String style) {
  651. treeGrid.setPrimaryStyleName(style);
  652. }
  653. @Override
  654. public void setId(String id) {
  655. treeGrid.setId(id);
  656. }
  657. @Override
  658. public String getId() {
  659. return treeGrid.getId();
  660. }
  661. @Override
  662. public void setCaptionAsHtml(boolean captionAsHtml) {
  663. treeGrid.setCaptionAsHtml(captionAsHtml);
  664. }
  665. @Override
  666. public boolean isCaptionAsHtml() {
  667. return treeGrid.isCaptionAsHtml();
  668. }
  669. @Override
  670. public void setDescription(String description) {
  671. treeGrid.setDescription(description);
  672. }
  673. @Override
  674. public void setDescription(String description, ContentMode mode) {
  675. treeGrid.setDescription(description, mode);
  676. }
  677. @Override
  678. public ErrorMessage getErrorMessage() {
  679. return treeGrid.getErrorMessage();
  680. }
  681. @Override
  682. public ErrorMessage getComponentError() {
  683. return treeGrid.getComponentError();
  684. }
  685. @Override
  686. public void setComponentError(ErrorMessage componentError) {
  687. treeGrid.setComponentError(componentError);
  688. }
  689. /**
  690. * Sets the height of a row. If -1 (default), the row height is calculated
  691. * based on the theme for an empty row before the Tree is displayed.
  692. *
  693. * @param rowHeight
  694. * The height of a row in pixels or -1 for automatic calculation
  695. */
  696. public void setRowHeight(double rowHeight) {
  697. treeGrid.setRowHeight(rowHeight);
  698. }
  699. /**
  700. * Sets the content mode of the item caption.
  701. *
  702. * @param contentMode
  703. * the content mode
  704. */
  705. public void setContentMode(ContentMode contentMode) {
  706. renderer.getState().mode = contentMode;
  707. }
  708. /**
  709. * Adds a context click listener that gets notified when a context click
  710. * happens.
  711. *
  712. * @param listener
  713. * the context click listener to add, not null
  714. * actual event provided to the listener is {@link TreeContextClickEvent}
  715. * @return a registration object for removing the listener
  716. *
  717. * @since 8.1
  718. * @see #addItemClickListener
  719. * @see Registration
  720. */
  721. @Override
  722. public Registration addContextClickListener(ContextClickEvent.ContextClickListener listener) {
  723. Registration registration =
  724. addListener(EventId.CONTEXT_CLICK, ContextClickEvent.class,
  725. listener, ContextClickEvent.CONTEXT_CLICK_METHOD);
  726. setupContextClickListener();
  727. return () -> {
  728. registration.remove();
  729. setupContextClickListener();
  730. };
  731. }
  732. @Override
  733. @Deprecated
  734. public void removeContextClickListener(ContextClickEvent.ContextClickListener listener) {
  735. super.removeContextClickListener(listener);
  736. setupContextClickListener();
  737. }
  738. private void setupContextClickListener() {
  739. if (hasListeners(ContextClickEvent.class)) {
  740. if (contextClickRegistration == null) {
  741. contextClickRegistration = treeGrid.addContextClickListener(
  742. event -> {
  743. T item = null;
  744. if (event instanceof Grid.GridContextClickEvent) {
  745. item = ((Grid.GridContextClickEvent<T>) event).getItem();
  746. }
  747. fireEvent(new TreeContextClickEvent<>(this, event.getMouseEventDetails(), item));
  748. }
  749. );
  750. }
  751. } else if (contextClickRegistration != null) {
  752. contextClickRegistration.remove();
  753. contextClickRegistration = null;
  754. }
  755. }
  756. /**
  757. * ContextClickEvent for the Tree Component.
  758. * <p>
  759. * Usage:
  760. * <pre>
  761. * tree.addContextClickListener(event -&gt; Notification.show(
  762. * ((TreeContextClickEvent&lt;Person&gt;)event).getItem() + " Clicked")
  763. * );
  764. * </pre>
  765. *
  766. * @param <T> the tree bean type
  767. */
  768. public static class TreeContextClickEvent<T> extends ContextClickEvent {
  769. private final T item;
  770. /**
  771. * Creates a new context click event.
  772. *
  773. * @param source the tree where the context click occurred
  774. * @param mouseEventDetails details about mouse position
  775. * @param item the item which was clicked or {@code null}
  776. * if the click happened outside any item
  777. */
  778. public TreeContextClickEvent(Tree<T> source,
  779. MouseEventDetails mouseEventDetails,
  780. T item) {
  781. super(source, mouseEventDetails);
  782. this.item = item;
  783. }
  784. /**
  785. * Returns the item of context clicked row.
  786. *
  787. * @return clicked item; {@code null}
  788. * the click happened outside any item
  789. */
  790. public T getItem() {
  791. return item;
  792. }
  793. @Override
  794. public Tree<T> getComponent() {
  795. return (Tree<T>) super.getComponent();
  796. }
  797. }
  798. }