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