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