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.

PopupView.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. package com.vaadin.ui;
  2. import java.io.Serializable;
  3. import java.lang.reflect.Method;
  4. import java.util.Iterator;
  5. import java.util.Map;
  6. import com.vaadin.terminal.PaintException;
  7. import com.vaadin.terminal.PaintTarget;
  8. import com.vaadin.terminal.gwt.client.ui.VPopupView;
  9. /**
  10. *
  11. * A component for displaying a two different views to data. The minimized view
  12. * is normally used to render the component, and when it is clicked the full
  13. * view is displayed on a popup. The inner class {@link PopupView.Content} is
  14. * used to deliver contents to this component.
  15. *
  16. * @author IT Mill Ltd.
  17. */
  18. @SuppressWarnings("serial")
  19. @ClientWidget(VPopupView.class)
  20. public class PopupView extends AbstractComponentContainer {
  21. private Content content;
  22. private boolean hideOnMouseOut;
  23. private Component visibleComponent;
  24. private static final Method POPUP_VISIBILITY_METHOD;
  25. static {
  26. try {
  27. POPUP_VISIBILITY_METHOD = PopupVisibilityListener.class
  28. .getDeclaredMethod("popupVisibilityChange",
  29. new Class[] { PopupVisibilityEvent.class });
  30. } catch (final java.lang.NoSuchMethodException e) {
  31. // This should never happen
  32. throw new java.lang.RuntimeException(
  33. "Internal error finding methods in PopupView");
  34. }
  35. }
  36. /* Constructors */
  37. /**
  38. * A simple way to create a PopupPanel. Note that the minimal representation
  39. * may not be dynamically updated, in order to achieve this create your own
  40. * Content object and use {@link PopupView#PopupView(Content)}.
  41. *
  42. * @param small
  43. * the minimal textual representation as HTML
  44. * @param large
  45. * the full, Component-type representation
  46. */
  47. public PopupView(final java.lang.String small, final Component large) {
  48. this(new PopupView.Content() {
  49. public java.lang.String getMinimizedValueAsHTML() {
  50. return small;
  51. }
  52. public Component getPopupComponent() {
  53. return large;
  54. }
  55. });
  56. }
  57. /**
  58. * Creates a PopupView through the PopupView.Content interface. This allows
  59. * the creator to dynamically change the contents of the PopupView.
  60. *
  61. * @param content
  62. * the PopupView.Content that contains the information for this
  63. */
  64. public PopupView(PopupView.Content content) {
  65. super();
  66. hideOnMouseOut = true;
  67. setContent(content);
  68. }
  69. /**
  70. * This method will replace the current content of the panel with a new one.
  71. *
  72. * @param newContent
  73. * PopupView.Content object containing new information for the
  74. * PopupView
  75. * @throws IllegalArgumentException
  76. * if the method is passed a null value, or if one of the
  77. * content methods returns null
  78. */
  79. public void setContent(PopupView.Content newContent)
  80. throws IllegalArgumentException {
  81. if (newContent == null) {
  82. throw new IllegalArgumentException("Content must not be null");
  83. }
  84. content = newContent;
  85. requestRepaint();
  86. }
  87. /**
  88. * Returns the content-package for this PopupView.
  89. *
  90. * @return the PopupView.Content for this object or null
  91. */
  92. public PopupView.Content getContent() {
  93. return content;
  94. }
  95. /**
  96. * @deprecated Use {@link #setPopupVisible()} instead.
  97. */
  98. @Deprecated
  99. public void setPopupVisibility(boolean visible) {
  100. setPopupVisible(visible);
  101. }
  102. /**
  103. * @deprecated Use {@link #isPopupVisible()} instead.
  104. */
  105. @Deprecated
  106. public boolean getPopupVisibility() {
  107. return isPopupVisible();
  108. }
  109. /**
  110. * Set the visibility of the popup. Does not hide the minimal
  111. * representation.
  112. *
  113. * @param visible
  114. */
  115. public void setPopupVisible(boolean visible) {
  116. if (isPopupVisible() != visible) {
  117. if (visible) {
  118. visibleComponent = content.getPopupComponent();
  119. if (visibleComponent == null) {
  120. throw new java.lang.IllegalStateException(
  121. "PopupView.Content did not return Component to set visible");
  122. }
  123. super.addComponent(visibleComponent);
  124. } else {
  125. super.removeComponent(visibleComponent);
  126. visibleComponent = null;
  127. }
  128. fireEvent(new PopupVisibilityEvent(this));
  129. requestRepaint();
  130. }
  131. }
  132. /**
  133. * Return whether the popup is visible.
  134. *
  135. * @return true if the popup is showing
  136. */
  137. public boolean isPopupVisible() {
  138. return visibleComponent != null;
  139. }
  140. /**
  141. * Check if this popup will be hidden when the user takes the mouse cursor
  142. * out of the popup area.
  143. *
  144. * @return true if the popup is hidden on mouse out, false otherwise
  145. */
  146. public boolean isHideOnMouseOut() {
  147. return hideOnMouseOut;
  148. }
  149. /**
  150. * Should the popup automaticly hide when the user takes the mouse cursor
  151. * out of the popup area? If this is false, the user must click outside the
  152. * popup to close it. The default is true.
  153. *
  154. * @param hideOnMouseOut
  155. *
  156. */
  157. public void setHideOnMouseOut(boolean hideOnMouseOut) {
  158. this.hideOnMouseOut = hideOnMouseOut;
  159. }
  160. /*
  161. * Methods inherited from AbstractComponentContainer. These are unnecessary
  162. * (but mandatory). Most of them are not supported in this implementation.
  163. */
  164. /**
  165. * This class only contains other components when the popup is showing.
  166. *
  167. * @see com.vaadin.ui.ComponentContainer#getComponentIterator()
  168. */
  169. public Iterator<Component> getComponentIterator() {
  170. return new Iterator<Component>() {
  171. private boolean first = visibleComponent == null;
  172. public boolean hasNext() {
  173. return !first;
  174. }
  175. public Component next() {
  176. if (!first) {
  177. first = true;
  178. return visibleComponent;
  179. } else {
  180. return null;
  181. }
  182. }
  183. public void remove() {
  184. throw new UnsupportedOperationException();
  185. }
  186. };
  187. }
  188. /**
  189. * Not supported in this implementation.
  190. *
  191. * @see com.vaadin.ui.AbstractComponentContainer#removeAllComponents()
  192. * @throws UnsupportedOperationException
  193. */
  194. @Override
  195. public void removeAllComponents() {
  196. throw new UnsupportedOperationException();
  197. }
  198. /**
  199. * Not supported in this implementation.
  200. *
  201. * @see com.vaadin.ui.AbstractComponentContainer#moveComponentsFrom(com.vaadin.ui.ComponentContainer)
  202. * @throws UnsupportedOperationException
  203. */
  204. @Override
  205. public void moveComponentsFrom(ComponentContainer source)
  206. throws UnsupportedOperationException {
  207. throw new UnsupportedOperationException();
  208. }
  209. /**
  210. * Not supported in this implementation.
  211. *
  212. * @see com.vaadin.ui.AbstractComponentContainer#addComponent(com.vaadin.ui.Component)
  213. * @throws UnsupportedOperationException
  214. */
  215. @Override
  216. public void addComponent(Component c) throws UnsupportedOperationException {
  217. throw new UnsupportedOperationException();
  218. }
  219. /**
  220. * Not supported in this implementation.
  221. *
  222. * @see com.vaadin.ui.ComponentContainer#replaceComponent(com.vaadin.ui.Component,
  223. * com.vaadin.ui.Component)
  224. * @throws UnsupportedOperationException
  225. */
  226. public void replaceComponent(Component oldComponent, Component newComponent)
  227. throws UnsupportedOperationException {
  228. throw new UnsupportedOperationException();
  229. }
  230. /**
  231. * Not supported in this implementation
  232. *
  233. * @see com.vaadin.ui.AbstractComponentContainer#removeComponent(com.vaadin.ui.Component)
  234. */
  235. @Override
  236. public void removeComponent(Component c)
  237. throws UnsupportedOperationException {
  238. throw new UnsupportedOperationException();
  239. }
  240. /*
  241. * Methods for server-client communications.
  242. */
  243. /**
  244. * @see com.vaadin.ui.AbstractComponent#getTag()
  245. */
  246. @Override
  247. public java.lang.String getTag() {
  248. return "popupview";
  249. }
  250. /**
  251. * Paint (serialize) the component for the client.
  252. *
  253. * @see com.vaadin.ui.AbstractComponent#paintContent(com.vaadin.terminal.PaintTarget)
  254. */
  255. @Override
  256. public void paintContent(PaintTarget target) throws PaintException {
  257. // Superclass writes any common attributes in the paint target.
  258. super.paintContent(target);
  259. String html = content.getMinimizedValueAsHTML();
  260. if (html == null) {
  261. html = "";
  262. }
  263. target.addAttribute("html", html);
  264. target.addAttribute("hideOnMouseOut", hideOnMouseOut);
  265. // Only paint component to client if we know that the popup is showing
  266. if (isPopupVisible()) {
  267. target.startTag("popupComponent");
  268. visibleComponent.paint(target);
  269. target.endTag("popupComponent");
  270. }
  271. target.addVariable(this, "popupVisibility", isPopupVisible());
  272. }
  273. /**
  274. * Deserialize changes received from client.
  275. *
  276. * @see com.vaadin.ui.AbstractComponent#changeVariables(java.lang.Object,
  277. * java.util.Map)
  278. */
  279. @Override
  280. public void changeVariables(Object source, Map variables) {
  281. if (variables.containsKey("popupVisibility")) {
  282. setPopupVisible(((Boolean) variables.get("popupVisibility"))
  283. .booleanValue());
  284. }
  285. }
  286. /**
  287. * Used to deliver customized content-packages to the PopupView. These are
  288. * dynamically loaded when they are redrawn. The user must take care that
  289. * neither of these methods ever return null.
  290. */
  291. public interface Content extends Serializable {
  292. /**
  293. * This should return a small view of the full data.
  294. *
  295. * @return value in HTML format
  296. */
  297. public String getMinimizedValueAsHTML();
  298. /**
  299. * This should return the full Component representing the data
  300. *
  301. * @return a Component for the value
  302. */
  303. public Component getPopupComponent();
  304. }
  305. /**
  306. * Add a listener that is called whenever the visibility of the popup is
  307. * changed.
  308. *
  309. * @param listener
  310. * the listener to add
  311. * @see PopupVisibilityListener
  312. * @see PopupVisibilityEvent
  313. * @see #removeListener(PopupVisibilityListener)
  314. *
  315. */
  316. public void addListener(PopupVisibilityListener listener) {
  317. addListener(PopupVisibilityEvent.class, listener,
  318. POPUP_VISIBILITY_METHOD);
  319. }
  320. /**
  321. * Removes a previously added listener, so that it no longer receives events
  322. * when the visibility of the popup changes.
  323. *
  324. * @param listener
  325. * the listener to remove
  326. * @see PopupVisibilityListener
  327. * @see #addListener(PopupVisibilityListener)
  328. */
  329. public void removeListener(PopupVisibilityListener listener) {
  330. removeListener(PopupVisibilityEvent.class, listener,
  331. POPUP_VISIBILITY_METHOD);
  332. }
  333. /**
  334. * This event is received by the PopupVisibilityListeners when the
  335. * visibility of the popup changes. You can get the new visibility directly
  336. * with {@link #isPopupVisible()}, or get the PopupView that produced the
  337. * event with {@link #getPopupView()}.
  338. *
  339. */
  340. public class PopupVisibilityEvent extends Event {
  341. public PopupVisibilityEvent(PopupView source) {
  342. super(source);
  343. }
  344. /**
  345. * Get the PopupView instance that is the source of this event.
  346. *
  347. * @return the source PopupView
  348. */
  349. public PopupView getPopupView() {
  350. return (PopupView) getSource();
  351. }
  352. /**
  353. * Returns the current visibility of the popup.
  354. *
  355. * @return true if the popup is visible
  356. */
  357. public boolean isPopupVisible() {
  358. return getPopupView().isPopupVisible();
  359. }
  360. }
  361. /**
  362. * Defines a listener that can receive a PopupVisibilityEvent when the
  363. * visibility of the popup changes.
  364. *
  365. */
  366. public interface PopupVisibilityListener extends Serializable {
  367. /**
  368. * Pass to {@link PopupView#PopupVisibilityEvent} to start listening for
  369. * popup visibility changes.
  370. *
  371. * @param event
  372. * the event
  373. *
  374. * @see {@link PopupVisibilityEvent}
  375. * @see {@link PopupView#addListener(PopupVisibilityListener)}
  376. */
  377. public void popupVisibilityChange(PopupVisibilityEvent event);
  378. }
  379. }