View Javadoc

1   /*--------------------------------------------------------------------------
2    *  Copyright 2007 utgenome.org
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   *--------------------------------------------------------------------------*/
16  //--------------------------------------
17  // GenomeBrowser Project
18  //
19  // EditableTable.java
20  // Since: Jun 18, 2007
21  //
22  // $URL$ 
23  // $Author$
24  //--------------------------------------
25  package org.utgenome.gwt.utgb.client.ui;
26  
27  import java.util.ArrayList;
28  import java.util.HashMap;
29  import java.util.HashSet;
30  import java.util.Iterator;
31  import java.util.Map;
32  
33  import org.utgenome.gwt.utgb.client.track.Design;
34  import org.utgenome.gwt.utgb.client.util.TableData;
35  
36  import com.google.gwt.event.dom.client.ChangeEvent;
37  import com.google.gwt.event.dom.client.ChangeHandler;
38  import com.google.gwt.event.dom.client.KeyPressEvent;
39  import com.google.gwt.event.dom.client.KeyPressHandler;
40  import com.google.gwt.user.client.ui.Composite;
41  import com.google.gwt.user.client.ui.FlexTable;
42  import com.google.gwt.user.client.ui.Image;
43  import com.google.gwt.user.client.ui.TextBox;
44  import com.google.gwt.user.client.ui.Widget;
45  import com.google.gwt.widgetideas.client.event.KeyboardHandler;
46  
47  /**
48   * You can insert table data into a {@link EditableTable}. Inserted data must have a key column (default "id")
49   * 
50   * @author leo
51   * 
52   */
53  public class EditableTable extends Composite {
54  	private final static int LABEL_ROW_INDEX = 0;
55  	private FlexTable _table = new FlexTable();
56  	private boolean _enableInsertionOfNewRows = false;
57  	private HashSet<Integer> _disabledColumn = new HashSet<Integer>();
58  	private ArrayList<TextBox> _newRowBox = new ArrayList<TextBox>();
59  
60  	// table data
61  	private TableData _tableData;
62  	private ArrayList<TableChangeListener> _tableChangeListenerList = new ArrayList<TableChangeListener>();
63  
64  	class RowChangeListener implements ChangeHandler, KeyPressHandler {
65  		public void onChange(ChangeEvent e) {
66  			onChange((Widget) e.getSource());
67  		}
68  
69  		private void onChange(Widget sender) {
70  			EditableLabel label = (EditableLabel) sender;
71  			CellReference cell = label.getCellReference();
72  			Object key = cell.getKey();
73  			String column = cell.getColumnName();
74  
75  			for (Iterator<TableChangeListener> it = _tableChangeListenerList.iterator(); it.hasNext();) {
76  				TableChangeListener listener = it.next();
77  				listener.onUpdateRow(key, column, label.getText());
78  			}
79  
80  		}
81  
82  		public void onKeyPress(KeyPressEvent e) {
83  			if (e.getCharCode() == KeyboardHandler.KEY_ENTER) {
84  				onChange((Widget) e.getSource());
85  			}
86  		}
87  	}
88  
89  	class NewRowListener implements KeyPressHandler {
90  
91  		public void onKeyPress(KeyPressEvent e) {
92  			if (e.getCharCode() == KeyboardHandler.KEY_ENTER) {
93  				Object[] row = new Object[_tableData.getColumnCount()];
94  				int col = 0;
95  				for (Iterator<TextBox> it = _newRowBox.iterator(); it.hasNext(); col++) {
96  					TextBox textBox = it.next();
97  					row[col] = new String(textBox.getText()); // clone the input string
98  					textBox.setText("");
99  				}
100 
101 				// notify the insertion
102 				for (Iterator<TableChangeListener> it = _tableChangeListenerList.iterator(); it.hasNext();) {
103 					TableChangeListener listener = it.next();
104 					listener.onInsertNewRow(row);
105 				}
106 
107 			}
108 		}
109 
110 	}
111 
112 	public EditableTable(String[] columnLabel) {
113 		_tableData = new TableData(columnLabel);
114 		init(columnLabel);
115 	}
116 
117 	public EditableTable(String[] columnLabel, int keyColumn) {
118 		_tableData = new TableData(columnLabel, keyColumn);
119 		init(columnLabel);
120 	}
121 
122 	private void init(String[] columnLabel) {
123 		for (int i = 0; i < _tableData.getColumnCount(); i++)
124 			_table.setText(0, i + 1, _tableData.getColumnLabel(i));
125 
126 		_table.setStyleName("editable-table");
127 		_table.getRowFormatter().setStyleName(LABEL_ROW_INDEX, "table-label");
128 
129 		int keyColumn = _tableData.getKeyColumn();
130 		disableEdit(keyColumn);
131 
132 		initWidget(_table);
133 	}
134 
135 	public void disableEdit(int column) {
136 		if (column > _table.getCellCount(LABEL_ROW_INDEX))
137 			return;
138 
139 		_disabledColumn.add(new Integer(column));
140 
141 		for (int row = 1; row < _table.getRowCount(); row++) {
142 			EditableLabel label = (EditableLabel) _table.getWidget(row, column + 1);
143 			label.setEnabled(false);
144 		}
145 	}
146 
147 	private boolean isEditable(int column) {
148 		return !_disabledColumn.contains(new Integer(column));
149 	}
150 
151 	public void enableInsertionOfNewRow() {
152 		if (_enableInsertionOfNewRows)
153 			return; // already enabled
154 
155 		_enableInsertionOfNewRows = true;
156 		_newRowBox.clear();
157 		int newRowPos = _table.getRowCount();
158 		for (int i = 0; i < _tableData.getColumnCount(); i++) {
159 			TextBox input = new TextBox();
160 			input.setWidth("100%");
161 			input.addKeyPressHandler(new NewRowListener());
162 			_newRowBox.add(input);
163 			//if(isEditable(i))
164 			_table.setWidget(newRowPos, i + 1, input);
165 		}
166 	}
167 
168 	public void insertRow(Object[] row, int beforeIndex) {
169 		Object key = _tableData.addRow(row);
170 		int rowPos = _table.insertRow(beforeIndex);
171 
172 		for (int col = 0; col < row.length; col++) {
173 			EditableLabel text = new EditableLabel(new CellReference(key, _tableData.getColumnLabel(col)), row[col] != null ? row[col].toString() : "");
174 			if (!isEditable(col))
175 				text.setEnabled(false);
176 			else {
177 				RowChangeListener listener = new RowChangeListener();
178 				text.addChangeHandler(listener);
179 				text.addKeyPressHandler(listener);
180 			}
181 			_table.setWidget(rowPos, col + 1, text);
182 		}
183 
184 		Image deleteButton = new Image(Design.IMAGE_DELETE_BUTTON);
185 		_table.setWidget(rowPos, 0, deleteButton);
186 
187 	}
188 
189 	public void addRow(Object[] row) {
190 		insertRow(row, _enableInsertionOfNewRows ? _table.getRowCount() - 1 : _table.getRowCount());
191 	}
192 
193 	private Map<String, String> createRowDataMap(int row) {
194 		Map<String, String> rowDataMap = new HashMap<String, String>();
195 		for (int col = 0; col < _tableData.getColumnCount(); col++) {
196 			String data = _table.getText(row + 1, col + 1);
197 			rowDataMap.put(_tableData.getColumnLabel(col), data);
198 		}
199 		return rowDataMap;
200 	}
201 
202 	public void removeAllRows() {
203 		_tableData.clear();
204 		int maxRowPos = _enableInsertionOfNewRows ? _table.getRowCount() - 2 : _table.getRowCount() - 1;
205 		for (int i = maxRowPos; i >= 1; i--) {
206 			_table.removeRow(i);
207 		}
208 	}
209 
210 	public void addTableChangeListener(TableChangeListener listener) {
211 		_tableChangeListenerList.add(listener);
212 	}
213 
214 	public void removeTableChangeListener(TableChangeListener listener) {
215 		_tableChangeListenerList.remove(listener);
216 	}
217 
218 }
219 
220 class CellReference {
221 	private Object key;
222 	private String columnName;
223 
224 	public CellReference(Object key, String columnName) {
225 		super();
226 		this.key = key;
227 		this.columnName = columnName;
228 	}
229 
230 	public String getColumnName() {
231 		return columnName;
232 	}
233 
234 	public Object getKey() {
235 		return key;
236 	}
237 
238 }