Adding new code for feature save on unfocus. This is from ticket #542. It also adds...
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / wizards / html / TableElementModel.java
1 /*
2  * $Id: TableElementModel.java,v 1.2 2006-10-21 23:18:43 pombredanne Exp $
3  * Copyright Narushima Hironori. All rights reserved.
4  */
5 package net.sourceforge.phpeclipse.wizards.html;
6
7 import java.io.IOException;
8 import java.io.StringReader;
9 import java.util.ArrayList;
10 import java.util.Arrays;
11
12 import javax.xml.parsers.DocumentBuilder;
13 import javax.xml.parsers.DocumentBuilderFactory;
14 import javax.xml.parsers.FactoryConfigurationError;
15 import javax.xml.parsers.ParserConfigurationException;
16
17 import org.w3c.dom.Document;
18 import org.w3c.dom.Element;
19 import org.w3c.dom.Node;
20 import org.w3c.dom.NodeList;
21 import org.xml.sax.InputSource;
22 import org.xml.sax.SAXException;
23
24 /**
25  * TableElementModel
26  */
27 public class TableElementModel {
28
29         final static char[] CHAR_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
30
31         StringDivider stringDivider = new StringDivider();
32
33         ElementWriter writer;
34
35         DocumentBuilder docBuilder;
36
37         Document document;
38
39         Element tableElement;
40
41         String[] columnProperties;
42
43         public TableElementModel(String content, boolean parse)
44                         throws FactoryConfigurationError, ParserConfigurationException,
45                         SAXException, IOException {
46                 docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
47                 if (parse) {
48                         initAsParse(content);
49                 } else {
50                         initModel(content);
51                 }
52                 columnProperties = createColumnProperties();
53
54                 // create elementWriter
55                 writer = new ElementWriter(0, null);
56                 writer.setExpandOption("caption", ElementWriter.END_CHANGELINE);
57                 writer.setExpandOption("table", ElementWriter.BEGIN_CHANGELINE
58                                 | ElementWriter.END_CHANGELINE);
59                 writer.setExpandOption("thead", ElementWriter.BEGIN_CHANGELINE
60                                 | ElementWriter.END_CHANGELINE);
61                 writer.setExpandOption("tfoot", ElementWriter.BEGIN_CHANGELINE
62                                 | ElementWriter.END_CHANGELINE);
63                 writer.setExpandOption("tbody", ElementWriter.BEGIN_CHANGELINE
64                                 | ElementWriter.END_CHANGELINE);
65                 writer.setExpandOption("tr", ElementWriter.END_CHANGELINE);
66         }
67
68         void initModel(String content) throws ParserConfigurationException,
69                         SAXException, IOException {
70                 StringReader strReader = new StringReader(content);
71                 InputSource inputSrc = new InputSource(strReader);
72
73                 document = docBuilder.parse(inputSrc);
74                 tableElement = document.getDocumentElement();
75
76                 Element[] rows = getRows();
77                 for (int i = 0; i < rows.length; i++) {
78                         Element[] cells = chooseCellElements(rows[i]);
79                         for (int j = 0; j < cells.length; j++) {
80                                 Element cell = cells[j];
81                                 if (!cell.hasChildNodes()) {
82                                         cell.appendChild(document.createTextNode(""));
83                                 }
84                         }
85                 }
86         }
87
88         public void initAsParse(String content)
89                         throws ParserConfigurationException, FactoryConfigurationError {
90                 // create new table model.
91                 document = docBuilder.newDocument();
92                 tableElement = document.createElement("table");
93
94                 String[][] cells = stringDivider.divide(content);
95                 if (cells.length > 0) {
96                         for (int i = 0; i < cells.length; i++) {
97                                 String[] rows = cells[i];
98                                 Element tr = document.createElement("tr");
99                                 for (int j = 0; j < rows.length; j++) {
100                                         Element e = document.createElement("td");
101                                         e.appendChild(document.createTextNode(rows[j]));
102                                         tr.appendChild(e);
103                                 }
104                                 tableElement.appendChild(tr);
105                         }
106
107                         setColumnCount(cells[0].length);
108                 } else {
109                         Element tr = document.createElement("tr");
110                         Element td = document.createElement("td");
111                         td.appendChild(document.createTextNode(""));
112                         tr.appendChild(td);
113                         tableElement.appendChild(tr);
114
115                         setColumnCount(1);
116                 }
117         }
118
119         String[] createColumnProperties() {
120                 int len = getColumnCount();
121                 String[] props = new String[len];
122                 for (int i = 0; i < len; i++) {
123                         props[i] = toColumnName(i);
124                 }
125                 return props;
126         }
127
128         public void setRowCount(int rowCount) {
129                 Element[] rows = getRows();
130                 if (rowCount > rows.length) {
131                         for (int i = rows.length; i < rowCount; i++) {
132                                 tableElement.appendChild(createRowElement());
133                         }
134                 } else if (rowCount < rows.length) {
135                         for (int i = rowCount; i < rows.length; i++) {
136                                 tableElement.removeChild(rows[i]);
137                         }
138                 }
139         }
140
141         public Element[] getRows() {
142                 ArrayList rows = new ArrayList();
143                 NodeList nodes = tableElement.getElementsByTagName("tr");
144                 for (int i = 0; i < nodes.getLength(); i++) {
145                         rows.add(nodes.item(i));
146                 }
147                 return (Element[]) rows.toArray(new Element[rows.size()]);
148         }
149
150         public int getRowCount() {
151                 return getRows().length;
152         }
153
154         Element createRowElement() {
155                 Element tr = document.createElement("tr");
156                 for (int i = 0, columnCount = getColumnCount(); i < columnCount; i++) {
157                         Element td = document.createElement("td");
158                         td.appendChild(document.createTextNode(""));
159                         tr.appendChild(td);
160                 }
161                 return tr;
162         }
163
164         public void setColumnCount(int newLength) {
165                 NodeList trs = tableElement.getElementsByTagName("tr");
166                 for (int i = 0; i < trs.getLength(); i++) {
167                         Element tr = (Element) trs.item(i);
168                         Element[] cells = chooseCellElements(tr);
169                         int colLen = cells.length;
170
171                         if (newLength > colLen) {
172                                 for (int j = 0, len = newLength - colLen; j < len; j++) {
173                                         Element cell = document.createElement("td");
174                                         cell.appendChild(document.createTextNode(""));
175                                         tr.appendChild(cell);
176                                 }
177                         } else if (newLength < colLen) {
178                                 for (int j = newLength; j < colLen; j++) {
179                                         tr.removeChild(cells[j]);
180                                 }
181                         }
182                 }
183                 columnProperties = createColumnProperties();
184         }
185
186         public int getColumnCount() {
187                 NodeList trs = tableElement.getElementsByTagName("tr");
188                 if (trs.getLength() > 0) {
189                         Element tr = (Element) trs.item(0);
190                         return chooseCellElements(tr).length;
191                 } else {
192                         return 0;
193                 }
194         }
195
196         public static Element[] chooseCellElements(Element tr) {
197                 NodeList nodeList = tr.getChildNodes();
198
199                 ArrayList result = new ArrayList();
200                 for (int i = 0; i < nodeList.getLength(); i++) {
201                         Node node = nodeList.item(i);
202                         if (node instanceof Element) {
203                                 String nodeName = node.getNodeName();
204                                 if (nodeName.equals("td") || nodeName.equals("th")) {
205                                         result.add(node);
206                                 }
207                         }
208                 }
209
210                 return (Element[]) result.toArray(new Element[result.size()]);
211         }
212
213         public String expandCodes() {
214                 return writer.expandTag(tableElement);
215         }
216
217         public static String toColumnName(int i) {
218                 StringBuffer buff = new StringBuffer();
219                 int u = i / CHAR_TABLE.length;
220                 if (u > 0) {
221                         buff.append(CHAR_TABLE[u - 1]);
222                 }
223                 buff.append(CHAR_TABLE[i % CHAR_TABLE.length]);
224                 return buff.toString();
225         }
226
227         /**
228          * Return index of char map. If can not parse values return -1.
229          */
230         public static int toNumeric(String code) {
231                 int result = -1;
232                 for (int i = 0; i < code.length(); i++) {
233                         char c = code.charAt(i);
234                         int match = Arrays.binarySearch(CHAR_TABLE, c);
235                         if (match >= 0) {
236                                 if (result == -1) {
237                                         result = 0;
238                                 }
239                                 int v = match;
240                                 int u = code.length() - 1 - i;
241                                 if (u > 0) {
242                                         v = CHAR_TABLE.length * u * (v + 1);
243                                 }
244                                 result += v;
245                         }
246                 }
247                 return result;
248         }
249
250         public void move(Element tr, int moveCount) {
251                 Element[] rows = getRows();
252                 int index = -1;
253                 for (int i = 0; i < rows.length; i++) {
254                         if (tr.equals(rows[i])) {
255                                 index = i;
256                         }
257                 }
258                 if (index == -1) {
259                         throw new IllegalArgumentException(
260                                         "Invalid row node (not countained in this table):" + tr);
261                 }
262                 if (moveCount > 0) {
263                         // move down;
264                         for (int i = index; i < moveCount + index && i < rows.length - 1; i++) {
265                                 tableElement.insertBefore(rows[i + 1], rows[i]);
266                         }
267                 } else if (moveCount < 0) {
268                         // move up
269                         for (int i = index; i >= moveCount + index + 1 && i >= 1; i--) {
270                                 tableElement.insertBefore(rows[index], rows[i - 1]);
271                         }
272                 } else {
273                         return;
274                 }
275         }
276
277         public void insertNewRowBefore(Element tr) {
278                 Element newRow = createRowElement();
279                 if (tr == null) {
280                         tableElement.appendChild(newRow);
281                 } else {
282                         tableElement.insertBefore(newRow, tr);
283                 }
284         }
285
286         public void removeRow(Element tr) {
287                 tableElement.removeChild(tr);
288         }
289
290         public String[] getColumnProperties() {
291                 return (String[]) columnProperties.clone();
292         }
293
294 }