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.

AbstractOrderedLayout.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. @ITMillApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.ui;
  5. import java.util.HashMap;
  6. import java.util.Iterator;
  7. import java.util.LinkedList;
  8. import java.util.Map;
  9. import com.vaadin.event.LayoutEvents.LayoutClickEvent;
  10. import com.vaadin.event.LayoutEvents.LayoutClickListener;
  11. import com.vaadin.terminal.PaintException;
  12. import com.vaadin.terminal.PaintTarget;
  13. import com.vaadin.terminal.Sizeable;
  14. import com.vaadin.terminal.gwt.client.MouseEventDetails;
  15. import com.vaadin.terminal.gwt.client.ui.VOrderedLayout;
  16. @SuppressWarnings("serial")
  17. public abstract class AbstractOrderedLayout extends AbstractLayout implements
  18. Layout.AlignmentHandler, Layout.SpacingHandler {
  19. private static final String CLICK_EVENT = VOrderedLayout.CLICK_EVENT_IDENTIFIER;
  20. private static final Alignment ALIGNMENT_DEFAULT = Alignment.TOP_LEFT;
  21. /**
  22. * Custom layout slots containing the components.
  23. */
  24. protected LinkedList<Component> components = new LinkedList<Component>();
  25. /* Child component alignments */
  26. /**
  27. * Mapping from components to alignments (horizontal + vertical).
  28. */
  29. private final Map<Component, Alignment> componentToAlignment = new HashMap<Component, Alignment>();
  30. private final Map<Component, Float> componentToExpandRatio = new HashMap<Component, Float>();
  31. /**
  32. * Is spacing between contained components enabled. Defaults to false.
  33. */
  34. private boolean spacing = false;
  35. /**
  36. * Add a component into this container. The component is added to the right
  37. * or under the previous component.
  38. *
  39. * @param c
  40. * the component to be added.
  41. */
  42. @Override
  43. public void addComponent(Component c) {
  44. super.addComponent(c);
  45. components.add(c);
  46. requestRepaint();
  47. }
  48. /**
  49. * Adds a component into this container. The component is added to the left
  50. * or on top of the other components.
  51. *
  52. * @param c
  53. * the component to be added.
  54. */
  55. public void addComponentAsFirst(Component c) {
  56. super.addComponent(c);
  57. components.addFirst(c);
  58. requestRepaint();
  59. }
  60. /**
  61. * Adds a component into indexed position in this container.
  62. *
  63. * @param c
  64. * the component to be added.
  65. * @param index
  66. * the Index of the component position. The components currently
  67. * in and after the position are shifted forwards.
  68. */
  69. public void addComponent(Component c, int index) {
  70. super.addComponent(c);
  71. components.add(index, c);
  72. requestRepaint();
  73. }
  74. /**
  75. * Removes the component from this container.
  76. *
  77. * @param c
  78. * the component to be removed.
  79. */
  80. @Override
  81. public void removeComponent(Component c) {
  82. super.removeComponent(c);
  83. components.remove(c);
  84. componentToAlignment.remove(c);
  85. componentToExpandRatio.remove(c);
  86. requestRepaint();
  87. }
  88. /**
  89. * Gets the component container iterator for going trough all the components
  90. * in the container.
  91. *
  92. * @return the Iterator of the components inside the container.
  93. */
  94. public Iterator getComponentIterator() {
  95. return components.iterator();
  96. }
  97. /**
  98. * Paints the content of this component.
  99. *
  100. * @param target
  101. * the Paint Event.
  102. * @throws PaintException
  103. * if the paint operation failed.
  104. */
  105. @Override
  106. public void paintContent(PaintTarget target) throws PaintException {
  107. super.paintContent(target);
  108. // Add spacing attribute (omitted if false)
  109. if (spacing) {
  110. target.addAttribute("spacing", spacing);
  111. }
  112. // Adds all items in all the locations
  113. for (Component c : components) {
  114. // Paint child component UIDL
  115. c.paint(target);
  116. }
  117. // Add child component alignment info to layout tag
  118. target.addAttribute("alignments", componentToAlignment);
  119. target.addAttribute("expandRatios", componentToExpandRatio);
  120. }
  121. /* Documented in superclass */
  122. public void replaceComponent(Component oldComponent, Component newComponent) {
  123. // Gets the locations
  124. int oldLocation = -1;
  125. int newLocation = -1;
  126. int location = 0;
  127. for (final Iterator i = components.iterator(); i.hasNext();) {
  128. final Component component = (Component) i.next();
  129. if (component == oldComponent) {
  130. oldLocation = location;
  131. }
  132. if (component == newComponent) {
  133. newLocation = location;
  134. }
  135. location++;
  136. }
  137. if (oldLocation == -1) {
  138. addComponent(newComponent);
  139. } else if (newLocation == -1) {
  140. removeComponent(oldComponent);
  141. addComponent(newComponent, oldLocation);
  142. } else {
  143. if (oldLocation > newLocation) {
  144. components.remove(oldComponent);
  145. components.add(newLocation, oldComponent);
  146. components.remove(newComponent);
  147. componentToAlignment.remove(newComponent);
  148. components.add(oldLocation, newComponent);
  149. } else {
  150. components.remove(newComponent);
  151. components.add(oldLocation, newComponent);
  152. components.remove(oldComponent);
  153. componentToAlignment.remove(oldComponent);
  154. components.add(newLocation, oldComponent);
  155. }
  156. requestRepaint();
  157. }
  158. }
  159. /*
  160. * (non-Javadoc)
  161. *
  162. * @see com.vaadin.ui.Layout.AlignmentHandler#setComponentAlignment(com
  163. * .vaadin.ui.Component, int, int)
  164. */
  165. public void setComponentAlignment(Component childComponent,
  166. int horizontalAlignment, int verticalAlignment) {
  167. if (components.contains(childComponent)) {
  168. // Alignments are bit masks
  169. componentToAlignment.put(childComponent, new Alignment(
  170. horizontalAlignment + verticalAlignment));
  171. requestRepaint();
  172. } else {
  173. throw new IllegalArgumentException(
  174. "Component must be added to layout before using setComponentAlignment()");
  175. }
  176. }
  177. public void setComponentAlignment(Component childComponent,
  178. Alignment alignment) {
  179. if (components.contains(childComponent)) {
  180. componentToAlignment.put(childComponent, alignment);
  181. requestRepaint();
  182. } else {
  183. throw new IllegalArgumentException(
  184. "Component must be added to layout before using setComponentAlignment()");
  185. }
  186. }
  187. /*
  188. * (non-Javadoc)
  189. *
  190. * @see com.vaadin.ui.Layout.AlignmentHandler#getComponentAlignment(com
  191. * .vaadin.ui.Component)
  192. */
  193. public Alignment getComponentAlignment(Component childComponent) {
  194. Alignment alignment = componentToAlignment.get(childComponent);
  195. if (alignment == null) {
  196. return ALIGNMENT_DEFAULT;
  197. } else {
  198. return alignment;
  199. }
  200. }
  201. /*
  202. * (non-Javadoc)
  203. *
  204. * @see com.vaadin.ui.Layout.SpacingHandler#setSpacing(boolean)
  205. */
  206. public void setSpacing(boolean enabled) {
  207. spacing = enabled;
  208. requestRepaint();
  209. }
  210. /*
  211. * (non-Javadoc)
  212. *
  213. * @see com.vaadin.ui.Layout.SpacingHandler#isSpacing()
  214. */
  215. @Deprecated
  216. public boolean isSpacingEnabled() {
  217. return spacing;
  218. }
  219. /*
  220. * (non-Javadoc)
  221. *
  222. * @see com.vaadin.ui.Layout.SpacingHandler#isSpacing()
  223. */
  224. public boolean isSpacing() {
  225. return spacing;
  226. }
  227. /**
  228. * <p>
  229. * This method is used to control how excess space in layout is distributed
  230. * among components. Excess space may exist if layout is sized and contained
  231. * non relatively sized components don't consume all available space.
  232. *
  233. * <p>
  234. * Example how to distribute 1:3 (33%) for component1 and 2:3 (67%) for
  235. * component2 :
  236. *
  237. * <code>
  238. * layout.setExpandRatio(component1, 1);<br>
  239. * layout.setExpandRatio(component2, 2);
  240. * </code>
  241. *
  242. * <p>
  243. * If no ratios have been set, the excess space is distributed evenly among
  244. * all components.
  245. *
  246. * <p>
  247. * Note, that width or height (depending on orientation) needs to be defined
  248. * for this method to have any effect.
  249. *
  250. * @see Sizeable
  251. *
  252. * @param component
  253. * the component in this layout which expand ratio is to be set
  254. * @param ratio
  255. */
  256. public void setExpandRatio(Component component, float ratio) {
  257. if (components.contains(component)) {
  258. componentToExpandRatio.put(component, ratio);
  259. requestRepaint();
  260. } else {
  261. throw new IllegalArgumentException(
  262. "Component must be added to layout before using setExpandRatio()");
  263. }
  264. };
  265. /**
  266. * Returns the expand ratio of given component.
  267. *
  268. * @param component
  269. * which expand ratios is requested
  270. * @return expand ratio of given component, 0.0f by default
  271. */
  272. public float getExpandRatio(Component component) {
  273. Float ratio = componentToExpandRatio.get(component);
  274. return (ratio == null) ? 0 : ratio.floatValue();
  275. }
  276. public void setComponentAlignment(Component component, String alignment) {
  277. AlignmentUtils.setComponentAlignment(this, component, alignment);
  278. }
  279. @Override
  280. public void changeVariables(Object source, Map variables) {
  281. super.changeVariables(source, variables);
  282. if (variables.containsKey(CLICK_EVENT)) {
  283. fireClick((Object[]) variables.get(CLICK_EVENT));
  284. }
  285. }
  286. private void fireClick(Object[] parameters) {
  287. MouseEventDetails mouseDetails = MouseEventDetails
  288. .deserialize((String) parameters[0]);
  289. Component childComponent = (Component) parameters[1];
  290. fireEvent(new LayoutClickEvent(this, mouseDetails, childComponent));
  291. }
  292. public void addListener(LayoutClickListener listener) {
  293. addListener(CLICK_EVENT, LayoutClickEvent.class, listener,
  294. LayoutClickListener.clickMethod);
  295. }
  296. public void removeListener(LayoutClickListener listener) {
  297. removeListener(CLICK_EVENT, LayoutClickEvent.class, listener);
  298. }
  299. }