001: /*
002: * Copyright 2000,2005 wingS development team.
003: *
004: * This file is part of wingS (http://wingsframework.org).
005: *
006: * wingS is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU Lesser General Public License
008: * as published by the Free Software Foundation; either version 2.1
009: * of the License, or (at your option) any later version.
010: *
011: * Please see COPYING for the complete licence.
012: */
013: package org.wingx.plaf.css;
014:
015: import org.wings.plaf.Update.Handler;
016: import org.wings.plaf.css.*;
017: import org.wings.plaf.CGManager;
018: import org.wings.plaf.Update;
019: import org.wings.*;
020: import org.wings.session.SessionManager;
021: import org.wings.util.SStringBuilder;
022: import org.wings.io.Device;
023: import org.wings.io.StringBuilderDevice;
024: import org.wings.table.*;
025: import org.wingx.XTable;
026: import org.wingx.table.*;
027:
028: import java.awt.Rectangle;
029: import java.io.IOException;
030: import java.util.ArrayList;
031: import java.util.List;
032:
033: import javax.swing.table.TableModel;
034:
035: public class XTableCG extends AbstractComponentCG implements
036: org.wings.plaf.TableCG {
037: private static final long serialVersionUID = 1L;
038: protected String fixedTableBorderWidth;
039: protected SIcon editIcon;
040: protected String selectionColumnWidth = "22";
041: protected final SLabel resetLabel = new SLabel(XTable.ICON_RESET);
042: protected final SLabel refreshLabel = new SLabel(
043: XTable.ICON_REFRESH);
044: int horizontalOversize = 22;
045:
046: /**
047: * Initialize properties from config
048: */
049: public XTableCG() {
050: final CGManager manager = SessionManager.getSession()
051: .getCGManager();
052: setFixedTableBorderWidth((String) manager.getObject(
053: "TableCG.fixedTableBorderWidth", String.class));
054: setEditIcon(manager.getIcon("TableCG.editIcon"));
055: selectionColumnWidth = (String) manager.getObject(
056: "TableCG.selectionColumnWidth", String.class);
057: }
058:
059: public int getHorizontalOversize() {
060: return horizontalOversize;
061: }
062:
063: public void setHorizontalOversize(int horizontalOversize) {
064: this .horizontalOversize = horizontalOversize;
065: }
066:
067: /**
068: * Tweak property. Declares a deprecated BORDER=xxx attribute on the HTML TABLE element.
069: */
070: public String getFixedTableBorderWidth() {
071: return fixedTableBorderWidth;
072: }
073:
074: /**
075: * Tweak property. Declares a deprecated BORDER=xxx attribute on the HTML TABLE element.
076: */
077: public void setFixedTableBorderWidth(String fixedTableBorderWidth) {
078: this .fixedTableBorderWidth = fixedTableBorderWidth;
079: }
080:
081: /**
082: * Sets the icon used to indicated an editable cell (if content is not direct clickable).
083: */
084: public void setEditIcon(SIcon editIcon) {
085: this .editIcon = editIcon;
086: }
087:
088: /**
089: * @return Returns the icon used to indicated an editable cell (if content is not direct clickable).
090: */
091: public SIcon getEditIcon() {
092: return editIcon;
093: }
094:
095: /**
096: * @return The width of the (optional) row selection column in px
097: */
098: public String getSelectionColumnWidth() {
099: return selectionColumnWidth;
100: }
101:
102: /**
103: * The width of the (optional) row selection column in px
104: *
105: * @param selectionColumnWidth The width of the (optional) row selection column with unit
106: */
107: public void setSelectionColumnWidth(String selectionColumnWidth) {
108: this .selectionColumnWidth = selectionColumnWidth;
109: }
110:
111: public void installCG(final SComponent comp) {
112: super .installCG(comp);
113:
114: final STable table = (STable) comp;
115: final CGManager manager = table.getSession().getCGManager();
116: Object value;
117:
118: value = manager.getObject("STable.defaultRenderer",
119: STableCellRenderer.class);
120: if (value != null) {
121: table.setDefaultRenderer((STableCellRenderer) value);
122: if (value instanceof SDefaultTableCellRenderer) {
123: SDefaultTableCellRenderer cellRenderer = (SDefaultTableCellRenderer) value;
124: cellRenderer.setEditIcon(editIcon);
125: }
126: }
127:
128: value = manager.getObject("XTable.headerRenderer",
129: STableCellRenderer.class);
130: if (value != null)
131: table.setHeaderRenderer((STableCellRenderer) value);
132: else
133: table.setHeaderRenderer(new XTable.HeaderRenderer());
134:
135: value = manager.getObject("STable.rowSelectionRenderer",
136: org.wings.table.STableCellRenderer.class);
137: if (value != null) {
138: if (value instanceof SDefaultTableRowSelectionRenderer) {
139: SDefaultTableRowSelectionRenderer rowSelectionRenderer = (SDefaultTableRowSelectionRenderer) value;
140: rowSelectionRenderer.setUseIcons(true);
141: }
142: table
143: .setRowSelectionRenderer((org.wings.table.STableCellRenderer) value);
144: }
145: }
146:
147: public void uninstallCG(SComponent component) {
148: super .uninstallCG(component);
149: final STable table = (STable) component;
150: table.setHeaderRenderer(null);
151: table.setDefaultRenderer(null);
152: table.setRowSelectionRenderer(null);
153: }
154:
155: /**
156: * write a specific cell to the device
157: */
158: protected void renderCellContent(final Device device,
159: final STable table, final SCellRendererPane rendererPane,
160: final int row, final int col) throws IOException {
161: final boolean isEditingCell = table.isEditing()
162: && row == table.getEditingRow()
163: && col == table.getEditingColumn();
164: final boolean editableCell = table.isCellEditable(row, col);
165: final boolean selectableCell = table.getSelectionMode() != SListSelectionModel.NO_SELECTION
166: && !table.isEditable();
167:
168: final SComponent component;
169: if (isEditingCell) {
170: component = table.getEditorComponent();
171: } else {
172: component = table.prepareRenderer(table.getCellRenderer(
173: row, col), row, col);
174: }
175:
176: final boolean isClickable = component instanceof SClickable;
177: final boolean isEditableCellRenderer = component instanceof EditableTableCellRenderer;
178:
179: device.print("<td col=\"");
180: device.print(col);
181: device.print("\"");
182:
183: if (component == null) {
184: device.print("></td>");
185: return;
186: }
187: Utils.printTableCellAlignment(device, component,
188: SConstants.LEFT, SConstants.TOP);
189: Utils.optAttribute(device, "oversize", horizontalOversize);
190:
191: String parameter = null;
192: if (table.isEditable() && editableCell)
193: parameter = table.getEditParameter(row, col);
194: else if (selectableCell)
195: parameter = table.getToggleSelectionParameter(row, col);
196:
197: if (parameter != null && (selectableCell || editableCell)
198: && !isClickable) {
199: printClickability(device, table, parameter, table
200: .getShowAsFormComponent());
201: device
202: .print(isEditingCell || isEditableCellRenderer ? " editing=\"true\""
203: : " editing=\"false\"");
204: device
205: .print(isEditingCell || isEditableCellRenderer ? " class=\"cell\""
206: : " class=\"cell clickable\"");
207: } else
208: device.print(" class=\"cell\"");
209: device.print(">");
210:
211: rendererPane.writeComponent(device, component, table);
212:
213: device.print("</td>");
214: Utils.printNewline(device, component);
215: }
216:
217: protected void writeHeaderCell(final Device device,
218: final XTable table, final SCellRendererPane rendererPane,
219: final int col) throws IOException {
220: final SComponent comp = table.prepareHeaderRenderer(table
221: .getHeaderRenderer(col), col);
222:
223: device.print("<th col=\"");
224: device.print(col);
225: device.print("\"");
226:
227: Utils.printTableCellAlignment(device, comp, SConstants.CENTER,
228: SConstants.CENTER);
229:
230: String parameter = table.getToggleSortParameter(col);
231:
232: if (table.getModel() instanceof SortableTableModel) {
233: STableColumn column = table.getColumnModel().getColumn(col);
234: if (!(column instanceof XTableColumn)
235: || ((XTableColumn) column).isSortable()) {
236: Utils.printClickability(device, table, parameter, true,
237: table.getShowAsFormComponent());
238: device.print(" class=\"clickable head\"");
239: } else
240: device.print(" class=\"head\"");
241: } else
242: device.print(" class=\"head\"");
243:
244: device.print(">");
245:
246: rendererPane.writeComponent(device, comp, table);
247:
248: device.print("</th>");
249: Utils.printNewline(device, comp);
250: }
251:
252: protected void writeFilterCell(Device device, XTable table,
253: SCellRendererPane rendererPane, int c) throws IOException {
254: STableColumn column = table.getColumnModel().getColumn(c);
255:
256: if (column instanceof XTableColumn) {
257: XTableColumn xTableColumn = (XTableColumn) column;
258: if (!xTableColumn.isFilterable()) {
259: device.print("<th class=\"filter\"></th>");
260: return;
261: }
262: }
263:
264: EditableTableCellRenderer editableTableCellRenderer = table
265: .getFilterRenderer(c);
266: if (editableTableCellRenderer == null) {
267: device.print("<th class=\"filter\"></th>");
268: return;
269: }
270:
271: SComponent comp = table.prepareFilterRenderer(
272: editableTableCellRenderer, c);
273:
274: device.print("<th valign=\"middle\" class=\"filter\" col=\"");
275: device.print(c);
276: device.print("\"");
277:
278: //Utils.printTableCellAlignment(device, comp, SConstants.LEFT, SConstants.CENTER);
279: device.print(" align=\"left\">");
280:
281: rendererPane.writeComponent(device, comp, table);
282: device.print("</th>");
283: Utils.printNewline(device, comp);
284: }
285:
286: public final void writeInternal(final Device device,
287: final SComponent _c) throws IOException {
288: final XTable table = (XTable) _c;
289:
290: TableModel model = table.getModel();
291: boolean empty = model.getRowCount() == 0;
292: boolean filtered = isModelFiltered(model);
293:
294: device.print("<table");
295: if (empty)
296: table.addStyle("nodata");
297: Utils.writeAllAttributes(device, table);
298: if (empty)
299: table.removeStyle("nodata");
300: writeTableAttributes(device, table);
301: device.print("><thead>");
302: Utils.printNewline(device, table);
303:
304: Rectangle currentViewport = table.getViewportSize();
305: Rectangle maximalViewport = table.getScrollableViewportSize();
306: int startX = 0;
307: int endX = table.getVisibleColumnCount();
308: int startY = 0;
309: int endY = table.getRowCount();
310: int emptyIndex = maximalViewport != null ? maximalViewport.height
311: : endY;
312:
313: if (currentViewport != null) {
314: startX = currentViewport.x;
315: endX = startX + currentViewport.width;
316: startY = currentViewport.y;
317: endY = startY + currentViewport.height;
318: }
319:
320: writeColumnWidths(device, table, startX, endX);
321: writeHeader(device, table, startX, endX);
322:
323: if (!empty || filtered)
324: writeFilter(device, table, startX, endX);
325:
326: device.print("</thead>");
327: Utils.printNewline(device, table);
328: device.print("<tbody>");
329:
330: if (empty) {
331: writeNoData(device, table, startX, endX, endY, filtered);
332: } else
333: writeBody(device, table, startX, endX, startY, endY,
334: emptyIndex);
335:
336: writeFooter(device, table, startX, endX);
337:
338: device.print("</tbody></table>");
339: }
340:
341: private boolean isModelFiltered(TableModel model) {
342: return model instanceof FilterableTableModel;
343: }
344:
345: private void writeTableAttributes(Device device, XTable table)
346: throws IOException {
347: final SDimension intercellPadding = table.getIntercellPadding();
348: final SDimension intercellSpacing = table.getIntercellSpacing();
349: Utils.writeEvents(device, table, null);
350:
351: // TODO: border="" should be obsolete
352: // TODO: cellspacing and cellpadding may be in conflict with border-collapse
353: /* Tweaking: CG configured to have a fixed border="xy" width */
354: Utils.optAttribute(device, "border", fixedTableBorderWidth);
355: Utils.optAttribute(device, "cellspacing",
356: ((intercellSpacing != null) ? ""
357: + intercellSpacing.getWidthInt() : null));
358: Utils.optAttribute(device, "cellpadding",
359: ((intercellPadding != null) ? ""
360: + intercellPadding.getHeightInt() : null));
361: }
362:
363: private void writeColumnWidths(Device device, XTable table,
364: int startX, int endX) throws IOException {
365: STableColumnModel columnModel = table.getColumnModel();
366: if (columnModel != null
367: && atLeastOneColumnWidthIsNotNull(columnModel)) {
368: device.print("<colgroup>");
369: if (isSelectionColumnVisible(table))
370: writeCol(device, selectionColumnWidth);
371:
372: for (int i = startX; i < endX; ++i) {
373: STableColumn column = columnModel.getColumn(i);
374: if (!column.isHidden())
375: writeCol(device, column.getWidth());
376: else
377: ++endX;
378: }
379: device.print("</colgroup>");
380: Utils.printNewline(device, table);
381: }
382: }
383:
384: private void writeHeader(Device device, XTable table, int startX,
385: int endX) throws IOException {
386: if (!table.isHeaderVisible())
387: return;
388:
389: final SCellRendererPane rendererPane = table
390: .getCellRendererPane();
391: STableColumnModel columnModel = table.getColumnModel();
392:
393: SStringBuilder headerArea = Utils.inlineStyles(table
394: .getDynamicStyle(STable.SELECTOR_HEADER));
395: device.print("<tr class=\"header\"");
396: Utils.optAttribute(device, "style", headerArea);
397: device.print(">");
398:
399: Utils.printNewline(device, table, 1);
400: writeSelectionHeader(device, table);
401:
402: for (int i = startX; i < endX; ++i) {
403: STableColumn column = columnModel.getColumn(i);
404: if (!column.isHidden())
405: writeHeaderCell(device, table, rendererPane, i);
406: else
407: ++endX;
408: }
409: device.print("</tr>");
410: Utils.printNewline(device, table);
411: }
412:
413: private void writeFilter(Device device, XTable table, int startX,
414: int endX) throws IOException {
415: if (!table.isFilterVisible()
416: || !(table.getModel() instanceof FilterableTableModel))
417: return;
418:
419: final SCellRendererPane rendererPane = table
420: .getCellRendererPane();
421: STableColumnModel columnModel = table.getColumnModel();
422:
423: device.print("<tr class=\"filter\">\n");
424: Utils.printNewline(device, table, 1);
425: writeSelectionFilter(device, table);
426:
427: for (int i = startX; i < endX; ++i) {
428: STableColumn column = columnModel.getColumn(i);
429: if (!column.isHidden())
430: writeFilterCell(device, table, rendererPane, i);
431: else
432: ++endX;
433: }
434:
435: device.print("</tr>");
436: Utils.printNewline(device, table);
437: }
438:
439: protected void writeBody(Device device, XTable table, int startX,
440: int endX, int startY, int endY, int emptyIndex)
441: throws IOException {
442: final SListSelectionModel selectionModel = table
443: .getSelectionModel();
444:
445: SStringBuilder selectedArea = Utils.inlineStyles(table
446: .getDynamicStyle(STable.SELECTOR_SELECTED));
447: SStringBuilder evenArea = Utils.inlineStyles(table
448: .getDynamicStyle(STable.SELECTOR_EVEN_ROWS));
449: SStringBuilder oddArea = Utils.inlineStyles(table
450: .getDynamicStyle(STable.SELECTOR_ODD_ROWS));
451: final SCellRendererPane rendererPane = table
452: .getCellRendererPane();
453: STableColumnModel columnModel = table.getColumnModel();
454:
455: for (int r = startY; r < endY; ++r) {
456: writeTableRow(device, table, columnModel, selectionModel,
457: rendererPane, r, startX, endX, emptyIndex,
458: selectedArea, oddArea, evenArea);
459: }
460: }
461:
462: protected void writeTableRow(Device device, XTable table,
463: STableColumnModel columnModel,
464: SListSelectionModel selectionModel,
465: SCellRendererPane rendererPane, final int rowIndex,
466: int startX, int endX, int emptyIndex,
467: SStringBuilder selectedArea, SStringBuilder oddArea,
468: SStringBuilder evenArea) throws IOException {
469: if (rowIndex >= emptyIndex) {
470: int colspan = endX - startX;
471: device.print("<tr class=\"empty\">\n");
472: if (isSelectionColumnVisible(table)) {
473: device.print(" <td></td>\n");
474: }
475: device.print(" <td colspan=\"" + colspan
476: + "\"> </td>\n");
477: device.print("</tr>\n");
478: return;
479: }
480:
481: String rowStyle = table.getRowStyle(rowIndex);
482: SStringBuilder rowClass = new SStringBuilder(
483: rowStyle != null ? rowStyle + " " : "");
484: device.print("<tr");
485: if (selectionModel.isSelectedIndex(rowIndex)) {
486: Utils.optAttribute(device, "style", selectedArea);
487: rowClass.append("selected ");
488: } else if (rowIndex % 2 != 0)
489: Utils.optAttribute(device, "style", oddArea);
490: else
491: Utils.optAttribute(device, "style", evenArea);
492:
493: rowClass.append(rowIndex % 2 != 0 ? "odd" : "even");
494: Utils.optAttribute(device, "class", rowClass);
495: device.print(">");
496:
497: writeSelectionBody(device, table, rendererPane, rowIndex);
498:
499: for (int c = startX; c < endX; ++c) {
500: STableColumn column = columnModel.getColumn(c);
501: if (!column.isHidden())
502: renderCellContent(device, table, rendererPane,
503: rowIndex, c);
504: else
505: ++endX;
506: }
507:
508: device.print("</tr>");
509: Utils.printNewline(device, table);
510: }
511:
512: private void writeSelectionFilter(Device device, XTable table)
513: throws IOException {
514: if (isSelectionColumnVisible(table)) {
515: device.print("<th valign=\"middle\"");
516: Utils.optAttribute(device, "width", selectionColumnWidth);
517:
518: String parameter = table.getResetParameter();
519: Utils.printClickability(device, table, parameter, true,
520: table.getShowAsFormComponent());
521: device.print(" class=\"num clickable\"");
522:
523: device.print(">");
524:
525: resetLabel.write(device);
526:
527: device.print("</th>");
528: }
529: }
530:
531: protected void writeSelectionHeader(Device device, XTable table)
532: throws IOException {
533: if (isSelectionColumnVisible(table)) {
534: device.print("<th valign=\"middle\"");
535: Utils.optAttribute(device, "width", selectionColumnWidth);
536:
537: if (table.getModel() instanceof RefreshableModel) {
538: String parameter = table.getRefreshParameter();
539: Utils.printClickability(device, table, parameter, true,
540: table.getShowAsFormComponent());
541: device.print(" class=\"num clickable\">");
542:
543: refreshLabel.write(device);
544: } else {
545: device.print(" class=\"num\">");
546: }
547: device.print("</th>");
548: }
549: }
550:
551: private boolean atLeastOneColumnWidthIsNotNull(
552: STableColumnModel columnModel) {
553: int columnCount = columnModel.getColumnCount();
554: for (int i = 0; i < columnCount; i++)
555: if (columnModel.getColumn(i).getWidth() != null)
556: return true;
557: return false;
558: }
559:
560: private void writeCol(Device device, String width)
561: throws IOException {
562: device.print("<col");
563: Utils.optAttribute(device, "width", width);
564: device.print("/>");
565: }
566:
567: protected void writeFooter(Device device, XTable table, int startX,
568: int endX) throws IOException {
569: }
570:
571: private void writeNoData(Device device, XTable table, int startX,
572: int endX, int endY, boolean filtered) throws IOException {
573: int colspan = endX - startX;
574: int middle = endY / 2;
575:
576: // till middle
577: for (int i = 0; i < middle; ++i) {
578: device.print("<tr class=\"empty\"><td colspan=\""
579: + (colspan + 1) + "\"> </td></tr>");
580: }
581:
582: device.print("<tr class=\"nodata\">\n");
583: if (isSelectionColumnVisible(table))
584: device.print(" <td> </td>\n");
585:
586: device.print(" <td colspan=\"" + colspan
587: + "\" align=\"center\" valign=\"middle\">");
588: device.print(filtered ? table.getNoDataFoundLabel() : table
589: .getNoDataAvailableLabel());
590: device.print("</td>\n");
591: device.print("</tr>\n");
592:
593: for (int i = middle + 1; i < endY; ++i) {
594: device.print("<tr class=\"empty\"><td colspan=\""
595: + (colspan + 1) + "\"> </td></tr>");
596: }
597: }
598:
599: /**
600: * Renders the row sometimes needed to allow row selection.
601: */
602: protected void writeSelectionBody(final Device device,
603: final STable table, final SCellRendererPane rendererPane,
604: final int row) throws IOException {
605: final STableCellRenderer rowSelectionRenderer = table
606: .getRowSelectionRenderer();
607: if (isSelectionColumnVisible(table)) {
608: if (rowSelectionRenderer instanceof SDefaultTableRowSelectionRenderer) {
609: SDefaultTableRowSelectionRenderer defaultTableRowSelectionRenderer = (SDefaultTableRowSelectionRenderer) rowSelectionRenderer;
610: defaultTableRowSelectionRenderer
611: .setUseIcons(table.getSelectionMode() != SListSelectionModel.NO_SELECTION);
612: }
613: final SComponent comp = rowSelectionRenderer
614: .getTableCellRendererComponent(table, table
615: .getToggleSelectionParameter(row, -1),
616: table.isRowSelected(row), row, -1);
617: final String columnStyle = Utils.joinStyles(comp, "num");
618:
619: device.print("<td valign=\"top\" align=\"right\"");
620: Utils.optAttribute(device, "width", selectionColumnWidth);
621:
622: String value = table.getToggleSelectionParameter(row, -1);
623: if (table.getSelectionMode() != SListSelectionModel.NO_SELECTION) {
624: printClickability(device, table, value, table
625: .getShowAsFormComponent());
626: device.print(" class=\"clickable ");
627: device.print(columnStyle);
628: device.print("\"");
629: } else {
630: device.print(" class=\"");
631: device.print(columnStyle);
632: device.print("\"");
633: }
634: device.print(">");
635:
636: // Renders the content of the row selection row
637: rendererPane.writeComponent(device, comp, table);
638:
639: device.print("</td>");
640: }
641: }
642:
643: public static void printClickability(final Device device,
644: final SComponent component, final String eventValue,
645: final boolean formComponent) throws IOException {
646: device.print(" onclick=\"return wingS.table.cellClick(");
647: device.print("event,this,");
648: device.print(formComponent + ",");
649: device.print(!component.isReloadForced() + ",'");
650: device.print(Utils.event(component));
651: device.print("','");
652: device.print(eventValue == null ? "" : eventValue);
653: device.print("'");
654: device.print(");\"");
655: }
656:
657: private boolean isSelectionColumnVisible(STable table) {
658: if (table.getRowSelectionRenderer() != null
659: && table.getSelectionModel().getSelectionMode() != SListSelectionModel.NO_SELECTION)
660: return true;
661: return false;
662: }
663:
664: public Update getTableScrollUpdate(STable table,
665: Rectangle newViewport, Rectangle oldViewport) {
666: return new ComponentUpdate(this , table);
667: }
668:
669: public Update getSelectionUpdate(STable table,
670: List deselectedIndices, List selectedIndices) {
671: return new SelectionUpdate((XTable) table, deselectedIndices,
672: selectedIndices);
673: }
674:
675: public Update getEditCellUpdate(STable table, int row, int column) {
676: return new EditCellUpdate((XTable) table, row, column);
677: }
678:
679: public Update getRenderCellUpdate(STable table, int row, int column) {
680: return new RenderCellUpdate((XTable) table, row, column);
681: }
682:
683: protected class TableScrollUpdate extends AbstractUpdate {
684:
685: public TableScrollUpdate(SComponent component) {
686: super (component);
687: }
688:
689: public Handler getHandler() {
690: XTable table = (XTable) component;
691:
692: Rectangle currentViewport = table.getViewportSize();
693: Rectangle maximalViewport = table
694: .getScrollableViewportSize();
695: int startX = 0;
696: int endX = table.getVisibleColumnCount();
697: int startY = 0;
698: int endY = table.getRowCount();
699: int emptyIndex = maximalViewport != null ? maximalViewport.height
700: : endY;
701:
702: if (currentViewport != null) {
703: startX = currentViewport.x;
704: endX = startX + currentViewport.width;
705: startY = currentViewport.y;
706: endY = startY + currentViewport.height;
707: }
708:
709: String htmlCode = "";
710: String exception = null;
711:
712: try {
713: StringBuilderDevice htmlDevice = new StringBuilderDevice();
714: writeBody(htmlDevice, table, startX, endX, startY,
715: endY, emptyIndex);
716: htmlCode = htmlDevice.toString();
717: } catch (Throwable t) {
718: exception = t.getClass().getName();
719: }
720:
721: UpdateHandler handler = new UpdateHandler("tableScroll");
722: handler.addParameter(table.getName());
723: handler.addParameter(htmlCode);
724: if (exception != null) {
725: handler.addParameter(exception);
726: }
727: return handler;
728: }
729: }
730:
731: protected class SelectionUpdate extends AbstractUpdate<XTable> {
732: private List<Integer> deselectedIndices;
733: private List<Integer> selectedIndices;
734:
735: public SelectionUpdate(XTable component,
736: List<Integer> deselectedIndices,
737: List<Integer> selectedIndices) {
738: super (component);
739: this .deselectedIndices = deselectedIndices;
740: this .selectedIndices = selectedIndices;
741: }
742:
743: public Handler getHandler() {
744: int indexOffset = 0;
745: if (component.isHeaderVisible()) {
746: ++indexOffset;
747: }
748: if (component.isFilterVisible()
749: && component.getModel() instanceof FilterableTableModel) {
750: ++indexOffset;
751: }
752:
753: UpdateHandler handler = new UpdateHandler("selectionTable");
754: handler.addParameter(component.getName());
755: handler.addParameter(new Integer(indexOffset));
756: handler
757: .addParameter(Utils
758: .listToJsArray(deselectedIndices));
759: handler.addParameter(Utils.listToJsArray(selectedIndices));
760: if (isSelectionColumnVisible(component)) {
761: String exception = null;
762: List<String> deselectedBodies = new ArrayList<String>();
763: List<String> selectedBodies = new ArrayList<String>();
764: exception = writeSelectionBodies(deselectedIndices,
765: deselectedBodies);
766: exception = writeSelectionBodies(selectedIndices,
767: selectedBodies);
768: handler.addParameter(Utils
769: .listToJsArray(deselectedBodies));
770: handler.addParameter(Utils
771: .listToJsArray(selectedBodies));
772: if (exception != null) {
773: handler.addParameter(exception);
774: }
775: }
776: return handler;
777: }
778:
779: private String writeSelectionBodies(List<Integer> indices,
780: List<String> bodies) {
781: try {
782: final StringBuilderDevice htmlDevice = new StringBuilderDevice(
783: 512);
784: final SCellRendererPane rendererPane = component
785: .getCellRendererPane();
786: for (Integer index : indices) {
787: writeSelectionBody(htmlDevice, component,
788: rendererPane, index);
789: bodies.add(htmlDevice.toString());
790: htmlDevice.reset();
791: }
792: } catch (Throwable t) {
793: return t.getClass().getName();
794: }
795: return null;
796: }
797: }
798:
799: private class EditCellUpdate extends AbstractUpdate<XTable> {
800: private int row;
801: private int column;
802:
803: public EditCellUpdate(XTable table, int row, int column) {
804: super (table);
805: this .row = row;
806: this .column = column;
807: }
808:
809: public Handler getHandler() {
810: XTable table = this .component;
811:
812: String htmlCode = "";
813: String exception = null;
814:
815: try {
816: StringBuilderDevice device = new StringBuilderDevice(
817: 512);
818: /*
819: Utils.printTableCellAlignment(device, component, SConstants.LEFT, SConstants.TOP);
820: Utils.optAttribute(device, "oversize", horizontalOversize);
821: device.print(" class=\"cell\">");
822: */
823: SComponent component = table.getEditorComponent();
824: table.getCellRendererPane().writeComponent(device,
825: component, table);
826: htmlCode = device.toString();
827: } catch (Throwable t) {
828: exception = t.getClass().getName();
829: }
830:
831: row = table.isHeaderVisible() ? this .row + 1 : this .row;
832: row = (table.isFilterVisible() && table.getModel() instanceof FilterableTableModel) ? this .row + 1
833: : this .row;
834: column = columnInView(table, column);
835: column = isSelectionColumnVisible(table) ? column + 1
836: : column;
837:
838: Rectangle currentViewport = table.getViewportSize();
839: if (currentViewport != null) {
840: row -= currentViewport.y;
841: column -= currentViewport.x;
842: }
843:
844: UpdateHandler handler = new UpdateHandler("tableCell");
845: handler.addParameter(table.getName());
846: handler.addParameter(row);
847: handler.addParameter(column);
848: handler.addParameter(true);
849: handler.addParameter(htmlCode);
850: if (exception != null) {
851: handler.addParameter(exception);
852: }
853: return handler;
854: }
855: }
856:
857: private class RenderCellUpdate extends AbstractUpdate<XTable> {
858: private int row;
859: private int column;
860:
861: public RenderCellUpdate(XTable table, int row, int column) {
862: super (table);
863: this .row = row;
864: this .column = column;
865: }
866:
867: public Handler getHandler() {
868: XTable table = this .component;
869:
870: String htmlCode = "";
871: String exception = null;
872:
873: try {
874: StringBuilderDevice device = new StringBuilderDevice(
875: 256);
876: /*
877: Utils.printTableCellAlignment(device, component, SConstants.LEFT, SConstants.TOP);
878: Utils.optAttribute(device, "oversize", horizontalOversize);
879: device.print(" class=\"cell\">");
880: */
881: SComponent component = table.prepareRenderer(table
882: .getCellRenderer(row, column), row, column);
883: table.getCellRendererPane().writeComponent(device,
884: component, table);
885: htmlCode = device.toString();
886: } catch (Throwable t) {
887: exception = t.getClass().getName();
888: }
889:
890: row = table.isHeaderVisible() ? this .row + 1 : this .row;
891: row = (table.isFilterVisible() && table.getModel() instanceof FilterableTableModel) ? this .row + 1
892: : this .row;
893: column = columnInView(table, column);
894: column = isSelectionColumnVisible(table) ? column + 1
895: : column;
896:
897: Rectangle currentViewport = table.getViewportSize();
898: if (currentViewport != null) {
899: row -= currentViewport.y;
900: column -= currentViewport.x;
901: }
902:
903: UpdateHandler handler = new UpdateHandler("tableCell");
904: handler.addParameter(table.getName());
905: handler.addParameter(row);
906: handler.addParameter(column);
907: handler.addParameter(false);
908: handler.addParameter(htmlCode);
909: if (exception != null) {
910: handler.addParameter(exception);
911: }
912: return handler;
913: }
914:
915: public boolean equals(Object object) {
916: if (!super .equals(object))
917: return false;
918:
919: RenderCellUpdate other = (RenderCellUpdate) object;
920:
921: if (this .row != other.row)
922: return false;
923: if (this .column != other.column)
924: return false;
925:
926: return true;
927: }
928:
929: public int hashCode() {
930: int hashCode = super .hashCode();
931: int dispersionFactor = 37;
932:
933: hashCode = hashCode * dispersionFactor + row;
934: hashCode = hashCode * dispersionFactor + column;
935:
936: return hashCode;
937: }
938: }
939:
940: private int columnInView(STable table, int column) {
941: int viewColumn = 0;
942: for (int i = 0; i < column; i++) {
943: STableColumn tableColumn = table.getColumnModel()
944: .getColumn(i);
945: if (!tableColumn.isHidden())
946: viewColumn++;
947: }
948: return viewColumn;
949: }
950: }
|