during clone recursion on frameborder set new uid in parent ( frame or frameborder )
[scilab.git] / scilab / modules / graphic_objects / src / java / org / scilab / modules / graphic_objects / xmlloader / XmlLoader.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2010-2011 - DIGITEO - Manuel JULIACHS
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  *
11  */
12
13 package org.scilab.modules.graphic_objects.xmlloader;
14
15 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_AXES__;
16 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UICONTROL__;
17 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_CHILDREN__;
18 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_FIGURE__;
19 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_TYPE__;
20 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UIMENU__;
21 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_CHECKBOX__;
22 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_EDIT__;
23 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_FRAME_BORDER__;
24 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_FRAME_BORDER_OUT_BORDER__;
25 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_FRAME_BORDER_IN_BORDER__;
26 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_FRAME_BORDER_TITLE__;
27 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_FRAME__;
28 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_IMAGE__;
29 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_LAYER__;
30 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_LISTBOX__;
31 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_POPUPMENU__;
32 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_PUSHBUTTON__;
33 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_RADIOBUTTON__;
34 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_SLIDER__;
35 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_SPINNER__;
36 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_TAB__;
37 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_TEXT__;
38
39 import java.io.File;
40 import java.io.FileInputStream;
41 import java.io.FileNotFoundException;
42 import java.io.IOException;
43 import java.util.AbstractMap.SimpleEntry;
44 import java.util.HashMap;
45 import java.util.Map;
46 import java.util.Map.Entry;
47 import java.util.Set;
48 import java.util.Stack;
49
50 import javax.xml.parsers.SAXParser;
51 import javax.xml.parsers.SAXParserFactory;
52
53 import org.scilab.modules.commons.CommonFileUtils;
54 import org.scilab.modules.commons.gui.FindIconHelper;
55 import org.scilab.modules.graphic_objects.ScilabNativeView;
56 import org.scilab.modules.graphic_objects.builder.Builder;
57 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
58 import org.scilab.modules.graphic_objects.graphicModel.GraphicModel;
59 import org.scilab.modules.graphic_objects.graphicObject.GraphicObject.Type;
60 import org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties;
61 import org.xml.sax.Attributes;
62 import org.xml.sax.Locator;
63 import org.xml.sax.SAXException;
64 import org.xml.sax.helpers.DefaultHandler;
65
66 public class XmlLoader extends DefaultHandler {
67
68     private String filename = "";
69     private Locator locator;
70     private Integer uid = 0;
71     private String namespace = null;
72     private boolean isWaitingModelName = true;
73     private String myURI = "";
74     private boolean isFirst = false;
75
76     private static HashMap<String, Integer> nameToGO = new HashMap<String, Integer>();
77     private static HashMap<String, HashMap<String, Entry<Integer, Map<String, String>>>> models = new HashMap<String, HashMap<String, Entry<Integer, Map<String, String>>>>();
78     private Stack<Integer> stackGO = new Stack<Integer>();
79     private String currentPath = "";
80
81     private GraphicController controller;
82
83     static {
84         // init map to convert control name to id
85         nameToGO.put("UIScilabWindow", __GO_FIGURE__);
86
87         nameToGO.put("UIPanel", __GO_UI_FRAME__);
88         nameToGO.put("UIFrame", __GO_UI_FRAME__);
89         nameToGO.put("UILayer", __GO_UI_LAYER__);
90         nameToGO.put("UIButton", __GO_UI_PUSHBUTTON__);
91         nameToGO.put("UILabel", __GO_UI_TEXT__);
92         nameToGO.put("UILaTeXLabel", -1);
93         nameToGO.put("UICheckbox", __GO_UI_CHECKBOX__);
94         nameToGO.put("UITextfield", __GO_UI_EDIT__);
95         nameToGO.put("UISplashScreen", __GO_UI_IMAGE__);
96         nameToGO.put("UIList", __GO_UI_LISTBOX__);
97         nameToGO.put("UIComboBox", __GO_UI_POPUPMENU__);
98         nameToGO.put("UIComboColor", __GO_UI_POPUPMENU__);
99         nameToGO.put("UIRadio", __GO_UI_RADIOBUTTON__);
100         nameToGO.put("UISlider", __GO_UI_SLIDER__);
101         nameToGO.put("UITab", __GO_UI_TAB__);
102         nameToGO.put("UIScilabPlot", __GO_AXES__);
103         nameToGO.put("UINumberSpinner", __GO_UI_SPINNER__);
104
105
106         /** sdsdf*/
107         nameToGO.put("UITextarea", __GO_UI_EDIT__);
108
109         nameToGO.put("UIMenu", __GO_UIMENU__);
110         nameToGO.put("UIMenuItem", __GO_UIMENU__);
111
112     }
113
114     public XmlLoader(String filename) {
115         controller = GraphicController.getController();
116         this.filename = filename;
117     }
118
119     public int parse() throws SAXException {
120         int ret = 0;
121         if (filename != null && filename.equals("") == false) {
122             ret = parse(filename);
123         }
124
125         // clean model before leave.
126         Set<String> entries = models.keySet();
127         for (String key : entries) {
128             HashMap<String, Entry<Integer, Map<String, String>>> map = models.get(key);
129             Set<String> entries2 = map.keySet();
130             for (String key2 : entries2) {
131                 deleteObject(map.get(key2).getKey());
132             }
133         }
134
135         return ret;
136     }
137
138     public int parse(String filename) throws SAXException {
139         this.filename = filename;
140         File f = new File(filename);
141         if (f.exists()) {
142             //add filename filepath in ScilabSwingUtilities paths
143             if (f.isAbsolute()) {
144                 String filePath = f.getAbsolutePath();
145                 currentPath = filePath.substring(0, filePath.lastIndexOf(File.separator));
146                 FindIconHelper.addThemePath(currentPath);
147             } else {
148                 String initialDirectoryPath = CommonFileUtils.getCWD();
149                 String filePath = "";
150                 Integer index = filename.lastIndexOf(File.separator);
151                 if (index != -1) {
152                     filePath = filename.substring(0, index);
153                 }
154                 currentPath = initialDirectoryPath + File.separator + filePath;
155                 FindIconHelper.addThemePath(currentPath);
156             }
157         } else {
158             //try to find file in currentPath
159             if (f.isAbsolute()) {
160                 //failed
161                 return 1;
162             }
163
164             f = new File(currentPath + File.separator + filename);
165             if (f.exists() == false) {
166                 return 1;
167             }
168         }
169
170         FileInputStream in = null;
171         try {
172             in = new FileInputStream(f);
173         } catch (FileNotFoundException e1) {
174             e1.printStackTrace();
175             return 1;
176         }
177
178         SAXParser parser;
179         try {
180             SAXParserFactory factory;
181             factory = SAXParserFactory.newInstance();
182             factory.setValidating(false);
183             factory.setNamespaceAware(true);
184             factory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
185             parser = factory.newSAXParser();
186         } catch (Exception e) {
187             try {
188                 in.close();
189             } catch (IOException e1) {
190                 e1.printStackTrace();
191                 return 1;
192             }
193             throw new SAXException(String.format("Cannot initialize the XML parser: %s", e.getMessage()));
194         }
195
196         try {
197             parser.parse(in, this);
198         } catch (SAXException e) {
199             if (locator != null) {
200                 throw new SAXException(String.format("Parse error at line %d: %s", locator.getLineNumber(), e.getMessage()));
201             } else {
202                 throw new SAXException(String.format("Parse error: %s", e.getMessage()));
203             }
204         } catch (IOException e) {
205             e.printStackTrace();
206         } finally {
207             try {
208                 in.close();
209             } catch (IOException e) {
210             }
211         }
212
213         return uid;
214     }
215
216     public void characters(char[] ch, int start, int length) throws SAXException {
217         super.characters(ch, start, length);
218     }
219
220     public void endDocument() throws SAXException {
221     }
222
223     public void endElement(String uri, String localName, String qName) throws SAXException {
224
225         if (localName.equals("modele")) {
226             namespace = null;
227             isWaitingModelName = false;
228         }
229
230         if (stackGO.size() != 0) {
231             Integer go = stackGO.pop();
232             if (go == null) {
233                 //nothing to do
234             } else if (stackGO.size() > 0) {
235                 Integer parent = stackGO.peek();
236
237                 controller.setGraphicObjectRelationship(parent, go);
238                 //controller.setProperty(go, __GO_VISIBLE__, true);
239             } else {
240                 uid = go;
241             }
242         }
243     }
244
245     public void setDocumentLocator(Locator locator) {
246         this.locator = locator;
247     }
248
249     public void startDocument() throws SAXException {
250         isFirst = true;
251     }
252
253     public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
254         if (localName.equals("interface")) {
255             if (isFirst) {
256                 myURI = attributes.getValue("xmlns");
257                 isFirst = false;
258             }
259         } else if (localName.equals("include")) {
260             String path = attributes.getValue("path");
261             parse(path);
262         } else if (localName.equals("modele")) {
263             namespace = attributes.getValue("namespace");
264             isWaitingModelName = true;
265         } else {
266             Integer uitype = getTypeFromName(localName);
267             Integer go = 0;
268             if (uitype != null) {
269                 if (uitype == __GO_FIGURE__) {
270                     // never create a new figure, clone figure model !
271                     go = GOBuilder.figureBuilder(controller, attributes);
272                 } else if (uitype == __GO_AXES__) {
273                     go = GraphicController.getController().askObject(Type.AXES);
274                 } else if (uitype == __GO_UIMENU__) {
275                     Integer parent = 0;
276                     if (stackGO.isEmpty() == false) {
277                         parent = stackGO.peek();
278                     }
279
280                     go = GOBuilder.uimenuBuilder(controller, attributes, parent);
281                 } else {
282                     Integer parent = 0;
283                     if (stackGO.isEmpty() == false) {
284                         parent = stackGO.peek();
285                     }
286
287                     go = GOBuilder.uicontrolBuilder(controller, uitype, attributes, parent);
288                 }
289             } else { // namespace or bad name ...
290                 if (myURI.equals(uri)) {
291                     // bad name
292                 } else {
293                     HashMap<String, Entry<Integer, Map<String, String>>> m = models.get(uri);
294                     if (m == null) {
295                         // bad namespace
296                     } else {
297                         Entry<Integer, Map<String, String>> entry = m.get(localName);
298                         go = entry.getKey();
299                         // need to clone object and children
300                         Integer newgo = cloneObject(go);
301                         GOBuilder.uicontrolUpdater(controller, newgo, attributes, stackGO.peek(), entry.getValue());
302                         go = newgo;
303
304                     }
305                 }
306             }
307
308             // we are in a model
309             // the first child must have field "model-name"
310             if (namespace != null) {
311                 if (isWaitingModelName) {
312                     String name = attributes.getValue("modele-name");
313                     if (name == null) {
314                         // unmaned model ? :s
315                     } else {
316                         if (models.get(namespace) == null) {
317                             models.put(namespace, new HashMap<String, Entry<Integer, Map<String, String>>>());
318                         }
319
320                         // copy attributes to a Map, i do not know why a can use
321                         // attributes ? Oo
322                         Map<String, String> attrib = new HashMap<String, String>();
323                         for (int i = 0; i < attributes.getLength(); i++) {
324                             attrib.put(attributes.getLocalName(i), attributes.getValue(i));
325                         }
326
327                         // add root element in map model
328                         models.get(namespace).put(name, new SimpleEntry<Integer, Map<String, String>>(go, attrib));
329                     }
330                 }
331             }
332
333             stackGO.add(go);
334         }
335     }
336
337     Integer cloneObject(Integer root) {
338         Integer newGo = controller.cloneObject(root);
339         Integer[] children = (Integer[]) controller.getProperty(root, __GO_CHILDREN__);
340         for (int i = children.length - 1; i >= 0 ; i--) {
341             Integer childType = (Integer)controller.getProperty(children[i], __GO_TYPE__);
342             if (childType == __GO_AXES__) {
343                 Integer go = controller.cloneObject(GraphicModel.getAxesModel().getIdentifier());
344                 Builder.createLabel(go, GraphicObjectProperties.__GO_X_AXIS_LABEL__);
345                 Builder.createLabel(go, GraphicObjectProperties.__GO_Y_AXIS_LABEL__);
346                 Builder.createLabel(go, GraphicObjectProperties.__GO_Z_AXIS_LABEL__);
347                 Builder.createLabel(go, GraphicObjectProperties.__GO_TITLE__);
348
349                 controller.setGraphicObjectRelationship(newGo, go);
350                 controller.setProperty(newGo, GraphicObjectProperties.__GO_SELECTED_CHILD__, go);
351
352                 ScilabNativeView.ScilabNativeView__setCurrentSubWin(go);
353                 ScilabNativeView.ScilabNativeView__setCurrentObject(go);
354             } else if (childType == __GO_UI_FRAME_BORDER__) {
355                 Integer newChild = cloneObject(children[i]);
356                 controller.setGraphicObjectRelationship(newGo, newChild);
357
358                 Integer rootType = (Integer)controller.getProperty(root, __GO_TYPE__);
359                 if (rootType == __GO_UICONTROL__) {
360                     controller.setProperty(newGo, __GO_UI_FRAME_BORDER__, newChild);
361                 } else { //__GO_UI_FRAME_BORDER__
362                     Integer border = (Integer) controller.getProperty(root, __GO_UI_FRAME_BORDER_TITLE__);
363                     if (border == children[i]) {
364                         controller.setProperty(newGo, __GO_UI_FRAME_BORDER_TITLE__, newChild);
365                     } else {
366                         border = (Integer) controller.getProperty(root, __GO_UI_FRAME_BORDER_OUT_BORDER__);
367                         if (border == children[i]) {
368                             controller.setProperty(newGo, __GO_UI_FRAME_BORDER_OUT_BORDER__, newChild);
369                         } else {
370                             border = (Integer) controller.getProperty(root, __GO_UI_FRAME_BORDER_OUT_BORDER__);
371                             if (border == children[i]) {
372                                 controller.setProperty(newGo, __GO_UI_FRAME_BORDER_OUT_BORDER__, newChild);
373                             }
374                         }
375                     }
376                 }
377             } else {
378                 Integer newChild = cloneObject(children[i]);
379                 controller.setGraphicObjectRelationship(newGo, newChild);
380             }
381         }
382
383         return newGo;
384     }
385
386     private void deleteObject(Integer root) {
387         controller.removeRelationShipAndDelete(root);
388     }
389
390     private Integer getTypeFromName(String localName) {
391         return nameToGO.get(localName);
392     }
393 }