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.

FlyweightCell.java 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Copyright 2000-2018 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.client.widget.escalator;
  17. import java.util.List;
  18. import com.google.gwt.dom.client.Style.Display;
  19. import com.google.gwt.dom.client.Style.Unit;
  20. import com.google.gwt.dom.client.TableCellElement;
  21. import com.vaadin.client.widget.escalator.FlyweightRow.CellIterator;
  22. import com.vaadin.client.widgets.Escalator;
  23. /**
  24. * A {@link FlyweightCell} represents a cell in the
  25. * {@link com.vaadin.client.widgets.Grid Grid} or {@link Escalator} at a certain
  26. * point in time.
  27. *
  28. * <p>
  29. * Since the {@link FlyweightCell} follows the <code>Flyweight</code>-pattern
  30. * any instance of this object is subject to change without the user knowing it
  31. * and so should not be stored anywhere outside of the method providing these
  32. * instances.
  33. *
  34. * @since 7.4
  35. * @author Vaadin Ltd
  36. */
  37. public class FlyweightCell {
  38. public static final String COLSPAN_ATTR = "colSpan";
  39. private final int column;
  40. private final FlyweightRow row;
  41. private TableCellElement element = null;
  42. private CellIterator currentIterator = null;
  43. public FlyweightCell(final FlyweightRow row, final int column) {
  44. this.row = row;
  45. this.column = column;
  46. }
  47. /**
  48. * Returns the row index of the cell.
  49. */
  50. public int getRow() {
  51. assertSetup();
  52. return row.getRow();
  53. }
  54. /**
  55. * Returns the column index of the cell.
  56. */
  57. public int getColumn() {
  58. assertSetup();
  59. return column;
  60. }
  61. /**
  62. * Returns the element of the cell. Can be either a <code>TD</code> element
  63. * or a <code>TH</code> element.
  64. */
  65. public TableCellElement getElement() {
  66. assertSetup();
  67. return element;
  68. }
  69. /**
  70. * Return the colspan attribute of the element of the cell.
  71. */
  72. public int getColSpan() {
  73. assertSetup();
  74. return element.getPropertyInt(COLSPAN_ATTR);
  75. }
  76. /**
  77. * Sets the DOM element for this FlyweightCell, either a <code>TD</code> or
  78. * a <code>TH</code>. It is the caller's responsibility to actually insert
  79. * the given element to the document when needed.
  80. *
  81. * @param element
  82. * the element corresponding to this cell, cannot be null
  83. */
  84. public void setElement(TableCellElement element) {
  85. assert element != null;
  86. assertSetup();
  87. this.element = element;
  88. }
  89. void setup(final CellIterator iterator) {
  90. currentIterator = iterator;
  91. if (iterator.areCellsAttached()) {
  92. final TableCellElement e = row.getElement().getCells()
  93. .getItem(column);
  94. assert e != null : "Cell " + column + " for logical row "
  95. + row.getRow() + " doesn't exist in the DOM!";
  96. e.setPropertyInt(COLSPAN_ATTR, 1);
  97. if (row.getColumnWidth(column) >= 0) {
  98. e.getStyle().setWidth(row.getColumnWidth(column), Unit.PX);
  99. }
  100. e.getStyle().clearDisplay();
  101. setElement(e);
  102. }
  103. }
  104. /**
  105. * Tear down the state of the Cell.
  106. * <p>
  107. * This is an internal check method, to prevent retrieving uninitialized
  108. * data by calling {@link #getRow()}, {@link #getColumn()} or
  109. * {@link #getElement()} at an improper time.
  110. * <p>
  111. * This should only be used with asserts ("
  112. * <code>assert flyweightCell.teardown()</code> ") so that the code is never
  113. * run when asserts aren't enabled.
  114. *
  115. * @return always <code>true</code>
  116. * @see FlyweightRow#teardown()
  117. */
  118. boolean teardown() {
  119. currentIterator = null;
  120. element = null;
  121. return true;
  122. }
  123. /**
  124. * Asserts that the flyweight cell has properly been set up before trying to
  125. * access any of its data.
  126. */
  127. private void assertSetup() {
  128. assert currentIterator != null : "FlyweightCell was not properly "
  129. + "initialized. This is either a bug in Grid/Escalator "
  130. + "or a Cell reference has been stored and reused "
  131. + "inappropriately.";
  132. }
  133. public void setColSpan(final int numberOfCells) {
  134. if (numberOfCells < 1) {
  135. throw new IllegalArgumentException(
  136. "Number of cells should be more than 0");
  137. }
  138. /*-
  139. * This will default to 1 if unset, as per DOM specifications:
  140. * http://www.w3.org/TR/html5/tabular-data.html#attributes-common-to-td-and-th-elements
  141. */
  142. final int prevColSpan = getElement().getPropertyInt(COLSPAN_ATTR);
  143. if (numberOfCells == 1 && prevColSpan == 1) {
  144. return;
  145. }
  146. getElement().setPropertyInt(COLSPAN_ATTR, numberOfCells);
  147. adjustCellWidthForSpan(numberOfCells);
  148. hideOrRevealAdjacentCellElements(numberOfCells, prevColSpan);
  149. currentIterator.setSkipNext(numberOfCells - 1);
  150. }
  151. private void adjustCellWidthForSpan(final int numberOfCells) {
  152. final int cellsToTheRight = currentIterator
  153. .rawPeekNext(numberOfCells - 1).size();
  154. final double selfWidth = row.getColumnWidth(column);
  155. double widthsOfColumnsToTheRight = 0;
  156. for (int i = 0; i < cellsToTheRight; i++) {
  157. widthsOfColumnsToTheRight += row.getColumnWidth(column + i + 1);
  158. }
  159. getElement().getStyle().setWidth(selfWidth + widthsOfColumnsToTheRight,
  160. Unit.PX);
  161. }
  162. private void hideOrRevealAdjacentCellElements(final int numberOfCells,
  163. final int prevColSpan) {
  164. final int affectedCellsNumber = Math.max(prevColSpan, numberOfCells);
  165. final List<FlyweightCell> affectedCells = currentIterator
  166. .rawPeekNext(affectedCellsNumber - 1);
  167. if (prevColSpan < numberOfCells) {
  168. for (int i = 0; i < affectedCells.size(); i++) {
  169. affectedCells.get(prevColSpan + i - 1).getElement().getStyle()
  170. .setDisplay(Display.NONE);
  171. }
  172. } else if (prevColSpan > numberOfCells) {
  173. for (int i = 0; i < affectedCells.size(); i++) {
  174. affectedCells.get(numberOfCells + i - 1).getElement().getStyle()
  175. .clearDisplay();
  176. }
  177. }
  178. }
  179. }