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.ArrayList;
011: import java.util.List;
012:
013: import net.mygwt.ui.client.Events;
014: import net.mygwt.ui.client.MyDOM;
015: import net.mygwt.ui.client.MyGWT;
016: import net.mygwt.ui.client.Style;
017: import net.mygwt.ui.client.event.BaseEvent;
018: import net.mygwt.ui.client.event.Listener;
019: import net.mygwt.ui.client.event.SelectionListener;
020: import net.mygwt.ui.client.util.DelayedTask;
021: import net.mygwt.ui.client.widget.Component;
022: import net.mygwt.ui.client.widget.SplitBar;
023: import net.mygwt.ui.client.widget.menu.Menu;
024: import net.mygwt.ui.client.widget.menu.MenuItem;
025:
026: import com.google.gwt.user.client.Command;
027: import com.google.gwt.user.client.DOM;
028: import com.google.gwt.user.client.DeferredCommand;
029: import com.google.gwt.user.client.Element;
030: import com.google.gwt.user.client.Event;
031: import com.google.gwt.user.client.ui.WidgetHelper;
032:
033: public class TableHeader extends Component {
034:
035: protected static String html;
036:
037: static {
038: StringBuffer sb = new StringBuffer();
039: sb
040: .append("<div class=my-tbl-header style='position: relative'>");
041: sb
042: .append("<table border=0 cellpadding=0 cellspacing=0 style='position:relative'><tbody><tr class=my-tbl-header-row>");
043: sb.append("</tr></table></div>");
044: html = sb.toString();
045: }
046:
047: protected List columns;
048: protected ITable table;
049: protected TableColumnModel columnModel;
050: protected TableColumnUI sortColumn, endColumn, hoverColumn;
051: protected Element headerRow;
052: private DelayedTask task = new DelayedTask(new Listener() {
053: public void handleEvent(BaseEvent be) {
054: updateSplitBars();
055: }
056: });
057:
058: protected TableHeader() {
059:
060: }
061:
062: protected TableHeader(ITable table) {
063: this .table = table;
064: this .columnModel = this .table.getColumnModel();
065: }
066:
067: public void sort(int index, int dir) {
068: TableColumn column = table.getColumn(index);
069: column.sortDir = dir;
070: onSortChange(column, dir);
071: }
072:
073: protected void addColumn(TableColumnUI ui) {
074: Element td = DOM.createTD();
075: MyDOM.setStyleName(td, "my-tbl-col");
076: DOM.appendChild(td, ui.getElement());
077: DOM.appendChild(headerRow, td);
078: columns.add(ui);
079: }
080:
081: protected SplitBar createSplitBar(int direction,
082: TableColumnUI column) {
083: return new SplitBar(direction, column, (Component) table);
084: }
085:
086: protected TableColumnUI createTableColumnUI(int index) {
087: return new TableColumnUI(table, index);
088: }
089:
090: protected void doAttachChildren() {
091: int count = columns.size() - 1;
092: for (int i = 0; i < count; i++) {
093: WidgetHelper.doAttach(getColumnUI(i));
094: }
095: }
096:
097: protected void doDetachChildren() {
098: int count = columns.size() - 1;
099: for (int i = 0; i < count; i++) {
100: WidgetHelper.doDetach(getColumnUI(i));
101: }
102: }
103:
104: protected TableColumnUI getColumnUI(int index) {
105: return (TableColumnUI) columns.get(index);
106: }
107:
108: protected void init(ITable table) {
109: this .table = table;
110: this .columnModel = this .table.getColumnModel();
111: }
112:
113: protected void onColumnClick(TableColumnUI columnUI) {
114: BaseEvent be = new BaseEvent((Component) table);
115: be.index = columnUI.index;
116:
117: if (!((Component) table).fireEvent(Events.ColumnClick, be)) {
118: return;
119: }
120:
121: if (columnUI.column.isSortable()) {
122:
123: int sortDir = columnUI.column.sortDir;
124: switch (sortDir) {
125: case Style.NONE:
126: case Style.DESC:
127: sortDir = Style.ASC;
128: break;
129: default:
130: sortDir = Style.DESC;
131: }
132: table.sort(be.index, sortDir);
133: }
134: }
135:
136: protected void onColumnMouseMove(TableColumnUI column, BaseEvent be) {
137:
138: }
139:
140: protected void onRender() {
141: setElement(MyDOM.create(html));
142: headerRow = MyDOM.findChild("my-tbl-header-row", getElement());
143:
144: columns = new ArrayList();
145: int cols = columnModel.getColumnCount();
146: for (int i = 0; i < cols; i++) {
147: TableColumnUI columnUI = createTableColumnUI(i);
148: addColumn(columnUI);
149: }
150: endColumn = new TableColumnUI(table, cols);
151: endColumn.end = true;
152: addColumn(endColumn);
153:
154: disableContextMenu(true);
155: }
156:
157: protected void onRightClick(final TableColumn column, Event event) {
158: DOM.eventCancelBubble(event, true);
159: DOM.eventPreventDefault(event);
160:
161: if (!table.getColumnContextMenu()) {
162: return;
163: }
164:
165: final int x = DOM.eventGetClientX(event);
166: final int y = DOM.eventGetClientY(event);
167: DeferredCommand.addCommand(new Command() {
168: public void execute() {
169: onShowContextMenu(column).show(x, y);
170: }
171: });
172: }
173:
174: protected Menu onShowContextMenu(final TableColumn column) {
175: final Menu menu = new Menu();
176:
177: if (column.isSortable()) {
178: MenuItem item = new MenuItem(Style.PUSH);
179: item.setText(MyGWT.MESSAGES.sortAsc());
180: item.setIconStyle("icon-sort-asc");
181: item.addSelectionListener(new SelectionListener() {
182: public void widgetSelected(BaseEvent be) {
183: table.sort(column.index, Style.ASC);
184: }
185:
186: });
187: menu.add(item);
188:
189: item = new MenuItem(Style.PUSH);
190: item.setText(MyGWT.MESSAGES.sortDesc());
191: item.setIconStyle("icon-sort-desc");
192: item.addSelectionListener(new SelectionListener() {
193: public void widgetSelected(BaseEvent be) {
194: table.sort(column.index, Style.DESC);
195: }
196: });
197: menu.add(item);
198: }
199:
200: MenuItem columns = new MenuItem(Style.MENU);
201: columns.setText(MyGWT.MESSAGES.columns());
202: columns.setIconStyle("icon-columns");
203:
204: final Menu columnMenu = new Menu();
205:
206: int cols = columnModel.getColumnCount();
207: for (int i = 0; i < cols; i++) {
208: final TableColumn def = columnModel.getColumn(i);
209: final MenuItem check = new MenuItem(Style.CHECK);
210: check.setHideOnClick(false);
211: check.setText(def.getText());
212: check.setSelected(!def.isHidden());
213: check.addSelectionListener(new SelectionListener() {
214:
215: public void widgetSelected(BaseEvent be) {
216: def.setHidden(!check.isSelected());
217: showColumn(def.index, !def.isHidden());
218:
219: if (columnModel.getVariableColumnCount() > 0) {
220: resizeColumns(false, true);
221: }
222:
223: if (columnModel.getVisibleColumnCount() == 1) {
224: int count = columnMenu.getItemCount();
225: for (int j = 0; j < count; j++) {
226: MenuItem item = columnMenu.getItem(j);
227: if (item.isSelected()) {
228: item.disable();
229: }
230: }
231: } else if (columnModel.getVisibleColumnCount() == 2) {
232: int count = columnMenu.getItemCount();
233: for (int j = 0; j < count; j++) {
234: MenuItem item = columnMenu.getItem(j);
235: item.enable();
236: }
237: }
238: }
239:
240: });
241: columnMenu.add(check);
242:
243: if (columnModel.getVisibleColumnCount() == 1) {
244: int count = columnMenu.getItemCount();
245: for (int j = 0; j < count; j++) {
246: MenuItem item = columnMenu.getItem(j);
247: if (item.isSelected()) {
248: item.disable();
249: }
250: }
251: }
252: }
253:
254: columns.setSubMenu(columnMenu);
255: menu.add(columns);
256:
257: return menu;
258: }
259:
260: public int getSortColumn() {
261: if (sortColumn != null) {
262: return sortColumn.index;
263: }
264: return Style.DEFAULT;
265: }
266:
267: protected void onSortChange(TableColumn column, int sortDir) {
268: column.sortDir = sortDir;
269: if (sortColumn != null) {
270: getColumnUI(sortColumn.index).onSortChange(Style.NONE);
271: }
272: sortColumn = getColumnUI(column.index);
273: sortColumn.onSortChange(sortDir);
274: }
275:
276: protected void resizeColumn(int index, boolean resizeBody) {
277: TableColumn column = columnModel.getColumn(index);
278: TableColumnUI ui = getColumnUI(index);
279: if (column.isHidden()) {
280: ui.setVisible(false);
281: return;
282: } else {
283: ui.setVisible(true);
284: }
285: int w = columnModel.getWidthInPixels(column.index);
286:
287: if (w != ui.lastWidth) {
288: Element td = DOM.getParent(ui.getElement());
289: w -= MyDOM.getBorderWidth(td, Style.LEFT | Style.RIGHT);
290:
291: MyDOM.setWidth(ui.getElement(), w);
292:
293: SplitBar splitBar = ui.splitBar;
294: if (splitBar != null) {
295: if (column.isResizable()) {
296: splitBar.setVisible(true);
297: }
298: splitBar.setMinSize(column.getMinWidth());
299: splitBar.setMaxSize(column.getMaxWidth());
300: }
301: task.delay(400);
302: doTableComponentResizeCells(index);
303: }
304:
305: ui.lastWidth = w;
306:
307: if (resizeBody) {
308: doTableComponentResize();
309: }
310: }
311:
312: protected void resizeColumns(boolean fireEvent, boolean resizeBody) {
313: int cols = columnModel.getColumnCount();
314: int totWidth = 0;
315: for (int i = 0; i < cols; i++) {
316: resizeColumn(i, false);
317: }
318:
319: int tableWidth = ((Component) table).getOffsetWidth();
320: if (totWidth < tableWidth) {
321: MyDOM.setWidth(endColumn.getElement(), tableWidth
322: - totWidth + 25);
323: } else {
324: MyDOM.setWidth(endColumn.getElement(), 25);
325: }
326: task.delay(400);
327:
328: if (resizeBody) {
329: doTableComponentResize();
330: }
331:
332: }
333:
334: protected void showColumn(int index, boolean show) {
335: TableColumnUI ui = getColumnUI(index);
336: Element td = DOM.getParent(ui.getElement());
337: MyDOM.setVisible(td, show);
338: doTableComponentShowColumn(index, show);
339: updateSplitBars();
340: doTableComponentResize();
341: }
342:
343: protected void updateSplitBars() {
344: int count = columns.size() - 1;
345: for (int i = 0; i < count; i++) {
346: TableColumnUI ui = getColumnUI(i);
347: if (ui.splitBar != null) {
348: ui.splitBar.updateHandle();
349: }
350: }
351: }
352:
353: protected void doTableComponentResize() {
354: if (table instanceof Table) {
355: ((Table) table).getView().resize();
356: }
357: }
358:
359: protected void doTableComponentResizeCells(int columnIndex) {
360: if (table instanceof Table) {
361: ((Table) table).getView().resizeCells(columnIndex);
362: }
363: }
364:
365: protected void doTableComponentShowColumn(int index, boolean show) {
366: if (table instanceof Table) {
367: ((Table) table).getView().showColumn(index, show);
368: }
369: }
370:
371: }
|