001: /*
002: * MyGWT Widget Library
003: * Copyright(c) 2007, MyGWT.
004: * licensing@mygwt.net
005: *
006: * http://mygwt.net/license
007: */
008: package net.mygwt.ui.client.widget.table;
009:
010: import java.util.Collections;
011: import java.util.Comparator;
012:
013: import net.mygwt.ui.client.MyDOM;
014: import net.mygwt.ui.client.MyGWT;
015: import net.mygwt.ui.client.Style;
016:
017: import com.google.gwt.user.client.DOM;
018: import com.google.gwt.user.client.Element;
019: import com.google.gwt.user.client.Event;
020: import com.google.gwt.user.client.ui.Widget;
021: import com.google.gwt.user.client.ui.WidgetHelper;
022:
023: /**
024: * This class encapsulates the user interface of a {@link Table}.
025: */
026: public class TableView {
027:
028: private static String bodyHTML;
029:
030: static {
031: StringBuffer sb = new StringBuffer();
032: sb.append("<div style='overflow: hidden;'>");
033: sb.append("<div style='overflow: scroll;'>");
034: sb.append("<div class='my-tbl-data'></div>");
035: sb.append("</div></div>");
036: bodyHTML = sb.toString();
037: }
038:
039: // styles
040: protected String baseStyle = "my-tbl-item";
041: protected String overStyle = baseStyle + "-over";
042: protected String selStyle = baseStyle + "-sel";
043: protected String cellStyle = baseStyle + "-" + "cell";
044: protected String cellOverflowStyle = cellStyle + "-" + "overflow";
045: protected String textStyle = cellStyle + "-text";
046: protected String widgetStyle = cellStyle + "-widget";
047:
048: protected TableColumnModel cm;
049: protected Element scrollElem, dataElem;
050: protected Table table;
051: protected int scrollBarWidth;
052:
053: /**
054: * Sorts the table items based on the current order.
055: */
056: public void reorderItems() {
057: MyDOM.removeChildren(dataElem);
058: int numRows = table.getItemCount();
059: for (int i = 0; i < numRows; i++) {
060: TableItem item = table.getItem(i);
061: DOM.appendChild(dataElem, item.getElement());
062: }
063: table.getSelectionModel().refresh();
064: }
065:
066: protected void applyCellStyles(TableItem item) {
067: if (item.cellStyles != null) {
068: for (int i = 0; i < item.cellStyles.length; i++) {
069: setCellStyle(item, i, item.cellStyles[i]);
070: }
071: }
072: }
073:
074: protected void clearHoverStyles() {
075: int count = table.getItemCount();
076: for (int i = 0; i < count; i++) {
077: TableItem item = table.getItem(i);
078: item.onMouseOut(null);
079: }
080: }
081:
082: protected void onSelectItem(TableItem item, boolean select) {
083: if (select) {
084: item.addStyleName(selStyle);
085: } else {
086: item.removeStyleName(selStyle);
087: }
088: }
089:
090: protected void doSort(int index, int direction) {
091: TableColumn column = table.getColumn(index);
092: final Comparator comparator = column.getComparator();
093: final int col = index;
094: Collections.sort(table.getItems(), new Comparator() {
095: public int compare(Object arg0, Object arg1) {
096: TableItem item1 = (TableItem) arg0;
097: TableItem item2 = (TableItem) arg1;
098: Object o1 = item1.getValue(col);
099: Object o2 = item2.getValue(col);
100: return comparator.compare(o1, o2);
101: }
102: });
103:
104: if (direction == Style.DESC) {
105: Collections.reverse(table.getItems());
106: }
107: reorderItems();
108: }
109:
110: protected int getCellIndex(Element target) {
111: String index = MyDOM.getAnyElementProperty(target, "index");
112: if (index == null) {
113: target = DOM.getParent(target);
114: while (target != null) {
115: index = MyDOM.getAnyElementProperty(target, "index");
116: if (index == null) {
117: target = DOM.getParent(target);
118: } else {
119: break;
120: }
121: }
122: }
123: return index == null ? Style.DEFAULT : Integer.parseInt(index);
124: }
125:
126: protected Element getScrollElement() {
127: return scrollElem;
128: }
129:
130: protected Element getTextCellElement(TableItem item, int cell) {
131: return getTextCellInternal(item.getElement(), cell);
132: }
133:
134: protected native Element getTextCellInternal(Element elem,
135: int column) /*-{
136: return elem.firstChild.firstChild.firstChild.childNodes[column].firstChild.firstChild;
137: }-*/;
138:
139: protected void init(Table table) {
140: this .table = table;
141: this .cm = table.getColumnModel();
142: }
143:
144: protected void onHighlightRow(TableItem item, boolean highlight) {
145: if (highlight) {
146: item.addStyleName(overStyle);
147: } else {
148: item.removeStyleName(overStyle);
149: }
150: }
151:
152: protected void removeItem(TableItem item) {
153: DOM.removeChild(dataElem, item.getElement());
154: }
155:
156: protected void render() {
157: scrollBarWidth = MyDOM.getScrollBarWidth();
158:
159: Element div = DOM.createDiv();
160: MyDOM.setInnerHTML(div, bodyHTML.toString());
161: scrollElem = MyDOM.getSubChild(div, 2);
162: dataElem = DOM.getFirstChild(scrollElem);
163: DOM.appendChild(table.getElement(), DOM.getFirstChild(div));
164:
165: if (table.verticalLines) {
166: table.addStyleName("my-tbl-vlines");
167: }
168:
169: if (!MyGWT.isIE) {
170: DOM
171: .setElementPropertyInt(table.getElement(),
172: "tabIndex", 0);
173: }
174:
175: DOM.sinkEvents(scrollElem, Event.ONSCROLL);
176:
177: table.disableTextSelection(true);
178: }
179:
180: protected void renderItem(TableItem item, int index) {
181: item.setStyleName(baseStyle);
182: item.init(table);
183:
184: int cols = cm.getColumnCount();
185: Object[] values = item.getValues();
186: Object[] svalues = new Object[cols];
187: for (int i = 0; i < cols; i++) {
188: if (!item.hasWidgets && values[i] instanceof Widget) {
189: item.hasWidgets = true;
190: }
191: svalues[i] = table.getRenderedValue(i, values[i]);
192: }
193:
194: StringBuffer sb = new StringBuffer();
195: sb.append("<table cellpadding=0 cellspacing=0 tabIndex=1><tr>");
196: for (int i = 0; i < cols; i++) {
197: TableColumn c = cm.getColumn(i);
198: String display = c.isHidden() ? "none" : "static";
199: int w = table.getColumnModel().getWidthInPixels(c.index);
200: int align = c.getAlignment();
201: String salign = "left";
202: if (align == Style.CENTER) {
203: salign = "center";
204: } else if (align == Style.RIGHT) {
205: salign = "right";
206: }
207: sb.append("<td class=" + cellStyle + " style='display: "
208: + display + ";width: " + w + "px' index=" + i
209: + "><div class=" + cellOverflowStyle
210: + " style='width:" + w + "'><div class="
211: + textStyle + " style='text-align:" + salign + "'>"
212: + svalues[i] + "</div></div></td>");
213: }
214: sb.append("</tr></table>");
215:
216: MyDOM.setInnerHTML(item.getElement(), sb.toString());
217: DOM.insertChild(dataElem, item.getElement(), index);
218:
219: if (item.hasWidgets) {
220: for (int i = 0; i < cols; i++) {
221: if (values[i] instanceof Widget) {
222: Widget w = (Widget) values[i];
223: Element text = getTextCellElement(item, i);
224: MyDOM.setInnerHTML(text, "");
225: MyDOM.setStyleName(text, widgetStyle);
226: DOM.appendChild(text, w.getElement());
227: if (table.isAttached()) {
228: WidgetHelper.doAttach(w);
229: }
230: }
231: }
232: }
233: applyCellStyles(item);
234:
235: item.cellsRendered = true;
236: }
237:
238: protected void renderItems() {
239: int count = table.getItemCount();
240: for (int i = 0; i < count; i++) {
241: TableItem item = table.getItem(i);
242: renderItem(item, i);
243: }
244: }
245:
246: protected void renderItemValue(TableItem item, int index,
247: Object value) {
248: Element textElem = getTextCellElement(item, index);
249: if (textElem != null) {
250: DOM.setInnerHTML(textElem, "");
251: if (value instanceof Widget) {
252: Widget widget = (Widget) value;
253: MyDOM.setStyleName(textElem, widgetStyle);
254: DOM.appendChild(textElem, widget.getElement());
255: if (table.isAttached()) {
256: WidgetHelper.doAttach(widget);
257: }
258: } else {
259: String s = table.getRenderedValue(index, value);
260: MyDOM.setInnerHTML(textElem, s);
261: }
262: }
263: applyCellStyles(item);
264: }
265:
266: protected void resize() {
267: int width = table.getOffsetWidth();
268: int headerHeight = table.getTableHeader().getOffsetHeight();
269: int bodyHeight = table.getOffsetHeight() - headerHeight;
270: int bodyWidth = width;
271:
272: MyDOM.setWidth(dataElem, cm.getTotalWidth());
273:
274: boolean vscroll = MyDOM.getHeight(dataElem) > bodyHeight;
275: int adj = vscroll ? scrollBarWidth : 0;
276:
277: if ((table.getStyle() & Style.HORIZONTAL) != 0) {
278: if (MyDOM.getWidth(dataElem) < (width - adj)) {
279: bodyHeight += scrollBarWidth;
280: MyDOM.setLeft(table.getTableHeader().getElement(), 0);
281: }
282: } else {
283: bodyHeight += scrollBarWidth;
284: }
285: if (MyDOM.getHeight(dataElem) > bodyHeight) {
286: width -= scrollBarWidth;
287: }
288:
289: bodyHeight -= MyDOM.getBorderWidth(table.getElement(),
290: Style.TOP | Style.BOTTOM);
291: bodyWidth -= MyDOM.getBorderWidth(table.getElement(),
292: Style.LEFT | Style.RIGHT);
293:
294: MyDOM.setSize(scrollElem, bodyWidth, bodyHeight);
295:
296: int w = cm.getTotalWidth();
297:
298: if (w < width) {
299: adj = width - w;
300: }
301: MyDOM.setWidth(dataElem, cm.getTotalWidth() + adj);
302: }
303:
304: protected void resizeCells(int columnIndex) {
305: TableColumn c = cm.getColumn(columnIndex);
306: int w = cm.getWidthInPixels(c.index);
307: if (table.verticalLines) {
308: --w;
309: }
310: int rows = table.getItemCount();
311: for (int j = 0; j < rows; j++) {
312: TableItem item = table.getItem(j);
313: sizeCell(item.getElement(), columnIndex, w);
314: if (j == 0) {
315: showColumn(item.getElement(), !c.isHidden(),
316: columnIndex);
317: }
318: }
319: }
320:
321: protected void setCellStyle(TableItem item, int index, String style) {
322: if (item.cellsRendered) {
323: Element cell = getTextCellElement(item, index);
324: MyDOM.setStyleName(cell, textStyle + " " + style);
325: }
326: }
327:
328: protected native void showColumn(Element elem, boolean show,
329: int index) /*-{
330: var tbl = elem.firstChild;
331: var cell = tbl.firstChild.firstChild.childNodes[index]
332: cell.style.display = show ? '' : 'none';
333: }-*/;
334:
335: protected void showColumn(int index, boolean show) {
336: int count = table.getItemCount();
337: for (int i = 0; i < count; i++) {
338: showColumn(table.getItem(i).getElement(), show, index);
339: }
340: }
341:
342: protected native void sizeCell(Element elem, int index, int width) /*-{
343: var tbl = elem.firstChild;
344: var cell = tbl.firstChild.firstChild.childNodes[index];
345: cell.style.width = width;
346: cell.firstChild.style.width = width;
347: }-*/;
348:
349: protected void sort(int index, int direction) {
350: doSort(index, direction);
351: }
352:
353: }
|