001: /*
002: * This file is not part of the ItsNat framework.
003: *
004: * Original source code use and closed source derivatives are authorized
005: * to third parties with no restriction or fee.
006: * The original source code is owned by the author.
007: *
008: * This program is distributed AS IS in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
011: *
012: * Author: Jose Maria Arranz Santamaria
013: * (C) Innowhere Software Services S.L., Spanish company, year 2007
014: */
015:
016: package org.itsnat.feashow.features.components.tables;
017:
018: import javax.swing.ListSelectionModel;
019: import javax.swing.event.ListSelectionEvent;
020: import javax.swing.event.ListSelectionListener;
021: import javax.swing.event.TableModelEvent;
022: import javax.swing.event.TableModelListener;
023: import javax.swing.table.DefaultTableModel;
024: import javax.swing.table.TableModel;
025: import org.itsnat.comp.ItsNatComponentManager;
026: import org.itsnat.comp.html.ItsNatHTMLInputButton;
027: import org.itsnat.comp.html.ItsNatHTMLInputText;
028: import org.itsnat.comp.html.ItsNatHTMLTable;
029: import org.itsnat.comp.html.ui.ItsNatHTMLTableUI;
030: import org.itsnat.core.ItsNatDocument;
031: import org.itsnat.feashow.FeatureTreeNode;
032: import org.w3c.dom.events.Event;
033: import org.w3c.dom.events.EventListener;
034: import org.w3c.dom.events.EventTarget;
035: import org.w3c.dom.html.HTMLTableCellElement;
036:
037: public class TableRowSpanTreeNode extends FeatureTreeNode implements
038: EventListener, TableModelListener, ListSelectionListener {
039: protected ItsNatHTMLTable tableComp;
040: protected ItsNatHTMLInputButton removeButton;
041: protected ItsNatHTMLInputText[] newItemComp;
042: protected ItsNatHTMLInputText posComp;
043: protected ItsNatHTMLInputButton updateButton;
044: protected ItsNatHTMLInputButton insertButton;
045:
046: public TableRowSpanTreeNode() {
047: }
048:
049: public void startExamplePanel() {
050: ItsNatDocument itsNatDoc = getItsNatDocument();
051: ItsNatComponentManager componentMgr = itsNatDoc
052: .getItsNatComponentManager();
053:
054: this .tableComp = (ItsNatHTMLTable) componentMgr
055: .createItsNatComponentById("compId");
056:
057: DefaultTableModel dataModel = (DefaultTableModel) tableComp
058: .getTableModel();
059: dataModel.addTableModelListener(this );
060: tableComp.setTableModel(dataModel); // resets the internal listeners, the internal TableModelListener listener is called first
061:
062: dataModel.addColumn("City");
063: dataModel.addColumn("Turistic Place/Monument");
064: dataModel.addRow(new String[] { "Madrid", "Plaza Mayor" });
065: dataModel.addRow(new String[] { "Madrid", "Palacio Real" });
066: dataModel.addRow(new String[] { "Sevilla", "Plaza de España" });
067: dataModel.addRow(new String[] { "Sevilla",
068: "Parque de María Luisa" });
069: dataModel
070: .addRow(new String[] { "Segovia", "Plaza del Azoguejo" });
071: dataModel.addRow(new String[] { "Segovia", "Alcázar" });
072:
073: ListSelectionModel rowSelModel = tableComp
074: .getRowSelectionModel();
075: ListSelectionModel columnSelModel = tableComp
076: .getColumnSelectionModel();
077:
078: rowSelModel
079: .setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
080: // columnSelModel.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
081:
082: tableComp.setRowSelectionAllowed(true);
083: tableComp.setColumnSelectionAllowed(false);
084:
085: rowSelModel
086: .addListSelectionListener(new TableRowSelectionDecoration(
087: tableComp));
088:
089: rowSelModel.setSelectionInterval(1, 1);
090:
091: rowSelModel.addListSelectionListener(this );
092: columnSelModel.addListSelectionListener(this );
093:
094: this .removeButton = (ItsNatHTMLInputButton) componentMgr
095: .createItsNatComponentById("removeId");
096: removeButton.addEventListener("click", this );
097:
098: this .newItemComp = new ItsNatHTMLInputText[dataModel
099: .getColumnCount()];
100: for (int i = 0; i < newItemComp.length; i++) {
101: this .newItemComp[i] = (ItsNatHTMLInputText) componentMgr
102: .createItsNatComponentById("itemId" + i);
103: newItemComp[i].setText(dataModel.getValueAt(
104: rowSelModel.getMinSelectionIndex(), i).toString());
105: }
106:
107: this .posComp = (ItsNatHTMLInputText) componentMgr
108: .createItsNatComponentById("posId");
109: posComp.setText(Integer.toString(rowSelModel
110: .getMinSelectionIndex()));
111:
112: this .updateButton = (ItsNatHTMLInputButton) componentMgr
113: .createItsNatComponentById("updateId");
114: updateButton.addEventListener("click", this );
115:
116: this .insertButton = (ItsNatHTMLInputButton) componentMgr
117: .createItsNatComponentById("insertId");
118: insertButton.addEventListener("click", this );
119: }
120:
121: public void endExamplePanel() {
122: this .tableComp.dispose();
123: this .tableComp = null;
124:
125: this .removeButton.dispose();
126: this .removeButton = null;
127:
128: for (int i = 0; i < newItemComp.length; i++) {
129: this .newItemComp[i].dispose();
130: this .newItemComp[i] = null;
131: }
132:
133: this .posComp.dispose();
134: this .posComp = null;
135:
136: this .updateButton.dispose();
137: this .updateButton = null;
138:
139: this .insertButton.dispose();
140: this .insertButton = null;
141: }
142:
143: public void handleEvent(Event evt) {
144: log(evt.getCurrentTarget() + " " + evt.getType());
145:
146: EventTarget currentTarget = evt.getCurrentTarget();
147: if (currentTarget == removeButton.getHTMLInputElement()) {
148: DefaultTableModel dataModel = (DefaultTableModel) tableComp
149: .getTableModel();
150: ListSelectionModel rowSelModel = tableComp
151: .getRowSelectionModel();
152: if (!rowSelModel.isSelectionEmpty()) {
153: // Selection Model is in SINGLE_INTERVAL_SELECTION mode
154: int min = rowSelModel.getMinSelectionIndex();
155: int max = rowSelModel.getMaxSelectionIndex();
156: for (int i = 0; i <= max - min; i++)
157: dataModel.removeRow(min);
158: }
159: } else if ((currentTarget == updateButton.getHTMLInputElement())
160: || (currentTarget == insertButton.getHTMLInputElement())) {
161: String[] newItem = new String[newItemComp.length];
162: for (int i = 0; i < newItemComp.length; i++)
163: newItem[i] = newItemComp[i].getText();
164:
165: int row;
166: try {
167: row = Integer.parseInt(posComp.getText());
168: DefaultTableModel dataModel = (DefaultTableModel) tableComp
169: .getTableModel();
170: if (currentTarget == updateButton.getHTMLInputElement()) {
171: for (int i = 0; i < newItemComp.length; i++)
172: dataModel.setValueAt(newItem[i], row, i);
173: } else
174: dataModel.insertRow(row, newItem);
175: } catch (NumberFormatException ex) {
176: getItsNatDocument().addCodeToSend(
177: "alert('Bad Position')");
178: } catch (ArrayIndexOutOfBoundsException ex) {
179: getItsNatDocument().addCodeToSend(
180: "alert('Bad Position')");
181: }
182: }
183: }
184:
185: public void tableChanged(TableModelEvent e) {
186: int firstRow = e.getFirstRow();
187: int lastRow = e.getLastRow();
188:
189: String action = "";
190: int type = e.getType();
191: switch (type) {
192: case TableModelEvent.INSERT:
193: action = "added";
194: break;
195: case TableModelEvent.DELETE:
196: action = "removed";
197: break;
198: case TableModelEvent.UPDATE:
199: action = "changed";
200: break;
201: }
202:
203: String interval = "";
204: if (firstRow != -1)
205: interval = "interval " + firstRow + "-" + lastRow;
206:
207: log(e.getClass().toString() + " " + action + " " + interval);
208:
209: // This listener is called *after* the effective UI change
210: switch (type) {
211: case TableModelEvent.INSERT:
212: for (int i = firstRow - 1; i <= lastRow + 1; i++)
213: updateRowSpanPrevContiguous(i);
214: break;
215: case TableModelEvent.DELETE:
216: updateRowSpanPrevContiguous(firstRow - 1);
217: updateRowSpanPrevContiguous(firstRow);
218: break;
219: case TableModelEvent.UPDATE:
220: for (int i = firstRow - 1; i <= lastRow + 1; i++)
221: updateRowSpanPrevContiguous(i);
222: break;
223: }
224: }
225:
226: public void valueChanged(ListSelectionEvent e) {
227: if (e.getValueIsAdjusting())
228: return;
229:
230: ListSelectionModel rowSelModel = tableComp
231: .getRowSelectionModel();
232: if (e.getSource() != rowSelModel)
233: return; // may be the column selector
234:
235: int first = e.getFirstIndex();
236: int last = e.getLastIndex();
237:
238: String fact = "";
239: for (int i = first; i <= last; i++) {
240: boolean selected = rowSelModel.isSelectedIndex(i);
241: if (selected)
242: fact += ", selected ";
243: else
244: fact += ", deselected ";
245: fact += i;
246: }
247:
248: log(e.getClass().toString() + " " + fact);
249:
250: int row = rowSelModel.getMinSelectionIndex(); // First selected
251: if (row != -1) {
252: for (int i = 0; i < newItemComp.length; i++) {
253: Object value = tableComp.getTableModel().getValueAt(
254: row, i);
255: newItemComp[i].setText(value.toString());
256: }
257: posComp.setText(Integer.toString(row));
258: }
259: }
260:
261: public static int getFirstContiguousEqual(int row, int col,
262: TableModel dataModel) {
263: if (row == 0)
264: return -1;
265: Object value = dataModel.getValueAt(row, col);
266: int prevIndex = -1;
267: for (int i = row - 1; i >= 0; i--) {
268: Object currValue = dataModel.getValueAt(i, col);
269: if (!value.equals(currValue))
270: return prevIndex;
271: prevIndex = i;
272: }
273: return prevIndex;
274: }
275:
276: public static int getLastContiguousEqual(int row, int col,
277: TableModel dataModel) {
278: if (row == dataModel.getRowCount() - 1)
279: return -1;
280: Object value = dataModel.getValueAt(row, col);
281: int nextIndex = -1;
282: for (int i = row + 1; i < dataModel.getRowCount(); i++) {
283: Object currValue = dataModel.getValueAt(i, col);
284: if (!value.equals(currValue))
285: return nextIndex;
286: nextIndex = i;
287: }
288: return nextIndex;
289: }
290:
291: public void updateRowSpanPrevContiguous(int row) {
292: if (row < 0)
293: return;
294: TableModel dataModel = tableComp.getTableModel();
295: if (row >= dataModel.getRowCount())
296: return;
297:
298: ItsNatHTMLTableUI tableUI = tableComp.getItsNatHTMLTableUI();
299: int first = getFirstContiguousEqual(row, 0, dataModel);
300: if (first == -1)
301: first = row;
302:
303: int last = getLastContiguousEqual(first, 0, dataModel);
304: if (last == -1)
305: last = first;
306: int rowSpan = last - first + 1;
307:
308: HTMLTableCellElement cell = tableUI.getHTMLTableCellElementAt(
309: first, 0);
310: if (cell.getParentNode() == null) {
311: HTMLTableCellElement cellNext = tableUI
312: .getHTMLTableCellElementAt(first, 1);
313: cellNext.getParentNode().insertBefore(cell, cellNext);
314: }
315:
316: if (rowSpan > 1)
317: cell.setAttribute("rowspan", Integer.toString(rowSpan));
318: else if (cell.hasAttribute("rowspan"))
319: cell.removeAttribute("rowspan");
320:
321: if (first != last) {
322: for (int i = first + 1; i <= last; i++) {
323: cell = tableUI.getHTMLTableCellElementAt(i, 0);
324: if (cell.getParentNode() != null)
325: cell.getParentNode().removeChild(cell);
326: }
327: }
328: }
329: }
|