da84c407bdbc7a283910f5599ec2b7bd4b99ee24
[scilab.git] / scilab / modules / gui / src / java / org / scilab / modules / gui / bridge / label / SwingScilabLabel.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2007 - INRIA - Vincent COUVERT
4  * Copyright (C) 2007 - INRIA - Marouane BEN JELLOUL
5  * Copyright (C) 2010-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 package org.scilab.modules.gui.bridge.label;
15
16 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_ICON__;
17
18 import java.awt.Color;
19 import java.awt.Dimension;
20 import java.awt.Font;
21 import java.awt.GridBagConstraints;
22 import java.awt.GridBagLayout;
23 import java.io.File;
24 import java.io.IOException;
25
26 import javax.imageio.ImageIO;
27 import javax.swing.BorderFactory;
28 import javax.swing.ImageIcon;
29 import javax.swing.JComponent;
30 import javax.swing.JEditorPane;
31 import javax.swing.JLabel;
32 import javax.swing.JPanel;
33 import javax.swing.JScrollPane;
34 import javax.swing.JTextPane;
35 import javax.swing.SwingConstants;
36 import javax.swing.UIManager;
37 import javax.swing.border.Border;
38 import javax.swing.event.HyperlinkEvent;
39 import javax.swing.event.HyperlinkListener;
40 import javax.swing.text.html.HTMLDocument;
41 import javax.swing.text.html.StyleSheet;
42
43 import org.scilab.modules.commons.gui.FindIconHelper;
44 import org.scilab.modules.console.utils.ScilabSpecialTextUtilities;
45 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
46 import org.scilab.modules.gui.SwingViewObject;
47 import org.scilab.modules.gui.SwingViewWidget;
48 import org.scilab.modules.gui.events.callback.CommonCallBack;
49 import org.scilab.modules.gui.label.SimpleLabel;
50 import org.scilab.modules.gui.menubar.MenuBar;
51 import org.scilab.modules.gui.textbox.TextBox;
52 import org.scilab.modules.gui.toolbar.ToolBar;
53 import org.scilab.modules.gui.utils.Position;
54 import org.scilab.modules.gui.utils.PositionConverter;
55 import org.scilab.modules.gui.utils.ScilabAlignment;
56 import org.scilab.modules.gui.utils.ScilabRelief;
57 import org.scilab.modules.gui.utils.ScilabSwingUtilities;
58 import org.scilab.modules.gui.utils.Size;
59 import org.scilab.modules.gui.utils.WebBrowser;
60
61 /**
62  * Swing implementation for Scilab Labels in GUIs
63  * @author Vincent COUVERT
64  * @author Marouane BEN JELLOUL
65  */
66 public class SwingScilabLabel extends JScrollPane implements SwingViewObject, SimpleLabel {
67
68     private static final long serialVersionUID = 7177323379068859441L;
69
70     private Integer uid;
71
72     private JComponent label = new JLabel(" ");
73
74     private Border defaultBorder = null;
75
76     private boolean isJLabel = true;
77
78     private String horizontalAlignment = "left"; /* Horizontal alignment property */
79
80     private String verticalAlignment = "middle"; /* Vertical alignment property */
81
82     private final JPanel alignmentPanel = new JPanel(); /* Used for alignment */
83
84     private final GridBagLayout alignmentLayout = new GridBagLayout();
85
86     private String labelText = ""; /* Used to save user given text */
87
88     private static HyperlinkListener urlOpener = new HyperlinkListener() {
89         public void hyperlinkUpdate(HyperlinkEvent event) {
90             if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
91                 WebBrowser.openUrl(event.getURL(), event.getDescription());
92             }
93         }
94     };
95
96     /**
97      * Constructor
98      */
99     public SwingScilabLabel() {
100         super();
101         alignmentPanel.setLayout(alignmentLayout);
102         //alignmentPanel.add(label);
103         //getViewport().add(label);
104         setViewportView(label);
105         setBorder(BorderFactory.createEmptyBorder());
106         setViewportBorder(BorderFactory.createEmptyBorder());
107         setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
108         // Initialize display
109         setAlignment();
110     }
111
112     /**
113      * Apply a new font for the label.
114      * @param font new font to use.
115      */
116     public void setFont(Font font) {
117         super.setFont(font);
118         if (label != null) {
119             label.setFont(font);
120             if (!isJLabel) {
121                 StyleSheet styleSheet = ((HTMLDocument) ((JTextPane) label).getDocument()).getStyleSheet();
122                 styleSheet.addRule("body {font-family:" + font.getName() + ";}");
123                 styleSheet.addRule("body {font-size:" + font.getSize() + "pt;}");
124                 if (font.isBold()) {
125                     styleSheet.addRule("body {font-weight:bold;}");
126                 } else {
127                     styleSheet.addRule("body {font-weight:normal;}");
128                 }
129                 if (font.isItalic()) {
130                     styleSheet.addRule("body {font-style:italic;}");
131                 } else {
132                     styleSheet.addRule("body {font-style:normal;}");
133                 }
134             }
135         }
136     }
137
138     /**
139      * To set the Foreground color of the element.
140      * @param color the Color
141      */
142     public void setForeground(Color color) {
143         super.setForeground(color);
144         if (label != null) {
145             label.setForeground(color);
146         }
147     }
148
149     public void setEnabled(boolean enabled) {
150         super.setEnabled(enabled);
151         if (label != null) {
152             label.setEnabled(enabled);
153         }
154     }
155
156     /**
157      * To set the Background color of the element.
158      * @param color the Color
159      */
160     public void setBackground(Color color) {
161         super.setBackground(color);
162         if (alignmentPanel != null) {
163             alignmentPanel.setBackground(color);
164         }
165         if (label != null) {
166             if (label instanceof JLabel) {
167                 ((JLabel)label).setOpaque(true);
168             }
169             label.setBackground(color);
170         }
171     }
172
173     /**
174      * Draws a swing Scilab PushButton
175      * @see org.scilab.modules.gui.uielement.UIElement#draw()
176      */
177     public void draw() {
178         this.setVisible(true);
179         this.doLayout();
180     }
181
182     /**
183      * Gets the dimensions (width and height) of a swing Scilab element
184      * @return the dimensions of the element
185      * @see org.scilab.modules.gui.uielement.UIElement#getDims()
186      */
187     public Size getDims() {
188         return new Size(getWidth(), getHeight());
189     }
190
191     /**
192      * Gets the position (X-coordinate and Y-coordinate) of a swing Scilab
193      * element
194      * @return the position of the element
195      * @see org.scilab.modules.gui.uielement.UIElement#getPosition()
196      */
197     public Position getPosition() {
198         return PositionConverter.javaToScilab(getLocation(), getSize(), getParent());
199     }
200
201     /**
202      * Sets the dimensions (width and height) of a swing Scilab element
203      * @param newSize the dimensions to set to the element
204      * @see org.scilab.modules.gui.uielement.UIElement#setDims(org.scilab.modules.gui.utils.Size)
205      */
206     public void setDims(Size newSize) {
207         setSize(newSize.getWidth(), newSize.getHeight());
208         // Need validate to force alignement to be applyed
209         setMinimumSize(new Dimension(
210                            Math.max((int)label.getMinimumSize().getWidth(), newSize.getWidth()),
211                            (int)label.getMinimumSize().getHeight()));
212     }
213
214     /**
215      * Sets the position (X-coordinate and Y-coordinate) of a swing Scilab
216      * element
217      * @param newPosition the position to set to the element
218      * @see org.scilab.modules.gui.uielement.UIElement#setPosition(org.scilab.modules.gui.utils.Position)
219      */
220     public void setPosition(Position newPosition) {
221         Position javaPosition = PositionConverter.scilabToJava(newPosition, getDims(), getParent());
222         setLocation(javaPosition.getX(), javaPosition.getY());
223     }
224
225     /**
226      * Add a callback to the Label
227      * @param callback the callback to set.
228      */
229     public void setCallback(CommonCallBack callback) {
230         // Nothing to do...
231     }
232
233     /**
234      * Setter for MenuBar
235      * @param menuBarToAdd the MenuBar associated to the Label.
236      */
237     public void addMenuBar(MenuBar menuBarToAdd) {
238         /* Unimplemented for Labels */
239         throw new UnsupportedOperationException();
240     }
241
242     /**
243      * Setter for ToolBar
244      * @param toolBarToAdd the ToolBar associated to the Label.
245      */
246     public void addToolBar(ToolBar toolBarToAdd) {
247         /* Unimplemented for Labels */
248         throw new UnsupportedOperationException();
249     }
250
251     /**
252      * Getter for MenuBar
253      * @return MenuBar: the MenuBar associated to the Label.
254      */
255     public MenuBar getMenuBar() {
256         /* Unimplemented for Labels */
257         throw new UnsupportedOperationException();
258     }
259
260     /**
261      * Getter for ToolBar
262      * @return ToolBar: the ToolBar associated to the Label.
263      */
264     public ToolBar getToolBar() {
265         /* Unimplemented for Labels */
266         throw new UnsupportedOperationException();
267     }
268
269     /**
270      * Set the horizontal alignment for the Label text
271      * @param alignment the value for the alignment (See ScilabAlignment.java)
272      */
273     public void setHorizontalAlignment(String alignment) {
274         horizontalAlignment = alignment;
275         setAlignment();
276     }
277
278     /**
279      * Set the vertical alignment for the Label text
280      * @param alignment the value for the alignment (See ScilabAlignment.java)
281      */
282     public void setVerticalAlignment(String alignment) {
283         verticalAlignment = alignment;
284         setAlignment();
285
286     }
287
288     /**
289      * Set the Relief of the Label
290      * @param reliefType the type of the relief to set (See ScilabRelief.java)
291      */
292     public void setRelief(String reliefType) {
293         if (defaultBorder == null) {
294             defaultBorder = getBorder();
295         }
296         setBorder(ScilabRelief.getBorderFromRelief(reliefType, defaultBorder));
297     }
298
299     /**
300      * Destroy the Label
301      */
302     public void destroy() {
303         ScilabSwingUtilities.removeFromParent(this);
304     }
305
306     /**
307      * Setter for InfoBar
308      * @param infoBarToAdd the InfoBar associated to the Label.
309      */
310     public void addInfoBar(TextBox infoBarToAdd) {
311         /* Unimplemented for Labels */
312         throw new UnsupportedOperationException();
313     }
314
315     /**
316      * Getter for InfoBar
317      * @return the InfoBar associated to the Label.
318      */
319     public TextBox getInfoBar() {
320         /* Unimplemented for Labels */
321         throw new UnsupportedOperationException();
322     }
323
324     /**
325      * get the text displayed in the label
326      * @return the label
327      * @see org.scilab.modules.gui.text.SimpleText#getText()
328      */
329     public String getText() {
330         return labelText;
331     }
332
333     /**
334      * Set the text displayed in the label
335      * @param newText the text
336      * @see org.scilab.modules.gui.text.SimpleText#setText(java.lang.String)
337      */
338     public void setText(String newText) {
339         // Save the data given by the user so that it can be retrieved
340         // (Java adds HTML tags in the getlabel().getText() returned value)
341         labelText = newText;
342         if (labelText.startsWith("<")) {
343             // Try if we are in MathML
344             if (isJLabel && ScilabSpecialTextUtilities.setText(label, newText)) {
345                 // MathML in JLabel : OK
346                 // Rendering will be done using Icon
347                 ((JLabel) label).setText(null);
348             } else if (!isJLabel) {
349                 // Try rendering in a new JLabel
350                 if (ScilabSpecialTextUtilities.setText(new JLabel(), newText)) {
351                     // MathML in JEditorPane : Change component
352                     changeLabelType(!isJLabel);
353                     ScilabSpecialTextUtilities.setText(label, newText);
354                     // Rendering will be done using Icon
355                     ((JLabel) label).setText(null);
356                 } else {
357                     // HTML in JEditorPane : OK
358                     ((JEditorPane) label).setText(newText);
359                 }
360             } else {
361                 // HTML in JLabel :
362                 changeLabelType(!isJLabel);
363                 ((JEditorPane) label).setText(newText);
364             }
365         } else {
366             if (!isJLabel) {
367                 changeLabelType(!isJLabel);
368             }
369
370             if (!ScilabSpecialTextUtilities.setText(label, newText)) {
371                 // Normal Text
372                 if (!newText.isEmpty()) {
373                     ((JLabel) label).setText(newText);
374                 } else {
375                     ((JLabel) label).setText(" ");
376                 }
377             } else {
378                 // Latex or MathML : Rendering will be done using Icon
379                 ((JLabel) label).setText(null);
380             }
381
382             ((JLabel) label).invalidate();
383             ((JLabel) label).validate();
384             ((JLabel) label).repaint();
385         }
386
387     }
388
389     /**
390      * Change Label type to switch between JLabel abd JEditorPane JLabel is
391      * quicker on simple text JEditorPane can enable HyperLinks
392      * @param isHtmlLabel
393      */
394     private void changeLabelType(boolean isJLabel) {
395         this.isJLabel = isJLabel;
396         Color bgColor = label.getBackground();
397         Color fgColor = label.getForeground();
398         Font font = label.getFont();
399         Dimension dims = label.getSize();
400         label.setVisible(false);
401
402         if (!isJLabel) {
403             JTextPane newLabel = new JTextPane();
404             newLabel.addHyperlinkListener(urlOpener);
405             newLabel.setContentType("text/html");
406             newLabel.setEditable(false);
407             StyleSheet styleSheet = ((HTMLDocument) newLabel.getDocument()).getStyleSheet();
408             styleSheet.addRule("body {font-family:" + font.getName() + ";}");
409             styleSheet.addRule("body {font-size:" + font.getSize() + "pt;}");
410             if (font.isBold()) {
411                 styleSheet.addRule("body {font-weight:bold;}");
412             } else {
413                 styleSheet.addRule("body {font-weight:normal;}");
414             }
415             if (font.isItalic()) {
416                 styleSheet.addRule("body {font-style:italic;}");
417             } else {
418                 styleSheet.addRule("body {font-style:normal;}");
419             }
420
421             label = newLabel;
422             alignmentPanel.add(label);
423             setViewportView(alignmentPanel);
424         } else {
425             alignmentPanel.remove(label);
426             label = new JLabel();
427             setViewportView(label);
428             //refresh icon
429             update(__GO_UI_ICON__, GraphicController.getController().getProperty(getId(), __GO_UI_ICON__));
430             setAlignment();
431             ((JLabel)label).setOpaque(false);
432         }
433
434         setBackground(bgColor);
435         label.setForeground(fgColor);
436         label.setFont(font);
437         label.setSize(dims);
438         label.setVisible(true);
439     }
440
441     /**
442      * Set alignment of the text component
443      */
444     private void setAlignment() {
445
446         if (isJLabel) {
447             ((JLabel)label).setVerticalAlignment(ScilabAlignment.toSwingAlignment(verticalAlignment));
448             ((JLabel)label).setHorizontalAlignment(ScilabAlignment.toSwingAlignment(horizontalAlignment));
449             return;
450         }
451         GridBagConstraints gbc = new GridBagConstraints();
452
453         gbc.gridx = 0;
454         gbc.gridy = 0;
455         gbc.weightx = 1;
456         gbc.weighty = 1;
457         gbc.gridwidth = 1;
458         gbc.gridheight = 1;
459
460         switch (ScilabAlignment.toSwingAlignment(horizontalAlignment)) {
461             case SwingConstants.LEFT:
462                 switch (ScilabAlignment.toSwingAlignment(verticalAlignment)) {
463                     case SwingConstants.TOP:
464                         gbc.anchor = GridBagConstraints.NORTHWEST;
465                         break;
466                     case SwingConstants.CENTER:
467                         gbc.anchor = GridBagConstraints.WEST;
468                         break;
469                     default: // SwingConstants.BOTTOM
470                         gbc.anchor = GridBagConstraints.SOUTHWEST;
471                         break;
472                 }
473                 break;
474             case SwingConstants.CENTER:
475                 switch (ScilabAlignment.toSwingAlignment(verticalAlignment)) {
476                     case SwingConstants.TOP:
477                         gbc.anchor = GridBagConstraints.NORTH;
478                         break;
479                     case SwingConstants.CENTER:
480                         gbc.anchor = GridBagConstraints.CENTER;
481                         break;
482                     default: // SwingConstants.BOTTOM
483                         gbc.anchor = GridBagConstraints.SOUTH;
484                         break;
485                 }
486                 break;
487             default: // SwingConstants.RIGHT
488                 switch (ScilabAlignment.toSwingAlignment(verticalAlignment)) {
489                     case SwingConstants.TOP:
490                         gbc.anchor = GridBagConstraints.NORTHEAST;
491                         break;
492                     case SwingConstants.CENTER:
493                         gbc.anchor = GridBagConstraints.EAST;
494                         break;
495                     default: // SwingConstants.BOTTOM
496                         gbc.anchor = GridBagConstraints.SOUTHEAST;
497                         break;
498                 }
499                 break;
500         }
501
502         alignmentLayout.setConstraints(label, gbc);
503     }
504
505     /**
506      * Set the UID
507      * @param id the UID
508      */
509     public void setId(Integer id) {
510         uid = id;
511     }
512
513     /**
514      * Get the UID
515      * @return the UID
516      */
517     public Integer getId() {
518         return uid;
519     }
520
521     /**
522      * Generic update method
523      * @param property property name
524      * @param value property value
525      */
526     public void update(int property, Object value) {
527         switch (property) {
528             case __GO_UI_ICON__: {
529                 if (isJLabel) {
530                     String icon = (String) value;
531                     if (icon != null && icon.equals("") == false) {
532                         File file = new File((String) value);
533                         if (file.exists() == false) {
534                             String filename = FindIconHelper.findImage((String) value);
535                             file = new File(filename);
536                         }
537
538                         try {
539                             ((JLabel) label).setIcon(new ImageIcon(ImageIO.read(file)));
540                         } catch (IOException e) {
541                         }
542                     } else {
543                         ((JLabel) label).setIcon(null);
544                     }
545                 } else {
546                     //Icon in JEditorPane ?
547                 }
548                 break;
549             }
550             default: {
551                 SwingViewWidget.update(this, property, value);
552             }
553         }
554     }
555
556     public void resetBackground() {
557         Color color = (Color) UIManager.getLookAndFeelDefaults().get("Label.background");
558         if (color != null) {
559             //bypass setBackground
560             if (label instanceof JLabel) {
561                 ((JLabel)label).setOpaque(true);
562             }
563             label.setBackground(color);
564         }
565     }
566
567     public void resetForeground() {
568         Color color = (Color)UIManager.getLookAndFeelDefaults().get("Label.foreground");
569         if (color != null) {
570             label.setForeground(color);
571         }
572     }
573 }