Disable ScrollableFrame should also disable children
[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.frame.SimpleFrame;
61 import org.scilab.modules.gui.menubar.MenuBar;
62 import org.scilab.modules.gui.textbox.TextBox;
63 import org.scilab.modules.gui.toolbar.ToolBar;
64 import org.scilab.modules.gui.utils.BorderConvertor;
65 import org.scilab.modules.gui.utils.Position;
66 import org.scilab.modules.gui.utils.PositionConverter;
67 import org.scilab.modules.gui.utils.ScilabRelief;
68 import org.scilab.modules.gui.utils.Size;
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, SimpleFrame {
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         getParent().remove(this);
368         this.setVisible(false);
369     }
370
371     /**
372      * Setter for InfoBar
373      * @param infoBarToAdd the InfoBar associated to the Frame.
374      */
375     public void addInfoBar(TextBox infoBarToAdd) {
376         /* Unimplemented for Frames */
377         throw new UnsupportedOperationException();
378     }
379
380     /**
381      * Getter for InfoBar
382      * @return the InfoBar associated to the Frame.
383      */
384     public TextBox getInfoBar() {
385         /* Unimplemented for Frames */
386         throw new UnsupportedOperationException();
387     }
388
389     /**
390      * Set the horizontal alignment for the Slider text
391      * @param alignment the value for the alignment (See ScilabAlignment.java)
392      */
393     public void setHorizontalAlignment(String alignment) {
394         // Nothing to do here
395     }
396
397     /**
398      * Set the vertical alignment for the Slider text
399      * @param alignment the value for the alignment (See ScilabAlignment.java)
400      */
401     public void setVerticalAlignment(String alignment) {
402         // Nothing to do here
403     }
404
405     /**
406      * Set the UID
407      * @param id the UID
408      */
409     public void setId(Integer id) {
410         uid = id;
411     }
412
413     /**
414      * Get the UID
415      * @return the UID
416      */
417     public Integer getId() {
418         return uid;
419     }
420
421     /**
422      * Generic update method
423      * @param property property name
424      * @param value property value
425      */
426     public void update(int property, Object value) {
427         GraphicController controller = GraphicController.getController();
428
429         switch (property) {
430             case __GO_UI_STRING__: {
431                 // Update tab title
432                 Container parent = getParent();
433                 if (parent instanceof SwingScilabTabGroup) {
434                     SwingScilabTabGroup tab = (SwingScilabTabGroup) parent;
435                     int index = tab.indexOfComponent(this);
436                     if (index != -1) {
437                         tab.setTitleAt(index, ((String[]) value)[0]);
438                     }
439                 }
440                 break;
441             }
442             case __GO_UI_FRAME_BORDER__: {
443                 Integer borderId = (Integer) value;
444                 Border border = BorderConvertor.getBorder(borderId);
445                 setBorder(border);
446                 break;
447             }
448             case __GO_LAYOUT__ : {
449                 LayoutType newLayout = LayoutType.intToEnum((Integer) value);
450
451                 invalidate();
452
453                 switch (newLayout) {
454                     case BORDER: {
455                         Integer[] padding = (Integer[]) controller.getProperty(getId(), __GO_BORDER_OPT_PADDING__);
456                         setLayout(new BorderLayout(padding[0], padding[1]));
457                         break;
458                     }
459                     case GRIDBAG:
460                         setLayout(new GridBagLayout());
461                         break;
462                     case GRID: {
463                         Integer[] padding = (Integer[]) controller.getProperty(getId(), __GO_GRID_OPT_PADDING__);
464                         Integer[] grid = (Integer[]) controller.getProperty(getId(), __GO_GRID_OPT_GRID__);
465                         if (grid[0] == 0 && grid[1] == 0) {
466                             grid[0] = 1;
467                         }
468                         setLayout(new GridLayout(grid[0], grid[1], padding[0], padding[1]));
469                         break;
470                     }
471                     case NONE:
472                     default: {
473                         setLayout(null);
474                         break;
475                     }
476                 }
477
478                 validate();
479                 break;
480             }
481             case __GO_GRID_OPT_PADDING__:
482             case __GO_GRID_OPT_GRID__: {
483                 Integer layout = (Integer) GraphicController.getController().getProperty(getId(), __GO_LAYOUT__);
484                 LayoutType layoutType = LayoutType.intToEnum(layout);
485
486                 if (layoutType != LayoutType.GRID) {
487                     break;
488                 }
489
490                 Integer[] padding = (Integer[]) GraphicController.getController().getProperty(getId(), __GO_GRID_OPT_PADDING__);
491
492                 Integer[] grid = (Integer[]) GraphicController.getController().getProperty(getId(), __GO_GRID_OPT_GRID__);
493                 Integer[] localGrid = new Integer[] { 0, 0 };
494                 localGrid[0] = grid[0];
495                 localGrid[1] = grid[1];
496
497                 if (localGrid[0] == 0 && localGrid[1] == 0) {
498                     localGrid[0] = 1;
499                 }
500
501                 invalidate();
502
503                 GridLayout gl = (GridLayout)getLayout();
504                 gl.setRows(localGrid[0]);
505                 gl.setColumns(localGrid[1]);
506                 gl.setHgap(padding[0]);
507                 gl.setVgap(padding[1]);
508
509                 validate();
510                 break;
511             }
512             case __GO_BORDER_OPT_PADDING__: {
513                 Integer layout = (Integer) GraphicController.getController().getProperty(getId(), __GO_LAYOUT__);
514                 LayoutType layoutType = LayoutType.intToEnum(layout);
515
516                 if (layoutType != LayoutType.BORDER) {
517                     break;
518                 }
519
520                 invalidate();
521
522                 Integer[] padding = (Integer[])value;
523                 BorderLayout bl = (BorderLayout)getLayout();
524                 bl.setHgap(padding[0]);
525                 bl.setVgap(padding[1]);
526
527                 validate();
528                 break;
529             }
530             case __GO_VISIBLE__ : {
531                 boolean needUpdate = true;
532                 Component parent = getParent();
533                 if (parent instanceof SwingScilabLayer) {
534                     //no no no don't touch visible on layer children !
535                     Boolean visible = (Boolean) value;
536                     SwingScilabLayer layer = (SwingScilabLayer) parent;
537                     Boolean isActive = layer.isLayerActive(this);
538                     if (isActive != visible) {
539                         controller.setProperty(uid, __GO_VISIBLE__, isActive);
540                     }
541
542                     needUpdate = false;
543                 } else if (parent instanceof SwingScilabTabGroup) {
544                     //no no no don't touch visible on layer children !
545                     Boolean visible = (Boolean) value;
546                     SwingScilabTabGroup layer = (SwingScilabTabGroup) parent;
547                     Boolean isActive = layer.isTabActive(this);
548                     if (isActive != visible) {
549                         controller.setProperty(uid, __GO_VISIBLE__, isActive);
550                     }
551
552                     needUpdate = false;
553                 }
554
555                 if (needUpdate) {
556                     setVisible(((Boolean) value).booleanValue());
557                 }
558
559                 break;
560             }
561             case __GO_TAG__ : {
562                 Component parent = getParent();
563                 if (parent instanceof SwingScilabLayer) {
564                     SwingScilabLayer layer = (SwingScilabLayer)parent;
565                     layer.updateModelProperties(null, layer.getActiveLayer());
566                 } else if (parent instanceof SwingScilabTabGroup) {
567                     ((SwingScilabTabGroup)parent).updateModelProperties();
568                 }
569                 break;
570             }
571             default:
572                 SwingViewWidget.update(this, property, value);
573                 break;
574         }
575     }
576
577     /**
578      * Set the enable status of the frame and its children
579      * @param status the status to set
580      */
581     public void setEnabled(boolean status) {
582         if (status) {
583             // Enable the frame
584             super.setEnabled(status);
585             panel.setEnabled(status);
586             // Enable its children according to their __GO_UI_ENABLE__ property
587             Integer[] children = (Integer[]) GraphicController.getController().getProperty(uid, __GO_CHILDREN__);
588             for (int kChild = 0; kChild < children.length; kChild++) {
589                 Integer type = (Integer)GraphicController.getController().getProperty(children[kChild], __GO_TYPE__);
590                 if (type == __GO_UICONTROL__) {
591                     Boolean childStatus = (Boolean) GraphicController.getController().getProperty(children[kChild], __GO_UI_ENABLE__);
592                     SwingView.getFromId(children[kChild]).update(__GO_UI_ENABLE__, childStatus);
593                 }
594             }
595         } else {
596             // Disable the frame
597             super.setEnabled(status);
598             panel.setEnabled(status);
599             // Disable its children
600             Component[] components = panel.getComponents();
601             for (int compIndex = 0; compIndex < components.length; compIndex++) {
602                 components[compIndex].setEnabled(false);
603             }
604         }
605
606         //if parent is a tab enable/disable children tab
607         Component parent = getParent();
608         if (parent instanceof SwingScilabTabGroup) {
609             SwingScilabTabGroup tab = (SwingScilabTabGroup)parent;
610             Integer index = tab.getIndex(this);
611             if (index != -1) {
612                 tab.setEnabledAt(index, status);
613             }
614         }
615     }
616
617     public void setLayout(LayoutManager layout) {
618         if (layout != null) {
619             if (layout instanceof ScrollPaneLayout) {
620                 super.setLayout(layout);
621             } else if (panel != null) {
622                 panel.setLayout(layout);
623             }
624         }
625     }
626
627     public LayoutManager getLayout() {
628         if (panel != null) {
629             return panel.getLayout();
630         }
631         return null;
632     }
633
634     public void setBorder(Border border) {
635         if (panel != null) {
636             panel.setBorder(border);
637         }
638     }
639
640     public Border getBorder() {
641         if (panel != null) {
642             return panel.getBorder();
643         }
644
645         return null;
646     }
647
648     public void setBackground(Color bg) {
649         if (panel != null) {
650             panel.setBackground(bg);
651         }
652     }
653
654     public void resetBackground() {
655         Color color = (Color)UIManager.getLookAndFeelDefaults().get("ScrollPane.background");
656         if (color != null) {
657             setBackground(color);
658         }
659     }
660
661     public void resetForeground() {
662         Color color = (Color)UIManager.getLookAndFeelDefaults().get("ScrollPane.foreground");
663         if (color != null) {
664             super.setForeground(color);
665         }
666     }
667 }