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