From 99d6de546c74f0eed230ea8253dda6b85109d2e7 Mon Sep 17 00:00:00 2001 From: Markus Koivisto Date: Fri, 22 Jan 2016 14:55:18 +0200 Subject: Add documentation to master branch Change-Id: I2504bb10f1ae73ec0cbc08b7ba5a88925caa1674 --- .../components/chapter-components.asciidoc | 71 + .../components/components-button.asciidoc | 71 + .../components/components-calendar.asciidoc | 1197 +++++++++++ .../components/components-checkbox.asciidoc | 72 + .../components/components-combobox.asciidoc | 112 + .../components/components-customcomponent.asciidoc | 87 + .../components/components-customfield.asciidoc | 33 + .../components/components-datefield.asciidoc | 391 ++++ .../components/components-embedded.asciidoc | 205 ++ .../components/components-extensions.asciidoc | 38 + .../components/components-features.asciidoc | 757 +++++++ .../components/components-fields.asciidoc | 345 ++++ documentation/components/components-grid.asciidoc | 1407 +++++++++++++ .../components/components-interfaces.asciidoc | 117 ++ documentation/components/components-label.asciidoc | 311 +++ documentation/components/components-link.asciidoc | 161 ++ .../components/components-listselect.asciidoc | 62 + .../components/components-menubar.asciidoc | 223 ++ .../components/components-nativeselect.asciidoc | 54 + .../components/components-optiongroup.asciidoc | 146 ++ .../components/components-overview.asciidoc | 81 + .../components/components-passwordfield.asciidoc | 54 + .../components/components-popupview.asciidoc | 92 + .../components/components-progressbar.asciidoc | 214 ++ .../components/components-richtextarea.asciidoc | 128 ++ .../components/components-selection.asciidoc | 464 +++++ .../components/components-slider.asciidoc | 117 ++ documentation/components/components-table.asciidoc | 1166 +++++++++++ .../components/components-textarea.asciidoc | 96 + .../components/components-textfield.asciidoc | 307 +++ documentation/components/components-tree.asciidoc | 98 + .../components/components-treetable.asciidoc | 101 + .../components/components-twincolselect.asciidoc | 100 + .../components/components-upload.asciidoc | 172 ++ documentation/components/img/button-example1.png | Bin 0 -> 47905 bytes documentation/components/img/calendar-monthly.png | Bin 0 -> 17802 bytes documentation/components/img/calendar-weekly.png | Bin 0 -> 16872 bytes documentation/components/img/checkbox-example1.png | Bin 0 -> 15144 bytes documentation/components/img/combobox-basic.png | Bin 0 -> 20444 bytes .../components/img/combobox-filtering.png | Bin 0 -> 28448 bytes .../components/img/component-abstractions-hi.png | Bin 0 -> 84173 bytes .../components/img/component-abstractions-lo.png | Bin 0 -> 45878 bytes .../components/img/component-diagram-hi.png | Bin 0 -> 200429 bytes .../components/img/component-diagram-lo.png | Bin 0 -> 111392 bytes .../components/img/customcomponent-example1.png | Bin 0 -> 13482 bytes .../components/img/datefield-example1.png | Bin 0 -> 30916 bytes .../components/img/datefield-formatting.png | Bin 0 -> 5607 bytes .../components/img/datefield-inlinedatefield.png | Bin 0 -> 25198 bytes .../img/features-caption-layoutmanaged.png | Bin 0 -> 19272 bytes .../components/img/features-enabled-simple.png | Bin 0 -> 4960 bytes documentation/components/img/features-icon.png | Bin 0 -> 6658 bytes .../components/img/features-locale-selection.png | Bin 0 -> 10479 bytes .../components/img/features-locale-simple.png | Bin 0 -> 20711 bytes .../components/img/features-readonly-simple.png | Bin 0 -> 7908 bytes .../components/img/features-stylename-simple.png | Bin 0 -> 5341 bytes .../components/img/features-visible-simple.png | Bin 0 -> 196 bytes documentation/components/img/field-diagram-hi.png | Bin 0 -> 108186 bytes documentation/components/img/field-diagram-lo.png | Bin 0 -> 59968 bytes .../components/img/field-interface-hi.png | Bin 0 -> 63449 bytes .../components/img/field-interface-lo.png | Bin 0 -> 33390 bytes documentation/components/img/grid-editor-basic.png | Bin 0 -> 34769 bytes .../components/img/grid-editor-errors.png | Bin 0 -> 29737 bytes documentation/components/img/grid-features.png | Bin 0 -> 60533 bytes documentation/components/img/grid-filtering.png | Bin 0 -> 23858 bytes documentation/components/img/grid-renderers.png | Bin 0 -> 156435 bytes .../components/img/grid-selection-multi.png | Bin 0 -> 55080 bytes documentation/components/img/grid-sorting.png | Bin 0 -> 29163 bytes documentation/components/img/label-example1.png | Bin 0 -> 19918 bytes documentation/components/img/label-modes.png | Bin 0 -> 77414 bytes documentation/components/img/label-withimage.png | Bin 0 -> 7506 bytes documentation/components/img/link-new.png | Bin 0 -> 1672 bytes documentation/components/img/link.png | Bin 0 -> 7434 bytes documentation/components/img/listselect-basic.png | Bin 0 -> 32906 bytes documentation/components/img/menubar-example1.png | Bin 0 -> 21202 bytes .../components/img/nativeselect-basic.png | Bin 0 -> 22844 bytes documentation/components/img/optiongroup-basic.png | Bin 0 -> 31636 bytes .../components/img/optiongroup-disabling.png | Bin 0 -> 19133 bytes .../components/img/optiongroup-horizontal.png | Bin 0 -> 11318 bytes .../components/img/passwordfield-basic.png | Bin 0 -> 4358 bytes documentation/components/img/progressbar-basic.png | Bin 0 -> 1289 bytes .../components/img/progressbar-indeterminate.png | Bin 0 -> 2532 bytes .../components/img/progressbar-thread.png | Bin 0 -> 7967 bytes .../components/img/richtextarea-example1.png | Bin 0 -> 30763 bytes .../img/richtextarea-toolbar-mod-whitebg.png | Bin 0 -> 2531 bytes .../img/richtextarea-toolbar-whitebg.png | Bin 0 -> 1958 bytes documentation/components/img/select-selected1.png | Bin 0 -> 8700 bytes .../components/img/slider-example1-hi.png | Bin 0 -> 8084 bytes .../components/img/slider-example1-lo.png | Bin 0 -> 4139 bytes documentation/components/img/slider-orig.png | Bin 0 -> 3308 bytes .../components/img/table-cellstylegenerator1.png | Bin 0 -> 8363 bytes .../components/img/table-column-collapsing.png | Bin 0 -> 7033 bytes .../components/img/table-column-resize.png | Bin 0 -> 6811 bytes .../components/img/table-columnformatting.png | Bin 0 -> 14101 bytes documentation/components/img/table-components.png | Bin 0 -> 20166 bytes documentation/components/img/table-editable3.png | Bin 0 -> 34976 bytes documentation/components/img/table-example1.png | Bin 0 -> 21987 bytes documentation/components/img/table-example2.png | Bin 0 -> 10847 bytes documentation/components/img/table-footer.png | Bin 0 -> 27975 bytes .../components/img/table-generatedcolumns1.png | Bin 0 -> 26349 bytes .../components/img/table-generatedcolumns2.png | Bin 0 -> 23515 bytes documentation/components/img/textarea-basic.png | Bin 0 -> 12927 bytes documentation/components/img/textarea-wordwrap.png | Bin 0 -> 23158 bytes documentation/components/img/textfield-css.png | Bin 0 -> 1356 bytes .../components/img/textfield-diagram-hi.png | Bin 0 -> 55555 bytes .../components/img/textfield-diagram-lo.png | Bin 0 -> 14012 bytes documentation/components/img/textfield-example.png | Bin 0 -> 4965 bytes .../img/textfield-nullrepresentation.png | Bin 0 -> 5575 bytes .../components/img/textfield-textchangeevents.png | Bin 0 -> 8631 bytes .../img/tooltip-plain-withpointer-hi.png | Bin 0 -> 10235 bytes .../img/tooltip-plain-withpointer-lo.png | Bin 0 -> 2781 bytes documentation/components/img/tooltip-plain.png | Bin 0 -> 3734 bytes .../img/tooltip-richtext-withpointer-hi.png | Bin 0 -> 33242 bytes .../img/tooltip-richtext-withpointer-lo.png | Bin 0 -> 10182 bytes documentation/components/img/tooltip-richtext.png | Bin 0 -> 12240 bytes documentation/components/img/tree-example1.png | Bin 0 -> 21923 bytes documentation/components/img/treetable-basic.png | Bin 0 -> 20786 bytes .../components/img/twincolselect-basic.png | Bin 0 -> 23709 bytes documentation/components/img/upload-example.png | Bin 0 -> 47045 bytes documentation/components/img/upload.png | Bin 0 -> 13788 bytes .../original-drawings/component-abstractions.svg | 1226 +++++++++++ .../original-drawings/component-diagram.svg | 2180 ++++++++++++++++++++ .../components/original-drawings/field-diagram.svg | 1488 +++++++++++++ .../original-drawings/field-interface.svg | 1222 +++++++++++ .../original-drawings/slider-example1.svg | 127 ++ .../original-drawings/textfield-diagram.svg | 868 ++++++++ .../tooltip-plain-withpointer.svg | 158 ++ .../tooltip-richtext-withpointer.svg | 165 ++ 127 files changed, 16484 insertions(+) create mode 100644 documentation/components/chapter-components.asciidoc create mode 100644 documentation/components/components-button.asciidoc create mode 100644 documentation/components/components-calendar.asciidoc create mode 100644 documentation/components/components-checkbox.asciidoc create mode 100644 documentation/components/components-combobox.asciidoc create mode 100644 documentation/components/components-customcomponent.asciidoc create mode 100644 documentation/components/components-customfield.asciidoc create mode 100644 documentation/components/components-datefield.asciidoc create mode 100644 documentation/components/components-embedded.asciidoc create mode 100644 documentation/components/components-extensions.asciidoc create mode 100644 documentation/components/components-features.asciidoc create mode 100644 documentation/components/components-fields.asciidoc create mode 100644 documentation/components/components-grid.asciidoc create mode 100644 documentation/components/components-interfaces.asciidoc create mode 100644 documentation/components/components-label.asciidoc create mode 100644 documentation/components/components-link.asciidoc create mode 100644 documentation/components/components-listselect.asciidoc create mode 100644 documentation/components/components-menubar.asciidoc create mode 100644 documentation/components/components-nativeselect.asciidoc create mode 100644 documentation/components/components-optiongroup.asciidoc create mode 100644 documentation/components/components-overview.asciidoc create mode 100644 documentation/components/components-passwordfield.asciidoc create mode 100644 documentation/components/components-popupview.asciidoc create mode 100644 documentation/components/components-progressbar.asciidoc create mode 100644 documentation/components/components-richtextarea.asciidoc create mode 100644 documentation/components/components-selection.asciidoc create mode 100644 documentation/components/components-slider.asciidoc create mode 100644 documentation/components/components-table.asciidoc create mode 100644 documentation/components/components-textarea.asciidoc create mode 100644 documentation/components/components-textfield.asciidoc create mode 100644 documentation/components/components-tree.asciidoc create mode 100644 documentation/components/components-treetable.asciidoc create mode 100644 documentation/components/components-twincolselect.asciidoc create mode 100644 documentation/components/components-upload.asciidoc create mode 100644 documentation/components/img/button-example1.png create mode 100644 documentation/components/img/calendar-monthly.png create mode 100644 documentation/components/img/calendar-weekly.png create mode 100644 documentation/components/img/checkbox-example1.png create mode 100644 documentation/components/img/combobox-basic.png create mode 100644 documentation/components/img/combobox-filtering.png create mode 100644 documentation/components/img/component-abstractions-hi.png create mode 100644 documentation/components/img/component-abstractions-lo.png create mode 100644 documentation/components/img/component-diagram-hi.png create mode 100644 documentation/components/img/component-diagram-lo.png create mode 100644 documentation/components/img/customcomponent-example1.png create mode 100644 documentation/components/img/datefield-example1.png create mode 100644 documentation/components/img/datefield-formatting.png create mode 100644 documentation/components/img/datefield-inlinedatefield.png create mode 100644 documentation/components/img/features-caption-layoutmanaged.png create mode 100644 documentation/components/img/features-enabled-simple.png create mode 100644 documentation/components/img/features-icon.png create mode 100644 documentation/components/img/features-locale-selection.png create mode 100644 documentation/components/img/features-locale-simple.png create mode 100644 documentation/components/img/features-readonly-simple.png create mode 100644 documentation/components/img/features-stylename-simple.png create mode 100644 documentation/components/img/features-visible-simple.png create mode 100644 documentation/components/img/field-diagram-hi.png create mode 100644 documentation/components/img/field-diagram-lo.png create mode 100644 documentation/components/img/field-interface-hi.png create mode 100644 documentation/components/img/field-interface-lo.png create mode 100644 documentation/components/img/grid-editor-basic.png create mode 100644 documentation/components/img/grid-editor-errors.png create mode 100644 documentation/components/img/grid-features.png create mode 100644 documentation/components/img/grid-filtering.png create mode 100644 documentation/components/img/grid-renderers.png create mode 100644 documentation/components/img/grid-selection-multi.png create mode 100644 documentation/components/img/grid-sorting.png create mode 100644 documentation/components/img/label-example1.png create mode 100644 documentation/components/img/label-modes.png create mode 100644 documentation/components/img/label-withimage.png create mode 100644 documentation/components/img/link-new.png create mode 100644 documentation/components/img/link.png create mode 100644 documentation/components/img/listselect-basic.png create mode 100644 documentation/components/img/menubar-example1.png create mode 100644 documentation/components/img/nativeselect-basic.png create mode 100644 documentation/components/img/optiongroup-basic.png create mode 100644 documentation/components/img/optiongroup-disabling.png create mode 100644 documentation/components/img/optiongroup-horizontal.png create mode 100644 documentation/components/img/passwordfield-basic.png create mode 100644 documentation/components/img/progressbar-basic.png create mode 100644 documentation/components/img/progressbar-indeterminate.png create mode 100644 documentation/components/img/progressbar-thread.png create mode 100644 documentation/components/img/richtextarea-example1.png create mode 100644 documentation/components/img/richtextarea-toolbar-mod-whitebg.png create mode 100644 documentation/components/img/richtextarea-toolbar-whitebg.png create mode 100644 documentation/components/img/select-selected1.png create mode 100644 documentation/components/img/slider-example1-hi.png create mode 100644 documentation/components/img/slider-example1-lo.png create mode 100644 documentation/components/img/slider-orig.png create mode 100644 documentation/components/img/table-cellstylegenerator1.png create mode 100644 documentation/components/img/table-column-collapsing.png create mode 100644 documentation/components/img/table-column-resize.png create mode 100644 documentation/components/img/table-columnformatting.png create mode 100644 documentation/components/img/table-components.png create mode 100644 documentation/components/img/table-editable3.png create mode 100644 documentation/components/img/table-example1.png create mode 100644 documentation/components/img/table-example2.png create mode 100644 documentation/components/img/table-footer.png create mode 100644 documentation/components/img/table-generatedcolumns1.png create mode 100644 documentation/components/img/table-generatedcolumns2.png create mode 100644 documentation/components/img/textarea-basic.png create mode 100644 documentation/components/img/textarea-wordwrap.png create mode 100644 documentation/components/img/textfield-css.png create mode 100644 documentation/components/img/textfield-diagram-hi.png create mode 100644 documentation/components/img/textfield-diagram-lo.png create mode 100644 documentation/components/img/textfield-example.png create mode 100644 documentation/components/img/textfield-nullrepresentation.png create mode 100644 documentation/components/img/textfield-textchangeevents.png create mode 100644 documentation/components/img/tooltip-plain-withpointer-hi.png create mode 100644 documentation/components/img/tooltip-plain-withpointer-lo.png create mode 100644 documentation/components/img/tooltip-plain.png create mode 100644 documentation/components/img/tooltip-richtext-withpointer-hi.png create mode 100644 documentation/components/img/tooltip-richtext-withpointer-lo.png create mode 100644 documentation/components/img/tooltip-richtext.png create mode 100644 documentation/components/img/tree-example1.png create mode 100644 documentation/components/img/treetable-basic.png create mode 100644 documentation/components/img/twincolselect-basic.png create mode 100644 documentation/components/img/upload-example.png create mode 100644 documentation/components/img/upload.png create mode 100644 documentation/components/original-drawings/component-abstractions.svg create mode 100644 documentation/components/original-drawings/component-diagram.svg create mode 100644 documentation/components/original-drawings/field-diagram.svg create mode 100644 documentation/components/original-drawings/field-interface.svg create mode 100644 documentation/components/original-drawings/slider-example1.svg create mode 100644 documentation/components/original-drawings/textfield-diagram.svg create mode 100644 documentation/components/original-drawings/tooltip-plain-withpointer.svg create mode 100644 documentation/components/original-drawings/tooltip-richtext-withpointer.svg (limited to 'documentation/components') diff --git a/documentation/components/chapter-components.asciidoc b/documentation/components/chapter-components.asciidoc new file mode 100644 index 0000000000..36e0287e30 --- /dev/null +++ b/documentation/components/chapter-components.asciidoc @@ -0,0 +1,71 @@ +[[components]] +== User Interface Components + +This chapter provides an overview and a detailed description of all non-layout +components in Vaadin. + +include::components-overview.asciidoc[leveloffset=+2] + +include::components-interfaces.asciidoc[leveloffset=+2] + +include::components-features.asciidoc[leveloffset=+2] + +include::components-fields.asciidoc[leveloffset=+2] + +include::components-selection.asciidoc[leveloffset=+2] + +include::components-extensions.asciidoc[leveloffset=+2] + +include::components-label.asciidoc[leveloffset=+2] + +include::components-link.asciidoc[leveloffset=+2] + +include::components-textfield.asciidoc[leveloffset=+2] + +include::components-textarea.asciidoc[leveloffset=+2] + +include::components-passwordfield.asciidoc[leveloffset=+2] + +include::components-richtextarea.asciidoc[leveloffset=+2] + +include::components-datefield.asciidoc[leveloffset=+2] + +include::components-button.asciidoc[leveloffset=+2] + +include::components-checkbox.asciidoc[leveloffset=+2] + +include::components-combobox.asciidoc[leveloffset=+2] + +include::components-listselect.asciidoc[leveloffset=+2] + +include::components-nativeselect.asciidoc[leveloffset=+2] + +include::components-optiongroup.asciidoc[leveloffset=+2] + +include::components-twincolselect.asciidoc[leveloffset=+2] + +include::components-table.asciidoc[leveloffset=+2] + +include::components-tree.asciidoc[leveloffset=+2] + +include::components-treetable.asciidoc[leveloffset=+2] + +include::components-grid.asciidoc[leveloffset=+2] + +include::components-menubar.asciidoc[leveloffset=+2] + +include::components-upload.asciidoc[leveloffset=+2] + +include::components-progressbar.asciidoc[leveloffset=+2] + +include::components-slider.asciidoc[leveloffset=+2] + +include::components-popupview.asciidoc[leveloffset=+2] + +include::components-calendar.asciidoc[leveloffset=+2] + +include::components-customcomponent.asciidoc[leveloffset=+2] + +include::components-customfield.asciidoc[leveloffset=+2] + +include::components-embedded.asciidoc[leveloffset=+2] diff --git a/documentation/components/components-button.asciidoc b/documentation/components/components-button.asciidoc new file mode 100644 index 0000000000..59ab380348 --- /dev/null +++ b/documentation/components/components-button.asciidoc @@ -0,0 +1,71 @@ +--- +title: Button +order: 14 +layout: page +--- + +[[components.button]] += [classname]#Button# + +ifdef::web[] +[.sampler] +image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/interaction/button"] +endif::web[] + + +The [classname]#Button# component is normally used for initiating some action, +such as finalizing input in forms. When the user clicks a button, a +[classname]#Button.ClickEvent# is fired, which can be handled with a +[interfacename]#Button.ClickListener# in the [methodname]#buttonClick()# method. + +You can handle button clicks with an anonymous class as follows: + + +[source, java] +---- +Button button = new Button("Do not press this button"); + +button.addClickListener(new Button.ClickListener() { + public void buttonClick(ClickEvent event) { + Notification.show("Do not press this button again"); + } +}); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.button.basic[on-line example, window="_blank"]. + +The result is shown in <>. The listener can also +be given in the constructor, which is often perhaps simpler. + +[[figure.component.button.basic]] +.Button in Different Styles of Valo Theme +image::img/button-example1.png[] + +If you handle several buttons in the same listener, you can differentiate +between them either by comparing the [classname]#Button# object reference +returned by the [methodname]#getButton()# method of +[classname]#Button.ClickEvent# to a kept reference. For a detailed description +of these patterns together with some examples, please see +<>. + +== CSS Style Rules + + +[source, css] +---- +.v-button { } + .v-button-wrap { } + .v-button-caption { } +---- + +A button has an overall [literal]#++v-button++# style. The caption has +[literal]#++v-button-caption++# style. There is also an intermediate wrap +element, which may help in styling in some cases. + +Some built-in themes contain a small style, which you can enable by adding +[parameter]#Reindeer.BUTTON_SMALL#, etc. The [classname]#BaseTheme# also has a +[parameter]#BUTTON_LINK# style, which makes the button look like a hyperlink. + + + + diff --git a/documentation/components/components-calendar.asciidoc b/documentation/components/components-calendar.asciidoc new file mode 100644 index 0000000000..0bc2791088 --- /dev/null +++ b/documentation/components/components-calendar.asciidoc @@ -0,0 +1,1197 @@ +--- +title: Calendar +order: 30 +layout: page +--- + +[[components.calendar]] += [classname]#Calendar# + +ifdef::web[] +[.sampler] +image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/data-input/dates/dates-calendar] +endif::web[] + +The [classname]#Calendar# component allows organizing and displaying calendar +events. The main features of the calendar include: + +* Monthly, weekly, and daily views +* Two types of events: all-day events and events with a time range +* Add events directly, from a [classname]#Container#, or with an event provider +* Control the range of the visible dates +* Selecting and editing date or time range by dragging +* Drag and drop events to calendar +* Support for localization and timezones + +User interaction with the calendar elements, such as date and week captions as +well as events, is handled with event listeners. Also date/time range +selections, event dragging, and event resizing can be listened by the server. +The weekly view has navigation buttons to navigate forward and backward in time. +These actions are also listened by the server. Custom navigation can be +implemented using event handlers + +ifdef::web[] +, as described in +<> +endif::web[] +. + +The data source of a calendar can be practically anything, as its events are +queried dynamically by the component. You can bind the calendar to a Vaadin +container, or to any other data source by implementing an __event provider__. + +The [classname]#Calendar# has undefined size by default and you usually want to +give it a fixed or relative size, for example as follows. + + +[source, java] +---- +Calendar cal = new Calendar("My Calendar"); +cal.setWidth("600px"); +cal.setHeight("300px"); +---- + +After creating the calendar, you need to set a time range for it, which also +controls the view mode, and set up the data source for calendar events. + +[[components.calendar.daterange]] +== Date Range and View Mode + +The Vaadin Calendar has two types of views that are shown depending on the date +range of the calendar. The __weekly view__ displays a week by default. It can +show anything between one to seven days a week, and is also used as a single-day +view. The view mode is determined from the __date range__ of the calendar, +defined by a start and an end date. Calendar will be shown in a __monthly view__ +when the date range is over than one week (seven days) long. The date range is +always calculated in an accuracy of one millisecond. + +[[figure.components.calendar.daterange.monthly]] +.Monthly view with All-Day and Normal Events +image::img/calendar-monthly.png[] + +The monthly view, shown in <>, can +easily be used to control all types of events, but it is best suited for events +that last for one or more days. You can drag the events to move them. In the +figure, you can see two longer events that are highlighted with a blue and green +background color. Other markings are shorter day events that last less than a 24 +hours. These events can not be moved by dragging in the monthly view. + +[[figure.components.calendar.daterange.weekly]] +.Weekly View +image::img/calendar-weekly.png[] + +In <>, you can see four normal day +events and also all-day events at the top of the time line grid. + +In the following, we set the calendar to show only one day, which is the current +day. + + +[source, java] +---- +cal.setStartDate(new Date()); +cal.setEndDate(new Date()); +---- + +Notice that although the range we set above is actually zero time long, the +calendar still renders the time from 00:00 to 23:59. This is normal, as the +Vaadin Calendar is guaranteed to render at least the date range provided, but +may expand it. This behaviour is important to notice when we implement our own +event providers. + + +[[components.calendar.events]] +== Calendar Events + +All occurrences in a calendar are represented as __events__. You have three ways +to manage the calendar events: + +* Add events directly to the [classname]#Calendar# object using the [methodname]#addEvent()# +* Use a [interfacename]#Container# as a data source +* Use the __event provider__ mechanism + +You can add events with [methodname]#addEvent()# and remove them with the +[methodname]#removeEvent()#. These methods will use the underlying event +provider to write the modifications to the data source. + +[[components.calendar.events.types]] +=== Event Interfaces and Providers + +Events are handled though the [interfacename]#CalendarEvent# interface. The +concrete class of the event depends on the specific +[classname]#CalendarEventProvider# used in the calendar. + +By default, [classname]#Calendar# uses a [classname]#BasicEventProvider# to +provide events, which uses [classname]#BasicEvent# instances. + +Calendar does not depend on any particular data source implementation. Events +are queried by the [classname]#Calendar# from the provider that just has to +implement the [interfacename]#CalendarEventProvider# interface. It is up to the +event provider that [classname]#Calendar# gets the correct events. + +You can bind any Vaadin [classname]#Container# to a calendar, in which case a +[classname]#ContainerEventProvider# is used transparently. The container must be +ordered by start date and time of the events. See +<> for basic information about containers. + + +[[components.calendar.events.details]] +=== Event Types + +A calendar event requires a start time and an end time. These are the only +mandatory properties. In addition, an event can also be set as an all-day event +by setting the [literal]#++all-day++# property of the event. You can also set +the [literal]#++description++# of an event, which is displayed as a tooltip in +the user interface. + +If the [literal]#++all-day++# field of the event is [literal]#++true++#, then +the event is always rendered as an all-day event. In the monthly view, this +means that no start time is displayed in the user interface and the event has an +colored background. In the weekly view, all-day events are displayed in the +upper part of the screen, and rendered similarly to the monthly view. In +addition, when the time range of an event is 24 hours or longer, it is rendered +as an all-day event in the monthly view. + +When the time range of an event is equal or less than 24 hours, with the +accuracy of one millisecond, the event is considered as a normal day event. +Normal event has a start and end times that may be on different days. + + +[[components.calendar.events.basic]] +=== Basic Events + +The easiest way to add and manage events in a calendar is to use the __basic +event__ management API. Calendar uses by default a +[classname]#BasicEventProvider#, which keeps the events in memory in an internal +reprensetation. + +For example, the following adds a two-hour event starting from the current time. +The standard Java [classname]#GregorianCalendar# provides various ways to +manipulate date and time. + + +[source, java] +---- +// Add a two-hour event +GregorianCalendar start = new GregorianCalendar(); +GregorianCalendar end = new GregorianCalendar(); +end.add(java.util.Calendar.HOUR, 2); +calendar.addEvent(new BasicEvent("Calendar study", + "Learning how to use Vaadin Calendar", + start.getTime(), end.getTime())); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#calendar.monthlyview[on-line example, window="_blank"]. + +This adds a new event that lasts for 3 hours. As the BasicEventProvider and +BasicEvent implement some optional event interfaces provided by the calendar +package, there is no need to refresh the calendar. Just create events, set their +properties and add them to the Event Provider. + + + +[[components.calendar.container]] +== Getting Events from a Container + +You can use any Vaadin [interfacename]#Container# that implements the +[interfacename]#Indexed# interface as the data source for calendar events. The +[classname]#Calendar# will listen to change events from the container as well as +write changes to the container. You can attach a container to a +[classname]#Calendar# with [methodname]#setContainerDataSource()#. + +In the following example, we bind a [classname]#BeanItemContainer# that contains +built-in [classname]#BasicEvent# events to a calendar. + + +[source, java] +---- +// Create the calendar +Calendar calendar = new Calendar("Bound Calendar"); + +// Use a container of built-in BasicEvents +final BeanItemContainer container = + new BeanItemContainer(BasicEvent.class); + +// Create a meeting in the container +container.addBean(new BasicEvent("The Event", "Single Event", + new GregorianCalendar(2012,1,14,12,00).getTime(), + new GregorianCalendar(2012,1,14,14,00).getTime())); + +// The container must be ordered by the start time. You +// have to sort the BIC every time after you have added +// or modified events. +container.sort(new Object[]{"start"}, new boolean[]{true}); + +calendar.setContainerDataSource(container, "caption", + "description", "start", "end", "styleName"); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#calendar.beanitemcontainer[on-line example, window="_blank"]. + +The container must either use the default property IDs for event data, as +defined in the [interfacename]#CalendarEvent# interface, or provide them as +parameters for the [methodname]#setContainerDataSource()# method, as we did in +the example above. + +[[components.calendar.container.sorting]] +=== Keeping the Container Ordered + +The events in the container __must__ be kept ordered by their start date/time. +Failing to do so may and will result in the events not showing in the calendar +properly. + +Ordering depends on the container. With some containers, such as +[classname]#BeanItemContainer#, you have to sort the container explicitly every +time after you have added or modified events, usually with the +[methodname]#sort()# method, as we did in the example above. Some container, +such as [classname]#JPAContainer#, keep the in container automatically order if +you provide a sorting rule. + +For example, you could order a [classname]#JPAContainer# by the following rule, +assuming that the start date/time is held in the [literal]#++startDate++# +property: + + +[source, java] +---- +// The container must be ordered by start date. For JPAContainer +// we can just set up sorting once and it will stay ordered. +container.sort(new String[]{"startDate"}, new boolean[]{true}); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#calendar.jpacontainer[on-line example, window="_blank"]. + + +ifdef::web[] +[[components.calendar.container.customization]] +=== Delegation of Event Management + +Setting a container as the calendar data source with +[methodname]#setContainerDataSource()# automatically switches to +[classname]#ContainerEventProvider#. You can manipulate the event data through +the API in [classname]#Calendar# and the user can move and resize event through +the user interface. The event provider delegates all such calendar operations to +the container. + +If you add events through the [classname]#Calendar# API, notice that you may be +unable to create events of the type held in the container or adding them +requires some container-specific operations. In such case, you may need to +customize the [methodname]#addEvent()# method. + +For example, [classname]#JPAContainer# requires adding new items with +[methodname]#addEntity()#. You could first add the entity to the container or +entity manager directly and then pass it to the [methodname]#addEvent()#. That +does not, however, work if the entity class does not implement +[interfacename]#CalendarEvent#. This is actually the case always if the property +names differ from the ones defined in the interface. You could handle creating +the underlying entity objects in the [methodname]#addEvent()# as follows: + + +[source, java] +---- +// Create a JPAContainer +final JPAContainer container = + JPAContainerFactory.make(MyCalendarEvent.class, + "book-examples"); + +// Customize the event provider for adding events +// as entities +ContainerEventProvider cep = + new ContainerEventProvider(container) { + @Override + public void addEvent(CalendarEvent event) { + MyCalendarEvent entity = new MyCalendarEvent( + event.getCaption(), event.getDescription(), + event.getStart(), event.getEnd(), + event.getStyleName()); + container.addEntity(entity); + } +} + +// Set the container as the data source +calendar.setEventProvider(cep); + +// Now we can add events to the database through the calendar +BasicEvent event = new BasicEvent("The Event", "Single Event", + new GregorianCalendar(2012,1,15,12,00).getTime(), + new GregorianCalendar(2012,1,15,14,00).getTime()); +calendar.addEvent(event); +---- + +endif::web[] + + +ifdef::web[] +[[components.calendar.eventprovider]] +== Implementing an Event Provider + +If the two simple ways of storing and managing events for a calendar are not +enough, you may need to implement a custom event provider. It is the most +flexible way of providing events. You need to attach the event provider to the +[classname]#Calendar# using the [methodname]#setEventProvider()# method. + +Event queries are done by asking the event provider for all the events between +two given dates. The range of these dates is guaranteed to be at least as long +as the start and end dates set for the component. The component can, however, +ask for a longer range to ensure correct rendering. In particular, all start +dates are expanded to the start of the day, and all end dates are expanded to +the end of the day. + +[[components.calendar.eventprovider.customevents]] +=== Custom Events + +An event provider could use the built-in [classname]#BasicEvent#, but it is +usually more proper to define a custom event type that is bound directly to the +data source. Custom events may be useful for some other purposes as well, such +as when you need to add extra information to an event or customize how it is +acquired. + +Custom events must implement the [interfacename]#CalendarEvent# interface or +extend an existing event class. The built-in [classname]#BasicEvent# class +should serve as a good example of implementing simple events. It keeps the data +in member variables. + + +[source, java] +---- +public class BasicEvent + implements CalendarEventEditor, EventChangeNotifier { + ... + + public String getCaption() { + return caption; + } + + public String getDescription() { + return description; + } + + public Date getEnd() { + return end; + } + + public Date getStart() { + return start; + } + + public String getStyleName() { + return styleName; + } + + public boolean isAllDay() { + return isAllDay; + } + + public void setCaption(String caption) { + this.caption = caption; + fireEventChange(); + } + + public void setDescription(String description) { + this.description = description; + fireEventChange(); + } + + public void setEnd(Date end) { + this.end = end; + fireEventChange(); + } + + public void setStart(Date start) { + this.start = start; + fireEventChange(); + } + + public void setStyleName(String styleName) { + this.styleName = styleName; + fireEventChange(); + } + + public void setAllDay(boolean isAllDay) { + this.isAllDay = isAllDay; + fireEventChange(); + } + + public void addEventChangeListener( + EventChangeListener listener) { + ... + } + + public void removeListener(EventChangeListener listener) { + ... + } + + protected void fireEventChange() {...} +} +---- + +You may have noticed that there was some additional code in the +[classname]#BasicEvent# that was not in the [interfacename]#CalendarEvent# +interface. Namely [classname]#BasicEvent# also implements two additional +interfaces: + +[interfacename]#CalendarEditor#:: This interface defines setters for all the fields, and is required for some of +the default handlers to work. + +[interfacename]#EventChangeNotifier#:: This interface adds the possibility to listen for changes in the event, and +enables the [classname]#Calendar# to render the changes immediately. + + + +The start time and end time are mandatory, but caption, description, and style +name are not. The style name is used as a part of the CSS class name for the +HTML DOM element of the event. + +In addition to the basic event interfaces, you can enhance the functionality of +your event and event provider classes by using the [classname]#EventChange# and +[classname]#EventSetChange# events. They let the [classname]#Calendar# component +to know about changes in events and update itself accordingly. The +[classname]#BasicEvent# and [classname]#BasicEventProvider# examples given +earlier include a simple implementation of these interfaces. + + +[[components.calendar.eventprovider.eventprovider]] +=== Implementing the Event Provider + +An event provider needs to implement the [interfacename]#CalendarEventProvider# +interface. It has only one method to be implemented. Whenever the calendar is +painted, [methodname]#getEvents(Date, Date)# method is called and it must return +a list of events between the given start and end time. + +The following example implementation returns only one example event. The event +starts from the current time and is five hours long. + + +[source, java] +---- +public class MyEventProvider implements CalendarEventProvider{ + public List getEvents(Date startDate, Date endDate){ + List events = new ArrayList(); + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(new Date()); + + Date start = cal.getTime(); + cal.add(GregorianCalendar.HOUR, 5); + Date end = cal.getTime(); + BasicEvent event = new BasicEvent(); + event.setCaption("My Event"); + event.setDescription("My Event Description"); + event.setStart(start); + event.setEnd(end); + events.add(event); + + return events; + } +} +---- + +It is important to notice that the [classname]#Calendar# may query for dates +beyond the range defined by start date and end date. Particularly, it may expand +the date range to make sure the user interface is rendered correctly. + + +endif::web[] + +ifdef::web[] +[[components.calendar.appearance]] +== Styling a Calendar + +Configuring the appearance of the Vaadin Calendar component is one of the basic +tasks. At the least, you need to consider its sizing in your user interface. You +also quite probably want to use some color or colors for events. + +[[components.calendar.appearance.sizing]] +=== Sizing + +The Calendar supports component sizing as usual for defined (fixed or relative) +sizes. When using an undefined size for the calendar, all the sizes come from +CSS. In addition, when the height is undefined, a scrollbar is displayed in the +weekly view to better fit the cells to the user interface. + +Below is a list of style rules that define the size of a Calendar with undefined +size (these are the defaults): + + +[source, css] +---- +.v-calendar-month-sizedheight .v-calendar-month-day { + height: 100px; +} + +.v-calendar-month-sizedwidth .v-calendar-month-day { + width: 100px; +} + +.v-calendar-header-month-Hsized .v-calendar-header-day { + width: 101px; +} + +/* for IE */ +.v-ie6 .v-calendar-header-month-Hsized .v-calendar-header-day { + width: 104px; +} + +/* for others */ +.v-calendar-header-month-Hsized td:first-child { + padding-left: 21px; +} + +.v-calendar-header-day-Hsized { + width: 200px; +} + +.v-calendar-week-numbers-Vsized .v-calendar-week-number { + height: 100px; + line-height: 100px; +} + +.v-calendar-week-wrapper-Vsized { + height: 400px; + overflow-x: hidden !important; +} + +.v-calendar-times-Vsized .v-calendar-time { + height: 38px; +} + +.v-calendar-times-Hsized .v-calendar-time { + width: 42px; +} + +.v-calendar-day-times-Vsized .v-slot,.v-calendar-day-times-Vsized .v-slot-even { + height: 18px; +} + +.v-calendar-day-times-Hsized, .v-calendar-day-times-Hsized .v-slot,.v-calendar-day-times-Hsized .v-slot-even { + width: 200px; +} +---- + + +[[components.calendar.appearance.event-style]] +=== Event Style + +Events can be styled with CSS by setting them a __style name suffix__. The +suffix is retrieved with the [methodname]#getStyleName()# method in +[interfacename]#CalendarEvent#. If you use [classname]#BasicEvent# events, you +can set the suffix with [methodname]#setStyleName()#. + + +[source, java] +---- +BasicEvent event = new BasicEvent("Wednesday Wonder", ... ); +event.setStyleName("mycolor"); +calendar.addEvent(event); +---- + +Suffix [literal]#++mycolor++# would create +[literal]#++v-calendar-event-mycolor++# class for regular events and +[literal]#++v-calendar-event-mycolor-add-day++# for all-day events. You could +style the events with the following rules: + + +[source, css] +---- +.v-calendar .v-calendar-event-mycolor {} +.v-calendar .v-calendar-event-mycolor-all-day {} +.v-calendar .v-calendar-event-mycolor .v-calendar-event-caption {} +.v-calendar .v-calendar-event-mycolor .v-calendar-event-content {} +---- + + +endif::web[] + +ifdef::web[] +[[components.calendar.visible-hours-days]] +== Visible Hours and Days + +As we saw in <>, you can set the range of dates +that are shown by the Calendar. But what if you wanted to show the entire month +but hide the weekends? Or show only hours from 8 to 16 in the weekly view? The +[methodname]#setVisibleDays()# and [methodname]#setVisibleHours()# methods allow +you to do that. + + +[source, java] +---- +calendar.setVisibleDays(1,5); // Monday to Friday +calendar.setVisibleHours(0,15); // Midnight until 4 pm +---- + +After the above settings, only weekdays from Monday to Friday would be shown. +And when the calendar is in the weekly view, only the time range from 00:00 to +16:00 would be shown. + +Note that the excluded times are never shown so you should take care when +setting the date range. If the date range contains only dates / times that are +excluded, nothing will be displayed. Also note that even if a date is not +rendered because these settings, the event provider may still be queried for +events for that date. + +endif::web[] + +ifdef::web[] +[[components.calendar.drag-and-drop]] +== Drag and Drop + +Vaadin Calendar can act as a drop target for drag and drop, described in +<>. With the functionality, the user could drag events, for example, +from a table to a calendar. + +To support dropping, a [classname]#Calendar# must have a drop handler. When the +drop handler is set, the days in the monthly view and the time slots in the +weekly view can receive drops. Other locations, such as day names in the weekly +view, can not currently receive drops. + +Calendar uses its own implementation of [interfacename]#TargetDetails#: +[classname]#CalendarTargetdetails#. It holds information about the the drop +location, which in the context of [classname]#Calendar# means the date and time. +The drop target location can be retrieved via the [methodname]#getDropTime()# +method. If the drop is done in the monthly view, the returned date does not have +exact time information. If the drop happened in the weekly view, the returned +date also contains the start time of the slot. + +Below is a short example of creating a drop handler and using the drop +information to create a new event: + + +[source, java] +---- +private Calendar createDDCalendar() { + Calendar calendar = new Calendar(); + calendar.setDropHandler(new DropHandler() { + public void drop(DragAndDropEvent event) { + CalendarTargetDetails details = + (CalendarTargetDetails) event.getTargetDetails(); + + TableTransferable transferable = + (TableTransferable) event.getTransferable(); + + createEvent(details, transferable); + removeTableRow(transferable); + } + + public AcceptCriterion getAcceptCriterion() { + return AcceptAll.get(); + } + + }); + + return calendar; +} + + +protected void createEvent(CalendarTargetDetails details, + TableTransferable transferable) { + Date dropTime = details.getDropTime(); + java.util.Calendar timeCalendar = details.getTargetCalendar() + .getInternalCalendar(); + timeCalendar.setTime(dropTime); + timeCalendar.add(java.util.Calendar.MINUTE, 120); + Date endTime = timeCalendar.getTime(); + + Item draggedItem = transferable.getSourceComponent(). + getItem(transferable.getItemId()); + + String eventType = (String)draggedItem. + getItemProperty("type").getValue(); + + String eventDescription = "Attending: " + + getParticipantString( + (String[]) draggedItem. + getItemProperty("participants").getValue()); + + BasicEvent newEvent = new BasicEvent(); + newEvent.setAllDay(!details.hasDropTime()); + newEvent.setCaption(eventType); + newEvent.setDescription(eventDescription); + newEvent.setStart(dropTime); + newEvent.setEnd(endTime); + + BasicEventProvider ep = (BasicEventProvider) details + .getTargetCalendar().getEventProvider(); + ep.addEvent(newEvent); +} +---- + +endif::web[] + +ifdef::web[] +[[components.calendar.contextmenu]] +== Using the Context Menu + +Vaadin Calendar allows the use of context menu (mouse right-click) to manage +events. As in other context menus in Vaadin, the menu items are handled in +Vaadin as __actions__ by an __action handler__. To enable a context menu, you +have to implement a Vaadin [interfacename]#Action.Handler# and add it to the +calendar with [methodname]#addActionHandler()#. + +An action handler must implement two methods: [methodname]#getActions()# and +[methodname]#handleAction()#. The [methodname]#getActions()# is called for each +day displayed in the calendar view. It should return a list of allowed actions +for that day, that is, the items of the context menu. The [parameter]#target# +parameter is the context of the click - a [classname]#CalendarDateRange# that +spans over the day. The [parameter]#sender# is the [classname]#Calendar# object. + +The [methodname]#handleActions()# receives the target context in the +[parameter]#target#. If the context menu was opened on an event, the target is +the [interfacename]#Event# object, otherwise it is a +[classname]#CalendarDateRange#. + +endif::web[] + +ifdef::web[] +[[components.calendar.localization]] +== Localization and Formatting + +[[components.calendar.localization.locale]] +=== Setting the Locale and Time Zone + +Month and weekday names are shown in the language of the locale setting of the +[classname]#Calendar#. The translations are acquired from the standard Java +locale data. By default, [classname]#Calendar# uses the system default locale +for its internal calendar, but you can change it with +[methodname]#setLocale(Locale locale)#. Setting the locale will update also +other location specific date and time settings, such as the first day of the +week, time zone, and time format. However, time zone and time format can be +overridden by settings in the [classname]#Calendar#. + +For example, the following would set the language to US English: + + +[source, java] +---- +cal.setLocale(Locale.US); +---- + +The locale defines the default time zone. You can change it with the +[methodname]#setTimeZone()# method, which takes a +[classname]#java.util.TimeZone# object as its parameter. Setting timezone to +null will reset timezone to the locale default. + +For example, the following would set the Finnish time zone, which is EET + + +[source, java] +---- +cal.setTimeZone(TimeZone.getTimeZone("Europe/Helsinki")); +---- + + +[[components.calendar.localization.datecaption]] +=== Time and Date Caption Format + +The time may be shown either in 24 or 12 hour format. The default format is +defined by the locale, but you can change it with the +[methodname]#setTimeFormat()# method. Giving a [literal]#++null++# setting will +reset the time format to the locale default. + + +[source, java] +---- +cal.setTimeFormat(TimeFormat.Format12H); +---- + +You can change the format of the date captions in the week view with the +[methodname]#setWeeklyCaptionFormat(String dateFormatPattern)# method. The date +format pattern should follow the format of the standard Java +[classname]#java.text.SimpleDateFormat# class. + +For example: + + +[source, java] +---- +cal.setWeeklyCaptionFormat("dd-MM-yyyy"); +---- + + +endif::web[] + +ifdef::web[] +[[components.calendar.customizing]] +== Customizing the Calendar + +In this section, we give a tutorial for how to make various basic customizations +of the Vaadin Calendar. The event provider and styling was described earlier, so +now we concentrate on other features of the Calendar API. + +[[components.calendar.customizing.overview]] +=== Overview of Handlers + +Most of the handlers related to calendar events have sensible default handlers. +These are found in the [package]#com.vaadin.ui.handler# package. The default +handlers and their functionalities are described below. + +* [classname]#BasicBackwardHandler#. Handles clicking the back-button of the weekly view so that the viewed month is changed to the previous one. +* [classname]#BasicForwardHandler#. Handles clicking the forward-button of the weekly view so that the viewed month is changed to the next one. +* [classname]#BasicWeekClickHandler#. Handles clicking the week numbers int the monthly view so that the viewable date range is changed to the clicked week. +* [classname]#BasicDateClickHandler#. Handles clicking the dates on both the monthly view and the weekly view. Changes the viewable date range so that only the clicked day is visible. +* [classname]#BasicEventMoveHandler#. Handles moving the events in both monthly view and the weekly view. Events can be moved and their start and end dates are changed correctly, but only if the event implements [classname]#CalendarEventEditor# (implemented by [classname]#BasicEvent#). +* [classname]#BasicEventResizeHandler#. Handles resizing the events in the weekly view. Events can be resized and their start and end dates are changed correctly, but only if the event implements [classname]#CalendarEventEditor# (implemented by the [classname]#BasicEvent#). + +All of these handlers are automatically set when creating a new +[classname]#Calendar#. If you wish to disable some of the default functionality, +you can simply set the corresponding handler to [literal]#++null++#. This will +prevent the functionality from ever appearing on the user interface. For +example, if you set the [classname]#EventMoveHandler# to [literal]#++null++#, +the user will be unable to move events in the browser. + + +[[components.calendar.customizing.creating]] +=== Creating a Calendar + +Let us first create a new [classname]#Calendar# instance. Here we use our own +event provider, the [classname]#MyEventProvider# described in +<>. + + +[source, java] +---- +Calendar cal = new Calendar(new MyEventProvider()); +---- + +This initializes the Calendar. To customize the viewable date range, we must set +a start and end date to it. + +There is only one visible event in the timeline, starting from the current time. +That is what our event provider passes to the client.//TODO See the figure +3. + +It would be nice to also be able to control the navigation forward and backward. +The default navigation is provided by the default handlers, but perhaps we want +to restrict the users so they can only navigate dates in the current year. Maybe +we also want to pose some other restrictions to the clicking week numbers and +dates. + +These restrictions and other custom logic can be defined with custom handlers. +You can find the handlers in the [package]#com.vaadin.addon.calendar.ui.handler# +package and they can be easily extended. Note that if you don not want to extend +the default handlers, you are free to implement your own. The interfaces are +described in [interfacename]#CalendarComponentEvents#. + + +endif::web[] + +[[components.calendar.navigation]] +== Backward and Forward Navigation + +Vaadin Calendar has only limited built-in navigation support. The weekly view +has navigation buttons in the top left and top right +corners.//// +TODO See the figure +4. +//// + +You can handle backward and forward navigation with a +[interfacename]#BackwardListener# and [interfacename]#ForwardListener#. + + +[source, java] +---- +cal.setHandler(new BasicBackwardHandler() { + protected void setDates(BackwardEvent event, + Date start, Date end) { + + java.util.Calendar calendar = event.getComponent() + .getInternalCalendar(); + if (isThisYear(calendar, end) + && isThisYear(calendar, start)) { + super.setDates(event, start, end); + } + }}); +---- + +The forward navigation handler can be implemented in the same way. The example +handler restricts the dates to the current year. + + +ifdef::web[] +[[components.calendar.dateclick]] +== Date Click Handling + +By default, clicking a date either in month or week view switches to single-day +view, while clicking on the date header in the day view has no effect. The date +click event is handled by a [interfacename]#DateClickHandler#. + +The following example handles click events on the date header in the day view to +zoom out to the week view. For other clicks it applies the default behavior; in +the week view clicking on a day switches to the day view. + + +[source, java] +---- +calendar.setHandler(new BasicDateClickHandler() { + public void dateClick(DateClickEvent event) { + Calendar cal = event.getComponent(); + + // Check if the current range is already one day long + long currentCalDateRange = cal.getEndDate().getTime() - + cal.getStartDate().getTime(); + + // From one-day view, zoom out to week view + if (currentCalDateRange <= DateConstants.DAYINMILLIS) { + // Change the date range to the current week + GregorianCalendar weekstart = new GregorianCalendar(); + GregorianCalendar weekend = new GregorianCalendar(); + weekstart.setTime(event.getDate()); + weekend.setTime(event.getDate()); + weekstart.setFirstDayOfWeek(java.util.Calendar.SUNDAY); + weekstart.set(java.util.Calendar.HOUR_OF_DAY, 0); + weekstart.set(java.util.Calendar.DAY_OF_WEEK, + java.util.Calendar.SUNDAY); + weekend.set(java.util.Calendar.HOUR_OF_DAY, 23); + weekend.set(java.util.Calendar.DAY_OF_WEEK, + java.util.Calendar.SATURDAY); + cal.setStartDate(weekstart.getTime()); + cal.setEndDate(weekend.getTime()); + + Notification.show("Custom zoom to week"); + } else { + // Default behavior, change date range to one day + super.dateClick(event); + } + } + }); +---- + +endif::web[] + +ifdef::web[] +[[components.calendar.weekclick]] +== Handling Week Clicks + +The monthly view displays week numbers for each week row on the left side of the +date grid. The week number are clickable and you can handle the click events by +setting a [interfacename]#WeekClickHandler# for the [classname]#Calendar# +object. The default handler changes the date range to be the clicked week. + +In the following example, we add a week click handler that changes the date +range of the calendar to one week only if the start and end dates of the week +are in the current month. + + +[source, java] +---- +cal.setHandler(new BasicWeekClickHandler() { + protected void setDates(WeekClick event, + Date start, Date end) { + java.util.Calendar calendar = event.getComponent() + .getInternalCalendar(); + if (isThisMonth(calendar, start) + && isThisMonth(calendar, end)) { + super.setDates(event, start, end); + } + } +}); +---- + +endif::web[] + +ifdef::web[] +[[components.calendar.eventclick]] +== Handling Event Clicks + +The calendar events in all views are are clickable. There is no default handler. +Just like the date and week click handlers, event click handling is enabled by +setting an [interfacename]#EventClickHandler# for the [classname]#Calendar# +object. + +You can get hold of the clicked event by the [methodname]#getCalendarEvent()# +method in the [classname]#EventClick# object passed to the handler, as shown in +the following example. + + +[source, java] +---- +cal.setHandler(new EventClickHandler() { + public void eventClick(EventClick event) { + BasicEvent e = (BasicEvent) event.getCalendarEvent(); + + // Do something with it + new Notification("Event clicked: " + e.getCaption(), + e.getDescription()).show(Page.getCurrent()); + } +}); +---- + +endif::web[] + +ifdef::web[] +[[components.calendar.eventdrag]] +== Event Dragging + +The user can drag an event to change its position in time. The default handler +sets the start and end time of the event accordingly. You can do many things +with a custom move handler, such as restrict moving events. + +In the following example, we add a [interfacename]#EventMoveHandler# to a +[classname]#Calendar#. The event handler updates the new position to the +datasource, but only if the new dates are in the current month. This requires +making some changes to the event provider class. + + +[source, java] +---- +cal.setHandler(new BasicEventMoveHandler() { + private java.util.Calendar javaCalendar; + + public void eventMove(MoveEvent event) { + javaCalendar = event.getComponent().getInternalCalendar(); + super.eventMove(event); + } + + protected void setDates(CalendarEventEditor event, + Date start, Date end) { + if (isThisMonth(javaCalendar, start) + && isThisMonth(javaCalendar, end)) { + super.setDates(event, start, end); + } + } +}); +---- + +For the above example to work, the example event provider presented earlier +needs to be changed slightly so that it doesn't always create a new event when +[methodname]#getEvents()# is called. + + +[source, java] +---- +public static class MyEventProvider + implements CalendarEventProvider { + private List events = + new ArrayList(); + + public MyEventProvider() { + events = new ArrayList(); + GregorianCalendar cal = new GregorianCalendar(); + cal.setTime(new Date()); + + Date start = cal.getTime(); + cal.add(GregorianCalendar.HOUR, 5); + Date end = cal.getTime(); + BasicEvent event = new BasicEvent(); + event.setCaption("My Event"); + event.setDescription("My Event Description"); + event.setStart(start); + event.setEnd(end); + events.add(event); + } + + public void addEvent(CalendarEvent BasicEvent) { + events.add(BasicEvent); + } + + public List getEvents(Date startDate, + Date endDate) { + return events; + } +} +---- + +After these changes, the user can move events around as earlier, but dropping an +event, the start and end dates are checked by the server. Note that as the +server-side must move the event in order for it to render to the place it was +dropped. The server can also reject moves by not doing anything when the event +is received. + +endif::web[] + +ifdef::web[] +[[components.calendar.dragselection]] +== Handling Drag Selection + +Drag selection works both in the monthly and weekly views. To listen for drag +selection, you can add a [interfacename]#RangeSelectListener# to the +[classname]#Calendar#. There is no default handler for range select. + +In the code example below, we create an new event when any date range is +selected. Drag selection opens a window where the user is asked for a caption +for the new event. After confirming, the new event is be passed to the event +provider and calendar is updated. Note that as our example event provider and +event classes do not implement the event change interface, we must refresh the +[classname]#Calendar# manually after changing the events. + + +[source, java] +---- +cal.setHandler(new RangeSelectHandler() { + public void rangeSelect(RangeSelectEvent event) { + BasicEvent calendarEvent = new BasicEvent(); + calendarEvent.setStart(event.getStart()); + calendarEvent.setEnd(event.getEnd()); + + // Create popup window and add a form in it. + VerticalLayout layout = new VerticalLayout(); + layout.setMargin(true); + layout.setSpacing(true); + + final Window w = new Window(null, layout); + ... + + // Wrap the calendar event to a BeanItem + // and pass it to the form + final BeanItem item = + new BeanItem(myEvent); + + final Form form = new Form(); + form.setItemDataSource(item); + ... + + layout.addComponent(form); + + HorizontalLayout buttons = new HorizontalLayout(); + buttons.setSpacing(true); + buttons.addComponent(new Button("OK", new ClickListener() { + + public void buttonClick(ClickEvent event) { + form.commit(); + + // Update event provider's data source + provider.addEvent(item.getBean()); + + UI.getCurrent().removeWindow(w); + } + })); + + ... + } +}); +---- + +endif::web[] + +ifdef::web[] +[[components.calendar.eventresizing]] +== Resizing Events + +The user can resize an event by dragging from both ends to change its start or +end time. This offers a convenient way to change event times without the need to +type anything. The default resize handler sets the start and end time of the +event according to the resize. + +In the example below, we set a custom handler for resize events. The handler +prevents any event to be resized over 12 hours in length. Note that this does +not prevent the user from resizing an event over 12 hours in the client. The +resize will just be corrected by the server. + + +[source, java] +---- +cal.setHandler(new BasicEventResizeHandler() { + private static final long twelveHoursInMs = 12*60*60*1000; + + protected void setDates(CalendarEventEditor event, + Date start, Date end) { + long eventLength = end.getTime() - start.getTime(); + if (eventLength <= twelveHoursInMs) { + super.setDates(event, start, end); + } + } +}); +---- + +endif::web[] + + + diff --git a/documentation/components/components-checkbox.asciidoc b/documentation/components/components-checkbox.asciidoc new file mode 100644 index 0000000000..95a60cd5fa --- /dev/null +++ b/documentation/components/components-checkbox.asciidoc @@ -0,0 +1,72 @@ +--- +title: CheckBox +order: 15 +layout: page +--- + +[[components.checkbox]] += [classname]#CheckBox# + +ifdef::web[] +[.sampler] +image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/data-input/other/check-box] +endif::web[] + +[classname]#CheckBox# is a two-state selection component that can be either +checked or unchecked. The caption of the check box will be placed right of the +actual check box. Vaadin provides two ways to create check boxes: individual +check boxes with the [classname]#CheckBox# component described in this section +and check box groups with the [classname]#OptionGroup# component in multiple +selection mode, as described in +<>. + +Clicking on a check box will change its state. The state is a +[classname]#Boolean# property that you can set with the [methodname]#setValue()# +method and obtain with the [methodname]#getValue()# method of the +[classname]#Property# interface. Changing the value of a check box will cause a +[classname]#ValueChangeEvent#, which can be handled by a +[classname]#ValueChangeListener#. + + +[source, java] +---- +CheckBox checkbox1 = new CheckBox("Box with no Check"); +CheckBox checkbox2 = new CheckBox("Box with a Check"); + +checkbox2.setValue(true); + +checkbox1.addValueChangeListener(event -> // Java 8 + checkbox2.setValue(! checkbox1.getValue())); + +checkbox2.addValueChangeListener(event -> // Java 8 + checkbox1.setValue(! checkbox2.getValue())); +---- + +The result is shown in <>. + +[[figure.components.checkbox.basic]] +.An Example of a Check Box +image::img/checkbox-example1.png[] + +For an example on the use of check boxes in a table, see +<>. + +== CSS Style Rules + + +[source, css] +---- +.v-checkbox { } + .v-checkbox > input { } + .v-checkbox > label { } +---- + +The top-level element of a [classname]#CheckBox# has the +[literal]#++v-checkbox++# style. It contains two sub-elements: the actual check +box [literal]#++input++# element and the [literal]#++label++# element. If you +want to have the label on the left, you can change the positions with " +[literal]#++direction: rtl++#" for the top element. + + + + diff --git a/documentation/components/components-combobox.asciidoc b/documentation/components/components-combobox.asciidoc new file mode 100644 index 0000000000..f119cfbc40 --- /dev/null +++ b/documentation/components/components-combobox.asciidoc @@ -0,0 +1,112 @@ +--- +title: ComboBox +order: 16 +layout: page +--- + +[[components.combobox]] += [classname]#ComboBox# + +ifdef::web[] +[.sampler] +image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/data-input/multiple-value/combo-box] +endif::web[] + +[classname]#ComboBox# is a selection component allows selecting an item from a +drop-down list. The component also has a text field area, which allows entering +search text by which the items shown in the drop-down list are filtered. Common +selection component features are described in +<>. + +.The [classname]#ComboBox# Component +image::img/combobox-basic.png[] + +[classname]#ComboBox# supports adding new items when the user presses +kbd:[Enter]. +ifdef::web[] +See <>. +endif::web[] + +[[components.combobox.filtering]] +== Filtered Selection + +[classname]#ComboBox# allows filtering the items available for selection in the +drop-down list by the text entered in the input box. + +[[figure.components.combobox.filter]] +.Filtered Selection in [classname]#ComboBox# +image::img/combobox-filtering.png[] + +Pressing kbd:[Enter] will complete the item in the input box. Pressing kbd:[Up] and kbd:[Down] arrow keys can be used for selecting an item from the drop-down list. The +drop-down list is paged and clicking on the scroll buttons will change to the +next or previous page. The list selection can also be done with the arrow keys +on the keyboard. The shown items are loaded from the server as needed, so the +number of items held in the component can be quite large. The number of matching +items is displayed by the drop-down list. + +Filtering is enabled by setting a __filtering mode__ with +[methodname]#setFilteringMode()#. + + +[source, java] +---- +cb.setFilteringMode(FilteringMode.CONTAINS); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.select.combobox.filtering[on-line example, window="_blank"]. + +The modes defined in the [classname]#FilteringMode# enum are as follows: + +[parameter]#CONTAINS#:: Matches any item that contains the string given in the text field part of the +component. + +[parameter]#STARTSWITH#:: Matches only items that begin with the given string. + +[parameter]#OFF#(default):: Filtering is by default off and all items are shown all the time. + + + +The above example uses the containment filter that matches to all items +containing the input string. As shown in <> +below, when we type some text in the input area, the drop-down list will show +all the matching items. + + +[[components.combobox.css]] +== CSS Style Rules + + +[source, css] +---- +.v-filterselect { } + .v-filterselect-input { } + .v-filterselect-button { } + +// Under v-overlay-container +.v-filterselect-suggestpopup { } + .popupContent { } + .v-filterselect-prevpage, + .v-filterselect-prevpage-off { } + .v-filterselect-suggestmenu { } + .gwt-MenuItem { } + .v-filterselect-nextpage, + .v-filterselect-nextpage-off { } + .v-filterselect-status { } +---- + +In its default state, only the input field of the [classname]#ComboBox# +component is visible. The entire component is enclosed in +[literal]#++v-filterselect++# style (a legacy remnant), the input field has +[literal]#++v-filterselect-input++# style and the button in the right end that +opens and closes the drop-down result list has +[literal]#++v-filterselect-button++# style. + +The drop-down result list has an overall +[literal]#++v-filterselect-suggestpopup++# style. It contains the list of +suggestions with [literal]#++v-filterselect-suggestmenu++# style. When there are +more items that fit in the menu, navigation buttons with +[literal]#++v-filterselect-prevpage++# and +[literal]#++v-filterselect-nextpage++# styles are shown. When they are not +shown, the elements have [literal]#++-off++# suffix. The status bar in the +bottom that shows the paging status has [literal]#++v-filterselect-status++# +style. diff --git a/documentation/components/components-customcomponent.asciidoc b/documentation/components/components-customcomponent.asciidoc new file mode 100644 index 0000000000..cce897daa9 --- /dev/null +++ b/documentation/components/components-customcomponent.asciidoc @@ -0,0 +1,87 @@ +--- +title: Composition with CustomComponent +order: 31 +layout: page +--- + +[[components.customcomponent]] += Composition with [classname]#CustomComponent# + +The ease of making new user interface components is one of the core features of +Vaadin. Typically, you simply combine existing built-in components to produce +composite components. In many applications, such composite components make up +the majority of the user interface. + +As described earlier in +<>, you have two basic ways to create a composite - either by +extending a layout component or the [classname]#CustomComponent#, which +typically wraps around a layout component. The benefit of wrapping a layout +composite in [classname]#CustomComponent# is mainly encapsulation - hiding the +implementation details of the composition. Otherwise, a user of the composite +could rely on implementation details, which would create an unwanted dependency. + +To create a composite, you need to inherit the [classname]#CustomComponent# and +set the __composition root__ component in the constructor. The composition root +is typically a layout component that contains other components. + +For example: + + +[source, java] +---- +class MyComposite extends CustomComponent { + public MyComposite(String message) { + // A layout structure used for composition + Panel panel = new Panel("My Custom Component"); + VerticalLayout panelContent = new VerticalLayout(); + panelContent.setMargin(true); // Very useful + panel.setContent(panelContent); + + // Compose from multiple components + Label label = new Label(message); + label.setSizeUndefined(); // Shrink + panelContent.addComponent(label); + panelContent.addComponent(new Button("Ok")); + + // Set the size as undefined at all levels + panelContent.setSizeUndefined(); + panel.setSizeUndefined(); + setSizeUndefined(); + + // The composition root MUST be set + setCompositionRoot(panel); + } +} +---- + +Take note of the sizing when trying to make a customcomponent that shrinks to +fit the contained components. You have to set the size as undefined at all +levels; the sizing of the composite component and the composition root are +separate. + +You can use the component as follows: + + +[source, java] +---- +MyComposite mycomposite = new MyComposite("Hello"); +---- + +The rendered component is shown in <>. + +[[figure.components.customcomponent]] +.A Custom Composite Component +image::img/customcomponent-example1.png[] + +You can also inherit any other components, such as layouts, to attain similar +composition. ((("Google Web +Toolkit"))) +Even further, you can create entirely new low-level components, by integrating +pure client-side components or by extending the client-side functionality of +built-in components. Development of new components is covered in +<>. + + + diff --git a/documentation/components/components-customfield.asciidoc b/documentation/components/components-customfield.asciidoc new file mode 100644 index 0000000000..f57eb2debf --- /dev/null +++ b/documentation/components/components-customfield.asciidoc @@ -0,0 +1,33 @@ +--- +title: Composite Fields with CustomField +order: 32 +layout: page +--- + +[[components.customfield]] += Composite Fields with [classname]#CustomField# + +The [classname]#CustomField# is a way to create composite components like with +[classname]#CustomComponent#, except that it implements the +[interfacename]#Field# interface and inherit [classname]#AbstractField#, +described in +<>. A field allows editing a property value in the Vaadin data model, +and can be bound to data with field groups, as described in +<>. The field values are buffered and can be +validated with validators. + +A composite field class must implement the [methodname]#getType()# and +[methodname]#initContent()# methods. The latter should return the content +composite of the field. It is typically a layout component, but can be any +component. + +It is also possible to override [methodname]#validate()#, +[methodname]#setInternalValue()#, [methodname]#commit()#, +[methodname]#setPropertyDataSource#, [methodname]#isEmpty()# and other methods +to implement different functionalities in the field. Methods overriding +[methodname]#setInternalValue()# should call the superclass method. + + + diff --git a/documentation/components/components-datefield.asciidoc b/documentation/components/components-datefield.asciidoc new file mode 100644 index 0000000000..0f15a0f6ad --- /dev/null +++ b/documentation/components/components-datefield.asciidoc @@ -0,0 +1,391 @@ +--- +title: Date and Time Input with DateField +order: 13 +layout: page +--- + +[[components.datefield]] += Date and Time Input with [classname]#DateField# + +ifdef::web[] +[.sampler] +image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/data-input/dates/popup-date-field] +endif::web[] + +The [classname]#DateField# component provides the means to display and input +date and time. The field comes in two variations: [classname]#PopupDateField#, +with a numeric input box and a popup calendar view, and +[classname]#InlineDateField#, with the calendar view always visible. The +[classname]#DateField# base class defaults to the popup variation. + +The example below illustrates the use of the [classname]#DateField# baseclass, +which is equivalent to the [classname]#PopupDateField#. We set the initial time +of the date field to current time by using the default constructor of the +[classname]#java.util.Date# class. + + +[source, java] +---- +// Create a DateField with the default style +DateField date = new DateField(); + +// Set the date and time to present +date.setValue(new Date()); +---- + +The result is shown in <>. + +[[figure.components.datefield.basic]] +.[classname]#DateField# ([classname]#PopupDateField#) for Selecting Date and Time +image::img/datefield-example1.png[] + +[[components.datefield.popupdatefield]] +== [classname]#PopupDateField# + +The [classname]#PopupDateField# provides date input using a text box for the +date and time. As the [classname]#DateField# defaults to this component, the use +is exactly the same as described earlier. Clicking the handle right of the date +opens a popup view for selecting the year, month, and day, as well as time. Also +the Down key opens the popup. Once opened, the user can navigate the calendar +using the cursor keys. + +The date and time selected from the popup are displayed in the text box +according to the default date and time format of the current locale, or as +specified with [methodname]#setDateFormat()#. The same format definitions are +used for parsing user input. + +[[components.datefield.popupdatefield.format]] +=== Date and Time Format + +The date and time are normally displayed according to the default format for the +current locale (see +<>). +You can specify a custom format with [methodname]#setDateFormat()#. It takes a +format string that follows the format of the [classname]#SimpleDateFormat# in +Java. + + +[source, java] +---- +// Display only year, month, and day in ISO format +date.setDateFormat("yyyy-MM-dd"); +---- + +The result is shown in <>. + +[[figure.components.datefield.popupdatefield.format]] +.Custom Date Format for [classname]#PopupDateField# +image::img/datefield-formatting.png[] + +The same format specification is also used for parsing user-input date and time, +as described later. + + +ifdef::web[] +[[components.datefield.popupdatefield.malformed]] +=== Handling Malformed User Input + +A user can easily input a malformed or otherwise invalid date or time. +[classname]#DateField# has two validation layers: first on the client-side and +then on the server-side. + +The validity of the entered date is first validated on the client-side, +immediately when the input box loses focus. If the date format is invalid, the +[literal]#++v-datefield-parseerror++# style is set. Whether this causes a +visible indication of a problem depends on the theme. The built-in +[literal]#++reindeer++# theme does not shown any indication by default, making +server-side handling of the problem more convenient. + + +[source, css] +---- +.mydate.v-datefield-parseerror .v-textfield { + background: pink; +} +---- + +The [methodname]#setLenient(true)# setting enables relaxed interpretation of +dates, so that invalid dates, such as February 30th or March 0th, are wrapped to +the next or previous month, for example. + +The server-side validation phase occurs when the date value is sent to the +server. If the date field is set in immediate state, it occurs immediately after +the field loses focus. Once this is done and if the status is still invalid, an +error indicator is displayed beside the component. Hovering the mouse pointer +over the indicator shows the error message. + +You can handle the errors by overriding the +[methodname]#handleUnparsableDateString()# method. The method gets the user +input as a string parameter and can provide a custom parsing mechanism, as shown +in the following example. + + +[source, java] +---- +// Create a date field with a custom parsing and a +// custom error message for invalid format +PopupDateField date = new PopupDateField("My Date") { + @Override + protected Date handleUnparsableDateString(String dateString) + throws Property.ConversionException { + // Try custom parsing + String fields[] = dateString.split("/"); + if (fields.length >= 3) { + try { + int year = Integer.parseInt(fields[0]); + int month = Integer.parseInt(fields[1])-1; + int day = Integer.parseInt(fields[2]); + GregorianCalendar c = + new GregorianCalendar(year, month, day); + return c.getTime(); + } catch (NumberFormatException e) { + throw new Property. + ConversionException("Not a number"); + } + } + + // Bad date + throw new Property. + ConversionException("Your date needs two slashes"); + } +}; + +// Display only year, month, and day in slash-delimited format +date.setDateFormat("yyyy/MM/dd"); + +// Don't be too tight about the validity of dates +// on the client-side +date.setLenient(true); +---- + +The handler method must either return a parsed [classname]#Date# object or throw +a [classname]#ConversionException#. Returning [parameter]#null# will set the +field value to [parameter]#null# and clear the input box. + +endif::web[] + +ifdef::web[] +[[components.datefield.popupdatefield.error-customization]] +=== Customizing the Error Message + +In addition to customized parsing, overriding the handler method for unparseable +input is useful for internationalization and other customization of the error +message. You can also use it for another way for reporting the errors, as is +done in the example below: + + +[source, java] +---- +// Create a date field with a custom error message for invalid format +PopupDateField date = new PopupDateField("My Date") { + @Override + protected Date handleUnparsableDateString(String dateString) + throws Property.ConversionException { + // Have a notification for the error + Notification.show( + "Your date needs two slashes", + Notification.TYPE_WARNING_MESSAGE); + + // A failure must always also throw an exception + throw new Property.ConversionException("Bad date"); + } +}; +---- + +If the input is invalid, you should always throw the exception; returning a +[parameter]#null# value would make the input field empty, which is probably +undesired. + +endif::web[] + +[[components.datefield.popupdatefield.prompt]] +=== Input Prompt + +Like other fields that have a text box, [classname]#PopupDateField# allows an +input prompt that is visible until the user has input a value. You can set the +prompt with [methodname]#setInputPrompt#. + + +[source, java] +---- +PopupDateField date = new PopupDateField(); + +// Set the prompt +date.setInputPrompt("Select a date"); + +// Set width explicitly to accommodate the prompt +date.setWidth("10em"); +---- + +The date field doesn't automatically scale to accommodate the prompt, so you +need to set it explicitly with [methodname]#setWidth()#. + +The input prompt is not available in the [classname]#DateField# superclass. + + +[[components.datefield.popupdatefield.css]] +=== CSS Style Rules + + +[source, css] +---- +.v-datefield, v-datefield-popupcalendar {} + .v-textfield, v-datefield-textfield {} + .v-datefield-button {} +---- + +The top-level element of [classname]#DateField# and all its variants have +[literal]#++v-datefield++# style. The base class and the +[classname]#PopupDateField# also have the +[literal]#++v-datefield-popupcalendar++# style. + +In addition, the top-level element has a style that indicates the resolution, +with [literal]#++v-datefield-++# basename and an extension, which is one of +[literal]#++full++#, [literal]#++day++#, [literal]#++month++#, or +[literal]#++year++#. The [literal]#++-full++# style is enabled when the +resolution is smaller than a day. These styles are used mainly for controlling +the appearance of the popup calendar. + +The text box has [literal]#++v-textfield++# and +[literal]#++v-datefield-textfield++# styles, and the calendar button +[literal]#++v-datefield-button++#. + +Once opened, the calendar popup has the following styles at the top level: + + +[source, css] +---- +.v-datefield-popup {} + .v-popupcontent {} + .v-datefield-calendarpanel {} +---- + +The top-level element of the floating popup calendar has +[literal]#++.v-datefield-popup++# style. Observe that the popup frame is outside +the HTML structure of the component, hence it is not enclosed in the +[literal]#++v-datefield++# element and does not include any custom styles. +//NOTE: May be changed in +#5752. +The content in the [literal]#++v-datefield-calendarpanel++# is the same as in +[classname]#InlineDateField#, as described in <>. + + + +[[components.datefield.calendar]] +== [classname]#InlineDateField# + +The [classname]#InlineDateField# provides a date picker component with a month +view. The user can navigate months and years by clicking the appropriate arrows. +Unlike with the popup variant, the month view is always visible in the inline +field. + + +[source, java] +---- +// Create a DateField with the default style +InlineDateField date = new InlineDateField(); + +// Set the date and time to present +date.setValue(new java.util.Date()); +---- + +The result is shown in <>. + +[[figure.components.datefield.inlinedatefield]] +.Example of the [classname]#InlineDateField# +image::img/datefield-inlinedatefield.png[] + +The user can also navigate the calendar using the cursor keys. + +=== CSS Style Rules + + +[source, css] +---- +.v-datefield {} + .v-datefield-calendarpanel {} + .v-datefield-calendarpanel-header {} + .v-datefield-calendarpanel-prevyear {} + .v-datefield-calendarpanel-prevmonth {} + .v-datefield-calendarpanel-month {} + .v-datefield-calendarpanel-nextmonth {} + .v-datefield-calendarpanel-nextyear {} + .v-datefield-calendarpanel-body {} + .v-datefield-calendarpanel-weekdays, + .v-datefield-calendarpanel-weeknumbers {} + .v-first {} + .v-last {} + .v-datefield-calendarpanel-weeknumber {} + .v-datefield-calendarpanel-day {} + .v-datefield-calendarpanel-time {} + .v-datefield-time {} + .v-select {} + .v-label {} +---- + +The top-level element has the [literal]#++v-datefield++# style. In addition, the +top-level element has a style name that indicates the resolution of the +calendar, with [literal]#++v-datefield-++# basename and an extension, which is +one of [literal]#++full++#, [literal]#++day++#, [literal]#++month++#, or +[literal]#++year++#. The [literal]#++-full++# style is enabled when the +resolution is smaller than a day. + +The [literal]#++v-datefield-calendarpanel-weeknumbers++# and +[literal]#++v-datefield-calendarpanel-weeknumber++# styles are enabled when the +week numbers are enabled. The former controls the appearance of the weekday +header and the latter the actual week numbers. + +The other style names should be self-explanatory. For weekdays, the +[literal]#++v-first++# and [literal]#++v-last++# styles allow making rounded +endings for the weekday bar. + + + +[[components.datefield.resolution]] +== Date and Time Resolution + +In addition to display a calendar with dates, [classname]#DateField# can also +display the time in hours and minutes, or just the month or year. The visibility +of the input components is controlled by __time resolution__, which you can set +with [methodname]#setResolution()#. The method takes as its parameters the +lowest visible component, [parameter]#DateField.Resolution.DAY# for just dates +and [parameter]#DateField.Resolution.MIN# for dates with time in hours and +minutes. Please see the API Reference for the complete list of resolution +parameters. + + +[[components.datefield.locale]] +== DateField Locale + +The date and time are displayed according to the locale of the user, as reported +by the browser. You can set a custom locale with the [methodname]#setLocale()# +method of [classname]#AbstractComponent#, as described in +<>. +Only Gregorian calendar is supported. + + +ifdef::web[] +[[components.datefield.weeknumbers]] +== Week Numbers + +You can enable week numbers in a date field with +[methodname]#setShowISOWeekNumbers()#. The numbers are shown in a column on the +left side of the field. + + +[source, java] +---- +df.setShowISOWeekNumbers(true); +---- + +The supported numbering is defined in the ISO 8601 standard. Note that the ISO +standard applies only to calendar locales where the week starts on Monday. This +is not the case in many countries, such as Americas (North and South), many +East-Asian countries, and some African countries, where the week starts on +Sunday, nor in some North African and Middle-Eastern countries, where the week +begins on Saturday. In such locales, the week numbers are not displayed. + +endif::web[] + + + diff --git a/documentation/components/components-embedded.asciidoc b/documentation/components/components-embedded.asciidoc new file mode 100644 index 0000000000..bea83971a8 --- /dev/null +++ b/documentation/components/components-embedded.asciidoc @@ -0,0 +1,205 @@ +--- +title: Embedded Resources +order: 33 +layout: page +--- + +[[components.embedded]] += Embedded Resources + +You can embed images in Vaadin UIs with the [classname]#Image# component, Adobe +Flash graphics with [classname]#Flash#, and other web content with +[classname]#BrowserFrame#. There is also a generic [classname]#Embedded# +component for embedding other object types. The embedded content is referenced +as __resources__, as described in +<>. + +The following example displays an image as a class resource loaded with the +class loader: + + +[source, java] +---- +Image image = new Image("Yes, logo:", + new ClassResource("vaadin-logo.png")); +main.addComponent(image); +---- + +The caption can be given as null to disable it. An empty string displays an +empty caption which takes a bit space. The caption is managed by the containing +layout. + +You can set an altenative text for an embedded resource with +[methodname]#setAlternateText()#, which can be shown if images are disabled in +the browser for some reason. The text can be used for accessibility purposes, +such as for text-to-speech generation. + +[[components.embedded.image]] +== Embedded [classname]#Image# + +The [classname]#Image# component allows embedding an image resource in a Vaadin +UI. + + +[source, java] +---- +// Serve the image from the theme +Resource res = new ThemeResource("img/myimage.png"); + +// Display the image without caption +Image image = new Image(null, res); +layout.addComponent(image); +---- + +The [classname]#Image# component has by default undefined size in both +directions, so it will automatically fit the size of the embedded image. +((("scroll +bars"))) +If you want scrolling with scroll bars, you can put the image inside a +[classname]#Panel# that has a defined size to enable scrolling, as described in +<>. You can also put it inside some other component container +and set the [literal]#++overflow: auto++# CSS property for the container element +in a theme to enable automatic scrollbars. (((overflow CSS +property))) + +[[components.embedded.image.generated]] +=== Generating and Reloading Images + +You can also generate the image content dynamically using a +[classname]#StreamResource#, as described in +<>, or with a [classname]#RequestHandler#. + +If the image changes, the browser needs to reload it. Simply updating the stream +resource is not enough. Because of how caching is handled in some browsers, you +can cause a reload easiest by renaming the filename of the resource with a +unique name, such as one including a timestamp. You should set cache time to +zero with [methodname]#setCacheTime()# for the resource object when you create +it.//BUG +#2470. + + +[source, java] +---- +// Create the stream resource with some initial filename +StreamResource imageResource = + new StreamResource(imageSource, "initial-filename.png"); + +// Instruct browser not to cache the image +imageResource.setCacheTime(0); + +// Display the image +Image image = new Image(null, imageResource); +---- + +When refreshing, you also need to call [methodname]#markAsDirty()# for the +[classname]#Image# object. + + +[source, java] +---- +// This needs to be done, but is not sufficient +image.markAsDirty(); + +// Generate a filename with a timestamp +SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmssSSS"); +String filename = "myfilename-" + df.format(new Date()) + ".png"; + +// Replace the filename in the resource +imageResource.setFilename(makeImageFilename()); +---- + + + +[[components.embedded.flash]] +== Adobe [classname]#Flash# Graphics + +The [classname]#Flash# component allows embedding Adobe Flash animations in +Vaadin UIs. + + +[source, java] +---- +Flash flash = new Flash(null, + new ThemeResource("img/vaadin_spin.swf")); +layout.addComponent(flash); +---- + +You can set Flash parameters with [methodname]#setParameter()#, which takes a +parameter's name and value as strings. You can also set the +[parameter]#codeBase#, [parameter]#archive#, and [parameter]#standBy# attributes +for the Flash object element in HTML. + + +[[components.embedded.browserframe]] +== [classname]#BrowserFrame# + +The [classname]#BrowserFrame# allows embedding web content inside an HTML +<iframe> element. You can refer to an external URL with +[classname]#ExternalResource#. + +As the [classname]#BrowserFrame# has undefined size by default, it is critical +that you define a meaningful size for it, either fixed or relative. + + +[source, java] +---- +BrowserFrame browser = new BrowserFrame("Browser", + new ExternalResource("http://demo.vaadin.com/sampler/")); +browser.setWidth("600px"); +browser.setHeight("400px"); +layout.addComponent(browser); +---- + +Notice that web pages can prevent embedding them in an <iframe>. + + +[[components.embedded.embedded]] +== Generic [classname]#Embedded# Objects + +The generic [classname]#Embedded# component allows embedding all sorts of +objects, such as SVG graphics, Java applets, and PDF documents, in addition to +the images, Flash graphics, and browser frames which you can embed with the +specialized components. + +For example, to display a Flash animation: + + +[source, java] +---- +// A resource reference to some object +Resource res = new ThemeResource("img/vaadin_spin.swf"); + +// Display the object +Embedded object = new Embedded("My Object", res); +layout.addComponent(object); +---- + +Or an SVG image: + + +[source, java] +---- +// A resource reference to some object +Resource res = new ThemeResource("img/reindeer.svg"); + +// Display the object +Embedded object = new Embedded("My SVG", res); +object.setMimeType("image/svg+xml"); // Unnecessary +layout.addComponent(object); +---- + +The MIME type of the objects is usually detected automatically from the filename +extension with the [classname]#FileTypeResolver# utility in Vaadin. If not, you +can set it explicitly with [methodname]#setMimeType()#, as was done in the +example above (where it was actually unnecessary). + +Some embeddable object types may require special support in the browser. You +should make sure that there is a proper fallback mechanism if the browser does +not support the embedded type. + + + + diff --git a/documentation/components/components-extensions.asciidoc b/documentation/components/components-extensions.asciidoc new file mode 100644 index 0000000000..a84ad92f6e --- /dev/null +++ b/documentation/components/components-extensions.asciidoc @@ -0,0 +1,38 @@ +--- +title: Component Extensions +order: 6 +layout: page +--- + +[[components.extensions]] += Component Extensions + +Components and UIs can have extensions which are attached to the component +dynamically. Especially, many add-ons are extensions. + +How a component is extended depends on the extension. Typically, they have an +[methodname]#extend()# method that takes the component to be extended as the +parameter. + + +[source, java] +---- +TextField tf = new TextField("Hello"); +layout.addComponent(tf); + +// Add a simple extension +new CapsLockWarning().extend(tf); + +// Add an extension that requires some parameters +CSValidator validator = new CSValidator(); +validator.setRegExp("[0-9]*"); +validator.setErrorMessage("Must be a number"); +validator.extend(tf); +---- + +Development of custom extensions is described in +<>. + + + diff --git a/documentation/components/components-features.asciidoc b/documentation/components/components-features.asciidoc new file mode 100644 index 0000000000..9374b93bc1 --- /dev/null +++ b/documentation/components/components-features.asciidoc @@ -0,0 +1,757 @@ +--- +title: Common Component Features +order: 3 +layout: page +--- + +[[components.features]] += Common Component Features + +The component base classes and interfaces provide a large number of features. +Let us look at some of the most commonly needed features. Features not +documented here can be found from the Java API Reference. + +The interface defines a number of properties, which you can retrieve or +manipulate with the corresponding setters and getters. + +[[components.features.caption]] +== Caption + +((("caption property"))) +((("Component interface", "caption"))) +A caption is an explanatory textual label accompanying a user interface +component, usually shown above, left of, or inside the component. The contents +of a caption are automatically quoted, so no raw HTML can be rendered in a +caption. + +The caption text can usually be given as the first parameter of a constructor of +a component or with [methodname]#setCaption()#. + + +[source, java] +---- +// New text field with caption "Name" +TextField name = new TextField("Name"); +layout.addComponent(name); +---- + +The caption of a component is, by default, managed and displayed by the layout +component or component container inside which the component is placed. For +example, the [classname]#VerticalLayout# component shows the captions +left-aligned above the contained components, while the [classname]#FormLayout# +component shows the captions on the left side of the vertically laid components, +with the captions and their associated components left-aligned in their own +columns. The [classname]#CustomComponent# does not manage the caption of its +composition root, so if the root component has a caption, it will not be +rendered. + +[[figure.components.features.caption.layoutmanaged]] +.Caption Management by [classname]#VerticalLayout# and [classname]#FormLayout#. +image::img/features-caption-layoutmanaged.png[] + +Some components, such as [classname]#Button# and [classname]#Panel#, manage the +caption themselves and display it inside the component. + +Icon (see <>) is closely related to caption and is +usually displayed horizontally before or after it, depending on the component +and the containing layout. Also the required indicator in field components is +usually shown before or after the caption. + +An alternative way to implement a caption is to use another component as the +caption, typically a [classname]#Label#, a [classname]#TextField#, or a +[classname]#Panel#. A [classname]#Label#, for example, allows highlighting a +shortcut key with HTML markup or to bind the caption to a data source. The +[classname]#Panel# provides an easy way to add both a caption and a border +around a component. + +=== CSS Style Rules + + +[source, css] +---- +.v-caption {} + .v-captiontext {} + .v-caption-clearelem {} + .v-required-field-indicator {} +---- + +A caption is be rendered inside an HTML element that has the +[literal]#++v-caption++# CSS style class. The containing layout may enclose a +caption inside other caption-related elements. + +Some layouts put the caption text in a [literal]#++v-captiontext++# element. A +[literal]#++v-caption-clearelem++# is used in some layouts to clear a CSS +[literal]#++float++# property in captions. An optional required indicator in +field components is contained in a separate element with +[literal]#++v-required-field-indicator++# style. + + + +[[components.features.description]] +== Description and Tooltips + +((("description property"))) +((("Component interface", "description"))) +((("tooltips"))) +All components (that inherit [classname]#AbstractComponent#) have a description +separate from their caption. The description is usually shown as a tooltip that +appears when the mouse pointer hovers over the component for a short time. + +You can set the description with [methodname]#setDescription()# and retrieve +with [methodname]#getDescription()#. + + +[source, java] +---- +Button button = new Button("A Button"); +button.setDescription("This is the tooltip"); +---- + +The tooltip is shown in <>. + +[[figure.components.tooltip.plain]] +.Component Description as a Tooltip +image::img/tooltip-plain-withpointer-hi.png[] + +A description is rendered as a tooltip in most components. + +When a component error has been set with [methodname]#setComponentError()#, the +error is usually also displayed in the tooltip, below the description. +Components that are in error state will also display the error indicator. See +<>. + +The description is actually not plain text, but you can use HTML tags to format +it. Such a rich text description can contain any HTML elements, including +images. + + +[source, java] +---- +button.setDescription( + "

"+ + "A richtext tooltip

"+ + "
    "+ + "
  • Use rich formatting with HTML
  • "+ + "
  • Include images from themes
  • "+ + "
  • etc.
  • "+ + "
"); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.features.description.richtext[on-line example, window="_blank"]. + +The result is shown in <>. + +[[figure.components.tooltip.richtext]] +.A Rich Text Tooltip +image::img/tooltip-richtext-withpointer-hi.png[] + +Notice that the setter and getter are defined for all fields in the +[classname]#Field# interface, not for all components in the +[classname]#Component# interface. + + +[[components.features.enabled]] +== Enabled + +((("enabled property"))) +((("Component interface", "enabled"))) +The __enabled__ property controls whether the user can actually use the +component. A disabled component is visible, but grayed to indicate the disabled +state. + +Components are always enabled by default. You can disable a component with +[methodname]#setEnabled(false)#. + + +[source, java] +---- +Button enabled = new Button("Enabled"); +enabled.setEnabled(true); // The default +layout.addComponent(enabled); + +Button disabled = new Button("Disabled"); +disabled.setEnabled(false); +layout.addComponent(disabled); +---- + +<> shows the enabled and disabled +buttons. + +[[figure.components.features.enabled.simple]] +.An Enabled and Disabled [classname]#Button# +image::img/features-enabled-simple.png[] + +A disabled component is automatically put in read-only state. No client +interaction with such a component is sent to the server and, as an important +security feature, the server-side components do not receive state updates from +the client in the read-only state. This feature exists in all built-in +components in Vaadin and is automatically handled for all [classname]#Field# +components for the field property value. For custom widgets, you need to make +sure that the read-only state is checked on the server-side for all +safety-critical variables. + +=== CSS Style Rules + +Disabled components have the [literal]#++v-disabled++# CSS style in addition to +the component-specific style. To match a component with both the styles, you +have to join the style class names with a dot as done in the example below. + + +[source, css] +---- +.v-textfield.v-disabled { + border: dotted; +} +---- + +This would make the border of all disabled text fields dotted. + + +//TODO This may change to +$v-button-disabled-opacity +In Valo theme, the opacity of disabled components is specified with the +$v-disabled-opacity parameter + +ifdef::web[] +, as described in +<> +endif::web[] +. + + +[[components.features.icon]] +== Icon + +((("icon property"))) +((("Component interface", "icon"))) +An icon is an explanatory graphical label accompanying a user interface +component, usually shown above, left of, or inside the component. Icon is +closely related to caption (see <>) and is usually +displayed horizontally before or after it, depending on the component and the +containing layout. + +The icon of a component can be set with the [methodname]#setIcon()# method. The +image is provided as a resource, perhaps most typically a +[classname]#ThemeResource#. + + +[source, java] +---- +// Component with an icon from a custom theme +TextField name = new TextField("Name"); +name.setIcon(new ThemeResource("icons/user.png")); +layout.addComponent(name); + +// Component with an icon from another theme ('runo') +Button ok = new Button("OK"); +ok.setIcon(new ThemeResource("../runo/icons/16/ok.png")); +layout.addComponent(ok); +---- + +The icon of a component is, by default, managed and displayed by the layout +component or component container in which the component is placed. For example, +the [classname]#VerticalLayout# component shows the icons left-aligned above the +contained components, while the [classname]#FormLayout# component shows the +icons on the left side of the vertically laid components, with the icons and +their associated components left-aligned in their own columns. The +[classname]#CustomComponent# does not manage the icon of its composition root, +so if the root component has an icon, it will not be rendered. + +[[figure.components.features.icon]] +.Displaying an Icon from a Theme Resource. +image::img/features-icon.png[] + +Some components, such as [classname]#Button# and [classname]#Panel#, manage the +icon themselves and display it inside the component. + +In addition to image resources, you can use __font icons__, which are icons +included in special fonts, but which are handled as special resources. See +<> +for more details. + +=== CSS Style Rules + +An icon will be rendered inside an HTML element that has the +[literal]#++v-icon++# CSS style class. The containing layout may enclose an icon +and a caption inside elements related to the caption, such as +[literal]#++v-caption++#. + + + +[[components.features.locale]] +== Locale + +((("locale property", "in [classname]#Component#"))) +((("Component interface", "locale"))) +The locale property defines the country and language used in a component. You +can use the locale information in conjunction with an internationalization +scheme to acquire localized resources. Some components, such as +[classname]#DateField#, use the locale for component localization. + +You can set the locale of a component (or the application) with +[methodname]#setLocale()# as follows: + + +[source, java] +---- +// Component for which the locale is meaningful +InlineDateField date = new InlineDateField("Datum"); + +// German language specified with ISO 639-1 language +// code and ISO 3166-1 alpha-2 country code. +date.setLocale(new Locale("de", "DE")); + +date.setResolution(Resolution.DAY); +layout.addComponent(date); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.features.locale.simple[on-line example, window="_blank"]. + +The resulting date field is shown in +<>. + +[[figure.components.features.locale.simple]] +.Set Locale for [classname]#InlineDateField# +image::img/features-locale-simple.png[] + +ifdef::web[] +[[components.features.locale.get]] +=== Getting the Locale + +((("[methodname]#getLocale()#"))) +You can get the locale of a component with [methodname]#getLocale()#. If the +locale is undefined for a component, that is, not explicitly set, the locale of +the parent component is used. If none of the parent components have a locale +set, the locale of the UI is used, and if that is not set, the default system +locale is set, as given by [methodname]#Locale.getDefault()#. + +The [methodname]#getLocale()# returns null if the component is not yet attached +to the UI, which is usually the case in most constructors, so it is a bit +awkward to use it for internationalization. You can get the locale in +[methodname]#attach()#, as shown in the following example: + + +[source, java] +---- +Button cancel = new Button() { + @Override + public void attach() { + super.attach(); + ResourceBundle bundle = ResourceBundle.getBundle( + MyAppCaptions.class.getName(), getLocale()); + setCaption(bundle.getString(MyAppCaptions.CancelKey)); + } +}; +layout.addComponent(cancel); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.features.locale.get-attach[on-line example, window="_blank"]. + +However, it is normally a better practice to use the locale of the current UI to +get the localized resource right when the component is created. + + +[source, java] +---- +// Captions are stored in MyAppCaptions resource bundle +// and the UI object is known in this context. +ResourceBundle bundle = + ResourceBundle.getBundle(MyAppCaptions.class.getName(), + UI.getCurrent().getLocale()); + +// Get a localized resource from the bundle +Button cancel = + new Button(bundle.getString(MyAppCaptions.CancelKey)); +layout.addComponent(cancel); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.features.locale.get-ui[on-line example, window="_blank"]. + +endif::web[] + +ifdef::web[] +[[component.features.locale.selecting]] +=== Selecting a Locale + +A common task in many applications is selecting a locale. This is done in the +following example with a [classname]#ComboBox#, which gets the available locales +in Java. + + +[source, java] +---- +// The locale in which we want to have the language +// selection list +Locale displayLocale = Locale.ENGLISH; + +// All known locales +final Locale[] locales = Locale.getAvailableLocales(); + +// Allow selecting a language. We are in a constructor of a +// CustomComponent, so preselecting the current +// language of the application can not be done before +// this (and the selection) component are attached to +// the application. +final ComboBox select = new ComboBox("Select a language") { + @Override + public void attach() { + super.attach(); + setValue(getLocale()); + } +}; +for (int i=0; i>. + +[[figure.components.features.locale.selection]] +.Selecting a Locale +image::img/features-locale-selection.png[] + +endif::web[] + + +[[components.features.readonly]] +== Read-Only + +((("read-only property"))) +((("Component interface", "read-only"))) +The property defines whether the value of a component can be changed. The +property is mainly applicable to [classname]#Field# components, as they have a +value that can be edited by the user. + + +[source, java] +---- +TextField readwrite = new TextField("Read-Write"); +readwrite.setValue("You can change this"); +readwrite.setReadOnly(false); // The default +layout.addComponent(readwrite); + +TextField readonly = new TextField("Read-Only"); +readonly.setValue("You can't touch this!"); +readonly.setReadOnly(true); +layout.addComponent(readonly); +---- + +The resulting read-only text field is shown in +<>. + +[[figure.components.features.readonly.simple]] +.A Read-Only Component. +image::img/features-readonly-simple.png[] + +Setting a layout or some other component container as read-only does not usually +make the contained components read-only recursively. This is different from, for +example, the disabled state, which is usually applied recursively. + +Notice that the value of a selection component is the selection, not its items. +A read-only selection component doesn't therefore allow its selection to be +changed, but other changes are possible. For example, if you have a read-only +[classname]#Table# in editable mode, its contained fields and the underlying +data model can still be edited, and the user could sort it or reorder the +columns. + +Client-side state modifications will not be communicated to the server-side and, +more importantly, server-side field components will not accept changes to the +value of a read-only [classname]#Field# component. The latter is an important +security feature, because a malicious user can not fabricate state changes in a +read-only field. This is handled at the level of [classname]#AbstractField# in +[methodname]#setValue()#, so you can not change the value programmatically +either. Calling [methodname]#setValue()# on a read-only field results in +[classname]#Property.ReadOnlyException#. + +Also notice that while the read-only status applies automatically to the +property value of a field, it does not apply to other component variables. A +read-only component can accept some other variable changes from the client-side +and some of such changes could be acceptable, such as change in the scroll bar +position of a [classname]#Table#. Custom widgets should check the read-only +state for variables bound to business +data.//// +TODO: Note this also in the Advanced: Security section and possibly also in the +GWT +chapter. +//// + +=== CSS Style Rules + +Setting a normally editable component to read-only state can change its +appearance to disallow editing the value. In addition to CSS styling, also the +HTML structure can change. For example, [classname]#TextField# loses the edit +box and appears much like a [classname]#Label#. + +A read-only component will have the [literal]#++v-readonly++# style. The +following CSS rule would make the text in all read-only [classname]#TextField# +components appear in italic. + + +[source, css] +---- +.v-textfield.v-readonly { + font-style: italic; +} +---- + + + +[[components.features.stylename]] +== Style Name + +((("style name property"))) +((("Component interface", "style name"))) +The __style name__ property defines one or more custom CSS style class names for +the component. The [methodname]#getStyleName()# returns the current style names +as a space-separated list. The [methodname]#setStyleName()# replaces all the +styles with the given style name or a space-separated list of style names. You +can also add and remove individual style names with [methodname]#addStylename()# +and [methodname]#removeStyleName()#. A style name must be a valid CSS style +name. + + +[source, java] +---- +Label label = new Label("This text has a lot of style"); +label.addStyleName("mystyle"); +layout.addComponent(label); +---- + +The style name will appear in the component's HTML element in two forms: +literally as given and prefixed with the component-specific style name. For +example, if you add a style name [literal]#++mystyle++# to a +[classname]#Button#, the component would get both [literal]#++mystyle++# and +[literal]#++v-button-mystyle++# styles. Neither form may conflict with built-in +style names of Vaadin. For example, [literal]#++focus++# style would conflict +with a built-in style of the same name, and an [literal]#++content++# style for +a [classname]#Panel# component would conflict with the built-in +[literal]#++v-panel-content++# style. + +The following CSS rule would apply the style to any component that has the +[literal]#++mystyle++# style. + + +[source, css] +---- +.mystyle { + font-family: fantasy; + font-style: italic; + font-size: 25px; + font-weight: bolder; + line-height: 30px; +} +---- + +The resulting styled component is shown in +<> + +[[figure.components.features.stylename]] +.Component with a Custom Style +image::img/features-stylename-simple.png[] + + +[[components.features.visible]] +== Visible + +((("visible property"))) +((("Component interface", "visible"))) +Components can be hidden by setting the __visible__ property to __false__. Also +the caption, icon and any other component features are made hidden. Hidden +components are not just invisible, but their content is not communicated to the +browser at all. That is, they are not made invisible cosmetically with only CSS +rules. This feature is important for security if you have components that +contain security-critical information that must only be shown in specific +application states. + + +[source, java] +---- +TextField invisible = new TextField("No-see-um"); +invisible.setValue("You can't see this!"); +invisible.setVisible(false); +layout.addComponent(invisible); +---- + +The resulting invisible component is shown in +<>. + +[[figure.components.features.visible.simple]] +.An Invisible Component. +image::img/features-visible-simple.png[] + +Beware that invisible beings can leave footprints. The containing layout cell +that holds the invisible component will not go away, but will show in the layout +as extra empty space. Also expand ratios work just like if the component was +visible - it is the layout cell that expands, not the component. + +If you need to make a component only cosmetically invisible, you should use a +custom theme to set it [literal]#++display: none++# style. This is mainly useful +for some special components that have effects even when made invisible in CSS. +If the hidden component has undefined size and is enclosed in a layout that also +has undefined size, the containing layout will collapse when the component +disappears. If you want to have the component keep its size, you have to make it +invisible by setting all its font and other attributes to be transparent. In +such cases, the invisible content of the component can be made visible easily in +the browser. + +A component made invisible with the __visible__ property has no particular CSS +style class to indicate that it is hidden. The element does exist though, but +has [literal]#++display: none++# style, which overrides any CSS styling. + + +[[components.features.sizeable]] +== Sizing Components + +((("[classname]#Sizeable# interface"))) +Vaadin components are sizeable; not in the sense that they were fairly large or +that the number of the components and their features are sizeable, but in the +sense that you can make them fairly large on the screen if you like, or small or +whatever size. + +The [classname]#Sizeable# interface, shared by all components, provides a number +of manipulation methods and constants for setting the height and width of a +component in absolute or relative units, or for leaving the size undefined. + +The size of a component can be set with [methodname]#setWidth()# and +[methodname]#setHeight()# methods. The methods take the size as a floating-point +value. You need to give the unit of the measure as the second parameter for the +above methods. The available units are listed in +<> below. + + +[source, java] +---- +mycomponent.setWidth(100, Sizeable.UNITS_PERCENTAGE); +mycomponent.setWidth(400, Sizeable.UNITS_PIXELS); +---- + +Alternatively, you can speficy the size as a string. The format of such a string +must follow the HTML/CSS standards for specifying measures. + + +[source, java] +---- +mycomponent.setWidth("100%"); +mycomponent.setHeight("400px"); +---- + +The " [literal]#++100%++#" percentage value makes the component take all +available size in the particular direction (see the description of +[parameter]#Sizeable.UNITS_PERCENTAGE# in the table below). You can also use the +shorthand method [methodname]#setSizeFull()# to set the size to 100% in both +directions. + +The size can be __undefined__ in either or both dimensions, which means that the +component will take the minimum necessary space. Most components have undefined +size by default, but some layouts have full size in horizontal direction. You +can set the height or width as undefined with +[parameter]#Sizeable.SIZE_UNDEFINED# parameter for [methodname]#setWidth()# and +[methodname]#setHeight()#. + +You always need to keep in mind that __a layout with undefined size may not +contain components with defined relative size__, such as "full size". See +<> for details. + +The <> lists the available units and +their codes defined in the [classname]#Sizeable# interface. + +[[components.features.sizeable.units.table]] +.Size Units + +|=============== +|[parameter]#Unit.PIXELS#|px|The__pixel__is the basic hardware-specific measure of one physical display pixel. +|[parameter]#Unit.POINTS#|pt|The__point__is a typographical unit, which is usually defined as 1/72 inches or about 0.35 mm. However, on displays the size can vary significantly depending on display metrics. +|[parameter]#Unit.PICAS#|pc|The__pica__is a typographical unit, defined as 12 points, or 1/7 inches or about 4.233 mm. On displays, the size can vary depending on display metrics. +|[parameter]#Unit.EM#|em|A unit relative to the used font, the width of the upper-case "M" letter. +|[parameter]#Unit.EX#|ex|A unit relative to the used font, the height of the lower-case "x" letter. +|[parameter]#Unit.MM#|mm|A physical length unit, millimeters on the surface of a display device. However, the actual size depends on the display, its metrics in the operating system, and the browser. +|[parameter]#Unit.CM#|cm|A physical length unit,__centimeters__on the surface of a display device. However, the actual size depends on the display, its metrics in the operating system, and the browser. +|[parameter]#Unit.INCH#|in|A physical length unit,__inches__on the surface of a display device. However, the actual size depends on the display, its metrics in the operating system, and the browser. +|[parameter]#Unit.PERCENTAGE#|%|A relative percentage of the available size. For example, for the top-level layout[parameter]#100%#would be the full width or height of the browser window. The percentage value must be between 0 and 100. + +|=============== + + + +If a component inside [classname]#HorizontalLayout# or +[classname]#VerticalLayout# has full size in the namesake direction of the +layout, the component will expand to take all available space not needed by the +other components. See +<> for details. + + +== Managing Input Focus + +When the user clicks on a component, the component gets the __input focus__, +which is indicated by highlighting according to style definitions. If the +component allows inputting text, the focus and insertion point are indicated by +a cursor. Pressing the Tab key moves the focus to the component next in the +__focus order__. + +Focusing is supported by all [classname]#Field# components and also by +[classname]#Upload#. + +The focus order or __tab index__ of a component is defined as a positive integer +value, which you can set with [methodname]#setTabIndex()# and get with +[methodname]#getTabIndex()#. The tab index is managed in the context of the page +in which the components are contained. The focus order can therefore jump +between two any lower-level component containers, such as sub-windows or panels. + +The default focus order is determined by the natural hierarchical order of +components in the order in which they were added under their parents. The +default tab index is 0 (zero). + +Giving a negative integer as the tab index removes the component from the focus +order entirely. + +=== CSS Style Rules + +The component having the focus will have an additional style class with the +[literal]#++-focus++# suffix. For example, a [classname]#TextField#, which +normally has the [literal]#++v-textfield++# style, would additionally have the +[literal]#++v-textfield-focus++# style. + +For example, the following would make a text field blue when it has focus. + + +[source, css] +---- +.v-textfield-focus { + background: lightblue; +} +---- + + + + + diff --git a/documentation/components/components-fields.asciidoc b/documentation/components/components-fields.asciidoc new file mode 100644 index 0000000000..229592c74e --- /dev/null +++ b/documentation/components/components-fields.asciidoc @@ -0,0 +1,345 @@ +--- +title: Field Components +order: 4 +layout: page +--- + +[[components.fields]] += Field Components + +((("[classname]#Field#", id="term.components.fields", range="startofrange"))) + + +__Fields__ are components that have a value that the user can change through the +user interface. <> illustrates the inheritance +relationships and the important interfaces and base classes. + +[[figure.components.fields]] +.Field Components +image::img/field-diagram-hi.png[] + +Field components are built upon the framework defined in the [classname]#Field# +interface and the [classname]#AbstractField# base class. +[classname]#AbstractField# is the base class for all field components. In +addition to the component features inherited from +[classname]#AbstractComponent#, it implements a number of features defined in +[classname]#Property#, [classname]#Buffered#, [classname]#Validatable#, and +[classname]#Component.Focusable# interfaces. + +The description of the field interfaces and base classes is broken down in the +following sections. + +[[components.fields.field]] +== [classname]#Field# Interface + +The [classname]#Field# interface inherits the [classname]#Component# +superinterface and also the [classname]#Property# interface to have a value for +the field. [classname]#AbstractField# is the only class implementing the +[classname]#Field# interface directly. The relationships are illustrated in +<>. + +[[figure.components.fields.field]] +.[classname]#Field# Interface Inheritance Diagram +image::img/field-interface-hi.png[] + +You can set the field value with the [methodname]#setValue()# and read with the +[methodname]#getValue()# method defined in the [classname]#Property# interface. +The actual value type depends on the component. + +The [classname]#Field# interface defines a number of properties, which you can +access with the corresponding setters and getters. + +[methodname]#required#:: When enabled, a required indicator (usually the asterisk * character) is +displayed on the left, above, or right the field, depending on the containing +layout and whether the field has a caption. If such fields are validated but are +empty and the [methodname]#requiredError# property (see below) is set, an error +indicator is shown and the component error is set to the text defined with the +error property. Without validation, the required indicator is merely a visual +guide. + +[methodname]#requiredError#:: Defines the error message to show when a value is required, but none is entered. +The error message is set as the component error for the field and is usually +displayed in a tooltip when the mouse pointer hovers over the error indicator. + + + + +[[components.fields.databinding]] +== Data Binding and Conversions + +Fields are strongly coupled with the Vaadin data model. The field value is +handled as a [classname]#Property# of the field component, as documented in +<>. +Selection fields allow management of the selectable items through the +[classname]#Container# interface. + +Fields are __editors__ for some particular type. For example, +[classname]#TextField# allows editing [classname]#String# values. When bound to +a data source, the property type of the data model can be something different, +say an [classname]#Integer#. __Converters__ are used for converting the values +between the representation and the model. They are described in +<>. + + +[[components.fields.valuechanges]] +== Handling Field Value Changes + +[classname]#Field# inherits [classname]#Property.ValueChangeListener# to allow +listening for field value changes and [classname]#Property.Editor# to allow +editing values. + +When the value of a field changes, a [classname]#Property.ValueChangeEvent# is +triggered for the field. You should not implement the +[methodname]#valueChange()# method in a class inheriting +[classname]#AbstractField#, as it is already implemented in +[classname]#AbstractField#. You should instead implement the method explicitly +by adding the implementing object as a listener. + + +[[components.fields.buffering]] +== Field Buffering + +Field components implement the [interfacename]#Buffered# and +[interfacename]#BufferedValidatable# interfaces. When buffering is enabled for a +field with [methodname]#setBuffered(true)#, the value is not written to the +property data source before the [methodname]#commit()# method is called for the +field. Calling [methodname]#commit()# also runs validators added to the field, +and if any fail (and the [parameter]#invalidCommitted# is disabled), the value +is not written. + + +[source, java] +---- +form.addComponent(new Button("Commit", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + try { + editor.commit(); + } catch (InvalidValueException e) { + Notification.show(e.getMessage()); + } + } +})); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.field.buffering.basic[on-line example, window="_blank"]. + +Calling [methodname]#discard()# reads the value from the property data source to +the current input. + +If the fields are bound in a [classname]#FieldGroup# that has buffering enabled, +calling [methodname]#commit()# for the group runs validation on all fields in +the group, and if successful, all the field values are written to the item data +source. See +<>. + + +[[components.fields.validation]] +== Field Validation + +The input for a field component can be syntactically or semantically invalid. +Fields implement the [interfacename]#Validatable# interface, which allows +checking validity of the input with __validators__ that implement the +[interfacename]#Validator# interface. You can add validators to fields with +[methodname]#addValidator()#. + + +[source, java] +---- +TextField field = new TextField("Name"); +field.addValidator(new StringLengthValidator( + "The name must be 1-10 letters (was {0})", + 1, 10, true)); +field.setNullRepresentation(""); +field.setNullSettingAllowed(true); +layout.addComponent(field); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.field.validation.basic[on-line example, window="_blank"]. + +Failed validation is indicated with the error indicator of the field, described +in +<>, unless disabled with +[methodname]#setValidationVisible(false)#. Hovering mouse on the field displays +the error message given as a parameter for the validator. If validated +explicitly with [methodname]#validate()#, as described later, the +[classname]#InvalidValueException# is thrown if the validation fails, also +carrying the error message. The value [literal]#++{0}++# in the error message +string is replaced with the invalid input value. + +Validators validate the property type of the field after a possible conversion, +not the presentation type. For example, an [classname]#IntegerRangeValidator# +requires that the value type of the property data source is +[classname]#Integer#. + +[[components.fields.validation.builtin]] +=== Built-in Validators + +Vaadin includes the following built-in validators. The property value type is +indicated. + +[classname]#BeanValidator#:: Validates a bean property according to annotations defined in the Bean +Validation API 1.0 (JSR-303). This validator is usually not used explicitly, but +they are created implicitly when binding fields in a +[classname]#BeanFieldGroup#. Using bean validation requires an implementation +library of the API. See +<> for details. + +[classname]#CompositeValidator#:: Combines validators using logical AND and OR operators. + +[classname]#DateRangeValidator#:[classname]#Date#:: Checks that the date value is within the range at or between two given +dates/times. + +[classname]#DoubleRangeValidator#:[classname]#Double#:: Checks that the double value is at or between two given values. + +[classname]#EmailValidator#:[classname]#String#:: Checks that the string value is a syntactically valid email address. The +validated syntax is close to the RFC 822 standard regarding email addresses. + +[classname]#IntegerRangeValidator#:[classname]#Integer#:: Checks that the integer value is at or between two given values. + +[classname]#NullValidator#:: Checks that the value is or is not a null value. + ++ +For the validator to be meaningful, the component must support inputting null +values. For example, for selection components and [classname]#TextField#, +inputting null values can be enabled with [methodname]#setNullSettingAllowed()#. +You also need to set the representation of null values: in selection components +with [methodname]#setNullSelectionItemId()# and in [classname]#TextField# with +[methodname]#setNullRepresentation()#. + +ifdef::web[] ++ +Setting field as __required__ can be used for similar effect, and it also +enables an indicator to indicate that a value is required. +endif::web[] + +[classname]#RegexpValidator#:[classname]#String#:: Checks that the value matches with the given regular expression. + +[classname]#StringLengthValidator#:[classname]#String#:: Checks that the length of the input string is at or between two given lengths. + +ifdef::web[] ++ +The [parameter]#allowNull# parameter determines whether null values should be +allowed for the string, regardless of the string length. A null value has zero +length, so it will be invalid if the minimum length is greater than zero. +Allowing null value is meaningful only if inputting null values is enabled with +[methodname]#setNullSettingAllowed(true)#, and typically in such case, you want +to set the null representation to empty string with +[methodname]#setNullRepresentation("")#. Note that __this parameter is +deprecated__ and should normally be [parameter]#true#; then you can use +[methodname]#setRequired()# (for the false case) or [classname]#NullValidator#. +endif::web[] + + + +Please see the API documentation for more details. + + +[[components.fields.validation.automatic]] +=== Automatic Validation + +The validators are normally, when [literal]#++validationVisible++# is true for +the field, executed implicitly on the next server request if the input has +changed. If the field is in immediate mode, it (and any other fields with +changed value) are validated immediately when the focus leaves the field. + + +[source, java] +---- +TextField field = new TextField("Name"); +field.addValidator(new StringLengthValidator( + "The name must be 1-10 letters (was {0})", + 1, 10, true)); +field.setImmediate(true); +field.setNullRepresentation(""); +field.setNullSettingAllowed(true); +layout.addComponent(field); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.field.validation.basic[on-line example, window="_blank"]. + + +[[components.fields.validation.explicit]] +=== Explicit Validation + +The validators are executed when the [methodname]#validate()# or +[methodname]#commit()# methods are called for the field. + + +[source, java] +---- +// A field with automatic validation disabled +final TextField field = new TextField("Name"); +field.setNullRepresentation(""); +field.setNullSettingAllowed(true); +layout.addComponent(field); + +// Define validation as usual +field.addValidator(new StringLengthValidator( + "The name must be 1-10 letters (was {0})", + 1, 10, true)); + +// Run validation explicitly +Button validate = new Button("Validate"); +validate.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + field.setValidationVisible(false); + try { + field.validate(); + } catch (InvalidValueException e) { + Notification.show(e.getMessage()); + field.setValidationVisible(true); + } + } +}); +layout.addComponent(validate); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.field.validation.explicit[on-line example, window="_blank"]. + + +[[components.fields.validation.custom]] +=== Implementing a Custom Validator + +You can create custom validators by implementing the [interfacename]#Validator# +interface and implementing its [methodname]#validate()# method. If the +validation fails, the method should throw either +[classname]#InvalidValueException# or [classname]#EmptyValueException#. + + +[source, java] +---- +class MyValidator implements Validator { + @Override + public void validate(Object value) + throws InvalidValueException { + if (!(value instanceof String && + ((String)value).equals("hello"))) + throw new InvalidValueException("You're impolite"); + } +} + +final TextField field = new TextField("Say hello"); +field.addValidator(new MyValidator()); +field.setImmediate(true); +layout.addComponent(field); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.field.validation.customvalidator[on-line example, window="_blank"]. + + +[[components.fields.validation.fieldgroup]] +=== Validation in Field Groups + +If the field is bound to a [classname]#FieldGroup#, described in +<>, calling [methodname]#commit()# for the +group runs the validation for all the fields in the group, and if successful, +writes the input values to the data source. + + + +(((range="endofrange", startref="term.components.fields"))) + + diff --git a/documentation/components/components-grid.asciidoc b/documentation/components/components-grid.asciidoc new file mode 100644 index 0000000000..e2013b8daa --- /dev/null +++ b/documentation/components/components-grid.asciidoc @@ -0,0 +1,1407 @@ +--- +title: Grid +order: 24 +layout: page +--- + +[[components.grid]] += [classname]#Grid# + +ifdef::web[] +[.sampler] +image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/grids-and-trees/grid] +endif::web[] + +((("[classname]#Grid#"))) +[classname]#Grid# is many things, and perhaps the most versatile and powerful +component in Vaadin. Like [classname]#Table#, it allows presenting and editing +tabular data, but escapes many of [classname]#Table#'s limitations. Efficient +lazy loading of data while scrolling greatly improves performance. Grid is +scalable, mobile friendly, and extensible. + +[[components.grid.overview]] +== Overview + +[classname]#Grid# is for displaying and editing tabular data laid out in rows +and columns. At the top, a __header__ can be shown, and a __footer__ at the +bottom. In addition to plain text, the header and footer can contain HTML and +components. Having components in the header allows implementing filtering +easily. The grid data can be sorted by clicking on a column header; +shift-clicking a column header enables secondary sorting criteria. + +[[figure.components.grid.features]] +.A [classname]#Grid# Component +image::img/grid-features.png[] + +The data area can be scrolled both vertically and horizontally. The leftmost +columns can be frozen, so that they are never scrolled out of the view. The data +is loaded lazily from the server, so that only the visible data is loaded. The +smart lazy loading functionality gives excellent user experience even with low +bandwidth, such as mobile devices. + +The grid data can be edited with a row-based editor after double-clicking a row. +The fields are generated with a field factory, or set explicitly, and bound to +data with a field group. + +Grid is fully themeable with CSS and style names can be set for all grid +elements. For data rows and cells, the styles can be generated with a row or +cell style generator. + +Finally, [classname]#Grid# is designed to be extensible and used just as well +for client-side development - its GWT API is nearly identical to the server-side +API, including data binding. + +[[components.grid.overview.table]] +=== Differences to Table + +In addition to core features listed above, [classname]#Grid# has the following +API-level and functional differences to Table: + +* Grid is not a [interfacename]#Container# itself, even though it can be bound to a container data source. Consequently, columns are defined differently, and so forth. +* Rows can be added with [methodname]#addRow()# shorthand (during initialization) instead of [methodname]#addItem()#. +* Use [methodname]#setHeightByRows()# and [methodname]#setHeightMode()# instead of [methodname]#setPageLength()# to set the height in number of rows. +* Grid does not extend [classname]#AbstractSelect# and is not a field, but has its own selection API. [methodname]#addSelectionListener()# is called to define a [interfacename]#SelectionListener#. The listener also receives a collection of deselected items. +* Grid does not support having all cells in editable mode, it only supports row-based editing, with a row mini-editor that allows saving or discarding the changes. +* Grid has no generated columns. Instead, the container data source can be wrapped around a [classname]#GeneratedPropertyContainer#. +* No column icons; you can implement them in a column with an [classname]#ImageRenderer#. +* Components can not be shown in Grid cells; instead the much more efficient renderers can be used for the most common cases, and row editor for editing values. +* Limited support for drag and drop: the user can drag columns to reorder them. + +In addition, Grid has the following visual changes: + +* Multiple selection is indicated with check boxes in addition to highlighting. +* Grid does not show the row loading indicator like Table does. + + + +[[components.grid.data]] +== Binding to Data + +[classname]#Grid# is normally used by binding it to a container data source, +described in +<>. The container must implement +[interfacename]#Container.Indexed# interface. By default, it is bound to an +[classname]#IndexedContainer#; Grid offers some shorthand methods to operate on +the default container, as described later. + +You can set the container in the constructor or with +[methodname]#setContainerDataSource()#. + +For example, if you have a collection of beans, you could wrap them in a Vaadin +[classname]#BeanContainer# or [classname]#BeanItemContainer#, and bind to a [classname]#Grid# as follows + + +[source, java] +---- +// Have some data +Collection people = Lists.newArrayList( + new Person("Nicolaus Copernicus", 1543), + new Person("Galileo Galilei", 1564), + new Person("Johannes Kepler", 1571)); + +// Have a container of some type to contain the data +BeanItemContainer container = + new BeanItemContainer(Person.class, people); + +// Create a grid bound to the container +Grid grid = new Grid(container); +grid.setColumnOrder("name", "born"); +layout.addComponent(grid); +---- + +Note that you need to override [methodname]#equals()# and [methodname]#hashcode()# for +the bean ([classname]#Person#) class to make the [classname]#BeanItemContainer# work properly. + +[[components.grid.basic.manual]] +=== Default Data Source and Shorthands + +Sometimes, when you have just a few fixed items that you want to display, you +can define the grid columns and add data rows manually. [classname]#Grid# is by +default bound to a [classname]#IndexedContainer#. You can define new columns +(container properties) with [methodname]#addColumn()# and then add rows (items) +with [methodname]#addRow()#. The types in the row data must match the defined +column types. + +For example: + + +[source, java] +---- +// Create a grid +Grid grid = new Grid(); + +// Define some columns +grid.addColumn("name", String.class); +grid.addColumn("born", Integer.class); + +// Add some data rows +grid.addRow("Nicolaus Copernicus", 1543); +grid.addRow("Galileo Galilei", 1564); +grid.addRow("Johannes Kepler", 1571); + +layout.addComponent(grid); +---- + +Or, if you have the data in an array: + + +[source, java] +---- +// Have some data +Object[][] people = { {"Nicolaus Copernicus", 1543}, + {"Galileo Galilei", 1564}, + {"Johannes Kepler", 1571}}; +for (Object[] person: people) + grid.addRow(person); +---- + +Note that you can not use [methodname]#addRow()# to add items if the container +is read-only or has read-only columns, such as generated columns. + + + +[[components.grid.selection]] +== Handling Selection Changes + +Selection in [classname]#Grid# is handled a bit differently from other selection +components, as it is not an [classname]#AbstractSelect#. Grid supports both +single and multiple selection, defined by the __selection mode__. Selection +events can be handled with a [interfacename]#SelectionListener#. + +[[components.grid.selection.mode]] +=== Selection Mode + +A [classname]#Grid# can be set to be in [literal]#++SINGLE++# (default), +[literal]#++MULTI++#, or [literal]#++NONE++# selection mode, defined in the +[classname]#Grid.SelectionMode# enum. + + +[source, java] +---- +// Use single-selection mode (default) +grid.setSelectionMode(SelectionMode.SINGLE); +---- + +Empty (null) selection is allowed by default, but can be disabled +with [methodname]#setDeselectAllowed()# in single-selection mode. + +The selection is handled with a different selection model object in each +respective selection mode: [classname]#SingleSelectionModel#, +[classname]#MultiSelectionModel#, and [classname]#NoSelectionModel# (in which +selection is always empty). + + +[source, java] +---- +// Pre-select an item +SingleSelectionModel selection = + (SingleSelectionModel) grid.getSelectionModel(); +selection.select( // Select 3rd item + grid.getContainerDataSource().getIdByIndex(2)); +---- + + +[[components.grid.selection.single]] +=== Handling Selection + +Changes in the selection can be handled with a +[interfacename]#SelectionListener#. You need to implement the +[methodname]#select()# method, which gets a [classname]#SelectionEvent# as +parameter. In addition to selection, you can handle clicks on rows or cells with +a [interfacename]#ItemClickListener#. + +You can get the new selection from the selection event with +[methodname]#getSelected()#, which returns a set of item IDs, or more simply +from the grid or the selection model with [methodname]#getSelectedRow()#, which +returns the single selected item ID. + +For example: + + +[source, java] +---- +grid.addSelectionListener(selectionEvent -> { // Java 8 + // Get selection from the selection model + Object selected = ((SingleSelectionModel) + grid.getSelectionModel()).getSelectedRow(); + + if (selected != null) + Notification.show("Selected " + + grid.getContainerDataSource().getItem(selected) + .getItemProperty("name")); + else + Notification.show("Nothing selected"); +}); +---- + +The current selection can be obtained from the [classname]#Grid# object by +[methodname]#getSelectedRow()# or [methodname]#getSelectedRows()#, which return +one (in single-selection mode) or all (in multi-selection mode) selected items. + + +[WARNING] +==== +Note that changes to the item set of the container data source are not +automatically reflected in the selection model and may cause the selection model +to refer to stale item IDs. This always occurs, for example, when you delete the +selected item or items. So, if you modify the item set of the container, you +should synchronize or reset the selection with the container, such as by calling +[methodname]#reset()# on the selection model. + +==== + + + + +[[components.grid.selection.multi]] +=== Multiple Selection + +In the multiple selection mode, a user can select multiple items by clicking on +the checkboxes in the leftmost column, or by using the kbd:[Space] to select/deselect the currently focused row. +Space bar is the default key for toggling the selection, but it can be customized. + +[[figure.components.grid.selection.multi]] +.Multiple Selection in [classname]#Grid# +image::img/grid-selection-multi.png[] + +The selection is managed through the [classname]#MultiSelectionMode# class. The +currently selected rows can be set with [methodname]#setSelected()# by a +collection of item IDs, or you can use [methodname]#select()# to add items to +the selection. + + +[source, java] +---- +// Grid in multi-selection mode +Grid grid = new Grid(exampleDataSource()); +grid.setSelectionMode(SelectionMode.MULTI); + +// Pre-select some items +MultiSelectionModel selection = + (MultiSelectionModel) grid.getSelectionModel(); +selection.setSelected( // Items 2-4 + grid.getContainerDataSource().getItemIds(2, 3)); + +---- + +The current selection can be read with [methodname]#getSelectedRows()#; either +in the [classname]#MultiSelectionMode# object or in the [classname]#Grid#. + + +[source, java] +---- +// Allow deleting the selected items +Button delSelected = new Button("Delete Selected", e -> { + // Delete all selected data items + for (Object itemId: selection.getSelectedRows()) + grid.getContainerDataSource().removeItem(itemId); + + // Otherwise out of sync with container + grid.getSelectionModel().reset(); + + // Disable after deleting + e.getButton().setEnabled(false); +}); +delSelected.setEnabled(grid.getSelectedRows().size() > 0); +---- + +Changes in the selection can be handled with a +[interfacename]#SelectionListener#. The selection event object provides +[methodname]#getAdded()# and [methodname]#getRemoved()# to allow determining the +differences in the selection change. + + +[source, java] +---- +// Handle selection changes +grid.addSelectionListener(selection -> { // Java 8 + Notification.show(selection.getAdded().size() + + " items added, " + + selection.getRemoved().size() + + " removed."); + + // Allow deleting only if there's any selected + deleteSelected.setEnabled( + grid.getSelectedRows().size() > 0); +}); +---- + + +[[components.grid.selection.clicks]] +=== Focus and Clicks + +In addition to selecting rows, you can focus individual cells. The focus can be +moved with arrow keys and, if editing is enabled, pressing kbd:[Enter] opens the +editor. Normally, pressing kbd:[Tab] or kbd:[Shift+Tab] moves the focus to another component, +as usual. + +When editing or in unbuffered mode, kbd:[Tab] or kbd:[Shift+Tab] moves the focus to the next or +previous cell. The focus moves from the last cell of a row forward to the +beginning of the next row, and likewise, from the first cell backward to the +end of the previous row. Note that you can extend [classname]#DefaultEditorEventHandler# +to change this behavior. + +With the mouse, you can focus a cell by clicking on it. The clicks can be handled +with an [interfacename]#ItemClickListener#. The [classname]#ItemClickEvent# +object contains various information, most importantly the ID of the clicked row +and column. + + +[source, java] +---- +grid.addItemClickListener(event -> // Java 8 + Notification.show("Value: " + + container.getContainerProperty(event.getItemId(), + event.getPropertyId()).getValue().toString())); +---- + +The clicked grid cell is also automatically focused. + +The focus indication is themed so that the focused cell has a visible focus +indicator style by default, while the row doesn't. You can enable row focus, as +well as disable cell focus, in a custom theme. See <>. + + + +[[components.grid.columns]] +== Configuring Columns + +Columns are normally defined in the container data source. The +[methodname]#addColumn()# method can be used to add columns to a container that +supports it, such as the default [classname]#IndexedContainer#. + +Column configuration is defined in [classname]#Grid.Column# objects, which can +be obtained from the grid with [methodname]#getColumn()# by the column +(property) ID. + + +[source, java] +---- +Grid.Column bornColumn = grid.getColumn("born"); +bornColumn.setHeaderCaption("Born"); +---- + +In the following, we describe the basic column configuration. + +[[components.grid.columns.order]] +=== Column Order + +You can set the order of columns with [methodname]#setColumnOrder()# for the +grid. Columns that are not given for the method are placed after the specified +columns in their natural order. + + +[source, java] +---- +grid.setColumnOrder("firstname", "lastname", "born", + "birthplace", "died"); +---- + +Note that the method can not be used to hide columns. You can hide columns with +the [methodname]#removeColumn()#, as described later, or by hiding them in a +[classname]#GeneratedPropertyContainer#. + + +[[components.grid.columns.removing]] +=== Hiding Columns + +Columns can be hidden by removing them with [methodname]#removeColumn()#. You +can remove all columns with [methodname]#removeAllColumns()#. The removed columns +are only removed from the grid, not from the container data source. + +To restore a previously removed column, you can call [methodname]#addColumn()# +with the property ID. Instead of actually adding another column to the data +source, it merely restores the previously removed one. However, column settings +such as header or editor are not restored, but must be redone. + +You can also hide columns at container-level. At least +[classname]#GeneratedpropertyContainer# allows doing so, as described in +<>. + + +[[components.grid.columns.captions]] +=== Column Captions + +Column captions are displayed in the grid header. The default captions are +generated automatically from the property ID. You can set the header caption +explicitly through the column object with [methodname]#setHeaderCaption()#. + + +[source, java] +---- +Grid.Column bornColumn = grid.getColumn("born"); +bornColumn.setHeaderCaption("Born"); +---- + +This is equivalent to setting it with [methodname]#setText()# for the header +cell; the [classname]#HeaderCell# also allows setting the caption in HTML or as +a component, as well as styling it, as described later in +<>. + + +[[components.grid.columns.width]] +=== Column Widths + +Columns have by default undefined width, which causes automatic sizing based on +the widths of the displayed data. You can set column widths explicitly by pixel +value with [methodname]#setWidth()#, or relatively using expand ratios with +[methodname]#setExpandRatio()#. + +When using expand ratios, the columns with a non-zero expand ratio use the extra +space remaining from other columns, in proportion to the defined ratios. + +You can specify minimum and maximum widths for the expanding columns with +[methodname]#setMinimumWidth()# and [methodname]#setMaximumWidth()#, +respectively. + +The user can resize columns by dragging their separators with the mouse. When resized manually, +all the columns widths are set to explicit pixel values, even if they had +relative values before. + +[[components.grid.columns.frozen]] +=== Frozen Columns + +You can set the number of columns to be frozen with +[methodname]#setFrozenColumnCount()#, so that they are not scrolled off when +scrolling horizontally. + + +[source, java] +---- +grid.setFrozenColumnCount(2); +---- + +Setting the count to [parameter]#0# disables frozen data columns; setting it to +[parameter]#-1# also disables the selection column in multi-selection mode. + + + +[[components.grid.generatedcolumns]] +== Generating Columns + +Columns with values computed from other columns or in some other way can be +generated with a container or data model that generates the property values. The +[classname]#GeneratedPropertyContainer# can be used for this purpose. It wraps +around any indexed container to extend its properties with read-only generated +properties. The generated properties can have same IDs as the original ones, +thereby replacing them with formatted or converted values. See +<> +for a detailed description of using it. + +Generated columns are read-only, so you can not add grid rows with +[methodname]#addRow()#. In editable mode, editor fields are not generated for +generated columns. + +Note that, while [classname]#GeneratedPropertyContainer# implements +[interfacename]#Container.Sortable#, the wrapped container might not, and also +sorting on the generated properties requires special handling. In such cases, +generated properties or the entire container might not actually be sortable. + + +[[components.grid.renderer]] +== Column Renderers + +A __renderer__ is a feature that draws the client-side representation of a data +value. This allows having images, HTML, and buttons in grid cells. + +[[figure.components.grid.renderer]] +.Column Renderers: Image, Date, HTML, and Button +image::img/grid-renderers.png[] + +Renderers implement the [interfacename]#Renderer# interface. You set the column +renderer in the [classname]#Grid.Column# object as follows: + + +[source, java] +---- +grid.addColumn("born", Integer.class); +... +Grid.Column bornColumn = grid.getColumn("born"); +bornColumn.setRenderer(new NumberRenderer("born in %d AD")); +---- + +Renderers require a specific data type for the column. To convert to a property +type to a type required by a renderer, you can pass an optional +[interfacename]#Converter# to [methodname]#setRenderer()#, as described later in +this section. A converter can also be used to (pre)format the property values. +The converter is run on the server-side, before sending the values to the +client-side to be rendered with the renderer. + +The following renderers are available, as defined in the server-side +[package]#com.vaadin.ui.renderers# package: + +[classname]#ButtonRenderer#:: Renders the data value as the caption of a button. A +[interfacename]#RendererClickListener# can be given to handle the button clicks. + +ifdef::web[] +Typically, a button renderer is used to display buttons for operating on a data +item, such as edit, view, delete, etc. It is not meaningful to store the button +captions in the data source, rather you want to generate them, and they are +usually all identical. + + ++ +[source, java] +---- +BeanItemContainer people = + new BeanItemContainer<>(Person.class); + +people.addBean(new Person("Nicolaus Copernicus", 1473)); +people.addBean(new Person("Galileo Galilei", 1564)); +people.addBean(new Person("Johannes Kepler", 1571)); + +// Generate button caption column +GeneratedPropertyContainer gpc = + new GeneratedPropertyContainer(people); +gpc.addGeneratedProperty("delete", + new PropertyValueGenerator() { + + @Override + public String getValue(Item item, Object itemId, + Object propertyId) { + return "Delete"; // The caption + } + + @Override + public Class getType() { + return String.class; + } +}); + +// Create a grid +Grid grid = new Grid(gpc); + +// Render a button that deletes the data row (item) +grid.getColumn("delete") + .setRenderer(new ButtonRenderer(e -> // Java 8 + grid.getContainerDataSource() + .removeItem(e.getItemId()))); +---- +endif::web[] +[classname]#ImageRenderer#:: Renders the cell as an image. The column type must be a +[interfacename]#Resource#, as described in +<>; only [classname]#ThemeResource# and +[classname]#ExternalResource# are currently supported for images in +[classname]#Grid#. + +ifdef::web[] + +[source, java] +---- +grid.addColumn("picture", Resource.class) + .setRenderer(new ImageRenderer()); +... +// Add some data rows +grid.addRow(new ThemeResource("img/copernicus-128px.jpg"), + "Nicolaus Copernicus", 1543); +grid.addRow(new ThemeResource("img/galileo-128px.jpg"), + "Galileo Galilei", 1564); +---- + ++ +Instead of creating the resource objects explicitly, as was done above, you +could generate them dynamically from file name strings using a +[interfacename]#Converter# for the column. + + ++ +[source, java] +---- +// Define some columns +grid.addColumn("picture", String.class); // Filename +grid.addColumn("name", String.class); + +// Set the image renderer +grid.getColumn("picture").setRenderer(new ImageRenderer(), + new Converter() { + @Override + public String convertToModel(Resource value, + Class targetType, Locale l) + throws Converter.ConversionException { + return "not needed"; + } + + @Override + public Resource convertToPresentation(String value, + Class targetType, Locale l) + throws Converter.ConversionException { + return new ThemeResource("img/" + value); + } + + @Override + public Class getModelType() { + return String.class; + } + + @Override + public Class getPresentationType() { + return Resource.class; + } +}); + +// Add some data rows +grid.addRow("copernicus-128px.jpg", "Nicolaus Copernicus"); +grid.addRow("galileo-128px.jpg", "Galileo Galilei"); +grid.addRow("kepler-128px.jpg", "Johannes Kepler"); +---- ++ +You also need to define the row heights so that the images fit there. You can +set it in the theme for all data cells or for the column containing the images. + ++ +For the latter way, first define a CSS style name for grid and the column: + + ++ +[source, java] +---- +grid.setStyleName("gridwithpics128px"); +grid.setCellStyleGenerator(cell -> + "picture".equals(cell.getPropertyId())? + "imagecol" : null); +---- +ifdef::web[] ++ +Then, define the style in CSS (Sass): +endif::web[] + + ++ +[source, css] +---- +.gridwithpics128px .imagecol { + height: 128px; + background: black; + text-align: center; +} +---- +endif::web[] +[classname]#DateRenderer#:: Formats a column with a [classname]#Date# type using string formatter. The +format string is same as for [methodname]#String.format()# in Java API. The date +is passed in the parameter index 1, which can be omitted if there is only one +format specifier, such as " [literal]#++%tF++#". + +ifdef::web[] + +[source, java] +---- +Grid.Column bornColumn = grid.getColumn("born"); +bornColumn.setRenderer( + new DateRenderer("%1$tB %1$te, %1$tY", + Locale.ENGLISH)); +---- + ++ +Optionally, a locale can be given. Otherwise, the default locale (in the +component tree) is used. + +endif::web[] +[classname]#HTMLRenderer#:: Renders the cell as HTML. This allows formatting cell content, as well as using +HTML features such as hyperlinks. + +ifdef::web[] +First, set the renderer in the [classname]#Grid.Column# object: + + ++ +[source, java] +---- +grid.addColumn("link", String.class) + .setRenderer(new HtmlRenderer()); +---- +ifdef::web[] ++ +Then, in the grid data, give the cell content: +endif::web[] + + ++ +[source, java] +---- +grid.addRow("Nicolaus Copernicus", 1543, + "info"); +---- ++ +You could also use a [interfacename]#PropertyFormatter# or a generated column to +generate the HTML for the links. + +endif::web[] +[classname]#NumberRenderer#:: Formats column values with a numeric type extending [classname]#Number#: +[classname]#Integer#, [classname]#Double#, etc. The format can be specified +either by the subclasses of [classname]#java.text.NumberFormat#, namely +[classname]#DecimalFormat# and [classname]#ChoiceFormat#, or by +[methodname]#String.format()#. + +ifdef::web[] +For example: + + ++ +[source, java] +---- +// Define some columns +grid.addColumn("name", String.class); +grid.addColumn("born", Integer.class); +grid.addColumn("sletters", Integer.class); +grid.addColumn("rating", Double.class); + +// Use decimal format +grid.getColumn("born").setRenderer(new NumberRenderer( + new DecimalFormat("in #### AD"))); + +// Use textual formatting on numeric ranges +grid.getColumn("sletters").setRenderer(new NumberRenderer( + new ChoiceFormat("0#none|1#one|2#multiple"))); + +// Use String.format() formatting +grid.getColumn("rating").setRenderer(new NumberRenderer( + "%02.4f", Locale.ENGLISH)); + +// Add some data rows +grid.addRow("Nicolaus Copernicus", 1473, 2, 0.4); +grid.addRow("Galileo Galilei", 1564, 0, 4.2); +grid.addRow("Johannes Kepler", 1571, 1, 2.3); +---- +endif::web[] +[classname]#ProgressBarRenderer#:: Renders a progress bar in a column with a [classname]#Double# type. The value +must be between 0.0 and 1.0. + +ifdef::web[] +For example: + + ++ +[source, java] +---- +// Define some columns +grid.addColumn("name", String.class); +grid.addColumn("rating", Double.class) + .setRenderer(new ProgressBarRenderer()); + +// Add some data rows +grid.addRow("Nicolaus Copernicus", 0.1); +grid.addRow("Galileo Galilei", 0.42); +grid.addRow("Johannes Kepler", 1.0); +---- +endif::web[] +[classname]#TextRenderer#:: Displays plain text as is. Any HTML markup is quoted. + + + +[[components.grid.renderer.custom]] +=== Custom Renderers + +Renderers are component extensions that require a client-side counterpart. See +<> +for information on implementing custom renderers. + + +[[components.grid.renderer.converter]] +=== Converting for Rendering + +Optionally, you can give a [interfacename]#Converter# in the +[methodname]#setRenderer()#, or define it for the column, to convert the data +value to an intermediary representation that is rendered by the renderer. For +example, when using an [classname]#ImageRenderer#, you could store the image file name +in the data column, which the converter would convert to a resource, which would +then be rendered by the renderer. + +In the following example, we use a converter and [classname]#HTMLRenderer# to display boolean +values as [classname]#FontAwesome# icons +[source, java] +---- +// Have a column for hyperlink paths to Wikipedia +grid.addColumn("truth", Boolean.class); +Grid.Column truth = grid.getColumn("truth"); +truth.setRenderer(new HtmlRenderer(), + new StringToBooleanConverter( + FontAwesome.CHECK_CIRCLE_O.getHtml(), + FontAwesome.CIRCLE_O.getHtml())); +... +---- + +In this example, we use a converter to format URL paths to complete +HTML hyperlinks with [classname]#HTMLRenderer#: + + +[source, java] +---- +// Have a column for hyperlink paths to Wikipedia +grid.addColumn("link", String.class); + +Grid.Column linkColumn = grid.getColumn("link"); +linkColumn.setRenderer(new HtmlRenderer(), + new Converter(){ + @Override + public String convertToModel(String value, + Class targetType, Locale locale) + throws Converter.ConversionException { + return "not implemented"; + } + + @Override + public String convertToPresentation(String value, + Class targetType, Locale locale) + throws Converter.ConversionException { + return "more info"; + } + + @Override + public Class getModelType() { + return String.class; + } + + @Override + public Class getPresentationType() { + return String.class; + } +}); + +// Data with a hyperlink path in the third column +grid.addRow("Nicolaus Copernicus", 1473, + "Nicolaus_Copernicus"); +... +---- + +A [classname]#GeneratedPropertyContainer# could be used for much the same +purpose. + + + +[[components.grid.headerfooter]] +== Header and Footer + +A grid by default has a header, which displays column names, and can have a +footer. Both can have multiple rows and neighbouring header row cells can be +joined to feature column groups. + +[[components.grid.headerfooter.adding]] +=== Adding and Removing Header and Footer Rows + +A new header row is added with [methodname]#prependHeaderRow()#, which adds it +at the top of the header, [methodname]#appendHeaderRow()#, which adds it at the +bottom of the header, or with [methodname]#addHeaderRowAt()#, which inserts it +at the specified 0-base index. All of the methods return a +[classname]#HeaderRow# object, which you can use to work on the header further. + + +[source, java] +---- +// Group headers by joining the cells +HeaderRow groupingHeader = grid.prependHeaderRow(); +... + +// Create a header row to hold column filters +HeaderRow filterRow = grid.appendHeaderRow(); +... +---- + +Similarly, you can add footer rows with [methodname]#appendFooterRow()#, +[methodname]#prependFooterRow()#, and [methodname]#addFooterRowAt()#. + + +[[components.grid.headerfooter.joining]] +=== Joining Header and Footer Cells + +You can join two or more header or footer cells with the [methodname]#join()# +method. For header cells, the intention is usually to create column grouping, +while for footer cells, you typically calculate sums or averages. + + +[source, java] +---- +// Group headers by joining the cells +HeaderRow groupingHeader = grid.prependHeaderRow(); +HeaderCell namesCell = groupingHeader.join( + groupingHeader.getCell("firstname"), + groupingHeader.getCell("lastname")).setText("Person"); +HeaderCell yearsCell = groupingHeader.join( + groupingHeader.getCell("born"), + groupingHeader.getCell("died"), + groupingHeader.getCell("lived")).setText("Dates of Life"); +---- + + +[[components.grid.headerfooter.content]] +=== Text and HTML Content + +You can set the header caption with [methodname]#setText()#, in which case any +HTML formatting characters are quoted to ensure security. + + +[source, java] +---- +HeaderRow mainHeader = grid.getDefaultHeaderRow(); +mainHeader.getCell("firstname").setText("First Name"); +mainHeader.getCell("lastname").setText("Last Name"); +mainHeader.getCell("born").setText("Born In"); +mainHeader.getCell("died").setText("Died In"); +mainHeader.getCell("lived").setText("Lived For"); +---- + +To use raw HTML in the captions, you can use [methodname]#setHtml()#. + + +[source, java] +---- +namesCell.setHtml("Names"); +yearsCell.setHtml("Years"); +---- + + +[[components.grid.headerfooter.components]] +=== Components in Header or Footer + +You can set a component in a header or footer cell with +[methodname]#setComponent()#. Often, this feature is used to allow filtering, as +described in <>, which also gives an example of the +use. + + + +[[components.grid.filtering]] +== Filtering + +The ability to include components in the grid header can be used to create +filters for the grid data. Filtering is done in the container data source, so +the container must be of type that implements +[interfacename]#Container.Filterable#. + +[[figure.components.grid.filtering]] +.Filtering Grid +image::img/grid-filtering.png[] + +The filtering illustrated in <> can be created +as follows: + + +[source, java] +---- +// Have a filterable container +IndexedContainer container = exampleDataSource(); + +// Create a grid bound to it +Grid grid = new Grid(container); +grid.setSelectionMode(SelectionMode.NONE); +grid.setWidth("500px"); +grid.setHeight("300px"); + +// Create a header row to hold column filters +HeaderRow filterRow = grid.appendHeaderRow(); + +// Set up a filter for all columns +for (Object pid: grid.getContainerDataSource() + .getContainerPropertyIds()) { + HeaderCell cell = filterRow.getCell(pid); + + // Have an input field to use for filter + TextField filterField = new TextField(); + filterField.setColumns(8); + + // Update filter When the filter input is changed + filterField.addTextChangeListener(change -> { + // Can't modify filters so need to replace + container.removeContainerFilters(pid); + + // (Re)create the filter if necessary + if (! change.getText().isEmpty()) + container.addContainerFilter( + new SimpleStringFilter(pid, + change.getText(), true, false)); + }); + cell.setComponent(filterField); +} +---- + + +[[components.grid.sorting]] +== Sorting + +A user can sort the data in a grid on a column by clicking the column header. +Clicking another time on the current sort column reverses the sort direction. +Clicking on other column headers while keeping the Shift key pressed adds a +secondary or more sort criteria. + +[[figure.components.grid.sorting]] +.Sorting Grid on Multiple Columns +image::img/grid-sorting.png[] + +Defining sort criteria programmatically can be done with the various +alternatives of the [methodname]#sort()# method. You can sort on a specific +column with [methodname]#sort(Object propertyId)#, which defaults to ascending +sorting order, or [methodname]#sort(Object propertyId, SortDirection +direction)#, which allows specifying the sort direction. + + +[source, java] +---- +grid.sort("name", SortDirection.DESCENDING); +---- + +To sort on multiple columns, you need to use the fluid sort API with +[methodname]#sort(Sort)#, which allows chaining sorting rules. Sorting rules are +created with the static [methodname]#by()# method, which defines the primary +sort column, and [methodname]#then()#, which can be used to specify any +secondary sort columns. They default to ascending sort order, but the sort +direction can be given with an optional parameter. + + +[source, java] +---- +// Sort first by city and then by name +grid.sort(Sort.by("city", SortDirection.ASCENDING) + .then("name", SortDirection.DESCENDING)); +---- + +The container data source must support sorting. At least, it must implement +[interfacename]#Container.Sortable#. Note that when using +[classname]#GeneratedPropertyContainer#, as described in +<>, even though the container implements the +interface, the wrapped container must also support it. Also, the generated +properties are not normally sortable, but require special handling to enable +sorting. + + +[[components.grid.editing]] +== Editing + +Grid supports line-based editing, where double-clicking a row opens the row +editor. In the editor, the input fields can be edited, as well as navigated with +kbd:[Tab] and kbd:[Shift+Tab] keys. If validation fails, an error is displayed and the user +can correct the inputs. + +To enable editing, you need to call [methodname]#setEditorEnabled(true)# for the +grid. + + +[source, java] +---- +Grid grid = new Grid(GridExample.exampleDataSource()); +grid.setEditorEnabled(true); +---- + +Grid supports two row editor modes - buffered and unbuffered. The default mode is +buffered. The mode can be changed with [methodname]#setBuffered(false)# + +[[components.grid.editing.buffered]] +=== Buffered Mode + +The editor has a [guibutton]#Save# button that commits +the data item to the container data source and closes the editor. The +[guibutton]#Cancel# button discards the changes and exits the editor. + +A row under editing is illustrated in <>. + +[[figure.components.grid.editing]] +.Editing a Grid Row +image::img/grid-editor-basic.png[] + +[[components.grid.editing.unbuffered]] +=== Unbuffered Mode + +The editor has no buttons and all changed data is committed directly +to the container. If another row is clicked, the editor for the current row is closed and +a row editor for the clicked row is opened. + +[[components.grid.editing.fields]] +=== Editor Fields + +The editor fields are by default generated with a [interfacename]#FieldFactory# +and bound to the container data source with a [classname]#FieldGroup#, which +also handles tasks such as validation, as explained later. + +To disable editing in a particular column, you can call +[methodname]#setEditable()# in the [classname]#Column# object with +[parameter]#false# parameter. + +[[components.grid.editing.editorfields]] +=== Customizing Editor Fields + +The editor fields are normally created by the field factory of the editor's field +group, which creates the fields according to the data types of their respective +columns. To customize the editor fields of specific properties, such as to style +them or to set up validation, you can provide them with +[methodname]#setEditorField()# in the respective columns. + +In the following example, we configure a field with validation and styling: + + +[source, java] +---- +TextField nameEditor = new TextField(); + +// Custom CSS style +nameEditor.addStyleName("nameeditor"); + +// Custom validation +nameEditor.addValidator(new RegexpValidator( + "^\\p{Alpha}+ \\p{Alpha}+$", + "Need first and last name")); + +grid.getColumn("name").setEditorField(nameEditor); +---- + +Setting an editor field to [parameter]#null# deletes the currently existing +editor field, whether it was automatically generated or set explicitly with the +setter. It will be regenerated with the factory the next time it is needed. + + +ifdef::web[] +[[components.grid.editing.captions]] +=== Customizing Editor Buttons + +In the buffered mode, the editor has two buttons: [guibutton]#Save# and [guibutton]#Cancel#. You can +set their captions with [methodname]#setEditorSaveCaption()# and +[methodname]#setEditorCancelCaption()#, respectively. + +In the following example, we demonstrate one way to translate the captions: + + +[source, java] +---- +// Captions are stored in a resource bundle +ResourceBundle bundle = ResourceBundle.getBundle( + MyAppCaptions.class.getName(), + Locale.forLanguageTag("fi")); // Finnish + +// Localize the editor button captions +grid.setEditorSaveCaption( + bundle.getString(MyAppCaptions.SaveKey)); +grid.setEditorCancelCaption( + bundle.getString(MyAppCaptions.CancelKey)); +---- + +endif::web[] + +[[components.grid.editing.fieldgroup]] +=== Binding to Data with a Field Group + +Data binding to the item under editing is handled with a +[classname]#FieldGroup#, which you need to set with +[methodname]#setEditorFieldGroup#. This is mostly useful when using +special-purpose field groups, such as [classname]#BeanFieldGroup# to enable bean +validation. + +For example, assuming that we want to enable bean validation for a bean such as +the following: + + +[source, java] +---- +public class Person implements Serializable { + @NotNull + @Size(min=2, max=10) + private String name; + + @Min(1) + @Max(130) + private int age; + ...] +---- + +We can now use a [classname]#BeanFieldGroup# in the [classname]#Grid# as +follows: + + +[source, java] +---- +Grid grid = new Grid(exampleBeanDataSource()); +grid.setColumnOrder("name", "age"); +grid.setEditorEnabled(true); + +// Enable bean validation for the data +grid.setEditorFieldGroup( + new BeanFieldGroup(Person.class)); + +// Have some extra validation in a field +TextField nameEditor = new TextField(); +nameEditor.addValidator(new RegexpValidator( + "^\\p{Alpha}+ \\p{Alpha}+$", + "Need first and last name")); +grid.setEditorField("name", nameEditor); +---- + +To use bean validation as in the example above, you need to include an +implementation of the Bean Validation API in the classpath, as described in +<>. + + +ifdef::web[] +[[components.grid.editing.validation]] +=== Handling Validation Errors + +The input fields are validated when the value is updated. The default +error handler displays error indicators in the invalid fields, as well as the +first error in the editor. + +[[figure.components.grid.errors]] +.Editing a Grid Row +image::img/grid-editor-errors.png[] + +You can modify the error handling by implementing a custom +[interfacename]#EditorErrorHandler# or by extending the +[classname]#DefaultEditorErrorHandler#. + +endif::web[] + +[[components.grid.editing.fieldfactory]] +=== Editor Field Factory + +The fields are generated by the [classname]#FieldFactory# of the field group; +you can also set it with [methodname]#setEditorFieldFactory()#. Alternatively, +you can create the editor fields explicitly with [methodname]#setEditorField()#. + +[[components.grid.scrolling]] +== Programmatic Scrolling + +You can scroll to first item with [methodname]#scrollToStart()#, to end with +[methodname]#scrollToEnd()#, or to a specific row with [methodname]#scrollTo()#. + + +[[components.grid.stylegeneration]] +== Generating Row or Cell Styles + +You can style entire rows with a [interfacename]#RowStyleGenerator# or +individual cells with a [interfacename]#CellStyleGenerator#. + +[[components.grid.stylegeneration.row]] +=== Generating Row Styles + +You set a [interfacename]#RowStyleGenerator# to a grid with +[methodname]#setRowStyleGenerator()#. The [methodname]#getStyle()# method gets a +[classname]#RowReference#, which contains various information about the row and +a reference to the grid, and should return a style name or [parameter]#null# if +no style is generated. + +For example, to add a style names to rows having certain values in one column, +you can style them as follows: + + +[source, java] +---- +grid.setRowStyleGenerator(rowRef -> {// Java 8 + if (! ((Boolean) rowRef.getItem() + .getItemProperty("alive") + .getValue()).booleanValue()) + return "grayed"; + else + return null; +}); +---- + +You could then style the rows with CSS as follows: + + +[source, css] +---- +.v-grid-row.grayed { + color: gray; +} +---- + + +[[components.grid.stylegeneration.cell]] +=== Generating Cell Styles + +You set a [interfacename]#CellStyleGenerator# to a grid with +[methodname]#setCellStyleGenerator()#. The [methodname]#getStyle()# method gets +a [classname]#CellReference#, which contains various information about the cell +and a reference to the grid, and should return a style name or [parameter]#null# +if no style is generated. + +For example, to add a style name to a specific column, you can match on the +property ID of the column as follows: + + +[source, java] +---- +grid.setCellStyleGenerator(cellRef -> // Java 8 + "born".equals(cellRef.getPropertyId())? + "rightalign" : null); +---- + +You could then style the cells with a CSS rule as follows: + + +[source, css] +---- +.v-grid-cell.rightalign { + text-align: right; +} +---- + + + +[[components.grid.css]] +== Styling with CSS + + +[source, css] +---- +.v-grid { + .v-grid-scroller, .v-grid-scroller-horizontal { } + .v-grid-tablewrapper { + .v-grid-header { + .v-grid-row { + .v-grid-cell, .frozen, .v-grid-cell-focused { } + } + } + .v-grid-body { + .v-grid-row, + .v-grid-row-stripe, + .v-grid-row-has-data { + .v-grid-cell, .frozen, .v-grid-cell-focused { } + } + } + .v-grid-footer { + .v-grid-row { + .v-grid-cell, .frozen, .v-grid-cell-focused { } + } + } + } + .v-grid-header-deco { } + .v-grid-footer-deco { } + .v-grid-horizontal-scrollbar-deco { } + .v-grid-editor { + .v-grid-editor-cells { } + .v-grid-editor-footer { + .v-grid-editor-message { } + .v-grid-editor-buttons { + .v-grid-editor-save { } + .v-grid-editor-cancel { } + } + } + } +} +---- + +A [classname]#Grid# has an overall [literal]#++v-grid++# style. The actual grid +has three parts: a header, a body, and a footer. The scrollbar is a custom +element with [literal]#++v-grid-scroller++# style. In addition, there are some +decoration elements. + +Grid cells, whether thay are in the header, body, or footer, have a basic +[literal]#++v-grid-cell++# style. Cells in a frozen column additionally have a +[literal]#++frozen++# style. Rows have [literal]#++v-grid-row++# style, and +every other row has additionally a [literal]#++v-grid-row-stripe++# style. + +The focused row has additionally [literal]#++v-grid-row-focused++# style and +focused cell [literal]#++v-grid-cell-focused++#. By default, cell focus is +visible, with the border stylable with [parameter]#$v-grid-cell-focused-border# +parameter in Sass. Row focus has no visible styling, but can be made visible +with the [parameter]#$v-grid-row-focused-background-color# parameter or with a +custom style rule. + +In editing mode, a [literal]#++v-grid-editor++# overlay is placed on the row +under editing. In addition to the editor field cells, it has an error message +element, as well as the buttons. + + +((())) + + diff --git a/documentation/components/components-interfaces.asciidoc b/documentation/components/components-interfaces.asciidoc new file mode 100644 index 0000000000..4801ec52b1 --- /dev/null +++ b/documentation/components/components-interfaces.asciidoc @@ -0,0 +1,117 @@ +--- +title: Interfaces and Abstractions +order: 2 +layout: page +--- + +[[components.interfaces]] += Interfaces and Abstractions + +((("interfaces"))) +Vaadin user interface components are built on a skeleton of interfaces and +abstract classes that define and implement the features common to all components +and the basic logic how the component states are serialized between the server +and the client. + +This section gives details on the basic component interfaces and abstractions. +The layout and other component container abstractions are described in +<>. The interfaces that define the Vaadin data model are described in +<>. + +[[figure.components.interfaces]] +.Component Interfaces and Abstractions +image::img/component-abstractions-hi.png[] + +((("[classname]#Paintable#"))) +((("[classname]#VariableOwner#"))) +All components also implement the [classname]#Paintable# interface, which is +used for serializing ("painting") the components to the client, and the reverse +[classname]#VariableOwner# interface, which is needed for deserializing +component state or user interaction from the client. + +((("[classname]#Serializable#"))) +In addition to the interfaces defined within the Vaadin framework, all +components implement the [classname]#java.io.Serializable# interface to allow +serialization. Serialization is needed in many clustering and cloud computing +solutions. + +[[components.interfaces.component]] +== [classname]#Component# Interface + +((("[interfacename]#Component# interface"))) +The [interfacename]#Component# interface is paired with the +[classname]#AbstractComponent# class, which implements all the methods defined +in the interface. + +=== Component Tree Management + +Components are laid out in the user interface hierarchically. The layout is +managed by layout components, or more generally components that implement the +[classname]#ComponentContainer# interface. Such a container is the parent of the +contained components. + +The [methodname]#getParent()# method allows retrieving the parent component of a +component. While there is a [methodname]#setParent()#, you rarely need it as you +usually add components with the [methodname]#addComponent()# method of the +[classname]#ComponentContainer# interface, which automatically sets the parent. + +A component does not know its parent when the component is still being created, +so you can not refer to the parent in the constructor with +[methodname]#getParent()#. + +Attaching a component to an UI triggers a call to its [methodname]#attach()# +method. Correspondingly, removing a component from a container triggers calling +the [methodname]#detach()# method. If the parent of an added component is +already connected to the UI, the [methodname]#attach()# is called immediately +from [methodname]#setParent()#. + + +[source, java] +---- +public class AttachExample extends CustomComponent { + public AttachExample() { + } + + @Override + public void attach() { + super.attach(); // Must call. + + // Now we know who ultimately owns us. + ClassResource r = new ClassResource("smiley.jpg"); + Image image = new Image("Image:", r); + setCompositionRoot(image); + } +} +---- + +The attachment logic is implemented in [classname]#AbstractComponent#, as +described in <>. + + +((("[classname]#Component# interface"))) + +[[components.interfaces.abstractcomponent]] +== [classname]#AbstractComponent# + +((("[classname]#AbstractComponent#", id="term.components.interfaces.abstractcomponent", range="startofrange"))) + + +[classname]#AbstractComponent# is the base class for all user interface +components. It is the (only) implementation of the [classname]#Component# +interface, implementing all the methods defined in the interface. + +[classname]#AbstractComponent# has a single abstract method, +[methodname]#getTag()#, which returns the serialization identifier of a +particular component class. It needs to be implemented when (and only when) +creating entirely new components. [classname]#AbstractComponent# manages much of +the serialization of component states between the client and the server. +Creation of new components and serialization is described in +<>. + +(((range="endofrange", startref="term.components.interfaces.abstractcomponent"))) + + + diff --git a/documentation/components/components-label.asciidoc b/documentation/components/components-label.asciidoc new file mode 100644 index 0000000000..115de5b376 --- /dev/null +++ b/documentation/components/components-label.asciidoc @@ -0,0 +1,311 @@ +--- +title: Label +order: 7 +layout: page +--- + +[[components.label]] += [classname]#Label# + +ifdef::web[] +[.sampler] +image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/data-presentation/label] +endif::web[] + +[classname]#Label# component displays non-editable text. This text can be used +for short simple labels or for displaying long text, such as paragraphs. The +text can be formatted in HTML or as preformatted text, depending on the +__content mode__ of the label. + +You can give the label text most conviniently in the constructor, as is done in +the following. Label has 100% default width, so the containing layout must also +have defined width. + + +[source, java] +---- +// A container that is 100% wide by default +VerticalLayout layout = new VerticalLayout(); + +Label label = new Label("Labeling can be dangerous"); +layout.addComponent(label); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.label.basic[on-line example, window="_blank"]. + +[classname]#Label# implements the [interfacename]#Property# interface to allow +accessing the text value, so you can get and set the text with +[methodname]#getValue()# and [methodname]#setValue()#. + + +[source, java] +---- +// Get the label's text to initialize a field +TextField editor = new TextField(null, // No caption + label.getValue()); + +// Change the label's text +editor.addValueChangeListener(event -> // Java 8 + label.setValue(editor.getValue())); +editor.setImmediate(true); // Send on Enter +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.label.basic[on-line example, window="_blank"]. + +Label also supports data binding to a property data source, as described later +in <>. However, in that case the value can not be +set through the label, as [classname]#Label# is not a +[interfacename]#Property.Editor# and is not allowed to write to a bound +property. + +Even though [classname]#Label# is text and is often used as a caption, it is a +normal component and therefore also has a caption that you can set with +[methodname]#setCaption()#. As with most other components, the caption is +managed by the containing layout. + +[[components.label.wrap]] +== Text Width and Wrapping + +[classname]#Label# has 100% default width, so the containing layout must also +have a defined width. If the width of the label's text exceeds the width of the +label, the text will wrap around and continue on the next line. Some layout +components have undefined width by default, such as +[classname]#HorizontalLayout#, so you need to pay special care with them. + + +[source, java] +---- +// A container with a defined width. +Panel panel = new Panel("Panel Containing a Label"); +panel.setWidth("300px"); + +panel.setContent( + new Label("This is a Label inside a Panel. There is " + + "enough text in the label to make the text " + + "wrap when it exceeds the width of the panel.")); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.label.wrap[on-line example, window="_blank"]. + +As the size of the [classname]#Panel# in the above example is fixed and the +width of [classname]#Label# is the default 100%, the text in the +[classname]#Label# will wrap to fit the panel, as shown in +<>. + +[[figure.components.label]] +.The Label Component +image::img/label-example1.png[] + +Setting [classname]#Label# to undefined width will cause it to not wrap at the +end of the line, as the width of the content defines the width. If placed inside +a layout with defined width, the [classname]#Label# will overflow the layout +horizontally and, normally, be truncated. + + +[[components.label.content-mode]] +== Content Mode + +The content of a label is formatted depending on a __content mode__. By default, +the text is assumed to be plain text and any contained XML-specific characters +will be quoted appropriately to allow rendering the contents of a label in HTML +in a web browser. The content mode can be set in the constructor or with +[methodname]#setContentMode()#, and can have the values defined in the +[classname]#ContentMode# enumeration type in +[package]#com.vaadin.shared.ui.label# package: + +TEXT:: The default content mode where the label contains only plain text. All +characters are allowed, including the special [literal]#++<++#, +[literal]#++>++#, and [literal]#++&++# characters in XML or HTML, which are +quoted properly in HTML while rendering the component. This is the default mode. + +PREFORMATTED:: Content mode where the label contains preformatted text. It will be, by default, +rendered with a fixed-width typewriter font. Preformatted text can contain line +breaks, written in Java with the [literal]#++\n++# escape sequence for a newline +character (ASCII 0x0a), or tabulator characters written with [literal]#++\t++# +(ASCII 0x09). + +HTML:: Content mode where the label contains HTML. + ++ +Please note the following security and validity warnings regarding the HTML +content mode. + + + + +[WARNING] +.Cross-Site Scripting Warning +==== +Having [classname]#Label# in HTML content mode allows pure HTML content. If the +content comes from user input, you should always carefully sanitize it to +prevent cross-site scripting (XSS) attacks. Please see +<>. + +Also, the validity of the HTML content is not checked when rendering the +component and any errors can result in an error in the browser. If the content +comes from an uncertain source, you should always validate it before displaying +it in the component. + +==== + + + +The following example demonstrates the use of [classname]#Label# in different +modes. + + +[source, java] +---- +Label textLabel = new Label( + "Text where formatting characters, such as \\n, " + + "and HTML, such as here, are quoted.", + ContentMode.TEXT); + +Label preLabel = new Label( + "Preformatted text is shown in an HTML
 tag.\n" +
+    "Formatting such as\n" +
+    "  * newlines\n" + 
+    "  * whitespace\n" +
+    "and such are preserved. HTML tags, \n"+
+    "such as bold, are quoted.",
+    ContentMode.PREFORMATTED);
+
+Label htmlLabel = new Label(
+    "In HTML mode, all HTML formatting tags, such as \n" +
+    "
    "+ + "
  • bold
  • "+ + "
  • itemized lists
  • "+ + "
  • etc.
  • "+ + "
"+ + "are preserved.", + ContentMode.HTML); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.label.content-modes.contentmodes[on-line example, window="_blank"]. + +The rendering will look as shown in <>. + +[[figure.components.label.content-mode]] +.Label Content Modes +image::img/label-modes.png[] + + +ifdef::web[] +[[components.label.spacing]] +== Spacing with a [classname]#Label# + +You can use a [classname]#Label# to create vertical or horizontal space in a +layout. If you need a empty "line" in a vertical layout, having just a label +with empty text is not enough, as it will collapse to zero height. The same goes +for a label with only whitespace as the label text. You need to use a +non-breaking space character, either [literal]#++ ++# or +[literal]#++ ++#: + + +[source, java] +---- +layout.addComponent(new Label(" ", ContentMode.HTML)); +---- + +Using the [parameter]#ContentMode.PREFORMATTED# mode has the same effect; +preformatted spaces do not collapse in a vertical layout. In a +[classname]#HorizontalLayout#, the width of a space character may be +unpredictable if the label font is proportional, so you can use the preformatted +mode to add em-width wide spaces. + +If you want a gap that has adjustable width or height, you can use an empty +label if you specify a height or width for it. For example, to create vertical +space in a [classname]#VerticalLayout#: + + +[source, java] +---- +Label gap = new Label(); +gap.setHeight("1em"); +verticalLayout.addComponent(gap); +---- + +You can make a flexible expanding spacer by having a relatively sized empty +label with [literal]#++100%++# height or width and setting the label as +expanding in the layout. + + +[source, java] +---- +// A wide component bar +HorizontalLayout horizontal = new HorizontalLayout(); +horizontal.setWidth("100%"); + +// Have a component before the gap (a collapsing cell) +Button button1 = new Button("I'm on the left"); +horizontal.addComponent(button1); + +// An expanding gap spacer +Label expandingGap = new Label(); +expandingGap.setWidth("100%"); +horizontal.addComponent(expandingGap); +horizontal.setExpandRatio(expandingGap, 1.0f); + +// A component after the gap (a collapsing cell) +Button button2 = new Button("I'm on the right"); +horizontal.addComponent(button2); +---- + +endif::web[] + +[[components.label.databinding]] +== Data Binding + +While [classname]#Label# is not a field component, it is a +[interfacename]#Property.Viewer# and can be bound to a property data source, +described in +<>. +You can specify the data source either in the constructor or by the +[methodname]#setPropertyDataSource()# method. + + +[source, java] +---- +// Some property +ObjectProperty property = + new ObjectProperty("some value"); + +// Label that is bound to the property +Label label = new Label(property); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.label.binding[on-line example, window="_blank"]. + +Further, as [classname]#Label# is a [interfacename]#Property#, you can edit its +value with a property editor, such as a field: + + +[source, java] +---- +Label label = new Label("some value"); +TextField editor = new TextField(); +editor.setPropertyDataSource(label); +editor.setImmediate(true); +---- +See the http://demo.vaadin.com/book-examples-vaadin7/book#component.label.delegation[on-line example, window="_blank"]. + +However, [classname]#Label# is __not__ a [interfacename]#Property.Editor#, so it +is read-only when bound to a data source. Therefore, you can not use +[methodname]#setValue()# to set the value of a connected data source through a +[classname]#Label# nor bind the label to an editor field, in which case writes +would be delegated through the label. + + +[[components.label.css]] +== CSS Style Rules + + +[source, css] +---- +.v-label { } + pre { } /* In PREFORMATTED content mode */ +---- + +The [classname]#Label# component has a [literal]#++v-label++# overall style. In +the [parameter]#PREFORMATTED# content mode, the text is wrapped inside a +[literal]#++
++# element.
+
+
+
+
diff --git a/documentation/components/components-link.asciidoc b/documentation/components/components-link.asciidoc
new file mode 100644
index 0000000000..b2da97a39f
--- /dev/null
+++ b/documentation/components/components-link.asciidoc
@@ -0,0 +1,161 @@
+---
+title: Link
+order: 8
+layout: page
+---
+
+[[components.link]]
+= [classname]#Link#
+
+ifdef::web[]
+[.sampler]
+image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/interaction/link]
+endif::web[]
+
+The [classname]#Link# component allows making hyperlinks. References to
+locations are represented as resource objects, explained in
+<>. The [classname]#Link# is a regular HTML hyperlink, that
+is, an [literal]#++++# anchor element that is handled natively by the
+browser. Unlike when clicking a [classname]#Button#, clicking a
+[classname]#Link# does not cause an event on the server-side.
+
+Links to an arbitrary URL can be made by using an [classname]#ExternalResource#
+as follows:
+
+
+[source, java]
+----
+// Textual link
+Link link = new Link("Click Me!",
+        new ExternalResource("http://vaadin.com/"));
+----
+See the http://demo.vaadin.com/book-examples-vaadin7/book#component.link.basic[on-line example, window="_blank"].
+
+You can use [methodname]#setIcon()# to make image links as follows:
+
+
+[source, java]
+----
+// Image link
+Link iconic = new Link(null,
+        new ExternalResource("http://vaadin.com/"));
+iconic.setIcon(new ThemeResource("img/nicubunu_Chain.png"));
+
+// Image + caption
+Link combo = new Link("To appease both literal and visual",
+        new ExternalResource("http://vaadin.com/"));
+combo.setIcon(new ThemeResource("img/nicubunu_Chain.png"));
+----
+See the http://demo.vaadin.com/book-examples-vaadin7/book#component.link.basic[on-line example, window="_blank"].
+
+The resulting links are shown in <>. You could add
+a " [literal]#++display: block++#" style for the icon element to place the
+caption below it.
+
+[[figure.components.link.basic]]
+.[classname]#Link# Example
+image::img/link.png[]
+
+With the simple constructor used in the above example, the resource is opened in
+the current window. Using the constructor that takes the target window as a
+parameter, or by setting the target window with [methodname]#setTargetName()#,
+you can open the resource in another window, such as a popup browser window/tab.
+As the target name is an HTML [literal]#++target++# string managed by the
+browser, the target can be any window, including windows not managed by the
+application itself. You can use the special underscored target names, such as
+[literal]#++_blank++# to open the link to a new browser window or tab.
+
+
+[source, java]
+----
+// Hyperlink to a given URL
+Link link = new Link("Take me a away to a faraway land",
+        new ExternalResource("http://vaadin.com/"));
+
+// Open the URL in a new window/tab
+link.setTargetName("_blank");
+        
+// Indicate visually that it opens in a new window/tab
+link.setIcon(new ThemeResource("icons/external-link.png"));
+link.addStyleName("icon-after-caption");
+----
+See the http://demo.vaadin.com/book-examples-vaadin7/book#component.link.target[on-line example, window="_blank"].
+
+Normally, the link icon is before the caption. You can have it right of the
+caption by reversing the text direction in the containing element.
+
+
+[source, css]
+----
+/* Position icon right of the link caption. */
+.icon-after-caption {
+    direction: rtl;
+}
+/* Add some padding around the icon. */
+.icon-after-caption .v-icon {
+    padding: 0 3px;
+}
+----
+See the http://demo.vaadin.com/book-examples-vaadin7/book#component.link.target[on-line example, window="_blank"].
+
+The resulting link is shown in <>.
+
+[[figure.components.link.new-window]]
+.Link That Opens a New Window
+image::img/link-new.png[]
+
+With the [literal]#++_blank++# target, a normal new browser window is opened. If
+you wish to open it in a popup window (or tab), you need to give a size for the
+window with [methodname]#setTargetWidth()# and [methodname]#setTargetHeight()#.
+You can control the window border style with [methodname]#setTargetBorder()#,
+which takes any of the defined border styles [parameter]#TARGET_BORDER_DEFAULT#,
+[parameter]#TARGET_BORDER_MINIMAL#, and [parameter]#TARGET_BORDER_NONE#. The
+exact result depends on the browser.
+
+
+[source, java]
+----
+// Open the URL in a popup
+link.setTargetName("_blank");
+link.setTargetBorder(Link.TARGET_BORDER_NONE);
+link.setTargetHeight(300);
+link.setTargetWidth(400);
+----
+See the http://demo.vaadin.com/book-examples-vaadin7/book#component.link.target[on-line example, window="_blank"].
+
+In addition to the [classname]#Link# component, Vaadin allows alternative ways
+to make hyperlinks. The [classname]#Button# component has a
+[parameter]#Reindeer.BUTTON_LINK# style name that makes it look like a
+hyperlink, while handling clicks in a server-side click listener instead of in
+the browser. Also, you can make hyperlinks (or any other HTML) in a
+[classname]#Label# in HTML content mode.
+
+== CSS Style Rules
+
+
+[source, css]
+----
+.v-link { }
+  a { }
+    .v-icon {}
+    span {}
+----
+
+The overall style for the [classname]#Link# component is [literal]#++v-link++#.
+The root element contains the [literal]#++++# hyperlink anchor. Inside
+the anchor are the icon, with [literal]#++v-icon++# style, and the caption in a
+text span.
+
+Hyperlink anchors have a number of __pseudo-classes__ that are active at
+different times. An unvisited link has [literal]#++a:link++# class and a visited
+link [literal]#++a:visited++#. When the mouse pointer hovers over the link, it
+will have a:hover, and when the mouse button is being pressed over the link, the
+[literal]#++a:active++# class. When combining the pseudo-classes in a selector,
+please notice that [literal]#++a:hover++# must come after an
+[literal]#++a:link++# and [literal]#++a:visited++#, and [literal]#++a:active++#
+after the [literal]#++a:hover++#.
+
+
+
+
diff --git a/documentation/components/components-listselect.asciidoc b/documentation/components/components-listselect.asciidoc
new file mode 100644
index 0000000000..24f1bebc03
--- /dev/null
+++ b/documentation/components/components-listselect.asciidoc
@@ -0,0 +1,62 @@
+---
+title: ListSelect
+order: 17
+layout: page
+---
+
+[[components.listselect]]
+= [classname]#ListSelect#
+
+ifdef::web[]
+[.sampler]
+image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/data-input/multiple-value/list-select]
+endif::web[]
+
+The [classname]#ListSelect# component is list box that shows the selectable
+items in a vertical list. If the number of items exceeds the height of the
+component, a scrollbar is shown. The component allows both single and multiple
+selection modes, which you can set with [methodname]#setMultiSelect()#. It is
+visually identical in both modes.
+
+
+[source, java]
+----
+// Create the selection component
+ListSelect select = new ListSelect("The List");
+        
+// Add some items (here by the item ID as the caption)
+select.addItems("Mercury", "Venus", "Earth", ...);
+
+select.setNullSelectionAllowed(false);
+
+// Show 5 items and a scrollbar if there are more
+select.setRows(5);
+----
+
+The number of visible items is set with [methodname]#setRows()#.
+
+[[figure.components.listselect.basic]]
+.The [classname]#ListSelect# Component
+image::img/listselect-basic.png[]
+
+Common selection component features are described in
+<>.
+
+== CSS Style Rules
+
+
+[source, css]
+----
+.v-select {}
+  .v-select-select {}
+    option {}
+----
+
+The component has an overall [literal]#++v-select++# style. The native
+[literal]#++++# element.
+
+
+[source, java]
+----
+// Create the selection component
+NativeSelect select = new NativeSelect("Native Selection");
+        
+// Add some items
+select.addItems("Mercury", "Venus", ...);
+----
+
+The [methodname]#setColumns()# allows setting the width of the list as
+"columns", which is a measure that depends on the browser.
+
+[[figure.components.nativeselect.basic]]
+.The [classname]#NativeSelect# Component
+image::img/nativeselect-basic.png[]
+
+Common selection component features are described in
+<>.
+
+== CSS Style Rules
+
+
+[source, css]
+----
+.v-select {}
+  .v-select-select {}
+----
+
+The component has a [literal]#++v-select++# overall style. The native
+[literal]#++select++# element has [literal]#++v-select-select++# style.
+
+
+
+
diff --git a/documentation/components/components-optiongroup.asciidoc b/documentation/components/components-optiongroup.asciidoc
new file mode 100644
index 0000000000..8c4c0e2963
--- /dev/null
+++ b/documentation/components/components-optiongroup.asciidoc
@@ -0,0 +1,146 @@
+---
+title: OptionGroup
+order: 19
+layout: page
+---
+
+[[components.optiongroup]]
+= [classname]#OptionGroup#
+
+ifdef::web[]
+[.sampler]
+image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/data-input/multiple-value/option-group]
+endif::web[]
+
+[classname]#OptionGroup# is a selection component that allows selection from a
+group of radio buttons in single selection mode. In multiple selection mode, the
+items show up as check boxes. The common selection component features are
+described in
+<>.
+
+[[figure.components.optiongroup]]
+.Option Button Group in Single and Multiple Selection Mode
+image::img/optiongroup-basic.png[]
+
+Option group is by default in single selection mode. Multiple selection is
+enabled with [methodname]#setMultiSelect()#.
+
+
+[source, java]
+----
+// A single-select radio button group
+OptionGroup single = new OptionGroup("Single Selection");
+single.addItems("Single", "Sola", "Yksi");
+
+// A multi-select check box group
+OptionGroup multi = new OptionGroup("Multiple Selection");
+multi.setMultiSelect(true);
+multi.addItems("Many", "Muchos", "Monta");
+----
+
+<> shows the [classname]#OptionGroup# in both
+single and multiple selection mode.
+
+You can also create check boxes individually using the [classname]#CheckBox#
+class, as described in
+<>.
+The advantages of the [classname]#OptionGroup# component are that as it
+maintains the individual check box objects, you can get an array of the
+currently selected items easily, and that you can easily change the appearance
+of a single component.
+
+[[components.optiongroup.disabling]]
+== Disabling Items
+
+You can disable individual items in an [classname]#OptionGroup# with
+[methodname]#setItemEnabled()#. The user can not select or deselect disabled
+items in multi-select mode, but in single-select mode the use can change the
+selection from a disabled to an enabled item. The selections can be changed
+programmatically regardless of whether an item is enabled or disabled. You can
+find out whether an item is enabled with [methodname]#isItemEnabled()#.
+
+The [methodname]#setItemEnabled()# identifies the item to be disabled by its
+item ID.
+
+
+[source, java]
+----
+// Have an option group with some items
+OptionGroup group = new OptionGroup("My Disabled Group");
+group.addItems("One", "Two", "Three");
+
+// Disable one item by its item ID
+group.setItemEnabled("Two", false);
+----
+
+The item IDs are also used for the captions in this example. The result is shown
+in <>.
+
+[[figure.components.optiongroup.disabling]]
+.[classname]#OptionGroup# with a Disabled Item
+image::img/optiongroup-disabling.png[]
+
+Setting an item as disabled turns on the [literal]#++v-disabled++# style for it.
+
+
+[[components.optiongroup.css]]
+== CSS Style Rules
+
+
+[source, css]
+----
+.v-select-optiongroup {}
+  .v-select-option.v-checkbox {}
+  .v-select-option.v-radiobutton {}
+----
+
+The [literal]#++v-select-optiongroup++# is the overall style for the component.
+Each check box will have the [literal]#++v-checkbox++# style, borrowed from the
+[classname]#CheckBox# component, and each radio button the
+[literal]#++v-radiobutton++# style. Both the radio buttons and check boxes will
+also have the [literal]#++v-select-option++# style that allows styling
+regardless of the option type. Disabled items have additionally the
+[literal]#++v-disabled++# style.
+
+[[components.optiongroup.css.horizontal]]
+=== Horizontal Layout
+
+The options are normally laid out vertically. You can use horizontal layout by
+setting [literal]#++display: inline-block++# for the options. The
+[literal]#++nowrap++# setting for the overall element prevents wrapping if there
+is not enough horizontal space in the layout, or if the horizontal width is
+undefined.
+
+
+[source, css]
+----
+/* Lay the options horizontally */
+.v-select-optiongroup-horizontal .v-select-option {
+    display: inline-block;
+}
+
+/* Avoid wrapping if the layout is too tight */
+.v-select-optiongroup-horizontal {
+    white-space: nowrap;
+}
+
+/* Some extra spacing is needed */
+.v-select-optiongroup-horizontal
+  .v-select-option.v-radiobutton {
+    padding-right: 10px;
+}
+----
+
+Use of the above rules requires setting a custom [literal]#++horizontal++# style
+name for the component. The result is shown in
+<>.
+
+[[figure.components.optiongroup.horizontal]]
+.Horizontal [classname]#OptionGroup#
+image::img/optiongroup-horizontal.png[]
+
+
+
+
+
diff --git a/documentation/components/components-overview.asciidoc b/documentation/components/components-overview.asciidoc
new file mode 100644
index 0000000000..c1d133f9f9
--- /dev/null
+++ b/documentation/components/components-overview.asciidoc
@@ -0,0 +1,81 @@
+---
+title: Overview
+order: 1
+layout: page
+---
+
+[[components.overview]]
+= Overview
+
+Vaadin provides a comprehensive set of user interface components and allows you
+to define custom components. <> illustrates the inheritance
+hierarchy of the UI component classes and interfaces. Interfaces are displayed
+in gray, abstract classes in orange, and regular classes in blue. An annotated
+version of the diagram is featured in the __Vaadin Cheat Sheet__.
+
+[[figure.uicomponents]]
+.User Interface Component Class Hierarchy
+image::img/component-diagram-hi.png[]
+
+((("[classname]#Component#")))
+At the top of the interface hierarchy, we have the [classname]#Component#
+interface.
+((("[classname]#AbstractComponent#")))
+At the top of the class hierarchy, we have the [classname]#AbstractComponent#
+class.
+((("[classname]#AbstractField#")))
+((("[classname]#AbstractComponentContainer#")))
+It is inherited by two other abstract classes: [classname]#AbstractField#,
+inherited further by field components, and
+[classname]#AbstractComponentContainer#, inherited by various container and
+layout components. Components that are not bound to a content data model, such
+as labels and links, inherit [classname]#AbstractComponent# directly.
+
+((("layout")))
+((("[classname]#Layout#")))
+The layout of the various components in a window is controlled, logically, by
+layout components, just like in conventional Java UI toolkits for desktop
+applications. In addition, with the [classname]#CustomLayout# component, you can
+write a custom layout as an HTML template that includes the locations of any
+contained components. Looking at the inheritance diagram, we can see that layout
+components inherit the [classname]#AbstractComponentContainer# and the
+[classname]#Layout# interface. Layout components are described in detail in
+<>.
+
+((("[classname]#Window#")))
+Looking at it from the perspective of an object hierarchy, we would have a
+[classname]#Window# object, which contains a hierachy of layout components,
+which again contain other layout components, field components, and other visible
+components.
+
+((("Sampler")))
+((("JavaDoc")))
+You can browse the built-in UI components of Vaadin library in the Sampler
+application of the Vaadin Demo. The Sampler shows a description, JavaDoc
+documentation, and a code samples for each of the components.
+
+In addition to the built-in components, many components are available as
+add-ons, either from the Vaadin Directory or from independent sources. Both
+commercial and free components exist. The installation of add-ons is described
+in
+<>.
+
+
+[NOTE]
+.Vaadin Cheat Sheet and Refcard
+====
+<> is included in the Vaadin Cheat Sheet that illustrates
+the basic relationship hierarchy of the user interface components and data
+binding classes and interfaces. You can download it at http://vaadin.com/book.
+
+The diagram is also included in the six-page DZone Refcard, which you can find
+at https://vaadin.com/refcard.
+
+====
+
+
+
+
+
diff --git a/documentation/components/components-passwordfield.asciidoc b/documentation/components/components-passwordfield.asciidoc
new file mode 100644
index 0000000000..1280de7529
--- /dev/null
+++ b/documentation/components/components-passwordfield.asciidoc
@@ -0,0 +1,54 @@
+---
+title: PasswordField
+order: 11
+layout: page
+---
+
+[[components.passwordfield]]
+= [classname]#PasswordField#
+
+ifdef::web[]
+[.sampler]
+image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/data-input/text-input/password-field]
+endif::web[]
+
+The [classname]#PasswordField# is a variant of [classname]#TextField# that hides
+the typed input from visual inspection.
+
+
+[source, java]
+----
+PasswordField tf = new PasswordField("Keep it secret");
+----
+See the http://demo.vaadin.com/book-examples-vaadin7/book#component.passwordfield.basic[on-line example, window="_blank"].
+
+The result is shown in <>.
+
+[[figure.components.passwordfield.basic]]
+.[classname]#PasswordField#
+image::img/passwordfield-basic.png[]
+
+You should note that the [classname]#PasswordField# hides the input only from
+"over the shoulder" visual observation. Unless the server connection is
+encrypted with a secure connection, such as HTTPS, the input is transmitted in
+clear text and may be intercepted by anyone with low-level access to the
+network. Also phishing attacks that intercept the input in the browser may be
+possible by exploiting JavaScript execution security holes in the browser.
+
+[[components.passwordfield.css]]
+== CSS Style Rules
+
+
+[source, css]
+----
+.v-textfield { }
+----
+
+The [classname]#PasswordField# does not have its own CSS style name but uses the
+same [literal]#++v-textfield++# style as the regular [classname]#TextField#. See
+<> for information on styling it.
+
+CSS Styling
+
+
diff --git a/documentation/components/components-popupview.asciidoc b/documentation/components/components-popupview.asciidoc
new file mode 100644
index 0000000000..8f67c392d8
--- /dev/null
+++ b/documentation/components/components-popupview.asciidoc
@@ -0,0 +1,92 @@
+---
+title: PopupView
+order: 29
+layout: page
+---
+
+[[components.popupview]]
+= [classname]#PopupView#
+
+ifdef::web[]
+[.sampler]
+image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/structure/popup-view]
+endif::web[]
+
+The [classname]#PopupView# component allows opening a pop-up view either by
+clicking on a link or programmatically. The component has two representations: a
+minimized textual representation and the popped-up content. The view can contain
+any components. The view closes automatically when the mouse pointer moves
+outside the view.
+
+In the following, we have a popup view with a text field and a button that opens
+automatically when the user clicks on a "Open the popup" link:
+
+
+[source, java]
+----
+// Content for the PopupView
+VerticalLayout popupContent = new VerticalLayout();
+popupContent.addComponent(new TextField("Textfield"));
+popupContent.addComponent(new Button("Button"));
+
+// The component itself
+PopupView popup = new PopupView("Pop it up", popupContent);
+layout.addComponent(popup);
+----
+
+If the textual minimized representation is not given (a null is given), the
+component is invisible in the minimized state. The pop-up can be opened
+programmatically by calling [methodname]#setPopupVisible(true)#. For example:
+
+
+[source, java]
+----
+// A pop-up view without minimalized representation
+PopupView popup = new PopupView(null,
+    new Table(null, TableExample.generateContent()));
+
+// A component to open the view
+Button button = new Button("Show table", click -> // Java 8
+     popup.setPopupVisible(true));
+
+layout.addComponents(button, popup);
+----
+
+When the pop-up is opened or closed, a [classname]#PopupVisibilityEvent# is
+fired, which can be handled with a [interfacename]#PopupVisibilityListener#
+added with [methodname]#setPopupVisibilityListener()#.
+
+
+[source, java]
+----
+// Fill the pop-up content when it's popped up
+popup.addPopupVisibilityListener(event -> { 
+    if (event.isPopupVisible()) {
+        popupContent.removeAllComponents();
+        popupContent.addComponent(new Table(null,
+            TableExample.generateContent()));
+    }});
+----
+
+[[components.popupview.css]]
+== CSS Style Rules
+
+
+[source, css]
+----
+.v-popupview {}
+.v-overlay-container {
+  .v-popupview-popup {
+    .popupContent { }
+  }
+}
+----
+
+In minimalized state, the component has [literal]#++v-popupview++# style. When
+popped up, the pop-up content is shown in a [literal]#++v-popupview-popup++#
+overlay element under the [literal]#++v-overlay-container++#, which is contains
+all floating overlays outside the component hierarchy.
+
+
+
+
diff --git a/documentation/components/components-progressbar.asciidoc b/documentation/components/components-progressbar.asciidoc
new file mode 100644
index 0000000000..389855babf
--- /dev/null
+++ b/documentation/components/components-progressbar.asciidoc
@@ -0,0 +1,214 @@
+---
+title: ProgressBar
+order: 27
+layout: page
+---
+
+[[components.progressbar]]
+= [classname]#ProgressBar#
+
+ifdef::web[]
+[.sampler]
+image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/interaction/progress-bar]
+endif::web[]
+
+The [classname]#ProgressBar# component allows displaying the progress of a task
+graphically. The progress is specified as a floating-point value between 0.0 and
+1.0.
+
+[[figure.components.progressbar.basic]]
+.The Progress Bar Component
+image::img/progressbar-basic.png[]
+
+To display upload progress with the [classname]#Upload# component, you can
+update the progress bar in a [interfacename]#ProgressListener#.
+
+When the position of a progress bar is done in a background thread, the change
+is not shown in the browser immediately. You need to use either polling or
+server push to update the browser. You can enable polling with
+[methodname]#setPollInterval()# in the current UI instance. See
+<>
+for instructions about using server push. Whichever method you use to update the
+UI, it is important to lock the user session by modifying the progress bar value
+inside [methodname]#access()# call, as illustrated in the following example and
+described in
+<>.
+
+
+[source, java]
+----
+final ProgressBar bar = new ProgressBar(0.0f);
+layout.addComponent(bar);
+        
+layout.addComponent(new Button("Increase",
+    new ClickListener() {
+    @Override
+    public void buttonClick(ClickEvent event) {
+        float current = bar.getValue();
+        if (current < 1.0f)
+            bar.setValue(current + 0.10f);
+    }
+}));
+----
+
+[[components.progressbar.indeterminate]]
+== Indeterminate Mode
+
+In the indeterminate mode, a non-progressive indicator is displayed
+continuously. The indeterminate indicator is a circular wheel in the built-in
+themes. The progress value has no meaning in the indeterminate mode.
+
+
+[source, java]
+----
+ProgressBar bar = new ProgressBar();
+bar.setIndeterminate(true);
+----
+
+[[figure.components.progressbar.indeterminate]]
+.Indeterminate Progress Bar
+image::img/progressbar-indeterminate.png[]
+
+
+ifdef::web[]
+[[components.progressbar.thread]]
+== Doing Heavy Computation
+
+The progress indicator is often used to display the progress of a heavy
+server-side computation task, often running in a background thread. The UI,
+including the progress bar, can be updated either with polling or by using
+server push. When doing so, you must ensure thread-safety, most easily by
+updating the UI inside a [methodname]#UI.access()# call in a
+[interfacename]#Runnable#, as described in
+<>.
+
+In the following example, we create a thread in the server to do some "heavy
+work" and use polling to update the UI. All the thread needs to do is to set the
+value of the progress bar with [methodname]#setValue()# and the current progress
+is displayed automatically when the browser polls the server.
+
+
+[source, java]
+----
+HorizontalLayout barbar = new HorizontalLayout();
+layout.addComponent(barbar);
+        
+// Create the indicator, disabled until progress is started
+final ProgressBar progress = new ProgressBar(new Float(0.0));
+progress.setEnabled(false);
+barbar.addComponent(progress);
+        
+final Label status = new Label("not running");
+barbar.addComponent(status);
+
+// A button to start progress
+final Button button = new Button("Click to start");
+layout.addComponent(button);
+
+// A thread to do some work
+class WorkThread extends Thread {
+    // Volatile because read in another thread in access()
+    volatile double current = 0.0;
+
+    @Override
+    public void run() {
+        // Count up until 1.0 is reached
+        while (current < 1.0) {
+            current += 0.01;
+
+            // Do some "heavy work"
+            try {
+                sleep(50); // Sleep for 50 milliseconds
+            } catch (InterruptedException e) {}
+
+            // Update the UI thread-safely
+            UI.getCurrent().access(new Runnable() {
+                @Override
+                public void run() {
+                    progress.setValue(new Float(current));
+                    if (current < 1.0)
+                        status.setValue("" +
+                            ((int)(current*100)) + "% done");
+                    else
+                        status.setValue("all done");
+                }
+            });
+        }
+        
+        // Show the "all done" for a while
+        try {
+            sleep(2000); // Sleep for 2 seconds
+        } catch (InterruptedException e) {}
+
+        // Update the UI thread-safely
+        UI.getCurrent().access(new Runnable() {
+            @Override
+            public void run() {
+                // Restore the state to initial
+                progress.setValue(new Float(0.0));
+                progress.setEnabled(false);
+                        
+                // Stop polling
+                UI.getCurrent().setPollInterval(-1);
+                
+                button.setEnabled(true);
+                status.setValue("not running");
+            }
+        });
+    }
+}
+
+// Clicking the button creates and runs a work thread
+button.addClickListener(new Button.ClickListener() {
+    public void buttonClick(ClickEvent event) {
+        final WorkThread thread = new WorkThread();
+        thread.start();
+
+        // Enable polling and set frequency to 0.5 seconds
+        UI.getCurrent().setPollInterval(500);
+
+        // Disable the button until the work is done
+        progress.setEnabled(true);
+        button.setEnabled(false);
+
+        status.setValue("running...");
+    }
+});
+----
+
+The example is illustrated in <>.
+
+[[figure.components.progressbar.thread]]
+.Doing Heavy Work
+image::img/progressbar-thread.png[]
+
+endif::web[]
+
+[[components.progressbar.css]]
+== CSS Style Rules
+
+
+[source, css]
+----
+.v-progressbar, v-progressbar-indeterminate {}
+  .v-progressbar-wrapper {}
+    .v-progressbar-indicator {}
+----
+
+The progress bar has a [literal]#++v-progressbar++# base style. The animation is
+the background of the element with [literal]#++v-progressbar-wrapper++# style,
+by default an animated GIF image. The progress is an element with
+[literal]#++v-progressbar-indicator++# style inside the wrapper, and therefore
+displayed on top of it. When the progress element grows, it covers more and more
+of the animated background.
+
+In the indeterminate mode, the top element also has the
+[literal]#++v-progressbar-indeterminate++# style. The built-in themes simply
+display the animated GIF in the top element and have the inner elements
+disabled.
+
+
+
+
diff --git a/documentation/components/components-richtextarea.asciidoc b/documentation/components/components-richtextarea.asciidoc
new file mode 100644
index 0000000000..ff354cfe8d
--- /dev/null
+++ b/documentation/components/components-richtextarea.asciidoc
@@ -0,0 +1,128 @@
+---
+title: RichTextArea
+order: 12
+layout: page
+---
+
+[[components.richtextarea]]
+= [classname]#RichTextArea#
+
+ifdef::web[]
+[.sampler]
+image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/data-input/text-input/rich-text-area]
+endif::web[]
+
+The [classname]#RichTextArea# field allows entering or editing formatted text.
+The toolbar provides all basic editing functionalities. The text content of
+[classname]#RichTextArea# is represented in HTML format.
+[classname]#RichTextArea# inherits [classname]#TextField# and does not add any
+API functionality over it. You can add new functionality by extending the
+client-side components [classname]#VRichTextArea# and
+[classname]#VRichTextToolbar#.
+
+As with [classname]#TextField#, the textual content of the rich text area is the
+[classname]#Property# of the field and can be set with [methodname]#setValue()#
+and read with [methodname]#getValue()#.
+
+
+[source, java]
+----
+// Create a rich text area
+final RichTextArea rtarea = new RichTextArea();
+rtarea.setCaption("My Rich Text Area");
+
+// Set initial content as HTML
+rtarea.setValue("

Hello

\n" + + "

This rich text area contains some text.

"); +---- + +.Rich Text Area Component +image::img/richtextarea-example1.png[] + +Above, we used context-specific tags such as [literal]#++

++# in the initial +HTML content. The rich text area component does not allow creating such tags, +only formatting tags, but it does preserve them unless the user edits them away. +Any non-visible whitespace such as the new line character ( [literal]#++\n++#) +are removed from the content. For example, the value set above will be as +follows when read from the field with [methodname]#getValue()#: + + +[source, html] +---- +

Hello

This rich text area contains some text.

+---- + + +[WARNING] +.Cross-Site Scripting Warning +==== +The user input from a [classname]#RichTextArea# is transmitted as HTML from the +browser to server-side and is not sanitized. As the entire purpose of the +[classname]#RichTextArea# component is to allow input of formatted text, you can +not sanitize it just by removing all HTML tags. Also many attributes, such as +[parameter]#style#, should pass through the sanitization. + +See +<> for more details on Cross-Site +scripting vulnerabilities and sanitization of user input. + +==== + + + +ifdef::web[] +[[components.richtextarea.localization]] +== Localizing RichTextArea Toolbars + +The rich text area is one of the few components in Vaadin that contain textual +labels. The selection boxes in the toolbar are in English and currently can not +be localized in any other way than by inheriting or reimplementing the +client-side [classname]#VRichTextToolbar# widget. The buttons can be localized +simply with CSS by downloading a copy of the toolbar background image, editing +it, and replacing the default toolbar. The toolbar is a single image file from +which the individual button icons are picked, so the order of the icons is +different from the rendered. The image file depends on the client-side +implementation of the toolbar. + + +[source, css] +---- +.v-richtextarea-richtextexample .gwt-ToggleButton +.gwt-Image { + background-image: url(img/richtextarea-toolbar-fi.png) + !important; +} +---- + +.Regular English and a Localized Rich Text Area Toolbar +image::img/richtextarea-toolbar-whitebg.png[] + +endif::web[] + +== CSS Style Rules + + +[source, css] +---- +.v-richtextarea { } +.v-richtextarea .gwt-RichTextToolbar { } +.v-richtextarea .gwt-RichTextArea { } +---- + +The rich text area consists of two main parts: the toolbar with overall style +[literal]#++.gwt-RichTextToolbar++# and the editor area with style +[literal]#++.gwt-RichTextArea++#. The editor area obviously contains all the +elements and their styles that the HTML content contains. The toolbar contains +buttons and drop-down list boxes with the following respective style names: + + +[source, css] +---- +.gwt-ToggleButton { } +.gwt-ListBox { } +---- + + + + diff --git a/documentation/components/components-selection.asciidoc b/documentation/components/components-selection.asciidoc new file mode 100644 index 0000000000..5ad422555d --- /dev/null +++ b/documentation/components/components-selection.asciidoc @@ -0,0 +1,464 @@ +--- +title: Selection Components +order: 5 +layout: page +--- + +[[components.selection]] += Selection Components + +Vaadin offers many alternative ways for selecting one or more items. The core +library includes the following selection components, all based on the +[classname]#AbstractSelect# class: + +[classname]#ComboBox# (Section <>):: A drop-down list with a text box, where the user can type text to find matching items. The component also provides an input prompt and the user can enter new items. +[classname]#ListSelect# (Section <>):: A vertical list box for selecting items in either single or multiple selection mode. +[classname]#NativeSelect# (Section<>):: Provides selection using the native selection component of the browser, typically a drop-down list for single selection and a multi-line list in multiselect mode. This uses the [literal]#++