1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.vaadin.v7.client.ui.table;
17
18 import java.util.Collections;
19 import java.util.List;
20
21 import com.google.gwt.core.client.Scheduler;
22 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
23 import com.google.gwt.dom.client.Element;
24 import com.google.gwt.dom.client.EventTarget;
25 import com.google.gwt.event.shared.HandlerRegistration;
26 import com.google.gwt.user.client.ui.Widget;
27 import com.vaadin.client.ApplicationConnection;
28 import com.vaadin.client.ComponentConnector;
29 import com.vaadin.client.ConnectorHierarchyChangeEvent;
30 import com.vaadin.client.ConnectorHierarchyChangeEvent.ConnectorHierarchyChangeHandler;
31 import com.vaadin.client.DirectionalManagedLayout;
32 import com.vaadin.client.HasChildMeasurementHintConnector;
33 import com.vaadin.client.Paintable;
34 import com.vaadin.client.ServerConnector;
35 import com.vaadin.client.TooltipInfo;
36 import com.vaadin.client.UIDL;
37 import com.vaadin.client.WidgetUtil;
38 import com.vaadin.client.ui.PostLayoutListener;
39 import com.vaadin.shared.MouseEventDetails;
40 import com.vaadin.v7.client.ui.AbstractFieldConnector;
41 import com.vaadin.v7.client.ui.VScrollTable.FooterCell;
42 import com.vaadin.v7.client.ui.VScrollTable.HeaderCell;
43 import com.vaadin.v7.client.ui.VScrollTablePatched;
44 import com.vaadin.v7.client.ui.VScrollTablePatched.ContextMenuDetails;
45 import com.vaadin.v7.client.ui.VScrollTablePatched.VScrollTableBody.VScrollTableRow;
46 import com.vaadin.v7.shared.ui.table.TableConstants;
47 import com.vaadin.v7.shared.ui.table.TableConstants.Section;
48 import com.vaadin.v7.shared.ui.table.TableServerRpc;
49 import com.vaadin.v7.shared.ui.table.TableState;
50
51
52 public class TableConnectorPatched extends AbstractFieldConnector
53 implements ConnectorHierarchyChangeHandler,
54 Paintable, DirectionalManagedLayout, PostLayoutListener,
55 HasChildMeasurementHintConnector {
56
57 private List<ComponentConnector> childComponents;
58
59 public TableConnectorPatched() {
60 addConnectorHierarchyChangeHandler(this);
61 }
62
63 @Override
64 protected void init() {
65 super.init();
66 getWidget().init(getConnection());
67 }
68
69
70
71
72
73
74 @Override
75 public void onUnregister() {
76 super.onUnregister();
77 getWidget().onUnregister();
78 }
79
80 @Override
81 protected void sendContextClickEvent(MouseEventDetails details,
82 EventTarget eventTarget) {
83
84 if (!Element.is(eventTarget)) {
85 return;
86 }
87 Element e = Element.as(eventTarget);
88
89 Section section;
90 String colKey = null;
91 String rowKey = null;
92 if (getWidget().tFoot.getElement().isOrHasChild(e)) {
93 section = Section.FOOTER;
94 FooterCell w = WidgetUtil.findWidget(e, FooterCell.class);
95 colKey = w.getColKey();
96 } else if (getWidget().tHead.getElement().isOrHasChild(e)) {
97 section = Section.HEADER;
98 HeaderCell w = WidgetUtil.findWidget(e, HeaderCell.class);
99 colKey = w.getColKey();
100 } else {
101 section = Section.BODY;
102 if (getWidget().scrollBody.getElement().isOrHasChild(e)) {
103 VScrollTableRow w = getScrollTableRow(e);
104
105
106
107
108
109 if (w != null) {
110 rowKey = w.getKey();
111 colKey = getWidget().tHead
112 .getHeaderCell(getElementIndex(e, w.getElement()))
113 .getColKey();
114 }
115 }
116 }
117
118 getRpcProxy(TableServerRpc.class).contextClick(rowKey, colKey, section,
119 details);
120
121 WidgetUtil.clearTextSelection();
122 }
123
124 protected VScrollTableRow getScrollTableRow(Element e) {
125 return WidgetUtil.findWidget(e, VScrollTableRow.class);
126 }
127
128 private int getElementIndex(Element e,
129 com.google.gwt.user.client.Element element) {
130 int i = 0;
131 Element current = element.getFirstChildElement();
132 while (!current.isOrHasChild(e)) {
133 current = current.getNextSiblingElement();
134 ++i;
135 }
136 return i;
137 }
138
139
140
141
142
143
144
145 @Override
146 public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
147 getWidget().rendering = true;
148
149
150
151
152 ContextMenuDetails contextMenuBeforeUpdate = getWidget().contextMenu;
153
154 if (uidl.hasAttribute(TableConstants.ATTRIBUTE_PAGEBUFFER_FIRST)) {
155 getWidget().serverCacheFirst = uidl
156 .getIntAttribute(TableConstants.ATTRIBUTE_PAGEBUFFER_FIRST);
157 getWidget().serverCacheLast = uidl
158 .getIntAttribute(TableConstants.ATTRIBUTE_PAGEBUFFER_LAST);
159 } else {
160 getWidget().serverCacheFirst = -1;
161 getWidget().serverCacheLast = -1;
162 }
163
164
165
166
167
168 if (uidl.hasAttribute("colfooters")) {
169 getWidget().showColFooters = uidl.getBooleanAttribute("colfooters");
170 }
171
172 getWidget().tFoot.setVisible(getWidget().showColFooters);
173
174 if (!isRealUpdate(uidl)) {
175 getWidget().rendering = false;
176 return;
177 }
178
179 getWidget().paintableId = uidl.getStringAttribute("id");
180 getWidget().immediate = getState().immediate;
181
182 int previousTotalRows = getWidget().totalRows;
183 getWidget().updateTotalRows(uidl);
184 boolean totalRowsHaveChanged = (getWidget().totalRows != previousTotalRows);
185
186 getWidget().updateDragMode(uidl);
187
188
189 int childMeasureHint = uidl.hasAttribute("measurehint")
190 ? uidl.getIntAttribute("measurehint")
191 : 0;
192 getWidget().setChildMeasurementHint(
193 ChildMeasurementHint.values()[childMeasureHint]);
194
195 getWidget().updateSelectionProperties(uidl, getState(), isReadOnly());
196
197 if (uidl.hasAttribute("alb")) {
198 getWidget().bodyActionKeys = uidl.getStringArrayAttribute("alb");
199 } else {
200
201
202 getWidget().bodyActionKeys = null;
203 }
204
205 getWidget().setCacheRateFromUIDL(uidl);
206
207 getWidget().recalcWidths = uidl.hasAttribute("recalcWidths");
208 if (getWidget().recalcWidths) {
209 getWidget().tHead.clear();
210 getWidget().tFoot.clear();
211 }
212
213 getWidget().updatePageLength(uidl);
214
215 getWidget().updateFirstVisibleAndScrollIfNeeded(uidl);
216
217 getWidget().showRowHeaders = uidl.getBooleanAttribute("rowheaders");
218 getWidget().showColHeaders = uidl.getBooleanAttribute("colheaders");
219
220 getWidget().updateSortingProperties(uidl);
221
222 getWidget().updateActionMap(uidl);
223
224 getWidget().updateColumnProperties(uidl);
225
226 UIDL ac = uidl.getChildByTagName("-ac");
227 if (ac == null) {
228 if (getWidget().dropHandler != null) {
229
230 getWidget().dropHandler = null;
231 }
232 } else {
233 if (getWidget().dropHandler == null) {
234 getWidget().dropHandler = getWidget().new VScrollTableDropHandler();
235 }
236 getWidget().dropHandler.updateAcceptRules(ac);
237 }
238
239 UIDL partialRowAdditions = uidl.getChildByTagName("prows");
240 UIDL partialRowUpdates = uidl.getChildByTagName("urows");
241 if (partialRowUpdates != null || partialRowAdditions != null) {
242 getWidget().postponeSanityCheckForLastRendered = true;
243
244 getWidget().rowRequestHandler.cancel();
245
246 getWidget().updateRowsInBody(partialRowUpdates);
247 getWidget().addAndRemoveRows(partialRowAdditions);
248
249
250
251 getWidget().scrollBody
252 .setLastRendered(getWidget().scrollBody.getLastRendered());
253 getWidget().updateMaxIndent();
254 } else {
255 getWidget().postponeSanityCheckForLastRendered = false;
256 UIDL rowData = uidl.getChildByTagName("rows");
257 if (rowData != null) {
258
259 getWidget().rowRequestHandler.cancel();
260
261 if (!getWidget().recalcWidths
262 && getWidget().initializedAndAttached) {
263 getWidget().updateBody(rowData,
264 uidl.getIntAttribute("firstrow"),
265 uidl.getIntAttribute("rows"));
266 if (getWidget().headerChangedDuringUpdate) {
267 getWidget().triggerLazyColumnAdjustment(true);
268 }
269 } else {
270 getWidget().initializeRows(uidl, rowData);
271 }
272 }
273 }
274
275 boolean keyboardSelectionOverRowFetchInProgress = getWidget()
276 .selectSelectedRows(uidl);
277
278
279
280
281 showSavedContextMenu(contextMenuBeforeUpdate);
282
283 if (!getWidget().isSelectable()) {
284 getWidget().scrollBody.addStyleName(
285 getWidget().getStylePrimaryName() + "-body-noselection");
286 } else {
287 getWidget().scrollBody.removeStyleName(
288 getWidget().getStylePrimaryName() + "-body-noselection");
289 }
290
291 getWidget().hideScrollPositionAnnotation();
292
293
294
295 if (!keyboardSelectionOverRowFetchInProgress) {
296 getWidget().selectionChanged = false;
297 }
298
299
300
301
302
303
304 if (getWidget().selectFirstItemInNextRender
305 || getWidget().focusFirstItemInNextRender) {
306 getWidget().selectFirstRenderedRowInViewPort(
307 getWidget().focusFirstItemInNextRender);
308 getWidget().selectFirstItemInNextRender = getWidget().focusFirstItemInNextRender = false;
309 }
310
311
312
313
314
315
316 if (getWidget().selectLastItemInNextRender
317 || getWidget().focusLastItemInNextRender) {
318 getWidget().selectLastRenderedRowInViewPort(
319 getWidget().focusLastItemInNextRender);
320 getWidget().selectLastItemInNextRender = getWidget().focusLastItemInNextRender = false;
321 }
322 getWidget().multiselectPending = false;
323
324 if (getWidget().focusedRow != null) {
325 if (!getWidget().focusedRow.isAttached()
326 && !getWidget().rowRequestHandler
327 .isRequestHandlerRunning()) {
328
329 if (getWidget().selectedRowKeys
330 .contains(getWidget().focusedRow.getKey())) {
331
332
333 getWidget().setRowFocus(getWidget().getRenderedRowByKey(
334 getWidget().focusedRow.getKey()));
335 } else if (!getWidget().selectedRowKeys.isEmpty()) {
336
337 getWidget().setRowFocus(getWidget().getRenderedRowByKey(
338 getWidget().selectedRowKeys.iterator().next()));
339 } else {
340
341 getWidget().focusRowFromBody();
342 }
343 }
344 }
345
346
347
348
349
350
351
352
353 if (uidl.hasAttribute(TableConstants.ATTRIBUTE_KEY_MAPPER_RESET)
354 && uidl.getBooleanAttribute(
355 TableConstants.ATTRIBUTE_KEY_MAPPER_RESET)
356 && getWidget().selectionRangeStart != null) {
357 assert !getWidget().selectionRangeStart.isAttached();
358 getWidget().selectionRangeStart = getWidget().focusedRow;
359 }
360
361 getWidget().tabIndex = getState().tabIndex;
362 getWidget().setProperTabIndex();
363
364 Scheduler.get().scheduleFinally(new ScheduledCommand() {
365
366 @Override
367 public void execute() {
368 getWidget().resizeSortedColumnForSortIndicator();
369 }
370 });
371
372
373
374 getWidget().lastRenderedHeight = getWidget().scrollBody
375 .getOffsetHeight();
376
377 getWidget().rendering = false;
378 getWidget().headerChangedDuringUpdate = false;
379
380 getWidget().collapsibleMenuContent = getState().collapseMenuContent;
381 }
382
383 @Override
384 public void updateEnabledState(boolean enabledState) {
385 super.updateEnabledState(enabledState);
386 getWidget().enabled = isEnabled();
387
388
389 }
390
391 @Override
392 public VScrollTablePatched getWidget() {
393 return (VScrollTablePatched) super.getWidget();
394 }
395
396 @Override
397 public void updateCaption(ComponentConnector component) {
398
399 }
400
401 @Override
402 public void layoutVertically() {
403 getWidget().updateHeight();
404 }
405
406 @Override
407 public void layoutHorizontally() {
408 getWidget().updateWidth();
409 }
410
411 @Override
412 public void postLayout() {
413 VScrollTablePatched table = getWidget();
414 if (table.isVisibleInHierarchy() && table.sizeNeedsInit) {
415 table.sizeInit();
416 Scheduler.get().scheduleFinally(new ScheduledCommand() {
417 @Override
418 public void execute() {
419
420 getLayoutManager().setNeedsMeasure(TableConnectorPatched.this);
421 ServerConnector parent = getParent();
422 if (parent instanceof ComponentConnector) {
423 getLayoutManager()
424 .setNeedsMeasure((ComponentConnector) parent);
425 }
426 getLayoutManager()
427 .setNeedsVerticalLayout(TableConnectorPatched.this);
428 getLayoutManager().layoutNow();
429 }
430 });
431 }
432 }
433
434 @Override
435 public boolean isReadOnly() {
436 return super.isReadOnly() || getState().propertyReadOnly;
437 }
438
439 @Override
440 public TableState getState() {
441 return (TableState) super.getState();
442 }
443
444
445
446
447
448
449
450 public void showSavedContextMenu(ContextMenuDetails savedContextMenu) {
451 if (isEnabled() && savedContextMenu != null) {
452 for (Widget w : getWidget().scrollBody) {
453 VScrollTableRow row = (VScrollTableRow) w;
454 if (row.getKey().equals(savedContextMenu.rowKey)) {
455 row.showContextMenu(savedContextMenu.left,
456 savedContextMenu.top);
457 }
458 }
459 }
460 }
461
462 @Override
463 public TooltipInfo getTooltipInfo(Element element) {
464
465 TooltipInfo info = null;
466
467 if (element != getWidget().getElement()) {
468 Object node = WidgetUtil.findWidget(element, getWidget().scrollBody.iterator().next().getClass());
469
470 if (node != null) {
471 VScrollTableRow row = (VScrollTableRow) node;
472 info = row.getTooltip(element);
473 }
474 }
475
476 if (info == null) {
477 info = super.getTooltipInfo(element);
478 }
479
480 return info;
481 }
482
483 @Override
484 public boolean hasTooltip() {
485
486
487
488
489
490 return true;
491 }
492
493 @Override
494 public void onConnectorHierarchyChange(
495 ConnectorHierarchyChangeEvent connectorHierarchyChangeEvent) {
496
497 }
498
499 @Override
500 protected void updateComponentSize(String newWidth, String newHeight) {
501 super.updateComponentSize(newWidth, newHeight);
502
503 if ("".equals(newWidth)) {
504 getWidget().updateWidth();
505 }
506 if ("".equals(newHeight)) {
507 getWidget().updateHeight();
508 }
509 }
510
511 @Override
512 public List<ComponentConnector> getChildComponents() {
513 if (childComponents == null) {
514 return Collections.emptyList();
515 }
516
517 return childComponents;
518 }
519
520 @Override
521 public void setChildComponents(List<ComponentConnector> childComponents) {
522 this.childComponents = childComponents;
523 }
524
525 @Override
526 public HandlerRegistration addConnectorHierarchyChangeHandler(
527 ConnectorHierarchyChangeHandler handler) {
528 return ensureHandlerManager()
529 .addHandler(ConnectorHierarchyChangeEvent.TYPE, handler);
530 }
531
532 @Override
533 public void setChildMeasurementHint(ChildMeasurementHint hint) {
534 getWidget().setChildMeasurementHint(hint);
535 }
536
537 @Override
538 public ChildMeasurementHint getChildMeasurementHint() {
539 return getWidget().getChildMeasurementHint();
540 }
541
542 }