allow to change label background
[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     /**
150      * To set the Background color of the element.
151      * @param color the Color
152      */
153     public void setBackground(Color color) {
154         super.setBackground(color);
155         if (alignmentPanel != null) {
156             alignmentPanel.setBackground(color);
157         }
158         if (label != null) {
159             if (label instanceof JLabel) {
160                 ((JLabel)label).setOpaque(true);
161             }
162             label.setBackground(color);
163         }
164     }
165
166     /**
167      * Draws a swing Scilab PushButton
168      * @see org.scilab.modules.gui.uielement.UIElement#draw()
169      */
170     public void draw() {
171         this.setVisible(true);
172         this.doLayout();
173     }
174
175     /**
176      * Gets the dimensions (width and height) of a swing Scilab element
177      * @return the dimensions of the element
178      * @see org.scilab.modules.gui.uielement.UIElement#getDims()
179      */
180     public Size getDims() {
181         return new Size(getWidth(), getHeight());
182     }
183
184     /**
185      * Gets the position (X-coordinate and Y-coordinate) of a swing Scilab
186      * element
187      * @return the position of the element
188      * @see org.scilab.modules.gui.uielement.UIElement#getPosition()
189      */
190     public Position getPosition() {
191         return PositionConverter.javaToScilab(getLocation(), getSize(), getParent());
192     }
193
194     /**
195      * Sets the dimensions (width and height) of a swing Scilab element
196      * @param newSize the dimensions to set to the element
197      * @see org.scilab.modules.gui.uielement.UIElement#setDims(org.scilab.modules.gui.utils.Size)
198      */
199     public void setDims(Size newSize) {
200         setSize(newSize.getWidth(), newSize.getHeight());
201         // Need validate to force alignement to be applyed
202         setMinimumSize(new Dimension(
203                            Math.max((int)label.getMinimumSize().getWidth(), newSize.getWidth()),
204                            (int)label.getMinimumSize().getHeight()));
205         validate();
206     }
207
208     /**
209      * Sets the position (X-coordinate and Y-coordinate) of a swing Scilab
210      * element
211      * @param newPosition the position to set to the element
212      * @see org.scilab.modules.gui.uielement.UIElement#setPosition(org.scilab.modules.gui.utils.Position)
213      */
214     public void setPosition(Position newPosition) {
215         Position javaPosition = PositionConverter.scilabToJava(newPosition, getDims(), getParent());
216         setLocation(javaPosition.getX(), javaPosition.getY());
217     }
218
219     /**
220      * Add a callback to the Label
221      * @param callback the callback to set.
222      */
223     public void setCallback(CommonCallBack callback) {
224         // Nothing to do...
225     }
226
227     /**
228      * Setter for MenuBar
229      * @param menuBarToAdd the MenuBar associated to the Label.
230      */
231     public void addMenuBar(MenuBar menuBarToAdd) {
232         /* Unimplemented for Labels */
233         throw new UnsupportedOperationException();
234     }
235
236     /**
237      * Setter for ToolBar
238      * @param toolBarToAdd the ToolBar associated to the Label.
239      */
240     public void addToolBar(ToolBar toolBarToAdd) {
241         /* Unimplemented for Labels */
242         throw new UnsupportedOperationException();
243     }
244
245     /**
246      * Getter for MenuBar
247      * @return MenuBar: the MenuBar associated to the Label.
248      */
249     public MenuBar getMenuBar() {
250         /* Unimplemented for Labels */
251         throw new UnsupportedOperationException();
252     }
253
254     /**
255      * Getter for ToolBar
256      * @return ToolBar: the ToolBar associated to the Label.
257      */
258     public ToolBar getToolBar() {
259         /* Unimplemented for Labels */
260         throw new UnsupportedOperationException();
261     }
262
263     /**
264      * Set the horizontal alignment for the Label text
265      * @param alignment the value for the alignment (See ScilabAlignment.java)
266      */
267     public void setHorizontalAlignment(String alignment) {
268         horizontalAlignment = alignment;
269         setAlignment();
270     }
271
272     /**
273      * Set the vertical alignment for the Label text
274      * @param alignment the value for the alignment (See ScilabAlignment.java)
275      */
276     public void setVerticalAlignment(String alignment) {
277         verticalAlignment = alignment;
278         setAlignment();
279
280     }
281
282     /**
283      * Set the Relief of the Label
284      * @param reliefType the type of the relief to set (See ScilabRelief.java)
285      */
286     public void setRelief(String reliefType) {
287         if (defaultBorder == null) {
288             defaultBorder = getBorder();
289         }
290         setBorder(ScilabRelief.getBorderFromRelief(reliefType, defaultBorder));
291     }
292
293     /**
294      * Destroy the Label
295      */
296     public void destroy() {
297         ScilabSwingUtilities.removeFromParent(this);
298     }
299
300     /**
301      * Setter for InfoBar
302      * @param infoBarToAdd the InfoBar associated to the Label.
303      */
304     public void addInfoBar(TextBox infoBarToAdd) {
305         /* Unimplemented for Labels */
306         throw new UnsupportedOperationException();
307     }
308
309     /**
310      * Getter for InfoBar
311      * @return the InfoBar associated to the Label.
312      */
313     public TextBox getInfoBar() {
314         /* Unimplemented for Labels */
315         throw new UnsupportedOperationException();
316     }
317
318     /**
319      * get the text displayed in the label
320      * @return the label
321      * @see org.scilab.modules.gui.text.SimpleText#getText()
322      */
323     public String getText() {
324         return labelText;
325     }
326
327     /**
328      * Set the text displayed in the label
329      * @param newText the text
330      * @see org.scilab.modules.gui.text.SimpleText#setText(java.lang.String)
331      */
332     public void setText(String newText) {
333         // Save the data given by the user so that it can be retrieved
334         // (Java adds HTML tags in the getlabel().getText() returned value)
335         labelText = newText;
336         if (labelText.startsWith("<")) {
337             // Try if we are in MathML
338             if (isJLabel && ScilabSpecialTextUtilities.setText(label, newText)) {
339                 // MathML in JLabel : OK
340                 // Rendering will be done using Icon
341                 ((JLabel) label).setText(null);
342             } else if (!isJLabel) {
343                 // Try rendering in a new JLabel
344                 if (ScilabSpecialTextUtilities.setText(new JLabel(), newText)) {
345                     // MathML in JEditorPane : Change component
346                     changeLabelType(!isJLabel);
347                     ScilabSpecialTextUtilities.setText(label, newText);
348                     // Rendering will be done using Icon
349                     ((JLabel) label).setText(null);
350                 } else {
351                     // HTML in JEditorPane : OK
352                     ((JEditorPane) label).setText(newText);
353                 }
354             } else {
355                 // HTML in JLabel :
356                 changeLabelType(!isJLabel);
357                 ((JEditorPane) label).setText(newText);
358             }
359         } else {
360             if (!isJLabel) {
361                 changeLabelType(!isJLabel);
362             }
363
364             if (!ScilabSpecialTextUtilities.setText(label, newText)) {
365                 // Normal Text
366                 ((JLabel) label).setText(newText);
367                 ((JLabel) label).invalidate();
368                 invalidate();
369
370             } else {
371                 // Latex or MathML : Rendering will be done using Icon
372                 ((JLabel) label).setText(null);
373             }
374         }
375
376     }
377
378     /**
379      * Change Label type to switch between JLabel abd JEditorPane JLabel is
380      * quicker on simple text JEditorPane can enable HyperLinks
381      * @param isHtmlLabel
382      */
383     private void changeLabelType(boolean isJLabel) {
384         this.isJLabel = isJLabel;
385         Color bgColor = label.getBackground();
386         Color fgColor = label.getForeground();
387         Font font = label.getFont();
388         Dimension dims = label.getSize();
389         label.setVisible(false);
390
391         if (!isJLabel) {
392             JTextPane newLabel = new JTextPane();
393             newLabel.addHyperlinkListener(urlOpener);
394             newLabel.setContentType("text/html");
395             newLabel.setEditable(false);
396             StyleSheet styleSheet = ((HTMLDocument) newLabel.getDocument()).getStyleSheet();
397             styleSheet.addRule("body {font-family:" + font.getName() + ";}");
398             styleSheet.addRule("body {font-size:" + font.getSize() + "pt;}");
399             if (font.isBold()) {
400                 styleSheet.addRule("body {font-weight:bold;}");
401             } else {
402                 styleSheet.addRule("body {font-weight:normal;}");
403             }
404             if (font.isItalic()) {
405                 styleSheet.addRule("body {font-style:italic;}");
406             } else {
407                 styleSheet.addRule("body {font-style:normal;}");
408             }
409
410             label = newLabel;
411             alignmentPanel.add(label);
412             alignmentPanel.revalidate();
413             setViewportView(alignmentPanel);
414         } else {
415             alignmentPanel.remove(label);
416             label = new JLabel();
417             setViewportView(label);
418             //refresh icon
419             update(__GO_UI_ICON__, GraphicController.getController().getProperty(getId(), __GO_UI_ICON__));
420             setAlignment();
421             ((JLabel)label).setOpaque(false);
422         }
423
424         setBackground(bgColor);
425         label.setForeground(fgColor);
426         label.setFont(font);
427         label.setSize(dims);
428         label.setVisible(true);
429     }
430
431     /**
432      * Set alignment of the text component
433      */
434     private void setAlignment() {
435
436         if (isJLabel) {
437             ((JLabel)label).setVerticalAlignment(ScilabAlignment.toSwingAlignment(verticalAlignment));
438             ((JLabel)label).setHorizontalAlignment(ScilabAlignment.toSwingAlignment(horizontalAlignment));
439             return;
440         }
441         GridBagConstraints gbc = new GridBagConstraints();
442
443         gbc.gridx = 0;
444         gbc.gridy = 0;
445         gbc.weightx = 1;
446         gbc.weighty = 1;
447         gbc.gridwidth = 1;
448         gbc.gridheight = 1;
449
450         switch (ScilabAlignment.toSwingAlignment(horizontalAlignment)) {
451             case SwingConstants.LEFT:
452                 switch (ScilabAlignment.toSwingAlignment(verticalAlignment)) {
453                     case SwingConstants.TOP:
454                         gbc.anchor = GridBagConstraints.NORTHWEST;
455                         break;
456                     case SwingConstants.CENTER:
457                         gbc.anchor = GridBagConstraints.WEST;
458                         break;
459                     default: // SwingConstants.BOTTOM
460                         gbc.anchor = GridBagConstraints.SOUTHWEST;
461                         break;
462                 }
463                 break;
464             case SwingConstants.CENTER:
465                 switch (ScilabAlignment.toSwingAlignment(verticalAlignment)) {
466                     case SwingConstants.TOP:
467                         gbc.anchor = GridBagConstraints.NORTH;
468                         break;
469                     case SwingConstants.CENTER:
470                         gbc.anchor = GridBagConstraints.CENTER;
471                         break;
472                     default: // SwingConstants.BOTTOM
473                         gbc.anchor = GridBagConstraints.SOUTH;
474                         break;
475                 }
476                 break;
477             default: // SwingConstants.RIGHT
478                 switch (ScilabAlignment.toSwingAlignment(verticalAlignment)) {
479                     case SwingConstants.TOP:
480                         gbc.anchor = GridBagConstraints.NORTHEAST;
481                         break;
482                     case SwingConstants.CENTER:
483                         gbc.anchor = GridBagConstraints.EAST;
484                         break;
485                     default: // SwingConstants.BOTTOM
486                         gbc.anchor = GridBagConstraints.SOUTHEAST;
487                         break;
488                 }
489                 break;
490         }
491
492         alignmentLayout.setConstraints(label, gbc);
493         alignmentPanel.revalidate();
494     }
495
496     /**
497      * Set the UID
498      * @param id the UID
499      */
500     public void setId(Integer id) {
501         uid = id;
502     }
503
504     /**
505      * Get the UID
506      * @return the UID
507      */
508     public Integer getId() {
509         return uid;
510     }
511
512     /**
513      * Generic update method
514      * @param property property name
515      * @param value property value
516      */
517     public void update(int property, Object value) {
518         switch (property) {
519             case __GO_UI_ICON__: {
520                 if (isJLabel) {
521                     File file = new File((String) value);
522                     if (file.exists() == false) {
523                         String filename = FindIconHelper.findImage((String) value);
524                         file = new File(filename);
525                     }
526
527                     try {
528                         ((JLabel) label).setIcon(new ImageIcon(ImageIO.read(file)));
529                     } catch (IOException e) {
530                     }
531                 } else {
532                     //Icon in JEditorPane ?
533                 }
534                 break;
535             }
536             default: {
537                 SwingViewWidget.update(this, property, value);
538             }
539         }
540     }
541
542     public void resetBackground() {
543         Color color = (Color) UIManager.getLookAndFeelDefaults().get("Label.background");
544         if (color != null) {
545             //bypass setBackground
546             if (label instanceof JLabel) {
547                 ((JLabel)label).setOpaque(false);
548             }
549             label.setBackground(color);
550         }
551     }
552 }