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