add savegui as xml file, change xml format to manage all figure/uicontrol properties
[scilab.git] / scilab / modules / gui / src / java / org / scilab / modules / gui / bridge / editbox / SwingScilabEditBox.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2007-2008 - INRIA - Vincent Couvert
4  * Copyright (C) 2007 - INRIA - Marouane BEN JELLOUL
5  * Copyright (C) 2011 - DIGITEO - Vincent COUVERT
6  *
7  * This file must be used under the terms of the CeCILL.
8  * This source file is licensed as described in the file COPYING, which
9  * you should have received as part of this distribution.  The terms
10  * are also available at
11  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
12  *
13  */
14
15 package org.scilab.modules.gui.bridge.editbox;
16
17 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_MAX__;
18 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_STRING__;
19
20 import java.awt.Color;
21 import java.awt.Dimension;
22 import java.awt.Font;
23 import java.awt.Graphics;
24 import java.awt.event.ActionEvent;
25 import java.awt.event.FocusEvent;
26 import java.awt.event.FocusListener;
27 import java.awt.event.KeyEvent;
28
29 import javax.swing.AbstractAction;
30 import javax.swing.InputMap;
31 import javax.swing.JScrollPane;
32 import javax.swing.JTextArea;
33 import javax.swing.JTextPane;
34 import javax.swing.KeyStroke;
35 import javax.swing.ScrollPaneConstants;
36 import javax.swing.UIManager;
37 import javax.swing.text.AbstractDocument;
38 import javax.swing.text.BoxView;
39 import javax.swing.text.ComponentView;
40 import javax.swing.text.Element;
41 import javax.swing.text.IconView;
42 import javax.swing.text.LabelView;
43 import javax.swing.text.ParagraphView;
44 import javax.swing.text.SimpleAttributeSet;
45 import javax.swing.text.StyleConstants;
46 import javax.swing.text.StyledDocument;
47 import javax.swing.text.StyledEditorKit;
48 import javax.swing.text.View;
49 import javax.swing.text.ViewFactory;
50
51 import org.scilab.modules.graphic_objects.console.Console;
52 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
53 import org.scilab.modules.gui.SwingView;
54 import org.scilab.modules.gui.SwingViewObject;
55 import org.scilab.modules.gui.SwingViewWidget;
56 import org.scilab.modules.gui.editbox.SimpleEditBox;
57 import org.scilab.modules.gui.events.callback.CommonCallBack;
58 import org.scilab.modules.gui.menubar.MenuBar;
59 import org.scilab.modules.gui.textbox.TextBox;
60 import org.scilab.modules.gui.toolbar.ToolBar;
61 import org.scilab.modules.gui.utils.Position;
62 import org.scilab.modules.gui.utils.PositionConverter;
63 import org.scilab.modules.gui.utils.ScilabRelief;
64 import org.scilab.modules.gui.utils.ScilabSwingUtilities;
65 import org.scilab.modules.gui.utils.Size;
66
67 /**
68  * Swing implementation for Scilab EditBox in GUIs
69  * @author Vincent COUVERT
70  * @author Marouane BEN JELLOUL
71  */
72 public class SwingScilabEditBox extends JScrollPane implements SwingViewObject, SimpleEditBox {
73
74     private static final long serialVersionUID = 2048261239598753717L;
75
76     private Integer uid;
77
78     private CommonCallBack callback;
79
80     private FocusListener focusListener;
81
82     private StyledDocument doc;
83     private SimpleAttributeSet docAttributes = new SimpleAttributeSet();
84
85     private JTextPane textPane = new JTextPane();
86
87     private Object enterKeyAction;
88     private Object tabKeyAction;
89
90     private class EditBoxView extends BoxView {
91         public EditBoxView(Element elem, int axis) {
92             super(elem, axis);
93         }
94
95         protected void layoutMajorAxis(int targetSpan, int axis, int[] offsets, int[] spans) {
96             super.layoutMajorAxis(targetSpan, axis, offsets, spans);
97             int textBlockHeight = 0;
98             int offset = 0;
99
100             if (textPane.getAlignmentY() == BOTTOM_ALIGNMENT) {
101                 for (int i = 0; i < spans.length; i++) {
102                     textBlockHeight += spans[i];
103                 }
104                 offset = (targetSpan - textBlockHeight);
105                 for (int i = 0; i < offsets.length; i++) {
106                     offsets[i] += offset;
107                 }
108             } else if (textPane.getAlignmentY() == CENTER_ALIGNMENT) {
109                 for (int i = 0; i < spans.length; i++) {
110                     textBlockHeight += spans[i];
111                 }
112                 offset = (targetSpan - textBlockHeight) / 2;
113                 for (int i = 0; i < offsets.length; i++) {
114                     offsets[i] += offset;
115                 }
116             } else {
117                 // TOP_ALIGNEMENT or other
118                 // default behaviour : do nothing special
119             }
120         }
121     }
122
123     private class EditBoxEditorKit extends StyledEditorKit {
124         private static final long serialVersionUID = -3293325523458217074L;
125
126         public ViewFactory getViewFactory() {
127             return new ViewFactory() {
128                 public View create(Element elem) {
129                     String kind = elem.getName();
130                     if (kind != null) {
131                         if (kind.equals(AbstractDocument.ContentElementName)) {
132                             return new LabelView(elem);
133                         } else if (kind.equals(AbstractDocument.ParagraphElementName)) {
134                             return new ParagraphView(elem);
135                         } else if (kind.equals(AbstractDocument.SectionElementName)) {
136                             return new EditBoxView(elem, View.Y_AXIS);
137                         } else if (kind.equals(StyleConstants.ComponentElementName)) {
138                             return new ComponentView(elem);
139                         } else if (kind.equals(StyleConstants.IconElementName)) {
140                             return new IconView(elem);
141                         }
142                     }
143                     return new LabelView(elem);
144                 }
145             };
146         }
147     }
148
149     /**
150      * Constructor
151      */
152     public SwingScilabEditBox() {
153         super(new JTextPane());
154         textPane = (JTextPane) getViewport().getView();
155         setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
156
157         textPane.setEditorKit(new EditBoxEditorKit());
158         doc = (StyledDocument) textPane.getDocument();
159
160         // Create a focus listener to call the callback action
161         focusListener = new FocusListener() {
162             public void focusGained(FocusEvent arg0) {
163                 // Do nothing
164             }
165
166             public void focusLost(FocusEvent arg0) {
167                 validateUserInput();
168             }
169         };
170         textPane.addFocusListener(focusListener);
171         KeyStroke enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
172         KeyStroke tabKey = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
173         InputMap map = textPane.getInputMap();
174         enterKeyAction = map.get(enterKey);
175         tabKeyAction = map.get(tabKey);
176
177         if (Console.getConsole().getUseDeprecatedLF() == false) {
178             setEditFont(getFont());
179         }
180     }
181
182     /**
183      * Validate UserInput and call Scilab Callback if needed
184      */
185     private void validateUserInput() {
186         // Validates user input
187         if (getParent() != null) { // To avoid to execute the callback when then parent figure is destroyed
188
189             String[] stringProperty = getText().split("\n");
190             GraphicController.getController().setProperty(uid, __GO_UI_STRING__, stringProperty);
191
192             if (SwingView.getFromId(uid) != null && callback != null) {
193                 callback.actionPerformed(null);
194             }
195         }
196     }
197
198     /**
199      * Draws a swing Scilab EditBox
200      * @see org.scilab.modules.gui.uielement.UIElement#draw()
201      */
202     public void draw() {
203         this.setVisible(true);
204         this.doLayout();
205     }
206
207     /**
208      * Gets the dimensions (width and height) of a swing Scilab EditBox
209      * @return the dimensions of the EditBox
210      * @see org.scilab.modules.gui.uielement.UIElement#getDims()
211      */
212     public Size getDims() {
213         return new Size(this.getSize().width, this.getSize().height);
214     }
215
216     /**
217      * Gets the position (X-coordinate and Y-coordinate) of a swing Scilab
218      * EditBox
219      * @return the position of the EditBox
220      * @see org.scilab.modules.gui.uielement.UIElement#getPosition()
221      */
222     public Position getPosition() {
223         return PositionConverter.javaToScilab(getLocation(), getSize(), getParent());
224     }
225
226     /**
227      * Sets the dimensions (width and height) of a swing Scilab EditBox
228      * @param newSize the dimensions we want to set to the EditBox
229      * @see org.scilab.modules.gui.uielement.UIElement#setDims(org.scilab.modules.gui.utils.Size)
230      */
231     public void setDims(Size newSize) {
232         this.setSize(newSize.getWidth(), newSize.getHeight());
233     }
234
235     /**
236      * Sets the position (X-coordinate and Y-coordinate) of a swing Scilab
237      * EditBox
238      * @param newPosition the position we want to set to the EditBox
239      * @see org.scilab.modules.gui.uielement.UIElement#setPosition(org.scilab.modules.gui.utils.Position)
240      */
241     public void setPosition(Position newPosition) {
242         Position javaPosition = PositionConverter.scilabToJava(newPosition, getDims(), getParent());
243         setLocation(javaPosition.getX(), javaPosition.getY());
244     }
245
246     /**
247      * Add a callback to the EditBox
248      * @param cb the callback to set.
249      */
250     public void setCallback(CommonCallBack cb) {
251         this.callback = cb;
252     }
253
254     public void setText(String[] texts) {
255         StringBuffer newText = new StringBuffer(texts[0]);
256
257         for (int i = 1; i < texts.length; ++i) {
258             newText.append("\n" + texts[i]);
259         }
260
261         try {
262             textPane.setText(newText.toString());
263             doc.setParagraphAttributes(0, doc.getLength() - 1, docAttributes, true);
264         } catch (Exception e) {
265             // Do nothing
266         }
267     }
268
269     public void setText(String text) {
270         try {
271             textPane.setText(text);
272             doc.setParagraphAttributes(0, doc.getLength() - 1, docAttributes, true);
273         } catch (Exception e) {
274             // Do nothing
275         }
276     }
277
278     /**
279      * Set if the EditBox is enabled or not
280      * @param status true if the EditBox is enabled
281      */
282     public void setEnabled(boolean status) {
283         super.setEnabled(status);
284         /* (Des)Activate the callback */
285         if (callback != null) {
286             if (status) {
287                 removeFocusListener(focusListener); /*
288                                                      * To be sure the callback
289                                                      * is not added two times
290                                                      */
291                 //removeActionListener(actionListener); /* To be sure the callback is not added two times */
292                 addFocusListener(focusListener);
293                 //addActionListener(actionListener);
294             } else {
295                 removeFocusListener(focusListener);
296                 //removeActionListener(actionListener);
297             }
298         }
299     }
300
301     /**
302      * Setter for MenuBar
303      * @param menuBarToAdd the MenuBar associated to the Tab.
304      */
305     public void addMenuBar(MenuBar menuBarToAdd) {
306         /* Unimplemented for EditBoxes */
307         throw new UnsupportedOperationException();
308     }
309
310     /**
311      * Setter for ToolBar
312      * @param toolBarToAdd the ToolBar associated to the Tab.
313      */
314     public void addToolBar(ToolBar toolBarToAdd) {
315         /* Unimplemented for EditBoxes */
316         throw new UnsupportedOperationException();
317     }
318
319     /**
320      * Getter for MenuBar
321      * @return MenuBar: the MenuBar associated to the Tab.
322      */
323     public MenuBar getMenuBar() {
324         /* Unimplemented for EditBoxes */
325         throw new UnsupportedOperationException();
326     }
327
328     /**
329      * Getter for ToolBar
330      * @return ToolBar: the ToolBar associated to the Tab.
331      */
332     public ToolBar getToolBar() {
333         /* Unimplemented for EditBoxes */
334         throw new UnsupportedOperationException();
335     }
336
337     /**
338      * Set the horizontal alignment for the EditBox text
339      * @param alignment the value for the alignment (See ScilabAlignment.java)
340      */
341     public void setHorizontalAlignment(String alignment) {
342         if (alignment.equals("") == false) {
343             int alignConstant = StyleConstants.ALIGN_LEFT;
344             if (alignment.equals("right")) {
345                 alignConstant = StyleConstants.ALIGN_RIGHT;
346             } else if (alignment.equals("center")) {
347                 alignConstant = StyleConstants.ALIGN_CENTER;
348             }
349
350             StyleConstants.setAlignment(docAttributes, alignConstant);
351             doc.setParagraphAttributes(0, doc.getLength(), docAttributes, true);
352         }
353     }
354
355     /**
356      * Set the vertical alignment for the EditBox text
357      * @param alignment the value for the alignment (See ScilabAlignment.java)
358      */
359     public void setVerticalAlignment(String alignment) {
360         if (alignment.equals("") == false) {
361             if (alignment.equals("bottom")) {
362                 textPane.setAlignmentY(BOTTOM_ALIGNMENT);
363             } else if (alignment.equals("top")) {
364                 textPane.setAlignmentY(TOP_ALIGNMENT);
365             } else if (alignment.equals("middle")) {
366                 textPane.setAlignmentY(CENTER_ALIGNMENT);
367             }
368             // Force text update to render
369             setText(getText());
370         }
371     }
372
373     /**
374      * Set the Relief of the EditBox
375      * @param reliefType the type of the relief to set (See ScilabRelief.java)
376      */
377     public void setRelief(String reliefType) {
378         if (reliefType.equals("") == false) {
379             textPane.setBorder(ScilabRelief.getBorderFromRelief(reliefType));
380         }
381     }
382
383     /**
384      * Destroy the EditBox
385      */
386     public void destroy() {
387         ScilabSwingUtilities.removeFromParent(this);
388     }
389
390     /**
391      * Setter for InfoBar
392      * @param infoBarToAdd the InfoBar associated to the EditBox.
393      */
394     public void addInfoBar(TextBox infoBarToAdd) {
395         /* Unimplemented for EditBoxes */
396         throw new UnsupportedOperationException();
397     }
398
399     /**
400      * Getter for InfoBar
401      * @return the InfoBar associated to the EditBox.
402      */
403     public TextBox getInfoBar() {
404         /* Unimplemented for EditBoxes */
405         throw new UnsupportedOperationException();
406     }
407
408     /**
409      * Set the UID
410      * @param id the UID
411      */
412     public void setId(Integer id) {
413         uid = id;
414     }
415
416     /**
417      * Get the UID
418      * @return the UID
419      */
420     public Integer getId() {
421         return uid;
422     }
423
424     public void setBackground(Color bg) {
425         super.setBackground(bg);
426         if (docAttributes != null && textPane != null) {
427             textPane.setBackground(bg);
428             StyleConstants.setBackground(docAttributes, bg);
429         }
430     }
431
432     public void setEditFont(Font font) {
433         super.setFont(font);
434         if (textPane != null) {
435             textPane.setFont(font);
436             StyleConstants.setFontFamily(docAttributes, font.getFamily());
437             StyleConstants.setFontSize(docAttributes, font.getSize());
438             StyleConstants.setBold(docAttributes, font.isBold());
439             StyleConstants.setItalic(docAttributes, font.isItalic());
440             // Force rendering
441             //setText(getText());
442         }
443     }
444
445     /**
446      * Generic update method
447      * @param property property name
448      * @param value property value
449      */
450     public void update(int property, Object value) {
451         switch (property) {
452             case __GO_UI_MAX__ : {
453                 Double columns = (Double)value;
454                 Graphics g = textPane.getGraphics();
455                 Integer width = 50;
456                 if (g != null) {
457                     width = textPane.getGraphics().getFontMetrics(textPane.getFont()).charWidth('m');
458                 }
459                 Integer totalWidth = columns.intValue() * width;
460                 Dimension current = textPane.getPreferredSize();
461                 System.out.println("current : " + current.toString());
462                 current.width = totalWidth;
463                 textPane.setPreferredSize(current);
464                 current = textPane.getPreferredSize();
465                 System.out.println("new : " + current.toString());
466                 break;
467             }
468
469             default : {
470                 SwingViewWidget.update(this, property, value);
471                 break;
472             }
473         }
474     }
475
476     public String getText() {
477         return textPane.getText();
478     }
479
480     public void setMultiLineText(boolean enable) {
481         KeyStroke enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
482         KeyStroke tabKey = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
483         if (enable) {
484             setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
485             textPane.getInputMap().remove(enterKey);
486             textPane.getInputMap().remove(tabKey);
487             textPane.getInputMap().put(enterKey, enterKeyAction);
488             textPane.getInputMap().put(tabKey, tabKeyAction);
489         } else {
490             setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
491             AbstractAction validateUserInput = new AbstractAction() {
492                 private static final long serialVersionUID = -5286137769378297783L;
493
494                 public void actionPerformed(ActionEvent e) {
495                     validateUserInput();
496                 }
497             };
498             textPane.getInputMap().remove(enterKey);
499             textPane.getInputMap().remove(tabKey);
500             textPane.getInputMap().put(enterKey, validateUserInput);
501             textPane.getInputMap().put(tabKey, validateUserInput);
502         }
503     }
504
505     public void resetBackground() {
506         Color color = (Color) UIManager.getLookAndFeelDefaults().get("TextField.background");
507         if (color != null) {
508             setBackground(color);
509         }
510     }
511 }