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.

TableConnector.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /*
  2. @VaadinApache2LicenseForJavaFiles@
  3. */
  4. package com.vaadin.terminal.gwt.client.ui;
  5. import java.util.Iterator;
  6. import com.google.gwt.core.client.GWT;
  7. import com.google.gwt.core.client.Scheduler;
  8. import com.google.gwt.dom.client.Style.Position;
  9. import com.google.gwt.user.client.Command;
  10. import com.google.gwt.user.client.ui.Widget;
  11. import com.vaadin.terminal.gwt.client.AbstractFieldState;
  12. import com.vaadin.terminal.gwt.client.ApplicationConnection;
  13. import com.vaadin.terminal.gwt.client.BrowserInfo;
  14. import com.vaadin.terminal.gwt.client.ComponentConnector;
  15. import com.vaadin.terminal.gwt.client.DirectionalManagedLayout;
  16. import com.vaadin.terminal.gwt.client.Paintable;
  17. import com.vaadin.terminal.gwt.client.UIDL;
  18. import com.vaadin.terminal.gwt.client.Util;
  19. import com.vaadin.terminal.gwt.client.ui.VScrollTable.ContextMenuDetails;
  20. import com.vaadin.terminal.gwt.client.ui.VScrollTable.VScrollTableBody.VScrollTableRow;
  21. @Component(com.vaadin.ui.Table.class)
  22. public class TableConnector extends AbstractComponentContainerConnector
  23. implements Paintable, DirectionalManagedLayout, PostLayoutListener {
  24. @Override
  25. protected void init() {
  26. super.init();
  27. getWidget().init(getConnection());
  28. }
  29. /*
  30. * (non-Javadoc)
  31. *
  32. * @see
  33. * com.vaadin.terminal.gwt.client.Paintable#updateFromUIDL(com.vaadin.terminal
  34. * .gwt.client.UIDL, com.vaadin.terminal.gwt.client.ApplicationConnection)
  35. */
  36. public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
  37. getWidget().rendering = true;
  38. // If a row has an open context menu, it will be closed as the row is
  39. // detached. Retain a reference here so we can restore the menu if
  40. // required.
  41. ContextMenuDetails contextMenuBeforeUpdate = getWidget().contextMenu;
  42. if (uidl.hasAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_FIRST)) {
  43. getWidget().serverCacheFirst = uidl
  44. .getIntAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_FIRST);
  45. getWidget().serverCacheLast = uidl
  46. .getIntAttribute(VScrollTable.ATTRIBUTE_PAGEBUFFER_LAST);
  47. } else {
  48. getWidget().serverCacheFirst = -1;
  49. getWidget().serverCacheLast = -1;
  50. }
  51. /*
  52. * We need to do this before updateComponent since updateComponent calls
  53. * this.setHeight() which will calculate a new body height depending on
  54. * the space available.
  55. */
  56. if (uidl.hasAttribute("colfooters")) {
  57. getWidget().showColFooters = uidl.getBooleanAttribute("colfooters");
  58. }
  59. getWidget().tFoot.setVisible(getWidget().showColFooters);
  60. if (!isRealUpdate(uidl)) {
  61. getWidget().rendering = false;
  62. return;
  63. }
  64. getWidget().enabled = isEnabled();
  65. if (BrowserInfo.get().isIE8() && !getWidget().enabled) {
  66. /*
  67. * The disabled shim will not cover the table body if it is relative
  68. * in IE8. See #7324
  69. */
  70. getWidget().scrollBodyPanel.getElement().getStyle()
  71. .setPosition(Position.STATIC);
  72. } else if (BrowserInfo.get().isIE8()) {
  73. getWidget().scrollBodyPanel.getElement().getStyle()
  74. .setPosition(Position.RELATIVE);
  75. }
  76. getWidget().paintableId = uidl.getStringAttribute("id");
  77. getWidget().immediate = getState().isImmediate();
  78. int previousTotalRows = getWidget().totalRows;
  79. getWidget().updateTotalRows(uidl);
  80. boolean totalRowsChanged = (getWidget().totalRows != previousTotalRows);
  81. getWidget().updateDragMode(uidl);
  82. getWidget().updateSelectionProperties(uidl, getState(), isReadOnly());
  83. if (uidl.hasAttribute("alb")) {
  84. getWidget().bodyActionKeys = uidl.getStringArrayAttribute("alb");
  85. } else {
  86. // Need to clear the actions if the action handlers have been
  87. // removed
  88. getWidget().bodyActionKeys = null;
  89. }
  90. getWidget().setCacheRateFromUIDL(uidl);
  91. getWidget().recalcWidths = uidl.hasAttribute("recalcWidths");
  92. if (getWidget().recalcWidths) {
  93. getWidget().tHead.clear();
  94. getWidget().tFoot.clear();
  95. }
  96. getWidget().updatePageLength(uidl);
  97. getWidget().updateFirstVisibleAndScrollIfNeeded(uidl);
  98. getWidget().showRowHeaders = uidl.getBooleanAttribute("rowheaders");
  99. getWidget().showColHeaders = uidl.getBooleanAttribute("colheaders");
  100. getWidget().updateSortingProperties(uidl);
  101. boolean keyboardSelectionOverRowFetchInProgress = getWidget()
  102. .selectSelectedRows(uidl);
  103. getWidget().updateActionMap(uidl);
  104. getWidget().updateColumnProperties(uidl);
  105. UIDL ac = uidl.getChildByTagName("-ac");
  106. if (ac == null) {
  107. if (getWidget().dropHandler != null) {
  108. // remove dropHandler if not present anymore
  109. getWidget().dropHandler = null;
  110. }
  111. } else {
  112. if (getWidget().dropHandler == null) {
  113. getWidget().dropHandler = getWidget().new VScrollTableDropHandler();
  114. }
  115. getWidget().dropHandler.updateAcceptRules(ac);
  116. }
  117. UIDL partialRowAdditions = uidl.getChildByTagName("prows");
  118. UIDL partialRowUpdates = uidl.getChildByTagName("urows");
  119. if (partialRowUpdates != null || partialRowAdditions != null) {
  120. // we may have pending cache row fetch, cancel it. See #2136
  121. getWidget().rowRequestHandler.cancel();
  122. getWidget().updateRowsInBody(partialRowUpdates);
  123. getWidget().addAndRemoveRows(partialRowAdditions);
  124. } else {
  125. UIDL rowData = uidl.getChildByTagName("rows");
  126. if (rowData != null) {
  127. // we may have pending cache row fetch, cancel it. See #2136
  128. getWidget().rowRequestHandler.cancel();
  129. if (!getWidget().recalcWidths
  130. && getWidget().initializedAndAttached) {
  131. getWidget().updateBody(rowData,
  132. uidl.getIntAttribute("firstrow"),
  133. uidl.getIntAttribute("rows"));
  134. if (getWidget().headerChangedDuringUpdate) {
  135. getWidget().triggerLazyColumnAdjustment(true);
  136. } else if (!getWidget().isScrollPositionVisible()
  137. || totalRowsChanged
  138. || getWidget().lastRenderedHeight != getWidget().scrollBody
  139. .getOffsetHeight()) {
  140. // webkits may still bug with their disturbing scrollbar
  141. // bug, see #3457
  142. // Run overflow fix for the scrollable area
  143. // #6698 - If there's a scroll going on, don't abort it
  144. // by changing overflows as the length of the contents
  145. // *shouldn't* have changed (unless the number of rows
  146. // or the height of the widget has also changed)
  147. Scheduler.get().scheduleDeferred(new Command() {
  148. public void execute() {
  149. Util.runWebkitOverflowAutoFix(getWidget().scrollBodyPanel
  150. .getElement());
  151. }
  152. });
  153. }
  154. } else {
  155. getWidget().initializeRows(uidl, rowData);
  156. }
  157. }
  158. }
  159. // If a row had an open context menu before the update, and after the
  160. // update there's a row with the same key as that row, restore the
  161. // context menu. See #8526.
  162. showSavedContextMenu(contextMenuBeforeUpdate);
  163. if (!getWidget().isSelectable()) {
  164. getWidget().scrollBody.addStyleName(VScrollTable.CLASSNAME
  165. + "-body-noselection");
  166. } else {
  167. getWidget().scrollBody.removeStyleName(VScrollTable.CLASSNAME
  168. + "-body-noselection");
  169. }
  170. getWidget().hideScrollPositionAnnotation();
  171. // selection is no in sync with server, avoid excessive server visits by
  172. // clearing to flag used during the normal operation
  173. if (!keyboardSelectionOverRowFetchInProgress) {
  174. getWidget().selectionChanged = false;
  175. }
  176. /*
  177. * This is called when the Home or page up button has been pressed in
  178. * selectable mode and the next selected row was not yet rendered in the
  179. * client
  180. */
  181. if (getWidget().selectFirstItemInNextRender
  182. || getWidget().focusFirstItemInNextRender) {
  183. getWidget().selectFirstRenderedRowInViewPort(
  184. getWidget().focusFirstItemInNextRender);
  185. getWidget().selectFirstItemInNextRender = getWidget().focusFirstItemInNextRender = false;
  186. }
  187. /*
  188. * This is called when the page down or end button has been pressed in
  189. * selectable mode and the next selected row was not yet rendered in the
  190. * client
  191. */
  192. if (getWidget().selectLastItemInNextRender
  193. || getWidget().focusLastItemInNextRender) {
  194. getWidget().selectLastRenderedRowInViewPort(
  195. getWidget().focusLastItemInNextRender);
  196. getWidget().selectLastItemInNextRender = getWidget().focusLastItemInNextRender = false;
  197. }
  198. getWidget().multiselectPending = false;
  199. if (getWidget().focusedRow != null) {
  200. if (!getWidget().focusedRow.isAttached()
  201. && !getWidget().rowRequestHandler.isRunning()) {
  202. // focused row has been orphaned, can't focus
  203. getWidget().focusRowFromBody();
  204. }
  205. }
  206. getWidget().tabIndex = uidl.hasAttribute("tabindex") ? uidl
  207. .getIntAttribute("tabindex") : 0;
  208. getWidget().setProperTabIndex();
  209. getWidget().resizeSortedColumnForSortIndicator();
  210. // Remember this to detect situations where overflow hack might be
  211. // needed during scrolling
  212. getWidget().lastRenderedHeight = getWidget().scrollBody
  213. .getOffsetHeight();
  214. getWidget().rendering = false;
  215. getWidget().headerChangedDuringUpdate = false;
  216. }
  217. @Override
  218. protected Widget createWidget() {
  219. return GWT.create(VScrollTable.class);
  220. }
  221. @Override
  222. public VScrollTable getWidget() {
  223. return (VScrollTable) super.getWidget();
  224. }
  225. public void updateCaption(ComponentConnector component) {
  226. // NOP, not rendered
  227. }
  228. public void layoutVertically() {
  229. getWidget().updateHeight();
  230. }
  231. public void layoutHorizontally() {
  232. getWidget().updateWidth();
  233. }
  234. public void postLayout() {
  235. getWidget().sizeInit();
  236. }
  237. @Override
  238. public boolean isReadOnly() {
  239. return super.isReadOnly() || getState().isPropertyReadOnly();
  240. }
  241. @Override
  242. public AbstractFieldState getState() {
  243. return (AbstractFieldState) super.getState();
  244. }
  245. /**
  246. * Shows a saved row context menu if the row for the context menu is still
  247. * visible. Does nothing if a context menu has not been saved.
  248. *
  249. * @param savedContextMenu
  250. */
  251. public void showSavedContextMenu(ContextMenuDetails savedContextMenu) {
  252. if (isEnabled() && savedContextMenu != null) {
  253. Iterator<Widget> iterator = getWidget().scrollBody.iterator();
  254. while (iterator.hasNext()) {
  255. Widget w = iterator.next();
  256. VScrollTableRow row = (VScrollTableRow) w;
  257. if (row.getKey().equals(savedContextMenu.rowKey)) {
  258. getWidget().contextMenu = savedContextMenu;
  259. getConnection().getContextMenu().showAt(row,
  260. savedContextMenu.left, savedContextMenu.top);
  261. }
  262. }
  263. }
  264. }
  265. }