1 16 17 package com.google.gwt.user.client.ui; 18 19 import com.google.gwt.user.client.DOM; 20 import com.google.gwt.user.client.Element; 21 import com.google.gwt.user.client.Event; 22 import com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant; 23 import com.google.gwt.user.client.ui.HasVerticalAlignment.VerticalAlignmentConstant; 24 25 import java.util.ArrayList ; 26 import java.util.Iterator ; 27 import java.util.NoSuchElementException ; 28 29 37 public abstract class HTMLTable extends Panel implements SourcesTableEvents { 38 41 public class CellFormatter { 42 50 public void addStyleName(int row, int column, String styleName) { 51 prepareCell(row, column); 52 Element td = getCellElement(bodyElem, row, column); 53 UIObject.setStyleName(td, styleName, true); 54 } 55 56 64 public Element getElement(int row, int column) { 65 checkCellBounds(row, column); 66 return getCellElement(bodyElem, row, column); 67 } 68 69 78 public String getStyleName(int row, int column) { 79 return DOM.getElementProperty(getElement(row, column), "className"); 80 } 81 82 89 public boolean isVisible(int row, int column) { 90 Element e = getElement(row, column); 91 return UIObject.isVisible(e); 92 } 93 94 103 public void removeStyleName(int row, int column, String styleName) { 104 checkCellBounds(row, column); 105 Element td = getCellElement(bodyElem, row, column); 106 UIObject.setStyleName(td, styleName, false); 107 } 108 109 121 public void setAlignment(int row, int column, 122 HorizontalAlignmentConstant hAlign, VerticalAlignmentConstant vAlign) { 123 setHorizontalAlignment(row, column, hAlign); 124 setVerticalAlignment(row, column, vAlign); 125 } 126 127 135 public void setHeight(int row, int column, String height) { 136 prepareCell(row, column); 137 Element elem = getCellElement(bodyElem, row, column); 138 DOM.setElementProperty(elem, "height", height); 139 } 140 141 150 public void setHorizontalAlignment(int row, int column, 151 HorizontalAlignmentConstant align) { 152 prepareCell(row, column); 153 Element elem = getCellElement(bodyElem, row, column); 154 DOM.setElementProperty(elem, "align", align.getTextAlignString()); 155 } 156 157 166 public void setStyleName(int row, int column, String styleName) { 167 prepareCell(row, column); 168 Element elem = getCellElement(bodyElem, row, column); 169 DOM.setElementProperty(elem, "className", styleName); 172 } 173 174 183 public void setVerticalAlignment(int row, int column, 184 VerticalAlignmentConstant align) { 185 prepareCell(row, column); 186 DOM.setStyleAttribute(getCellElement(bodyElem, row, column), 187 "verticalAlign", align.getVerticalAlignString()); 188 } 189 190 200 public void setVisible(int row, int column, boolean visible) { 201 Element e = ensureElement(row, column); 202 UIObject.setVisible(e, visible); 203 } 204 205 213 public void setWidth(int row, int column, String width) { 214 prepareCell(row, column); 216 DOM.setElementProperty(getCellElement(bodyElem, row, column), "width", 217 width); 218 } 219 220 228 public void setWordWrap(int row, int column, boolean wrap) { 229 prepareCell(row, column); 230 String wrapValue = wrap ? "" : "nowrap"; 231 DOM.setStyleAttribute(getElement(row, column), "whiteSpace", wrapValue); 232 } 233 234 243 protected Element ensureElement(int row, int column) { 244 prepareCell(row, column); 245 return getCellElement(bodyElem, row, column); 246 } 247 248 257 protected String getAttr(int row, int column, String attr) { 258 Element elem = getElement(row, column); 259 return DOM.getElementAttribute(elem, attr); 260 } 261 262 271 protected void setAttr(int row, int column, String attrName, String value) { 272 Element elem = ensureElement(row, column); 273 DOM.setElementAttribute(elem, attrName, value); 274 } 275 276 284 285 private native Element getCellElement(Element table, int row, int col) ; 289 290 298 private Element getRawElement(int row, int column) { 299 return getCellElement(bodyElem, row, column); 300 } 301 } 302 303 307 public class ColumnFormatter { 308 protected Element columnGroup; 309 310 318 public void addStyleName(int col, String styleName) { 319 UIObject.setStyleName(ensureColumn(col), styleName, true); 320 } 321 322 330 public String getStyleName(int column) { 331 return DOM.getElementProperty(ensureColumn(column), "className"); 332 } 333 334 342 public void removeStyleName(int column, String styleName) { 343 UIObject.setStyleName(ensureColumn(column), styleName, false); 344 } 345 346 354 public void setStyleName(int column, String styleName) { 355 UIObject.resetStyleName(ensureColumn(column), styleName); 356 } 357 358 365 public void setWidth(int column, String width) { 366 DOM.setElementProperty(ensureColumn(column), "width", width); 367 } 368 369 private Element ensureColumn(int col) { 370 prepareColumn(col); 371 372 if (columnGroup == null) { 373 columnGroup = DOM.createElement("colgroup"); 374 DOM.insertChild(getElement(), columnGroup, 0); 375 } 376 377 int num = DOM.getChildCount(columnGroup); 378 if (num <= col) { 379 Element colElement = null; 380 for (int i = num; i <= col; i++) { 381 colElement = DOM.createElement("col"); 382 DOM.appendChild(columnGroup, colElement); 383 } 384 return colElement; 385 } 386 return DOM.getChild(columnGroup, col); 387 } 388 } 389 390 393 public class RowFormatter { 394 395 403 public void addStyleName(int row, String styleName) { 404 UIObject.setStyleName(ensureElement(row), styleName, true); 405 } 406 407 414 public Element getElement(int row) { 415 checkRowBounds(row); 416 return getRow(bodyElem, row); 417 } 418 419 427 public String getStyleName(int row) { 428 return DOM.getElementProperty(getElement(row), "className"); 429 } 430 431 438 public boolean isVisible(int row) { 439 Element e = getElement(row); 440 return UIObject.isVisible(e); 441 } 442 443 451 public void removeStyleName(int row, String styleName) { 452 UIObject.setStyleName(ensureElement(row), styleName, false); 453 } 454 455 463 public void setStyleName(int row, String styleName) { 464 UIObject.resetStyleName(ensureElement(row), styleName); 465 } 466 467 475 public void setVerticalAlign(int row, VerticalAlignmentConstant align) { 476 DOM.setStyleAttribute(ensureElement(row), "verticalAlign", 477 align.getVerticalAlignString()); 478 } 479 480 487 public void setVisible(int row, boolean visible) { 488 Element e = ensureElement(row); 489 UIObject.setVisible(e, visible); 490 } 491 492 500 protected Element ensureElement(int row) { 501 prepareRow(row); 502 return getRow(bodyElem, row); 503 } 504 505 protected native Element getRow(Element elem, int row); 508 509 517 protected void setAttr(int row, String attrName, String value) { 518 Element elem = ensureElement(row); 519 DOM.setElementAttribute(elem, attrName, value); 520 } 521 } 522 523 526 private static class WidgetMapper { 527 528 private static class FreeNode { 529 int index; 530 FreeNode next; 531 public FreeNode(int index, FreeNode next) { 532 this.index = index; 533 this.next = next; 534 } 535 } 536 537 private static native void clearWidgetIndex(Element elem) ; 540 541 private static native int getWidgetIndex(Element elem) ; 545 546 private static native void setWidgetIndex(Element elem, int index) ; 549 550 private FreeNode freeList = null; 551 552 private ArrayList widgetList = new ArrayList (); 553 554 560 public Widget getWidget(Element elem) { 561 int index = getWidgetIndex(elem); 562 if (index < 0) { 563 return null; 564 } 565 return (Widget) widgetList.get(index); 566 } 567 568 573 public void putWidget(Widget widget) { 574 int index; 575 if (freeList == null) { 576 index = widgetList.size(); 577 widgetList.add(widget); 578 } else { 579 index = freeList.index; 580 widgetList.set(index, widget); 581 freeList = freeList.next; 582 } 583 setWidgetIndex(widget.getElement(), index); 584 } 585 586 591 public void removeWidgetByElement(Element elem) { 592 int index = getWidgetIndex(elem); 593 removeImpl(elem, index); 594 } 595 596 601 public Iterator widgetIterator() { 602 return new Iterator () { 604 int lastIndex = -1; 605 int nextIndex = -1; 606 { 607 findNext(); 608 } 609 610 public boolean hasNext() { 611 return nextIndex < widgetList.size(); 612 } 613 614 public Object next() { 615 if (!hasNext()) { 616 throw new NoSuchElementException (); 617 } 618 Object result = widgetList.get(nextIndex); 619 lastIndex = nextIndex; 620 findNext(); 621 return result; 622 } 623 624 public void remove() { 625 if (lastIndex < 0) { 626 throw new IllegalStateException (); 627 } 628 Widget w = (Widget) widgetList.get(lastIndex); 629 removeImpl(w.getElement(), lastIndex); 630 lastIndex = -1; 631 } 632 633 private void findNext() { 634 while (++nextIndex < widgetList.size()) { 635 if (widgetList.get(nextIndex) != null) { 636 return; 637 } 638 } 639 } 640 }; 641 } 642 643 private void removeImpl(Element elem, int index) { 644 clearWidgetIndex(elem); 645 widgetList.set(index, null); 646 freeList = new FreeNode(index, freeList); 647 } 648 } 649 650 653 private final Element bodyElem; 654 655 658 private CellFormatter cellFormatter; 659 660 663 private ColumnFormatter columnFormatter; 664 665 668 private RowFormatter rowFormatter; 669 670 673 private final Element tableElem; 674 675 678 private TableListenerCollection tableListeners; 679 680 private WidgetMapper widgetMap = new WidgetMapper(); 681 682 685 public HTMLTable() { 686 tableElem = DOM.createTable(); 687 bodyElem = DOM.createTBody(); 688 DOM.appendChild(tableElem, bodyElem); 689 setElement(tableElem); 690 sinkEvents(Event.ONCLICK); 691 } 692 693 698 public void addTableListener(TableListener listener) { 699 if (tableListeners == null) { 700 tableListeners = new TableListenerCollection(); 701 } 702 tableListeners.add(listener); 703 } 704 705 709 public void clear() { 710 for (int row = 0; row < getRowCount(); ++row) { 711 for (int col = 0; col < getCellCount(row); ++col) { 712 Widget child = getWidgetImpl(row, col); 713 if (child != null) { 714 remove(child); 715 } 716 } 717 } 718 } 719 720 729 public boolean clearCell(int row, int column) { 730 Element td = getCellFormatter().getElement(row, column); 731 return internalClearCell(td, true); 732 } 733 734 740 public abstract int getCellCount(int row); 741 742 748 public CellFormatter getCellFormatter() { 749 return cellFormatter; 750 } 751 752 757 public int getCellPadding() { 758 return DOM.getElementPropertyInt(tableElem, "cellPadding"); 759 } 760 761 766 public int getCellSpacing() { 767 return DOM.getElementPropertyInt(tableElem, "cellSpacing"); 768 } 769 770 775 public ColumnFormatter getColumnFormatter() { 776 return columnFormatter; 777 } 778 779 787 public String getHTML(int row, int column) { 788 return DOM.getInnerHTML(cellFormatter.getElement(row, column)); 789 } 790 791 796 public abstract int getRowCount(); 797 798 803 public RowFormatter getRowFormatter() { 804 return rowFormatter; 805 } 806 807 815 public String getText(int row, int column) { 816 checkCellBounds(row, column); 817 Element e = cellFormatter.getElement(row, column); 818 return DOM.getInnerText(e); 819 } 820 821 830 public Widget getWidget(int row, int column) { 831 checkCellBounds(row, column); 832 return getWidgetImpl(row, column); 833 } 834 835 842 public boolean isCellPresent(int row, int column) { 843 if ((row >= getRowCount()) && (row < 0)) { 844 return false; 845 } 846 if ((column < 0) || (column >= getCellCount(row))) { 847 return false; 848 } else { 849 return true; 850 } 851 } 852 853 858 public Iterator iterator() { 859 return widgetMap.widgetIterator(); 860 } 861 862 867 public void onBrowserEvent(Event event) { 868 switch (DOM.eventGetType(event)) { 869 case Event.ONCLICK: { 870 if (tableListeners != null) { 871 Element td = getEventTargetCell(event); 873 if (td == null) { 874 return; 875 } 876 Element tr = DOM.getParent(td); 877 Element body = DOM.getParent(tr); 878 int row = DOM.getChildIndex(body, tr); 879 int column = DOM.getChildIndex(tr, td); 880 tableListeners.fireCellClicked(this, row, column); 882 } 883 break; 884 } 885 default: { 886 } 888 } 889 } 890 891 897 public boolean remove(Widget widget) { 898 if (widget.getParent() != this) { 900 return false; 901 } 902 widgetMap.removeWidgetByElement(widget.getElement()); 903 disown(widget); 904 return true; 905 } 906 907 912 public void removeTableListener(TableListener listener) { 913 if (tableListeners != null) { 914 tableListeners.remove(listener); 915 } 916 } 917 918 924 public void setBorderWidth(int width) { 925 DOM.setElementProperty(tableElem, "border", "" + width); 926 } 927 928 933 public void setCellPadding(int padding) { 934 DOM.setElementPropertyInt(tableElem, "cellPadding", padding); 935 } 936 937 942 public void setCellSpacing(int spacing) { 943 DOM.setElementPropertyInt(tableElem, "cellSpacing", spacing); 944 } 945 946 954 public void setHTML(int row, int column, String html) { 955 prepareCell(row, column); 956 Element td = cleanCell(row, column, html == null); 957 if (html != null) { 958 DOM.setInnerHTML(td, html); 959 } 960 } 961 962 970 public void setText(int row, int column, String text) { 971 prepareCell(row, column); 972 Element td; 973 td = cleanCell(row, column, text == null); 974 if (text != null) { 975 DOM.setInnerText(td, text); 976 } 977 } 978 979 996 public void setWidget(int row, int column, Widget widget) { 997 prepareCell(row, column); 998 if (widget != null) { 999 widget.removeFromParent(); 1002 1003 Element td = cleanCell(row, column, true); 1005 1006 widgetMap.putWidget(widget); 1008 1009 adopt(widget, td); 1011 } 1012 } 1013 1014 1021 protected void checkCellBounds(int row, int column) { 1022 checkRowBounds(row); 1023 if (column < 0) { 1024 throw new IndexOutOfBoundsException ("Column " + column 1025 + " must be non-negative: " + column); 1026 } 1027 int cellSize = getCellCount(row); 1028 if (cellSize <= column) { 1029 throw new IndexOutOfBoundsException ("Column index: " + column 1030 + ", Column size: " + getCellCount(row)); 1031 } 1032 } 1033 1034 1040 protected void checkRowBounds(int row) { 1041 int rowSize = getRowCount(); 1042 if ((row >= rowSize) || (row < 0)) { 1043 throw new IndexOutOfBoundsException ("Row index: " + row + ", Row size: " 1044 + rowSize); 1045 } 1046 } 1047 1048 1054 protected Element createCell() { 1055 return DOM.createTD(); 1056 } 1057 1058 1063 protected Element getBodyElement() { 1064 return bodyElem; 1065 } 1066 1067 1074 protected native int getDOMCellCount(Element tableBody, int row) ; 1077 1078 1084 protected int getDOMCellCount(int row) { 1085 return getDOMCellCount(bodyElem, row); 1086 } 1087 1088 1093 protected int getDOMRowCount() { 1094 return getDOMRowCount(bodyElem); 1095 } 1096 1097 protected native int getDOMRowCount(Element elem) ; 1100 1101 1108 protected Element getEventTargetCell(Event event) { 1109 Element td = DOM.eventGetTarget(event); 1110 for (; td != null; td = DOM.getParent(td)) { 1111 if (DOM.getElementProperty(td, "tagName").equalsIgnoreCase("td")) { 1113 Element tr = DOM.getParent(td); 1116 Element body = DOM.getParent(tr); 1117 if (DOM.compare(body, bodyElem)) { 1118 return td; 1119 } 1120 } 1121 if (DOM.compare(td, bodyElem)) { 1123 return null; 1124 } 1125 } 1126 return null; 1127 } 1128 1129 1136 protected void insertCell(int row, int column) { 1137 Element tr = rowFormatter.getRow(bodyElem, row); 1138 Element td = createCell(); 1139 DOM.insertChild(tr, td, column); 1140 } 1141 1142 1150 protected void insertCells(int row, int column, int count) { 1151 Element tr = rowFormatter.getRow(bodyElem, row); 1152 for (int i = column; i < column + count; i++) { 1153 Element td = createCell(); 1154 DOM.insertChild(tr, td, i); 1155 } 1156 } 1157 1158 1165 protected int insertRow(int beforeRow) { 1166 if (beforeRow != getRowCount()) { 1168 checkRowBounds(beforeRow); 1169 } 1170 Element tr = DOM.createTR(); 1171 DOM.insertChild(bodyElem, tr, beforeRow); 1172 return beforeRow; 1173 } 1174 1175 1184 protected boolean internalClearCell(Element td, boolean clearInnerHTML) { 1185 Element maybeChild = DOM.getFirstChild(td); 1186 Widget widget = null; 1187 if (maybeChild != null) { 1188 widget = widgetMap.getWidget(maybeChild); 1189 } 1190 if (widget != null) { 1191 remove(widget); 1193 return true; 1194 } else { 1195 if (clearInnerHTML) { 1197 DOM.setInnerHTML(td, ""); 1198 } 1199 return false; 1200 } 1201 } 1202 1203 1212 protected abstract void prepareCell(int row, int column); 1213 1214 1223 protected void prepareColumn(int column) { 1224 } 1226 1227 1234 protected abstract void prepareRow(int row); 1235 1236 1243 protected void removeCell(int row, int column) { 1244 checkCellBounds(row, column); 1245 Element td = cleanCell(row, column, false); 1246 Element tr = rowFormatter.getRow(bodyElem, row); 1247 DOM.removeChild(tr, td); 1248 } 1249 1250 1256 protected void removeRow(int row) { 1257 int columnCount = getCellCount(row); 1258 for (int column = 0; column < columnCount; ++column) { 1259 cleanCell(row, column, false); 1260 } 1261 DOM.removeChild(bodyElem, rowFormatter.getRow(bodyElem, row)); 1262 } 1263 1264 1269 protected void setCellFormatter(CellFormatter cellFormatter) { 1270 this.cellFormatter = cellFormatter; 1271 } 1272 1273 protected void setColumnFormatter(ColumnFormatter formatter) { 1274 columnFormatter = formatter; 1275 } 1276 1277 1282 protected void setRowFormatter(RowFormatter rowFormatter) { 1283 this.rowFormatter = rowFormatter; 1284 } 1285 1286 1295 private Element cleanCell(int row, int column, boolean clearInnerHTML) { 1296 Element td = getCellFormatter().getRawElement(row, column); 1298 internalClearCell(td, clearInnerHTML); 1299 return td; 1300 } 1301 1302 1309 private Widget getWidgetImpl(int row, int column) { 1310 Element e = cellFormatter.getRawElement(row, column); 1311 Element child = DOM.getFirstChild(e); 1312 if (child == null) { 1313 return null; 1314 } else { 1315 return widgetMap.getWidget(child); 1316 } 1317 } 1318} 1319 | Popular Tags |