Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

PopupView.java 14KB

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