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.

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