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.

IntegratingAnExistingGWTWidget.asciidoc 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. ---
  2. title: Integrating An Existing GWT Widget
  3. order: 33
  4. layout: page
  5. ---
  6. [[integrating-an-existing-gwt-widget]]
  7. Integrating an existing GWT widget
  8. ----------------------------------
  9. Integrating an existing, third party GWT widget usually just involves
  10. creating a regular Vaadin component with a client-side connector that
  11. uses the third-party widget, probably using a shared state, and possibly
  12. also with RPC - just as described in separate articles on these topics.
  13. Usually, the only addition is the need to modify your widgetset
  14. declaration to inherit the third-party widget's GWT module.
  15. In the following, we'll integrate the SimplePlot widget from the
  16. http://code.google.com/p/gflot/[GFlot library] (which in turn is a GWT
  17. adaptation of the pure JavaScript plotting library Flot) to create a
  18. simple line plot component. We'll start with modifying our widgetset's
  19. `gwt.xml` to inherit the GFlot GWT module, so if you're familiar with the
  20. rest of the process, you can basically stop once that is done.
  21. But first a note on package structure: this particular example uses the
  22. `com.example` package domain, and is set up to be a add-on project, with
  23. the actual component in the `addon` package, and the demo that uses the
  24. component in the `vaadingflot` package. The `addon` package contains the
  25. `widgetset gwt.xml` definition, the server-side component (LinePlot), as
  26. well as all the code related to the client-side in the `client.ui`
  27. subpackage.
  28. Once you have a working project, go ahead and
  29. http://code.google.com/p/gflot/downloads/list[download the GFlot jar],
  30. and add it to `WEB-INF/lib`, then update the widgetset `gwt.xml` as follows:
  31. [source,xml]
  32. ....
  33. <?xml version="1.0" encoding="UTF-8"?>
  34. <!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.7.0//EN"
  35. "http://google-web-toolkit.googlecode.com/svn/tags/1.7.0/distro-source/core/src/gwt-module.dtd">
  36. <module>
  37. <inherits name="com.vaadin.DefaultWidgetSet" />
  38. <inherits name="ca.nanometrics.gflot.GFlot" />
  39. </module>
  40. ....
  41. It inherits the default Vaadin widgetset as well as the GFlot GWT
  42. module.
  43. Now we're ready to integrate the SimplePlot widget from the GFlot
  44. package. Since we're familiar with the GFlot API, we know we want to add
  45. 'series' to the plot - we'll create a shared state for this purpose, and
  46. a `DataSeries` class to represent the actual series within the state:
  47. [source,java]
  48. ....
  49. package com.example.addon.client.ui;
  50. import java.util.ArrayList;
  51. import java.util.List;
  52. import com.vaadin.client.ComponentState;
  53. public class LinePlotState extends AbstractComponentState {
  54. public List<DataSeries> series = new ArrayList<DataSeries>();
  55. public static class DataSeries {
  56. public String label;
  57. public String color;
  58. public List<Float> data;
  59. }
  60. }
  61. ....
  62. Lets make the server-side component next:
  63. [source,java]
  64. ....
  65. package com.example.addon;
  66. import java.util.Arrays;
  67. import com.example.addon.client.ui.LinePlotState;
  68. import com.example.addon.client.ui.LinePlotState.DataSeries;
  69. import com.vaadin.ui.AbstractComponent;
  70. public class LinePlot extends AbstractComponent {
  71. public LinePlot() {
  72. }
  73. @Override
  74. public LinePlotState getState() {
  75. return (LinePlotState) super.getState();
  76. }
  77. public void addSeries(String label, String color, Float[] fs) {
  78. DataSeries ds = new DataSeries();
  79. ds.label = label;
  80. ds.color = color;
  81. ds.data = Arrays.asList(fs);
  82. getState().series.add(ds);
  83. }
  84. }
  85. ....
  86. We override `getState()` in order to narrow the return type to our own
  87. `LinePlotState`, and then implement a simple `addSeries()` that creates a
  88. `DataSeries` instance and adds it to the state. The state will be
  89. automatically transmitted to the client when needed, so the plots will
  90. remain intact over browser reloads for instance.The API for our
  91. component could obviously be expanded, but lets leave it like this for
  92. this example.
  93. Since the GWT widget we're going to use is already made for us (in the
  94. GFlot library), the only thing left for us to do is implement the
  95. client-side connector:
  96. [source,java]
  97. ....
  98. package com.example.addon.client.ui;
  99. import ca.nanometrics.gflot.client.DataPoint;
  100. import ca.nanometrics.gflot.client.SeriesHandler;
  101. import ca.nanometrics.gflot.client.SimplePlot;
  102. import com.example.addon.LinePlot;
  103. import com.example.addon.client.ui.LinePlotState.DataSeries;
  104. import com.google.gwt.core.client.GWT;
  105. import com.google.gwt.user.client.ui.Widget;
  106. import com.vaadin.client.communication.StateChangeEvent;
  107. import com.vaadin.client.ui.AbstractComponentConnector;
  108. import com.vaadin.client.ui.Connect;
  109. @Connect(LinePlot.class)
  110. public class LinePlotConnector extends AbstractComponentConnector {
  111. @Override
  112. public LinePlotState getState() {
  113. return (LinePlotState) super.getState();
  114. }
  115. @Override
  116. public SimplePlot getWidget() {
  117. return (SimplePlot) super.getWidget();
  118. }
  119. @Override
  120. protected Widget createWidget() {
  121. return GWT.create(SimplePlot.class);
  122. }
  123. @Override
  124. public void onStateChanged(StateChangeEvent stateChangeEvent) {
  125. super.onStateChanged(stateChangeEvent);
  126. getWidget().getModel().clear();
  127. for (DataSeries ds : getState().series) {
  128. SeriesHandler s = getWidget().getModel().addSeries(ds.label,
  129. ds.color);
  130. for (int i = 0; i < ds.data.size(); i++) {
  131. s.add(new DataPoint(i, ds.data.get(i)));
  132. }
  133. }
  134. getWidget().redraw();
  135. }
  136. }
  137. ....
  138. We override both `getState()` and `getWidget()` to narrow the return type to
  139. our liking, then make `createWidget()` return an instance of the GFlot
  140. widget we're going to use, `SimplePlot`.
  141. Last, we override `onStateChange()` which is called whenever the shared
  142. state has been changed. Here we make use of the `SimplePlot` API to add
  143. the series contained in the shared state (for simplicity, we clear the
  144. `SimplePlot` first, then add all the series in our state).
  145. That's it! The full source is available as an attachment to this
  146. article.
  147. link:img/vaadingflot.zip[Attachment vaadingflot.zip]