From bb358e50ddd19a8de6e495a0b58a5244ceed6440 Mon Sep 17 00:00:00 2001 From: Ilia Motornyi Date: Thu, 4 May 2017 09:00:14 +0300 Subject: [PATCH] Tree documentation --- .../components/chapter-components.asciidoc | 2 + .../components-customcomponent.asciidoc | 2 +- .../components-customfield.asciidoc | 2 +- .../components/components-embedded.asciidoc | 2 +- .../components/components-menubar.asciidoc | 2 +- .../components/components-popupview.asciidoc | 2 +- .../components-progressbar.asciidoc | 2 +- .../components/components-slider.asciidoc | 2 +- .../components/components-tree.asciidoc | 211 ++++++++++++++++++ .../components/components-upload.asciidoc | 2 +- .../datamodel/datamodel-hierarchical.asciidoc | 6 +- documentation/img/tree-basic.png | Bin 0 -> 4397 bytes 12 files changed, 225 insertions(+), 10 deletions(-) create mode 100644 documentation/components/components-tree.asciidoc create mode 100644 documentation/img/tree-basic.png diff --git a/documentation/components/chapter-components.asciidoc b/documentation/components/chapter-components.asciidoc index e1093ba03e..e53752f26c 100644 --- a/documentation/components/chapter-components.asciidoc +++ b/documentation/components/chapter-components.asciidoc @@ -48,6 +48,8 @@ include::components-grid.asciidoc[leveloffset=+2] include::components-treegrid.asciidoc[leveloffset=+2] +include::components-tree.asciidoc[leveloffset=+2] + include::components-menubar.asciidoc[leveloffset=+2] include::components-upload.asciidoc[leveloffset=+2] diff --git a/documentation/components/components-customcomponent.asciidoc b/documentation/components/components-customcomponent.asciidoc index 01679a3f9b..cf898ebf17 100644 --- a/documentation/components/components-customcomponent.asciidoc +++ b/documentation/components/components-customcomponent.asciidoc @@ -1,6 +1,6 @@ --- title: Composition with Composite and CustomComponent -order: 32 +order: 33 layout: page --- diff --git a/documentation/components/components-customfield.asciidoc b/documentation/components/components-customfield.asciidoc index a369f390a2..95f949da01 100644 --- a/documentation/components/components-customfield.asciidoc +++ b/documentation/components/components-customfield.asciidoc @@ -1,6 +1,6 @@ --- title: Composite Fields with CustomField -order: 33 +order: 34 layout: page --- diff --git a/documentation/components/components-embedded.asciidoc b/documentation/components/components-embedded.asciidoc index 84a7971500..1c1a6c90ae 100644 --- a/documentation/components/components-embedded.asciidoc +++ b/documentation/components/components-embedded.asciidoc @@ -1,6 +1,6 @@ --- title: Embedded Resources -order: 34 +order: 35 layout: page --- diff --git a/documentation/components/components-menubar.asciidoc b/documentation/components/components-menubar.asciidoc index 0c54196b87..a2c22b6b75 100644 --- a/documentation/components/components-menubar.asciidoc +++ b/documentation/components/components-menubar.asciidoc @@ -1,6 +1,6 @@ --- title: MenuBar -order: 26 +order: 27 layout: page --- diff --git a/documentation/components/components-popupview.asciidoc b/documentation/components/components-popupview.asciidoc index bc58fe6b19..c16411f420 100644 --- a/documentation/components/components-popupview.asciidoc +++ b/documentation/components/components-popupview.asciidoc @@ -1,6 +1,6 @@ --- title: PopupView -order: 30 +order: 31 layout: page --- diff --git a/documentation/components/components-progressbar.asciidoc b/documentation/components/components-progressbar.asciidoc index b6337ff3ad..54940799b3 100644 --- a/documentation/components/components-progressbar.asciidoc +++ b/documentation/components/components-progressbar.asciidoc @@ -1,6 +1,6 @@ --- title: ProgressBar -order: 28 +order: 29 layout: page --- diff --git a/documentation/components/components-slider.asciidoc b/documentation/components/components-slider.asciidoc index 7ae972ae77..a35b60b668 100644 --- a/documentation/components/components-slider.asciidoc +++ b/documentation/components/components-slider.asciidoc @@ -1,6 +1,6 @@ --- title: Slider -order: 29 +order: 30 layout: page --- diff --git a/documentation/components/components-tree.asciidoc b/documentation/components/components-tree.asciidoc new file mode 100644 index 0000000000..dd957a0308 --- /dev/null +++ b/documentation/components/components-tree.asciidoc @@ -0,0 +1,211 @@ +--- +title: Tree +order: 26 +layout: page +--- + +[[components.tree]] += Tree + +ifdef::web[] +[.sampler] +image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/grids-and-trees/tree"] +endif::web[] + +IMPORTANT: The [classname]#Tree# component is currently being developed and only available in the Framework 8.1 prerelease versions, starting from 8.1.0.beta1. + +[[components.tree.overview]] +== Overview + +The [classname]#Tree# component allows a natural way to represent data that has hierarchical relationships. +The user can drill down in the hierarchy by expanding items by clicking on the expand arrow, and likewise collapse items. +[classname]#Tree# is a selection component that allows selecting items. +It also supports drag and drop, so you can drag items to and from a tree, and drop them in the hierarchy. + +A typical use of the [classname]#Tree# component is for displaying a hierarchical menu, as illustrated in <>, or for displaying file systems or hierarchical datasets. + +[[figure.components.tree]] +.A [classname]#Tree# component +image::img/tree-basic.png[width=70%, scaledwidth=100%] + +[[components.tree.data]] +== Binding to Data + +[classname]#Tree# is used by binding it to a hierarchical data provider. The data provider can be based on in-memory or back end data. For in-memory data, the [classname]#InMemoryHierarchicalDataProvider# can be used, and for loading data from a back end, you need to implement three methods from the [interfacename]#HierarchicalDataProvider# interface. Usage of both data providers is described in +<>. + + +The [classname]#HierarchyData# class can be used to build the hierarchical data structure, +and it can then be passed on to [classname]#InMemoryHierarchicalDataProvider#. It is simply a hierarchical +collection, that the data provider uses to populate the [classname]#Tree#. + +The [methodname]#setItems# method in [classname]#Tree# can be used to set the root level items. Internally +an [classname]#InMemoryHierarchicalDataProvider# with [classname]#HierarchyData# is used. + +[source, java] +---- +// An initial planet tree +Tree tree = new Tree<>(); +HierarchyData hierarchyData = new HierarchyData<>(); + +// Couple of childless root items +hierarchyData.addItem(null,"Mercury"); +hierarchyData.addItem(null,"Venus"); + +// Items with hierarchy +hierarchyData.addItem(null,"Earth"); +hierarchyData.addItem("Earth","The Moon"); + +inMemoryDataProvider = new InMemoryHierarchicalDataProvider<>(hierarchyData); +tree.setDataProvider(inMemoryDataProvider); +tree.expand("Earth"); // Expand programmatically +---- + +If at any time you want to modify +the in-memory data in the tree, you may do it as follows: + +[source, java] +---- +// Add Mars with satellites +hierarchyData.addItem(null, "Mars"); +hierarchyData.addItem("Mars", "Phobos"); +hierarchyData.addItem("Mars", "Deimos"); +inMemoryDataProvider.refreshAll(); + +---- + + +The result was shown in <>. + +The caption and the icon of tree items is generated by the [classname]#ItemCaptionGenerator# and the +[classname]#IconGenerator#, set with [methodname]#setItemCaptionGenerator()# and [methodname]#setItemIconGenerator()# respectively. + +[[components.tree.selection]] +== Handling Selection and Clicks + +[classname]#Tree# supports single selection mode, you can use [methodname]#asSingleSelect()# to access the selection +object, which supports selection listeners and data binding. For more details, see link:<>. +The [classname]#Tree# also supports the shortcut method [methodname]#addSelectionListener()#. + +//// +todo not implemented yet. +[classname]#Tree# also emits [classname]##ItemClickEvent##s when items are clicked. +This way you can handle item clicks also when selection is not enabled or you want special user interaction specifically on clicks. + + +[source, Java] +---- +tree.addItemClickListener( + new ItemClickEvent.ItemClickListener() { + public void itemClick(ItemClickEvent event) { + // Pick only left mouse clicks + if (event.getButton() == ItemClickEvent.BUTTON_LEFT) + Notification.show("Left click", + Notification.Type.HUMANIZED_MESSAGE); + } + }); +---- +//// + +[[components.tree.expandcollapse]] +== Expanding and Collapsing Nodes + +[classname]#Tree# nodes that have children can be expanded and collapsed by either user interaction or through the server-side API: + +[source, java] +---- +// Expands a child project. If the child project is not yet +// in the visible hierarchy, nothing will be shown. +tree.expand(childProject); +// Expands the root project. If child project now becomes +// visible it is also expanded into view. +tree.expand(rootProject); +// Collapses the child project. +tree.collapse(childProject); +---- + +To use the server-side API with a backend data provider the [methodname]#hashCode# and [methodname]#equals# methods for the node's type must be implemented so that when the desired node is retrieved from the backend it can be correctly matched with the object passed to either [methodname]#expand# or [methodname]#collapse#. + +The [classname]#Tree# component supports listening to the expansion and collapsing of items in its hierarchy. +The expand and collapse listeners can be added as follows: + +[source, java] +---- +tree.addExpandListener(event -> log("Item expanded: " + event.getExpandedItem())); +tree.addCollapseListener(event -> log("Item collapsed: " + event.getCollapsedItem())); +---- + +The return types of the methods `getExpandedItem` and `getCollapsedItem` are the same as the type of the [classname]#Tree# the events originated from. +Note that collapse listeners will not be triggered for any expanded subtrees of the collapsed item. + +//// +todo not implemented yet +[[components.tree.node.collapsing]] +== Prevent Node Collapsing + +[classname]#Tree# supports setting a callback method that can allow or prevent the user from collapsing an expanded node. +It can be set with [methodname]#setItemCollapseAllowedProvider# method, that takes a [interfacename]#SerializablePredicate#. +For nodes that cannot be collapsed, the [literal]#++collapse-disabled++# class name is applied to the expansion element + +Avoid doing any heavy operations in the method, since it is called for each item when it is being sent to the client. + +Example using a predefined set of persons that can not be collapsed: +[source, java] +---- +Set alwaysExpanded; +personTree.setItemCollapseAllowedProvider(person -> + !alwaysExpanded.contains(person)); +---- +//// + +[[components.treegrid.keyboard]] +== Keyboard Navigation and Focus Handling in TreeGrid + +The user can navigate through rows with kbd:[Up] and kbd:[Down], collapse rows with kbd:[Left], +and expand them with kbd:[Right]. + +//// +todo styling documentation +[[components.tree.css]] +== CSS Style Rules + +[source, css] +---- +.v-tree {} + .v-tree-node {} /* A node (item) */ + .v-tree-node-caption {} /* Caption of the node */ + .v-tree-node-children {} /* Contains child nodes */ + .v-tree-node-root {} /* If node is a root node */ + .v-tree-node-leaf {} /* If node has no children */ +---- + +[[components.tree.css.itemstyles]] +=== Generating Item Styles + +You can style each tree item individually by generating a style name for them with a [interfacename]#Tree.ItemStyleGenerator#, which you assign to a tree with [methodname]#setItemStyleGenerator()#. +The generator should return a style name for each item or `null`. + +[source, Java] +---- +// Show all leaf nodes as disabled +tree.setItemStyleGenerator(new Tree.ItemStyleGenerator() { + @Override + public String getStyle(Tree source, Object itemId) { + if (! tree.hasChildren(itemId)) + return "disabled"; + return null; + } +}); +---- + +The style names are prefixed with `v-tree-node-caption-`. +You could thereby define the item styling as follows: + +[source, CSS] +---- +.v-tree-node-caption-disabled { + color: graytext; + font-style: italic; +} +---- +//// \ No newline at end of file diff --git a/documentation/components/components-upload.asciidoc b/documentation/components/components-upload.asciidoc index cde631d148..cb26663c7b 100644 --- a/documentation/components/components-upload.asciidoc +++ b/documentation/components/components-upload.asciidoc @@ -1,6 +1,6 @@ --- title: Upload -order: 27 +order: 28 layout: page --- diff --git a/documentation/datamodel/datamodel-hierarchical.asciidoc b/documentation/datamodel/datamodel-hierarchical.asciidoc index 24d023acd9..735317c519 100644 --- a/documentation/datamodel/datamodel-hierarchical.asciidoc +++ b/documentation/datamodel/datamodel-hierarchical.asciidoc @@ -9,9 +9,11 @@ layout: page IMPORTANT: The [interfacename]#HierarchicalDataProvider# is currently being developed and only available in the Framework 8.1 prerelease versions, starting from 8.1.0.alpha1. -The [classname]#TreeGrid# component allows you to show data with hierarchical relationships between items. +The [classname]#Tree# and the [classname]#TreeGrid# components allow you to show data with hierarchical relationships between items. That data can be populated by on-demand from a back end by implementing the [interfacename]#HierarchicalDataProvider# interface. If you have the data available in-memory on the server, -you use the collection style API of [classname]#HierarchyData# and then pass it to a [classname]#InMemoryHierarchicalDataProvider#. This chapter introduces the hierarchical data providers and how they work. For using them with the [classname]#TreeGrid# component you should see <>. +you use the collection style API of [classname]#HierarchyData# and then pass it to a [classname]#InMemoryHierarchicalDataProvider#. This chapter introduces the hierarchical data providers and how they work. +For using them with the components you should see <> +and <> documentation. == In-memory Hierarchical Data diff --git a/documentation/img/tree-basic.png b/documentation/img/tree-basic.png new file mode 100644 index 0000000000000000000000000000000000000000..260dd944131ee499098583675dab53bcc253e4d5 GIT binary patch literal 4397 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 literal 0 HcmV?d00001 -- 2.39.5