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

components-calendar.asciidoc 41KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187
  1. ---
  2. title: Calendar
  3. order: 30
  4. layout: page
  5. ---
  6. [[components.calendar]]
  7. = [classname]#Calendar#
  8. ifdef::web[]
  9. [.sampler]
  10. image:{live-demo-image}[alt="Live Demo", link="http://demo.vaadin.com/sampler/#ui/data-input/dates/dates-calendar"]
  11. endif::web[]
  12. The [classname]#Calendar# component allows organizing and displaying calendar
  13. events. The main features of the calendar include:
  14. * Monthly, weekly, and daily views
  15. * Two types of events: all-day events and events with a time range
  16. * Add events directly, from a [classname]#Container#, or with an event provider
  17. * Control the range of the visible dates
  18. * Selecting and editing date or time range by dragging
  19. * Drag and drop events to calendar
  20. * Support for localization and timezones
  21. User interaction with the calendar elements, such as date and week captions as
  22. well as events, is handled with event listeners. Also date/time range
  23. selections, event dragging, and event resizing can be listened by the server.
  24. The weekly view has navigation buttons to navigate forward and backward in time.
  25. These actions are also listened by the server. Custom navigation can be
  26. implemented using event
  27. ifdef::web[handlers, as described in <<components.calendar.customizing>>.]
  28. ifndef::web[handlers.]
  29. The data source of a calendar can be practically anything, as its events are
  30. queried dynamically by the component. You can bind the calendar to a Vaadin
  31. container, or to any other data source by implementing an __event provider__.
  32. The [classname]#Calendar# has undefined size by default and you usually want to
  33. give it a fixed or relative size, for example as follows.
  34. [source, java]
  35. ----
  36. Calendar cal = new Calendar("My Calendar");
  37. cal.setWidth("600px");
  38. cal.setHeight("300px");
  39. ----
  40. After creating the calendar, you need to set a time range for it, which also
  41. controls the view mode, and set up the data source for calendar events.
  42. [[components.calendar.daterange]]
  43. == Date Range and View Mode
  44. The Vaadin Calendar has two types of views that are shown depending on the date
  45. range of the calendar. The __weekly view__ displays a week by default. It can
  46. show anything between one to seven days a week, and is also used as a single-day
  47. view. The view mode is determined from the __date range__ of the calendar,
  48. defined by a start and an end date. Calendar will be shown in a __monthly view__
  49. when the date range is over than one week (seven days) long. The date range is
  50. always calculated in an accuracy of one millisecond.
  51. [[figure.components.calendar.daterange.monthly]]
  52. .Monthly view with All-Day and Normal Events
  53. image::img/calendar-monthly.png[width=60%, scaledwidth=100%]
  54. The monthly view, shown in <<figure.components.calendar.daterange.monthly>>, can
  55. easily be used to control all types of events, but it is best suited for events
  56. that last for one or more days. You can drag the events to move them. In the
  57. figure, you can see two longer events that are highlighted with a blue and green
  58. background color. Other markings are shorter day events that last less than a 24
  59. hours. These events can not be moved by dragging in the monthly view.
  60. [[figure.components.calendar.daterange.weekly]]
  61. .Weekly View
  62. image::img/calendar-weekly.png[width=60%, scaledwidth=100%]
  63. In <<figure.components.calendar.daterange.weekly>>, you can see four normal day
  64. events and also all-day events at the top of the time line grid.
  65. In the following, we set the calendar to show only one day, which is the current
  66. day.
  67. [source, java]
  68. ----
  69. cal.setStartDate(new Date());
  70. cal.setEndDate(new Date());
  71. ----
  72. Notice that although the range we set above is actually zero time long, the
  73. calendar still renders the time from 00:00 to 23:59. This is normal, as the
  74. Vaadin Calendar is guaranteed to render at least the date range provided, but
  75. may expand it. This behaviour is important to notice when we implement our own
  76. event providers.
  77. [[components.calendar.events]]
  78. == Calendar Events
  79. All occurrences in a calendar are represented as __events__. You have three ways
  80. to manage the calendar events:
  81. * Add events directly to the [classname]#Calendar# object using the [methodname]#addEvent()#
  82. * Use a [interfacename]#Container# as a data source
  83. * Use the __event provider__ mechanism
  84. You can add events with [methodname]#addEvent()# and remove them with the
  85. [methodname]#removeEvent()#. These methods will use the underlying event
  86. provider to write the modifications to the data source.
  87. [[components.calendar.events.types]]
  88. === Event Interfaces and Providers
  89. Events are handled though the [interfacename]#CalendarEvent# interface. The
  90. concrete class of the event depends on the specific
  91. [classname]#CalendarEventProvider# used in the calendar.
  92. By default, [classname]#Calendar# uses a [classname]#BasicEventProvider# to
  93. provide events, which uses [classname]#BasicEvent# instances.
  94. Calendar does not depend on any particular data source implementation. Events
  95. are queried by the [classname]#Calendar# from the provider that just has to
  96. implement the [interfacename]#CalendarEventProvider# interface. It is up to the
  97. event provider that [classname]#Calendar# gets the correct events.
  98. You can bind any Vaadin [classname]#Container# to a calendar, in which case a
  99. [classname]#ContainerEventProvider# is used transparently. The container must be
  100. ordered by start date and time of the events. See
  101. <<dummy/../../../framework/datamodel/datamodel-container#datamodel.container,"Collecting
  102. Items in Containers">> for basic information about containers.
  103. [[components.calendar.events.details]]
  104. === Event Types
  105. A calendar event requires a start time and an end time. These are the only
  106. mandatory properties. In addition, an event can also be set as an all-day event
  107. by setting the [literal]#++all-day++# property of the event. You can also set
  108. the [literal]#++description++# of an event, which is displayed as a tooltip in
  109. the user interface.
  110. If the [literal]#++all-day++# field of the event is [literal]#++true++#, then
  111. the event is always rendered as an all-day event. In the monthly view, this
  112. means that no start time is displayed in the user interface and the event has an
  113. colored background. In the weekly view, all-day events are displayed in the
  114. upper part of the screen, and rendered similarly to the monthly view. In
  115. addition, when the time range of an event is 24 hours or longer, it is rendered
  116. as an all-day event in the monthly view.
  117. When the time range of an event is equal or less than 24 hours, with the
  118. accuracy of one millisecond, the event is considered as a normal day event.
  119. Normal event has a start and end times that may be on different days.
  120. [[components.calendar.events.basic]]
  121. === Basic Events
  122. The easiest way to add and manage events in a calendar is to use the __basic
  123. event__ management API. Calendar uses by default a
  124. [classname]#BasicEventProvider#, which keeps the events in memory in an internal
  125. reprensetation.
  126. For example, the following adds a two-hour event starting from the current time.
  127. The standard Java [classname]#GregorianCalendar# provides various ways to
  128. manipulate date and time.
  129. [source, java]
  130. ----
  131. // Add a two-hour event
  132. GregorianCalendar start = new GregorianCalendar();
  133. GregorianCalendar end = new GregorianCalendar();
  134. end.add(java.util.Calendar.HOUR, 2);
  135. calendar.addEvent(new BasicEvent("Calendar study",
  136. "Learning how to use Vaadin Calendar",
  137. start.getTime(), end.getTime()));
  138. ----
  139. See the http://demo.vaadin.com/book-examples-vaadin7/book#calendar.monthlyview[on-line example, window="_blank"].
  140. This adds a new event that lasts for 3 hours. As the BasicEventProvider and
  141. BasicEvent implement some optional event interfaces provided by the calendar
  142. package, there is no need to refresh the calendar. Just create events, set their
  143. properties and add them to the Event Provider.
  144. [[components.calendar.container]]
  145. == Getting Events from a Container
  146. You can use any Vaadin [interfacename]#Container# that implements the
  147. [interfacename]#Indexed# interface as the data source for calendar events. The
  148. [classname]#Calendar# will listen to change events from the container as well as
  149. write changes to the container. You can attach a container to a
  150. [classname]#Calendar# with [methodname]#setContainerDataSource()#.
  151. In the following example, we bind a [classname]#BeanItemContainer# that contains
  152. built-in [classname]#BasicEvent# events to a calendar.
  153. [source, java]
  154. ----
  155. // Create the calendar
  156. Calendar calendar = new Calendar("Bound Calendar");
  157. // Use a container of built-in BasicEvents
  158. final BeanItemContainer<BasicEvent> container =
  159. new BeanItemContainer<BasicEvent>(BasicEvent.class);
  160. // Create a meeting in the container
  161. container.addBean(new BasicEvent("The Event", "Single Event",
  162. new GregorianCalendar(2012,1,14,12,00).getTime(),
  163. new GregorianCalendar(2012,1,14,14,00).getTime()));
  164. // The container must be ordered by the start time. You
  165. // have to sort the BIC every time after you have added
  166. // or modified events.
  167. container.sort(new Object[]{"start"}, new boolean[]{true});
  168. calendar.setContainerDataSource(container, "caption",
  169. "description", "start", "end", "styleName");
  170. ----
  171. See the http://demo.vaadin.com/book-examples-vaadin7/book#calendar.beanitemcontainer[on-line example, window="_blank"].
  172. The container must either use the default property IDs for event data, as
  173. defined in the [interfacename]#CalendarEvent# interface, or provide them as
  174. parameters for the [methodname]#setContainerDataSource()# method, as we did in
  175. the example above.
  176. [[components.calendar.container.sorting]]
  177. === Keeping the Container Ordered
  178. The events in the container __must__ be kept ordered by their start date/time.
  179. Failing to do so may and will result in the events not showing in the calendar
  180. properly.
  181. Ordering depends on the container. With some containers, such as
  182. [classname]#BeanItemContainer#, you have to sort the container explicitly every
  183. time after you have added or modified events, usually with the
  184. [methodname]#sort()# method, as we did in the example above. Some container,
  185. such as [classname]#JPAContainer#, keep the in container automatically order if
  186. you provide a sorting rule.
  187. For example, you could order a [classname]#JPAContainer# by the following rule,
  188. assuming that the start date/time is held in the [literal]#++startDate++#
  189. property:
  190. [source, java]
  191. ----
  192. // The container must be ordered by start date. For JPAContainer
  193. // we can just set up sorting once and it will stay ordered.
  194. container.sort(new String[]{"startDate"}, new boolean[]{true});
  195. ----
  196. See the http://demo.vaadin.com/book-examples-vaadin7/book#calendar.jpacontainer[on-line example, window="_blank"].
  197. ifdef::web[]
  198. [[components.calendar.container.customization]]
  199. === Delegation of Event Management
  200. Setting a container as the calendar data source with
  201. [methodname]#setContainerDataSource()# automatically switches to
  202. [classname]#ContainerEventProvider#. You can manipulate the event data through
  203. the API in [classname]#Calendar# and the user can move and resize event through
  204. the user interface. The event provider delegates all such calendar operations to
  205. the container.
  206. If you add events through the [classname]#Calendar# API, notice that you may be
  207. unable to create events of the type held in the container or adding them
  208. requires some container-specific operations. In such case, you may need to
  209. customize the [methodname]#addEvent()# method.
  210. For example, [classname]#JPAContainer# requires adding new items with
  211. [methodname]#addEntity()#. You could first add the entity to the container or
  212. entity manager directly and then pass it to the [methodname]#addEvent()#. That
  213. does not, however, work if the entity class does not implement
  214. [interfacename]#CalendarEvent#. This is actually the case always if the property
  215. names differ from the ones defined in the interface. You could handle creating
  216. the underlying entity objects in the [methodname]#addEvent()# as follows:
  217. [source, java]
  218. ----
  219. // Create a JPAContainer
  220. final JPAContainer<MyCalendarEvent> container =
  221. JPAContainerFactory.make(MyCalendarEvent.class,
  222. "book-examples");
  223. // Customize the event provider for adding events
  224. // as entities
  225. ContainerEventProvider cep =
  226. new ContainerEventProvider(container) {
  227. @Override
  228. public void addEvent(CalendarEvent event) {
  229. MyCalendarEvent entity = new MyCalendarEvent(
  230. event.getCaption(), event.getDescription(),
  231. event.getStart(), event.getEnd(),
  232. event.getStyleName());
  233. container.addEntity(entity);
  234. }
  235. }
  236. // Set the container as the data source
  237. calendar.setEventProvider(cep);
  238. // Now we can add events to the database through the calendar
  239. BasicEvent event = new BasicEvent("The Event", "Single Event",
  240. new GregorianCalendar(2012,1,15,12,00).getTime(),
  241. new GregorianCalendar(2012,1,15,14,00).getTime());
  242. calendar.addEvent(event);
  243. ----
  244. endif::web[]
  245. ifdef::web[]
  246. [[components.calendar.eventprovider]]
  247. == Implementing an Event Provider
  248. If the two simple ways of storing and managing events for a calendar are not
  249. enough, you may need to implement a custom event provider. It is the most
  250. flexible way of providing events. You need to attach the event provider to the
  251. [classname]#Calendar# using the [methodname]#setEventProvider()# method.
  252. Event queries are done by asking the event provider for all the events between
  253. two given dates. The range of these dates is guaranteed to be at least as long
  254. as the start and end dates set for the component. The component can, however,
  255. ask for a longer range to ensure correct rendering. In particular, all start
  256. dates are expanded to the start of the day, and all end dates are expanded to
  257. the end of the day.
  258. [[components.calendar.eventprovider.customevents]]
  259. === Custom Events
  260. An event provider could use the built-in [classname]#BasicEvent#, but it is
  261. usually more proper to define a custom event type that is bound directly to the
  262. data source. Custom events may be useful for some other purposes as well, such
  263. as when you need to add extra information to an event or customize how it is
  264. acquired.
  265. Custom events must implement the [interfacename]#CalendarEvent# interface or
  266. extend an existing event class. The built-in [classname]#BasicEvent# class
  267. should serve as a good example of implementing simple events. It keeps the data
  268. in member variables.
  269. [source, java]
  270. ----
  271. public class BasicEvent
  272. implements CalendarEventEditor, EventChangeNotifier {
  273. ...
  274. public String getCaption() {
  275. return caption;
  276. }
  277. public String getDescription() {
  278. return description;
  279. }
  280. public Date getEnd() {
  281. return end;
  282. }
  283. public Date getStart() {
  284. return start;
  285. }
  286. public String getStyleName() {
  287. return styleName;
  288. }
  289. public boolean isAllDay() {
  290. return isAllDay;
  291. }
  292. public void setCaption(String caption) {
  293. this.caption = caption;
  294. fireEventChange();
  295. }
  296. public void setDescription(String description) {
  297. this.description = description;
  298. fireEventChange();
  299. }
  300. public void setEnd(Date end) {
  301. this.end = end;
  302. fireEventChange();
  303. }
  304. public void setStart(Date start) {
  305. this.start = start;
  306. fireEventChange();
  307. }
  308. public void setStyleName(String styleName) {
  309. this.styleName = styleName;
  310. fireEventChange();
  311. }
  312. public void setAllDay(boolean isAllDay) {
  313. this.isAllDay = isAllDay;
  314. fireEventChange();
  315. }
  316. public void addEventChangeListener(
  317. EventChangeListener listener) {
  318. ...
  319. }
  320. public void removeListener(EventChangeListener listener) {
  321. ...
  322. }
  323. protected void fireEventChange() {...}
  324. }
  325. ----
  326. You may have noticed that there was some additional code in the
  327. [classname]#BasicEvent# that was not in the [interfacename]#CalendarEvent#
  328. interface. Namely [classname]#BasicEvent# also implements two additional
  329. interfaces:
  330. [interfacename]#CalendarEditor#:: This interface defines setters for all the fields, and is required for some of
  331. the default handlers to work.
  332. [interfacename]#EventChangeNotifier#:: This interface adds the possibility to listen for changes in the event, and
  333. enables the [classname]#Calendar# to render the changes immediately.
  334. The start time and end time are mandatory, but caption, description, and style
  335. name are not. The style name is used as a part of the CSS class name for the
  336. HTML DOM element of the event.
  337. In addition to the basic event interfaces, you can enhance the functionality of
  338. your event and event provider classes by using the [classname]#EventChange# and
  339. [classname]#EventSetChange# events. They let the [classname]#Calendar# component
  340. to know about changes in events and update itself accordingly. The
  341. [classname]#BasicEvent# and [classname]#BasicEventProvider# examples given
  342. earlier include a simple implementation of these interfaces.
  343. [[components.calendar.eventprovider.eventprovider]]
  344. === Implementing the Event Provider
  345. An event provider needs to implement the [interfacename]#CalendarEventProvider#
  346. interface. It has only one method to be implemented. Whenever the calendar is
  347. painted, [methodname]#getEvents(Date, Date)# method is called and it must return
  348. a list of events between the given start and end time.
  349. The following example implementation returns only one example event. The event
  350. starts from the current time and is five hours long.
  351. [source, java]
  352. ----
  353. public class MyEventProvider implements CalendarEventProvider{
  354. public List<Event> getEvents(Date startDate, Date endDate){
  355. List<Event> events = new ArrayList<Event>();
  356. GregorianCalendar cal = new GregorianCalendar();
  357. cal.setTime(new Date());
  358. Date start = cal.getTime();
  359. cal.add(GregorianCalendar.HOUR, 5);
  360. Date end = cal.getTime();
  361. BasicEvent event = new BasicEvent();
  362. event.setCaption("My Event");
  363. event.setDescription("My Event Description");
  364. event.setStart(start);
  365. event.setEnd(end);
  366. events.add(event);
  367. return events;
  368. }
  369. }
  370. ----
  371. It is important to notice that the [classname]#Calendar# may query for dates
  372. beyond the range defined by start date and end date. Particularly, it may expand
  373. the date range to make sure the user interface is rendered correctly.
  374. endif::web[]
  375. ifdef::web[]
  376. [[components.calendar.appearance]]
  377. == Styling a Calendar
  378. Configuring the appearance of the Vaadin Calendar component is one of the basic
  379. tasks. At the least, you need to consider its sizing in your user interface. You
  380. also quite probably want to use some color or colors for events.
  381. [[components.calendar.appearance.sizing]]
  382. === Sizing
  383. The Calendar supports component sizing as usual for defined (fixed or relative)
  384. sizes. When using an undefined size for the calendar, all the sizes come from
  385. CSS. In addition, when the height is undefined, a scrollbar is displayed in the
  386. weekly view to better fit the cells to the user interface.
  387. Below is a list of style rules that define the size of a Calendar with undefined
  388. size (these are the defaults):
  389. [source, css]
  390. ----
  391. .v-calendar-month-sizedheight .v-calendar-month-day {
  392. height: 100px;
  393. }
  394. .v-calendar-month-sizedwidth .v-calendar-month-day {
  395. width: 100px;
  396. }
  397. .v-calendar-header-month-Hsized .v-calendar-header-day {
  398. width: 101px;
  399. }
  400. /* for IE */
  401. .v-ie6 .v-calendar-header-month-Hsized .v-calendar-header-day {
  402. width: 104px;
  403. }
  404. /* for others */
  405. .v-calendar-header-month-Hsized td:first-child {
  406. padding-left: 21px;
  407. }
  408. .v-calendar-header-day-Hsized {
  409. width: 200px;
  410. }
  411. .v-calendar-week-numbers-Vsized .v-calendar-week-number {
  412. height: 100px;
  413. line-height: 100px;
  414. }
  415. .v-calendar-week-wrapper-Vsized {
  416. height: 400px;
  417. overflow-x: hidden !important;
  418. }
  419. .v-calendar-times-Vsized .v-calendar-time {
  420. height: 38px;
  421. }
  422. .v-calendar-times-Hsized .v-calendar-time {
  423. width: 42px;
  424. }
  425. .v-calendar-day-times-Vsized .v-slot,.v-calendar-day-times-Vsized .v-slot-even {
  426. height: 18px;
  427. }
  428. .v-calendar-day-times-Hsized, .v-calendar-day-times-Hsized .v-slot,.v-calendar-day-times-Hsized .v-slot-even {
  429. width: 200px;
  430. }
  431. ----
  432. [[components.calendar.appearance.event-style]]
  433. === Event Style
  434. Events can be styled with CSS by setting them a __style name suffix__. The
  435. suffix is retrieved with the [methodname]#getStyleName()# method in
  436. [interfacename]#CalendarEvent#. If you use [classname]#BasicEvent# events, you
  437. can set the suffix with [methodname]#setStyleName()#.
  438. [source, java]
  439. ----
  440. BasicEvent event = new BasicEvent("Wednesday Wonder", ... );
  441. event.setStyleName("mycolor");
  442. calendar.addEvent(event);
  443. ----
  444. Suffix [literal]#++mycolor++# would create
  445. [literal]#++v-calendar-event-mycolor++# class for regular events and
  446. [literal]#++v-calendar-event-mycolor-add-day++# for all-day events. You could
  447. style the events with the following rules:
  448. [source, css]
  449. ----
  450. .v-calendar .v-calendar-event-mycolor {}
  451. .v-calendar .v-calendar-event-mycolor-all-day {}
  452. .v-calendar .v-calendar-event-mycolor .v-calendar-event-caption {}
  453. .v-calendar .v-calendar-event-mycolor .v-calendar-event-content {}
  454. ----
  455. endif::web[]
  456. ifdef::web[]
  457. [[components.calendar.visible-hours-days]]
  458. == Visible Hours and Days
  459. As we saw in <<components.calendar.daterange>>, you can set the range of dates
  460. that are shown by the Calendar. But what if you wanted to show the entire month
  461. but hide the weekends? Or show only hours from 8 to 16 in the weekly view? The
  462. [methodname]#setVisibleDays()# and [methodname]#setVisibleHours()# methods allow
  463. you to do that.
  464. [source, java]
  465. ----
  466. calendar.setVisibleDays(1,5); // Monday to Friday
  467. calendar.setVisibleHours(0,15); // Midnight until 4 pm
  468. ----
  469. After the above settings, only weekdays from Monday to Friday would be shown.
  470. And when the calendar is in the weekly view, only the time range from 00:00 to
  471. 16:00 would be shown.
  472. Note that the excluded times are never shown so you should take care when
  473. setting the date range. If the date range contains only dates / times that are
  474. excluded, nothing will be displayed. Also note that even if a date is not
  475. rendered because these settings, the event provider may still be queried for
  476. events for that date.
  477. endif::web[]
  478. ifdef::web[]
  479. [[components.calendar.drag-and-drop]]
  480. == Drag and Drop
  481. Vaadin Calendar can act as a drop target for drag and drop, described in
  482. <<dummy/../../../framework/advanced/advanced-dragndrop#advanced.dragndrop,"Drag
  483. and Drop">>. With the functionality, the user could drag events, for example,
  484. from a table to a calendar.
  485. To support dropping, a [classname]#Calendar# must have a drop handler. When the
  486. drop handler is set, the days in the monthly view and the time slots in the
  487. weekly view can receive drops. Other locations, such as day names in the weekly
  488. view, can not currently receive drops.
  489. Calendar uses its own implementation of [interfacename]#TargetDetails#:
  490. [classname]#CalendarTargetdetails#. It holds information about the the drop
  491. location, which in the context of [classname]#Calendar# means the date and time.
  492. The drop target location can be retrieved via the [methodname]#getDropTime()#
  493. method. If the drop is done in the monthly view, the returned date does not have
  494. exact time information. If the drop happened in the weekly view, the returned
  495. date also contains the start time of the slot.
  496. Below is a short example of creating a drop handler and using the drop
  497. information to create a new event:
  498. [source, java]
  499. ----
  500. private Calendar createDDCalendar() {
  501. Calendar calendar = new Calendar();
  502. calendar.setDropHandler(new DropHandler() {
  503. public void drop(DragAndDropEvent event) {
  504. CalendarTargetDetails details =
  505. (CalendarTargetDetails) event.getTargetDetails();
  506. TableTransferable transferable =
  507. (TableTransferable) event.getTransferable();
  508. createEvent(details, transferable);
  509. removeTableRow(transferable);
  510. }
  511. public AcceptCriterion getAcceptCriterion() {
  512. return AcceptAll.get();
  513. }
  514. });
  515. return calendar;
  516. }
  517. protected void createEvent(CalendarTargetDetails details,
  518. TableTransferable transferable) {
  519. Date dropTime = details.getDropTime();
  520. java.util.Calendar timeCalendar = details.getTargetCalendar()
  521. .getInternalCalendar();
  522. timeCalendar.setTime(dropTime);
  523. timeCalendar.add(java.util.Calendar.MINUTE, 120);
  524. Date endTime = timeCalendar.getTime();
  525. Item draggedItem = transferable.getSourceComponent().
  526. getItem(transferable.getItemId());
  527. String eventType = (String)draggedItem.
  528. getItemProperty("type").getValue();
  529. String eventDescription = "Attending: "
  530. + getParticipantString(
  531. (String[]) draggedItem.
  532. getItemProperty("participants").getValue());
  533. BasicEvent newEvent = new BasicEvent();
  534. newEvent.setAllDay(!details.hasDropTime());
  535. newEvent.setCaption(eventType);
  536. newEvent.setDescription(eventDescription);
  537. newEvent.setStart(dropTime);
  538. newEvent.setEnd(endTime);
  539. BasicEventProvider ep = (BasicEventProvider) details
  540. .getTargetCalendar().getEventProvider();
  541. ep.addEvent(newEvent);
  542. }
  543. ----
  544. endif::web[]
  545. ifdef::web[]
  546. [[components.calendar.contextmenu]]
  547. == Using the Context Menu
  548. Vaadin Calendar allows the use of context menu (mouse right-click) to manage
  549. events. As in other context menus in Vaadin, the menu items are handled in
  550. Vaadin as __actions__ by an __action handler__. To enable a context menu, you
  551. have to implement a Vaadin [interfacename]#Action.Handler# and add it to the
  552. calendar with [methodname]#addActionHandler()#.
  553. An action handler must implement two methods: [methodname]#getActions()# and
  554. [methodname]#handleAction()#. The [methodname]#getActions()# is called for each
  555. day displayed in the calendar view. It should return a list of allowed actions
  556. for that day, that is, the items of the context menu. The [parameter]#target#
  557. parameter is the context of the click - a [classname]#CalendarDateRange# that
  558. spans over the day. The [parameter]#sender# is the [classname]#Calendar# object.
  559. The [methodname]#handleActions()# receives the target context in the
  560. [parameter]#target#. If the context menu was opened on an event, the target is
  561. the [interfacename]#Event# object, otherwise it is a
  562. [classname]#CalendarDateRange#.
  563. endif::web[]
  564. ifdef::web[]
  565. [[components.calendar.localization]]
  566. == Localization and Formatting
  567. [[components.calendar.localization.locale]]
  568. === Setting the Locale and Time Zone
  569. Month and weekday names are shown in the language of the locale setting of the
  570. [classname]#Calendar#. The translations are acquired from the standard Java
  571. locale data. By default, [classname]#Calendar# uses the system default locale
  572. for its internal calendar, but you can change it with
  573. [methodname]#setLocale(Locale locale)#. Setting the locale will update also
  574. other location specific date and time settings, such as the first day of the
  575. week, time zone, and time format. However, time zone and time format can be
  576. overridden by settings in the [classname]#Calendar#.
  577. For example, the following would set the language to US English:
  578. [source, java]
  579. ----
  580. cal.setLocale(Locale.US);
  581. ----
  582. The locale defines the default time zone. You can change it with the
  583. [methodname]#setTimeZone()# method, which takes a
  584. [classname]#java.util.TimeZone# object as its parameter. Setting timezone to
  585. null will reset timezone to the locale default.
  586. For example, the following would set the Finnish time zone, which is EET
  587. [source, java]
  588. ----
  589. cal.setTimeZone(TimeZone.getTimeZone("Europe/Helsinki"));
  590. ----
  591. [[components.calendar.localization.datecaption]]
  592. === Time and Date Caption Format
  593. The time may be shown either in 24 or 12 hour format. The default format is
  594. defined by the locale, but you can change it with the
  595. [methodname]#setTimeFormat()# method. Giving a [literal]#++null++# setting will
  596. reset the time format to the locale default.
  597. [source, java]
  598. ----
  599. cal.setTimeFormat(TimeFormat.Format12H);
  600. ----
  601. You can change the format of the date captions in the week view with the
  602. [methodname]#setWeeklyCaptionFormat(String dateFormatPattern)# method. The date
  603. format pattern should follow the format of the standard Java
  604. [classname]#java.text.SimpleDateFormat# class.
  605. For example:
  606. [source, java]
  607. ----
  608. cal.setWeeklyCaptionFormat("dd-MM-yyyy");
  609. ----
  610. endif::web[]
  611. ifdef::web[]
  612. [[components.calendar.customizing]]
  613. == Customizing the Calendar
  614. In this section, we give a tutorial for how to make various basic customizations
  615. of the Vaadin Calendar. The event provider and styling was described earlier, so
  616. now we concentrate on other features of the Calendar API.
  617. [[components.calendar.customizing.overview]]
  618. === Overview of Handlers
  619. Most of the handlers related to calendar events have sensible default handlers.
  620. These are found in the [package]#com.vaadin.ui.handler# package. The default
  621. handlers and their functionalities are described below.
  622. * [classname]#BasicBackwardHandler#. Handles clicking the back-button of the weekly view so that the viewed month is changed to the previous one.
  623. * [classname]#BasicForwardHandler#. Handles clicking the forward-button of the weekly view so that the viewed month is changed to the next one.
  624. * [classname]#BasicWeekClickHandler#. Handles clicking the week numbers int the monthly view so that the viewable date range is changed to the clicked week.
  625. * [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.
  626. * [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#).
  627. * [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#).
  628. All of these handlers are automatically set when creating a new
  629. [classname]#Calendar#. If you wish to disable some of the default functionality,
  630. you can simply set the corresponding handler to [literal]#++null++#. This will
  631. prevent the functionality from ever appearing on the user interface. For
  632. example, if you set the [classname]#EventMoveHandler# to [literal]#++null++#,
  633. the user will be unable to move events in the browser.
  634. [[components.calendar.customizing.creating]]
  635. === Creating a Calendar
  636. Let us first create a new [classname]#Calendar# instance. Here we use our own
  637. event provider, the [classname]#MyEventProvider# described in
  638. <<components.calendar.eventprovider.eventprovider>>.
  639. [source, java]
  640. ----
  641. Calendar cal = new Calendar(new MyEventProvider());
  642. ----
  643. This initializes the Calendar. To customize the viewable date range, we must set
  644. a start and end date to it.
  645. There is only one visible event in the timeline, starting from the current time.
  646. That is what our event provider passes to the client.//TODO See the figure
  647. 3.
  648. It would be nice to also be able to control the navigation forward and backward.
  649. The default navigation is provided by the default handlers, but perhaps we want
  650. to restrict the users so they can only navigate dates in the current year. Maybe
  651. we also want to pose some other restrictions to the clicking week numbers and
  652. dates.
  653. These restrictions and other custom logic can be defined with custom handlers.
  654. You can find the handlers in the [package]#com.vaadin.addon.calendar.ui.handler#
  655. package and they can be easily extended. Note that if you don not want to extend
  656. the default handlers, you are free to implement your own. The interfaces are
  657. described in [interfacename]#CalendarComponentEvents#.
  658. endif::web[]
  659. [[components.calendar.navigation]]
  660. == Backward and Forward Navigation
  661. Vaadin Calendar has only limited built-in navigation support. The weekly view
  662. has navigation buttons in the top left and top right
  663. corners.
  664. // TODO See the figure 4.
  665. You can handle backward and forward navigation with a
  666. [interfacename]#BackwardListener# and [interfacename]#ForwardListener#.
  667. [source, java]
  668. ----
  669. cal.setHandler(new BasicBackwardHandler() {
  670. protected void setDates(BackwardEvent event,
  671. Date start, Date end) {
  672. java.util.Calendar calendar = event.getComponent()
  673. .getInternalCalendar();
  674. if (isThisYear(calendar, end)
  675. && isThisYear(calendar, start)) {
  676. super.setDates(event, start, end);
  677. }
  678. }});
  679. ----
  680. The forward navigation handler can be implemented in the same way. The example
  681. handler restricts the dates to the current year.
  682. ifdef::web[]
  683. [[components.calendar.dateclick]]
  684. == Date Click Handling
  685. By default, clicking a date either in month or week view switches to single-day
  686. view, while clicking on the date header in the day view has no effect. The date
  687. click event is handled by a [interfacename]#DateClickHandler#.
  688. The following example handles click events on the date header in the day view to
  689. zoom out to the week view. For other clicks it applies the default behavior; in
  690. the week view clicking on a day switches to the day view.
  691. [source, java]
  692. ----
  693. calendar.setHandler(new BasicDateClickHandler() {
  694. public void dateClick(DateClickEvent event) {
  695. Calendar cal = event.getComponent();
  696. // Check if the current range is already one day long
  697. long currentCalDateRange = cal.getEndDate().getTime() -
  698. cal.getStartDate().getTime();
  699. // From one-day view, zoom out to week view
  700. if (currentCalDateRange <= DateConstants.DAYINMILLIS) {
  701. // Change the date range to the current week
  702. GregorianCalendar weekstart = new GregorianCalendar();
  703. GregorianCalendar weekend = new GregorianCalendar();
  704. weekstart.setTime(event.getDate());
  705. weekend.setTime(event.getDate());
  706. weekstart.setFirstDayOfWeek(java.util.Calendar.SUNDAY);
  707. weekstart.set(java.util.Calendar.HOUR_OF_DAY, 0);
  708. weekstart.set(java.util.Calendar.DAY_OF_WEEK,
  709. java.util.Calendar.SUNDAY);
  710. weekend.set(java.util.Calendar.HOUR_OF_DAY, 23);
  711. weekend.set(java.util.Calendar.DAY_OF_WEEK,
  712. java.util.Calendar.SATURDAY);
  713. cal.setStartDate(weekstart.getTime());
  714. cal.setEndDate(weekend.getTime());
  715. Notification.show("Custom zoom to week");
  716. } else {
  717. // Default behavior, change date range to one day
  718. super.dateClick(event);
  719. }
  720. }
  721. });
  722. ----
  723. endif::web[]
  724. ifdef::web[]
  725. [[components.calendar.weekclick]]
  726. == Handling Week Clicks
  727. The monthly view displays week numbers for each week row on the left side of the
  728. date grid. The week number are clickable and you can handle the click events by
  729. setting a [interfacename]#WeekClickHandler# for the [classname]#Calendar#
  730. object. The default handler changes the date range to be the clicked week.
  731. In the following example, we add a week click handler that changes the date
  732. range of the calendar to one week only if the start and end dates of the week
  733. are in the current month.
  734. [source, java]
  735. ----
  736. cal.setHandler(new BasicWeekClickHandler() {
  737. protected void setDates(WeekClick event,
  738. Date start, Date end) {
  739. java.util.Calendar calendar = event.getComponent()
  740. .getInternalCalendar();
  741. if (isThisMonth(calendar, start)
  742. && isThisMonth(calendar, end)) {
  743. super.setDates(event, start, end);
  744. }
  745. }
  746. });
  747. ----
  748. endif::web[]
  749. ifdef::web[]
  750. [[components.calendar.eventclick]]
  751. == Handling Event Clicks
  752. The calendar events in all views are are clickable. There is no default handler.
  753. Just like the date and week click handlers, event click handling is enabled by
  754. setting an [interfacename]#EventClickHandler# for the [classname]#Calendar#
  755. object.
  756. You can get hold of the clicked event by the [methodname]#getCalendarEvent()#
  757. method in the [classname]#EventClick# object passed to the handler, as shown in
  758. the following example.
  759. [source, java]
  760. ----
  761. cal.setHandler(new EventClickHandler() {
  762. public void eventClick(EventClick event) {
  763. BasicEvent e = (BasicEvent) event.getCalendarEvent();
  764. // Do something with it
  765. new Notification("Event clicked: " + e.getCaption(),
  766. e.getDescription()).show(Page.getCurrent());
  767. }
  768. });
  769. ----
  770. endif::web[]
  771. ifdef::web[]
  772. [[components.calendar.eventdrag]]
  773. == Event Dragging
  774. The user can drag an event to change its position in time. The default handler
  775. sets the start and end time of the event accordingly. You can do many things
  776. with a custom move handler, such as restrict moving events.
  777. In the following example, we add a [interfacename]#EventMoveHandler# to a
  778. [classname]#Calendar#. The event handler updates the new position to the
  779. datasource, but only if the new dates are in the current month. This requires
  780. making some changes to the event provider class.
  781. [source, java]
  782. ----
  783. cal.setHandler(new BasicEventMoveHandler() {
  784. private java.util.Calendar javaCalendar;
  785. public void eventMove(MoveEvent event) {
  786. javaCalendar = event.getComponent().getInternalCalendar();
  787. super.eventMove(event);
  788. }
  789. protected void setDates(CalendarEventEditor event,
  790. Date start, Date end) {
  791. if (isThisMonth(javaCalendar, start)
  792. && isThisMonth(javaCalendar, end)) {
  793. super.setDates(event, start, end);
  794. }
  795. }
  796. });
  797. ----
  798. For the above example to work, the example event provider presented earlier
  799. needs to be changed slightly so that it doesn't always create a new event when
  800. [methodname]#getEvents()# is called.
  801. [source, java]
  802. ----
  803. public static class MyEventProvider
  804. implements CalendarEventProvider {
  805. private List<CalendarEvent> events =
  806. new ArrayList<CalendarEvent>();
  807. public MyEventProvider() {
  808. events = new ArrayList<CalendarEvent>();
  809. GregorianCalendar cal = new GregorianCalendar();
  810. cal.setTime(new Date());
  811. Date start = cal.getTime();
  812. cal.add(GregorianCalendar.HOUR, 5);
  813. Date end = cal.getTime();
  814. BasicEvent event = new BasicEvent();
  815. event.setCaption("My Event");
  816. event.setDescription("My Event Description");
  817. event.setStart(start);
  818. event.setEnd(end);
  819. events.add(event);
  820. }
  821. public void addEvent(CalendarEvent BasicEvent) {
  822. events.add(BasicEvent);
  823. }
  824. public List<CalendarEvent> getEvents(Date startDate,
  825. Date endDate) {
  826. return events;
  827. }
  828. }
  829. ----
  830. After these changes, the user can move events around as earlier, but dropping an
  831. event, the start and end dates are checked by the server. Note that as the
  832. server-side must move the event in order for it to render to the place it was
  833. dropped. The server can also reject moves by not doing anything when the event
  834. is received.
  835. endif::web[]
  836. ifdef::web[]
  837. [[components.calendar.dragselection]]
  838. == Handling Drag Selection
  839. Drag selection works both in the monthly and weekly views. To listen for drag
  840. selection, you can add a [interfacename]#RangeSelectListener# to the
  841. [classname]#Calendar#. There is no default handler for range select.
  842. In the code example below, we create an new event when any date range is
  843. selected. Drag selection opens a window where the user is asked for a caption
  844. for the new event. After confirming, the new event is be passed to the event
  845. provider and calendar is updated. Note that as our example event provider and
  846. event classes do not implement the event change interface, we must refresh the
  847. [classname]#Calendar# manually after changing the events.
  848. [source, java]
  849. ----
  850. cal.setHandler(new RangeSelectHandler() {
  851. public void rangeSelect(RangeSelectEvent event) {
  852. BasicEvent calendarEvent = new BasicEvent();
  853. calendarEvent.setStart(event.getStart());
  854. calendarEvent.setEnd(event.getEnd());
  855. // Create popup window and add a form in it.
  856. VerticalLayout layout = new VerticalLayout();
  857. layout.setMargin(true);
  858. layout.setSpacing(true);
  859. final Window w = new Window(null, layout);
  860. ...
  861. // Wrap the calendar event to a BeanItem
  862. // and pass it to the form
  863. final BeanItem<CalendarEvent> item =
  864. new BeanItem<CalendarEvent>(myEvent);
  865. final Form form = new Form();
  866. form.setItemDataSource(item);
  867. ...
  868. layout.addComponent(form);
  869. HorizontalLayout buttons = new HorizontalLayout();
  870. buttons.setSpacing(true);
  871. buttons.addComponent(new Button("OK", new ClickListener() {
  872. public void buttonClick(ClickEvent event) {
  873. form.commit();
  874. // Update event provider's data source
  875. provider.addEvent(item.getBean());
  876. UI.getCurrent().removeWindow(w);
  877. }
  878. }));
  879. ...
  880. }
  881. });
  882. ----
  883. endif::web[]
  884. ifdef::web[]
  885. [[components.calendar.eventresizing]]
  886. == Resizing Events
  887. The user can resize an event by dragging from both ends to change its start or
  888. end time. This offers a convenient way to change event times without the need to
  889. type anything. The default resize handler sets the start and end time of the
  890. event according to the resize.
  891. In the example below, we set a custom handler for resize events. The handler
  892. prevents any event to be resized over 12 hours in length. Note that this does
  893. not prevent the user from resizing an event over 12 hours in the client. The
  894. resize will just be corrected by the server.
  895. [source, java]
  896. ----
  897. cal.setHandler(new BasicEventResizeHandler() {
  898. private static final long twelveHoursInMs = 12*60*60*1000;
  899. protected void setDates(CalendarEventEditor event,
  900. Date start, Date end) {
  901. long eventLength = end.getTime() - start.getTime();
  902. if (eventLength <= twelveHoursInMs) {
  903. super.setDates(event, start, end);
  904. }
  905. }
  906. });
  907. ----
  908. endif::web[]