Merge remote-tracking branch 'origin/5.5'
[scilab.git] / scilab / modules / gui / src / java / org / scilab / modules / gui / bridge / frame / SwingScilabScrollableFrame.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  *
6  * This file must be used under the terms of the CeCILL.
7  * This source file is licensed as described in the file COPYING, which
8  * you should have received as part of this distribution.  The terms
9  * are also available at
10  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
11  *
12  */
13
14 package org.scilab.modules.gui.bridge.frame;
15
16 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_BORDER_OPT_PADDING__;
17 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_CHILDREN__;
18 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_GRID_OPT_GRID__;
19 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_GRID_OPT_PADDING__;
20 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_LAYOUT__;
21 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_TAG__;
22 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_TYPE__;
23 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UICONTROL__;
24 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_ENABLE__;
25 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_FRAME_BORDER__;
26 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UI_STRING__;
27 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_VISIBLE__;
28
29 import java.awt.BorderLayout;
30 import java.awt.Color;
31 import java.awt.Component;
32 import java.awt.Container;
33 import java.awt.Dimension;
34 import java.awt.GridBagConstraints;
35 import java.awt.GridBagLayout;
36 import java.awt.GridLayout;
37 import java.awt.Insets;
38 import java.awt.LayoutManager;
39
40 import javax.swing.JPanel;
41 import javax.swing.JScrollPane;
42 import javax.swing.ScrollPaneLayout;
43 import javax.swing.SwingUtilities;
44 import javax.swing.UIManager;
45 import javax.swing.border.Border;
46
47 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
48 import org.scilab.modules.graphic_objects.graphicModel.GraphicModel;
49 import org.scilab.modules.graphic_objects.uicontrol.Uicontrol;
50 import org.scilab.modules.graphic_objects.utils.LayoutType;
51 import org.scilab.modules.gui.SwingView;
52 import org.scilab.modules.gui.SwingViewObject;
53 import org.scilab.modules.gui.SwingViewWidget;
54 import org.scilab.modules.gui.bridge.tab.SwingScilabPanel;
55 import org.scilab.modules.gui.bridge.tab.SwingScilabTabGroup;
56 import org.scilab.modules.gui.bridge.textbox.SwingScilabTextBox;
57 import org.scilab.modules.gui.bridge.window.SwingScilabWindow;
58 import org.scilab.modules.gui.dockable.Dockable;
59 import org.scilab.modules.gui.events.callback.CommonCallBack;
60 import org.scilab.modules.gui.menubar.MenuBar;
61 import org.scilab.modules.gui.textbox.TextBox;
62 import org.scilab.modules.gui.toolbar.ToolBar;
63 import org.scilab.modules.gui.utils.BorderConvertor;
64 import org.scilab.modules.gui.utils.Position;
65 import org.scilab.modules.gui.utils.PositionConverter;
66 import org.scilab.modules.gui.utils.ScilabRelief;
67 import org.scilab.modules.gui.utils.Size;
68 import org.scilab.modules.gui.widget.Widget;
69
70 /**
71  * Swing implementation for Scilab frames in GUI
72  * @author Vincent COUVERT
73  * @author Marouane BEN JELLOUL
74  */
75 public class SwingScilabScrollableFrame extends JScrollPane implements SwingViewObject, Widget {
76
77     private static final long serialVersionUID = -7401084975837285447L;
78
79     private Integer uid;
80     private JPanel panel = new JPanel();
81
82     private Border defaultBorder = null;
83
84     /**
85      * Constructor
86      */
87     public SwingScilabScrollableFrame() {
88         super();
89         setViewportView(panel);
90         panel.setLayout(null);
91         setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
92         setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
93     }
94
95     public JPanel getPanel() {
96         return panel;
97     }
98     /**
99      * Draws a Swing Scilab frame
100      * @see org.scilab.modules.gui.UIElement#draw()
101      */
102     public void draw() {
103         this.setVisible(true);
104         this.doLayout();
105     }
106
107     /**
108      * Gets the dimensions (width and height) of a swing Scilab frame
109      * @return the dimension of the frame
110      * @see org.scilab.modules.gui.UIElement#getDims()
111      */
112     public Size getDims() {
113         return new Size(this.getSize().width, this.getSize().height);
114     }
115
116     /**
117      * Gets the position (X-coordinate and Y-coordinate) of a swing Scilab frame
118      * @return the position of the frame
119      * @see org.scilab.modules.gui.UIElement#getPosition()
120      */
121     public Position getPosition() {
122         return PositionConverter.javaToScilab(getLocation(), getSize(), getParent());
123     }
124
125     /**
126      * Sets the dimensions (width and height) of a swing Scilab frame
127      * @param newSize the size we want to set to the frame
128      * @see org.scilab.modules.gui.UIElement#setDims(org.scilab.modules.gui.utils.Size)
129      */
130     public void setDims(Size newSize) {
131         setSize(newSize.getWidth(), newSize.getHeight());
132     }
133
134     /**
135      * Sets the position (X-coordinate and Y-coordinate) of a swing Scilab frame
136      * @param newPosition the position we want to set to the frame
137      * @see org.scilab.modules.gui.UIElement#setPosition(org.scilab.modules.gui.utils.Position)
138      */
139     public void setPosition(Position newPosition) {
140         Position javaPosition = PositionConverter.scilabToJava(newPosition, getDims(), getParent());
141         setLocation(javaPosition.getX(), javaPosition.getY());
142     }
143
144     /**
145      * Add a SwingViewObject (from SwingView.java) to container and returns its index
146      * @param member the member to add
147      */
148     public void addMember(SwingViewObject member) {
149         //forward disable status
150         if (isEnabled() == false) {
151             ((Component) member).setEnabled(false);
152         }
153
154         Uicontrol uicontrol = (Uicontrol) GraphicModel.getModel().getObjectFromId(member.getId());
155         if (getLayout() instanceof BorderLayout) {
156             switch (uicontrol.getBorderPositionAsEnum()) {
157                 case BOTTOM:
158                     panel.add((Component) member, BorderLayout.SOUTH);
159                     break;
160                 case TOP:
161                     panel.add((Component) member, BorderLayout.NORTH);
162                     break;
163                 case LEFT:
164                     panel.add((Component) member, BorderLayout.WEST);
165                     break;
166                 case RIGHT:
167                     panel.add((Component) member, BorderLayout.EAST);
168                     break;
169                 case CENTER:
170                     panel.add((Component) member, BorderLayout.CENTER);
171                     break;
172                 default:
173                     break;
174             }
175
176             Integer[] preferredSize = uicontrol.getBorderPreferredSize();
177             if (preferredSize[0].equals(-1) == false && preferredSize[1].equals(-1) == false) {
178                 ((Component) member).setPreferredSize(new Dimension(preferredSize[0], preferredSize[1]));
179             }
180         } else if (getLayout() instanceof GridBagLayout) {
181             GridBagConstraints constraints = new GridBagConstraints();
182
183             // Grid
184             Integer[] grid = uicontrol.getGridBagGrid();
185             constraints.gridx = grid[0];
186             constraints.gridy = grid[1];
187             constraints.gridwidth = grid[2];
188             constraints.gridheight = grid[3];
189
190             // Weight
191             Double[] weight = uicontrol.getGridBagWeight();
192             constraints.weightx = weight[0];
193             constraints.weighty = weight[1];
194
195             // Anchor
196             switch (uicontrol.getGridBagAnchorAsEnum()) {
197                 case LEFT :
198                     constraints.anchor = GridBagConstraints.WEST;
199                     break;
200                 case UPPER :
201                     constraints.anchor = GridBagConstraints.NORTH;
202                     break;
203                 case LOWER:
204                     constraints.anchor = GridBagConstraints.SOUTH;
205                     break;
206                 case LOWER_LEFT:
207                     constraints.anchor = GridBagConstraints.SOUTHWEST;
208                     break;
209                 case LOWER_RIGHT:
210                     constraints.anchor = GridBagConstraints.SOUTHEAST;
211                     break;
212                 case RIGHT:
213                     constraints.anchor = GridBagConstraints.EAST;
214                     break;
215                 case UPPER_LEFT:
216                     constraints.anchor = GridBagConstraints.NORTHWEST;
217                     break;
218                 case UPPER_RIGHT:
219                     constraints.anchor = GridBagConstraints.NORTHEAST;
220                     break;
221                 case CENTER :
222                 default :
223                     constraints.anchor = GridBagConstraints.CENTER;
224                     break;
225             }
226
227             // Fill
228             switch (uicontrol.getGridBagFillAsEnum()) {
229                 case BOTH :
230                     constraints.fill = GridBagConstraints.BOTH;
231                     break;
232                 case HORIZONTAL:
233                     constraints.fill = GridBagConstraints.HORIZONTAL;
234                     break;
235                 case VERTICAL:
236                     constraints.fill = GridBagConstraints.VERTICAL;
237                     break;
238                 case NONE:
239                 default:
240                     constraints.fill = GridBagConstraints.NONE;
241                     break;
242             }
243
244             // Insets
245             Double[] margins = uicontrol.getMargins();
246             constraints.insets = new Insets(
247                 margins[0].intValue(), margins[1].intValue(),
248                 margins[2].intValue(), margins[3].intValue());
249
250             // Padding
251             Integer[] padding = uicontrol.getGridBagPadding();
252             constraints.ipadx = padding[0];
253             constraints.ipady = padding[1];
254
255             Integer[] preferredSize = uicontrol.getGridBagPreferredSize();
256             if (preferredSize[0].equals(-1) == false && preferredSize[1].equals(-1) == false) {
257                 ((Component) member).setPreferredSize(new Dimension(preferredSize[0], preferredSize[1]));
258             }
259
260             panel.add((Component) member, constraints);
261             revalidate();
262         } else if (getLayout() instanceof GridLayout) {
263             this.panel.add((Component) member, 0);
264         } else {
265             panel.add((Component) member);
266         }
267
268         SwingScilabPanel win = (SwingScilabPanel)SwingUtilities.getAncestorOfClass(SwingScilabPanel.class, this);
269         if (win != null) {
270             SwingScilabWindow parentWindow = SwingScilabWindow.allScilabWindows.get(win.getParentWindowId());
271             parentWindow.pack();
272         }
273     }
274
275     /**
276      * Add a callback to the Frame
277      * @param callback the callback to set.
278      */
279     public void setCallback(CommonCallBack callback) {
280         // Nothing to do...
281     }
282
283     /**
284      * Setter for MenuBar
285      * @param menuBarToAdd the MenuBar associated to the Frame.
286      */
287     public void addMenuBar(MenuBar menuBarToAdd) {
288         /* Unimplemented for Frames */
289         throw new UnsupportedOperationException();
290     }
291
292     /**
293      * Setter for ToolBar
294      * @param toolBarToAdd the ToolBar associated to the Frame.
295      */
296     public void addToolBar(ToolBar toolBarToAdd) {
297         /* Unimplemented for Frames */
298         throw new UnsupportedOperationException();
299     }
300
301     /**
302      * Getter for MenuBar
303      * @return MenuBar: the MenuBar associated to the Frame.
304      */
305     public MenuBar getMenuBar() {
306         /* Unimplemented for Frames */
307         throw new UnsupportedOperationException();
308     }
309
310     /**
311      * Getter for ToolBar
312      * @return ToolBar: the ToolBar associated to the Frame.
313      */
314     public ToolBar getToolBar() {
315         /* Unimplemented for Frames */
316         throw new UnsupportedOperationException();
317     }
318
319     /**
320      * Get the text of the Frame
321      * @return the text of the frame
322      * @see org.scilab.modules.gui.frame.SimpleFrame#getText()
323      */
324     public String getText() {
325         return this.getName();
326     }
327
328     /**
329      * Set the text of the Frame
330      * @param text the text to set to the frame
331      * @see org.scilab.modules.gui.frame.SimpleFrame#setText()
332      */
333     public void setText(String text) {
334         this.setName(text);
335     }
336
337     public void setEmptyText() {
338         setText(null);
339     }
340
341     /**
342      * Add a dockable element in the Frame (Not available for the moment)
343      * @param member the object we want to add to the Frame
344      * @return the index of the member in the Frame
345      * @see org.scilab.modules.gui.container.Container#addMember(org.scilab.modules.gui.dockable.Dockable)
346      */
347     public int addMember(Dockable member) {
348         /* Unimplemented for Frames */
349         throw new UnsupportedOperationException();
350     }
351
352     /**
353      * Set the Relief of the Frame
354      * @param reliefType the type of the relief to set (See ScilabRelief.java)
355      */
356     public void setRelief(String reliefType) {
357         if (defaultBorder == null) {
358             defaultBorder = getBorder();
359         }
360         setBorder(ScilabRelief.getBorderFromRelief(reliefType, defaultBorder));
361     }
362
363     /**
364      * Destroy the Frame
365      */
366     public void destroy() {
367         this.setVisible(false);
368     }
369
370     /**
371      * Setter for InfoBar
372      * @param infoBarToAdd the InfoBar associated to the Frame.
373      */
374     public void addInfoBar(TextBox infoBarToAdd) {
375         /* Unimplemented for Frames */
376         throw new UnsupportedOperationException();
377     }
378
379     /**
380      * Getter for InfoBar
381      * @return the InfoBar associated to the Frame.
382      */
383     public TextBox getInfoBar() {
384         /* Unimplemented for Frames */
385         throw new UnsupportedOperationException();
386     }
387
388     /**
389      * Set the horizontal alignment for the Slider text
390      * @param alignment the value for the alignment (See ScilabAlignment.java)
391      */
392     public void setHorizontalAlignment(String alignment) {
393         // Nothing to do here
394     }
395
396     /**
397      * Set the vertical alignment for the Slider text
398      * @param alignment the value for the alignment (See ScilabAlignment.java)
399      */
400     public void setVerticalAlignment(String alignment) {
401         // Nothing to do here
402     }
403
404     /**
405      * Set the UID
406      * @param id the UID
407      */
408     public void setId(Integer id) {
409         uid = id;
410     }
411
412     /**
413      * Get the UID
414      * @return the UID
415      */
416     public Integer getId() {
417         return uid;
418     }
419
420     /**
421      * Generic update method
422      * @param property property name
423      * @param value property value
424      */
425     public void update(int property, Object value) {
426         GraphicController controller = GraphicController.getController();
427
428         switch (property) {
429             case __GO_UI_STRING__: {
430                 // Update tab title
431                 Container parent = getParent();
432                 if (parent instanceof SwingScilabTabGroup) {
433                     SwingScilabTabGroup tab = (SwingScilabTabGroup) parent;
434                     int index = tab.indexOfComponent(this);
435                     if (index != -1) {
436                         tab.setTitleAt(index, ((String[]) value)[0]);
437                     }
438                 }
439                 break;
440             }
441             case __GO_UI_FRAME_BORDER__: {
442                 Integer borderId = (Integer) value;
443                 Border border = BorderConvertor.getBorder(borderId);
444                 setBorder(border);
445                 break;
446             }
447             case __GO_LAYOUT__ : {
448                 LayoutType newLayout = LayoutType.intToEnum((Integer) value);
449
450                 invalidate();
451
452                 switch (newLayout) {
453                     case BORDER: {
454                         Integer[] padding = (Integer[]) controller.getProperty(getId(), __GO_BORDER_OPT_PADDING__);
455                         setLayout(new BorderLayout(padding[0], padding[1]));
456                         break;
457                     }
458                     case GRIDBAG:
459                         setLayout(new GridBagLayout());
460                         break;
461                     case GRID: {
462                         Integer[] padding = (Integer[]) controller.getProperty(getId(), __GO_GRID_OPT_PADDING__);
463                         Integer[] grid = (Integer[]) controller.getProperty(getId(), __GO_GRID_OPT_GRID__);
464                         if (grid[0] == 0 && grid[1] == 0) {
465                             grid[0] = 1;
466                         }
467                         setLayout(new GridLayout(grid[0], grid[1], padding[0], padding[1]));
468                         break;
469                     }
470                     case NONE:
471                     default: {
472                         setLayout(null);
473                         break;
474                     }
475                 }
476
477                 validate();
478                 break;
479             }
480             case __GO_GRID_OPT_PADDING__:
481             case __GO_GRID_OPT_GRID__: {
482                 Integer layout = (Integer) GraphicController.getController().getProperty(getId(), __GO_LAYOUT__);
483                 LayoutType layoutType = LayoutType.intToEnum(layout);
484
485                 if (layoutType != LayoutType.GRID) {
486                     break;
487                 }
488
489                 Integer[] padding = (Integer[]) GraphicController.getController().getProperty(getId(), __GO_GRID_OPT_PADDING__);
490
491                 Integer[] grid = (Integer[]) GraphicController.getController().getProperty(getId(), __GO_GRID_OPT_GRID__);
492                 Integer[] localGrid = new Integer[] { 0, 0 };
493                 localGrid[0] = grid[0];
494                 localGrid[1] = grid[1];
495
496                 if (localGrid[0] == 0 && localGrid[1] == 0) {
497                     localGrid[0] = 1;
498                 }
499
500                 invalidate();
501
502                 GridLayout gl = (GridLayout)getLayout();
503                 gl.setRows(localGrid[0]);
504                 gl.setColumns(localGrid[1]);
505                 gl.setHgap(padding[0]);
506                 gl.setVgap(padding[1]);
507
508                 validate();
509                 break;
510             }
511             case __GO_BORDER_OPT_PADDING__: {
512                 Integer layout = (Integer) GraphicController.getController().getProperty(getId(), __GO_LAYOUT__);
513                 LayoutType layoutType = LayoutType.intToEnum(layout);
514
515                 if (layoutType != LayoutType.BORDER) {
516                     break;
517                 }
518
519                 invalidate();
520
521                 Integer[] padding = (Integer[])value;
522                 BorderLayout bl = (BorderLayout)getLayout();
523                 bl.setHgap(padding[0]);
524                 bl.setVgap(padding[1]);
525
526                 validate();
527                 break;
528             }
529             case __GO_VISIBLE__ : {
530                 boolean needUpdate = true;
531                 Component parent = getParent();
532                 if (parent instanceof SwingScilabLayer) {
533                     //no no no don't touch visible on layer children !
534                     Boolean visible = (Boolean) value;
535                     SwingScilabLayer layer = (SwingScilabLayer) parent;
536                     Boolean isActive = layer.isLayerActive(this);
537                     if (isActive != visible) {
538                         controller.setProperty(uid, __GO_VISIBLE__, isActive);
539                     }
540
541                     needUpdate = false;
542                 } else if (parent instanceof SwingScilabTabGroup) {
543                     //no no no don't touch visible on layer children !
544                     Boolean visible = (Boolean) value;
545                     SwingScilabTabGroup layer = (SwingScilabTabGroup) parent;
546                     Boolean isActive = layer.isTabActive(this);
547                     if (isActive != visible) {
548                         controller.setProperty(uid, __GO_VISIBLE__, isActive);
549                     }
550
551                     needUpdate = false;
552                 }
553
554                 if (needUpdate) {
555                     setVisible(((Boolean) value).booleanValue());
556                 }
557
558                 break;
559             }
560             case __GO_TAG__ : {
561                 Component parent = getParent();
562                 if (parent instanceof SwingScilabLayer) {
563                     SwingScilabLayer layer = (SwingScilabLayer)parent;
564                     layer.updateModelProperties(null, layer.getActiveLayer());
565                 } else if (parent instanceof SwingScilabTabGroup) {
566                     ((SwingScilabTabGroup)parent).updateModelProperties();
567                 }
568                 break;
569             }
570             default:
571                 SwingViewWidget.update(this, property, value);
572                 break;
573         }
574     }
575
576     /**
577      * Set the enable status of the frame and its children
578      * @param status the status to set
579      */
580     public void setEnabled(boolean status) {
581         if (status) {
582             // Enable the frame
583             super.setEnabled(status);
584             panel.setEnabled(status);
585             // Enable its children according to their __GO_UI_ENABLE__ property
586             Integer[] children = (Integer[]) GraphicController.getController().getProperty(uid, __GO_CHILDREN__);
587             for (int kChild = 0; kChild < children.length; kChild++) {
588                 Integer type = (Integer)GraphicController.getController().getProperty(children[kChild], __GO_TYPE__);
589                 if (type == __GO_UICONTROL__) {
590                     Boolean childStatus = (Boolean) GraphicController.getController().getProperty(children[kChild], __GO_UI_ENABLE__);
591                     SwingView.getFromId(children[kChild]).update(__GO_UI_ENABLE__, childStatus);
592                 }
593             }
594         } else {
595             // Disable the frame
596             super.setEnabled(status);
597             panel.setEnabled(status);
598             // Disable its children
599             Component[] components = panel.getComponents();
600             for (int compIndex = 0; compIndex < components.length; compIndex++) {
601                 components[compIndex].setEnabled(false);
602             }
603         }
604
605         //if parent is a tab enable/disable children tab
606         Component parent = getParent();
607         if (parent instanceof SwingScilabTabGroup) {
608             SwingScilabTabGroup tab = (SwingScilabTabGroup)parent;
609             Integer index = tab.getIndex(this);
610             if (index != -1) {
611                 tab.setEnabledAt(index, status);
612             }
613         }
614     }
615
616     public void setLayout(LayoutManager layout) {
617         if (layout != null) {
618             if (layout instanceof ScrollPaneLayout) {
619                 super.setLayout(layout);
620             } else if (panel != null) {
621                 panel.setLayout(layout);
622             }
623         }
624     }
625
626     public LayoutManager getLayout() {
627         if (panel != null) {
628             return panel.getLayout();
629         }
630         return null;
631     }
632
633     public void setBorder(Border border) {
634         if (panel != null) {
635             panel.setBorder(border);
636         }
637     }
638
639     public Border getBorder() {
640         if (panel != null) {
641             return panel.getBorder();
642         }
643
644         return null;
645     }
646
647     public void setBackground(Color bg) {
648         if (panel != null) {
649             panel.setBackground(bg);
650         }
651     }
652
653     public void resetBackground() {
654         Color color = (Color)UIManager.getLookAndFeelDefaults().get("ScrollPane.background");
655         if (color != null) {
656             setBackground(color);
657         }
658     }
659
660     public void resetForeground() {
661         Color color = (Color)UIManager.getLookAndFeelDefaults().get("ScrollPane.foreground");
662         if (color != null) {
663             super.setForeground(color);
664         }
665     }
666 }