better management of frame borders
[scilab.git] / scilab / modules / gui / src / java / org / scilab / modules / gui / bridge / tab / SwingScilabCommonPanel.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2014 - Scilab Enterprises - Bruno JOFRET
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  *
11  */
12 package org.scilab.modules.gui.bridge.tab;
13
14 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_AUTORESIZE__;
15 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_AXES_SIZE__;
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_CALLBACK__;
18 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_CHILDREN__;
19 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_EVENTHANDLER_ENABLE__;
20 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_EVENTHANDLER_NAME__;
21 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_GRID_OPT_GRID__;
22 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_GRID_OPT_PADDING__;
23 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_ID__;
24 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_INFOBAR_VISIBLE__;
25 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_INFO_MESSAGE__;
26 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_LAYOUT__;
27 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_MENUBAR_VISIBLE__;
28 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_NAME__;
29 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_POSITION__;
30 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_RESIZE__;
31 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_SIZE__;
32 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_TOOLBAR_VISIBLE__;
33 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_TYPE__;
34 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UICHECKEDMENU__;
35 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UICHILDMENU__;
36 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UIMENU__;
37 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_UIPARENTMENU__;
38 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_VISIBLE__;
39
40 import java.awt.BorderLayout;
41 import java.awt.Component;
42 import java.awt.Dimension;
43 import java.awt.GridBagConstraints;
44 import java.awt.GridBagLayout;
45 import java.awt.GridLayout;
46
47 import javax.swing.JLayeredPane;
48
49 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
50 import org.scilab.modules.graphic_objects.graphicModel.GraphicModel;
51 import org.scilab.modules.graphic_objects.uicontrol.Uicontrol;
52 import org.scilab.modules.graphic_objects.utils.LayoutType;
53 import org.scilab.modules.gui.SwingView;
54 import org.scilab.modules.gui.SwingViewObject;
55 import org.scilab.modules.gui.bridge.frame.SwingScilabFrame;
56 import org.scilab.modules.gui.bridge.window.SwingScilabWindow;
57 import org.scilab.modules.gui.events.callback.ScilabCloseCallBack;
58 import org.scilab.modules.gui.utils.Position;
59 import org.scilab.modules.gui.utils.Size;
60 import org.scilab.modules.gui.utils.ToolBarBuilder;
61
62 public class SwingScilabCommonPanel {
63
64     public static final String GRAPHICS_TOOLBAR_DESCRIPTOR = System.getenv("SCI") + "/modules/gui/etc/graphics_toolbar.xml";
65
66     /**
67      * Update the tab after a modification of its properties
68      * @param property the property name
69      * @param value the property value
70      * @see org.scilab.modules.gui.SwingViewObject#update(java.lang.String, java.lang.Object)
71      */
72     protected static void update(SwingScilabPanel component, int property, Object value) {
73         String name;
74         Integer figureId;
75         switch (property) {
76             case  __GO_NAME__ :
77                 name = ((String) value);
78                 figureId = (Integer) GraphicController.getController().getProperty(component.getId(), __GO_ID__);
79                 updateTitle(component, name, figureId);
80                 break;
81             case __GO_ID__ :
82                 /* Update title */
83                 figureId = ((Integer) value);
84                 name = (String) GraphicController.getController().getProperty(component.getId(), __GO_NAME__);
85                 updateTitle(component, name, figureId);
86
87                 /** Update tool bar */
88                 component.setToolBar(ToolBarBuilder.buildToolBar(GRAPHICS_TOOLBAR_DESCRIPTOR, figureId));
89                 SwingScilabWindow parentWindow = SwingScilabWindow.allScilabWindows.get(component.getParentWindowId());
90
91                 /* Update callback */
92                 String closingCommand =
93                     "if (get_figure_handle(" + figureId + ") <> []) then"
94                     +      "  if (get(get_figure_handle(" + figureId + "), 'event_handler_enable') == 'on') then"
95                     +      "    execstr(get(get_figure_handle(" + figureId + "), 'event_handler')+'(" + figureId + ", -1, -1, -1000)', 'errcatch', 'm');"
96                     +      "  end;"
97                     +      "  delete(get_figure_handle(" + figureId + "));"
98                     +      "end;";
99                 component.setCallback(null);
100                 component.setCallback(ScilabCloseCallBack.create(component.getId(), closingCommand));
101                 /* Update menus callback */
102                 Integer[] children = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_CHILDREN__);
103                 updateChildrenCallbacks(children, figureId);
104                 break;
105             case __GO_SIZE__ :
106                 Integer[] size = (Integer[]) value;
107                 SwingScilabWindow figure = SwingScilabWindow.allScilabWindows.get(component.getParentWindowId());
108                 Size oldFigureSize = figure.getDims();
109                 figure.setDims(new Size(size[0], size[1]));
110                 int deltaFigureX = size[0] - oldFigureSize.getWidth();
111                 int deltaFigureY = size[1] - oldFigureSize.getHeight();
112                 if ( oldFigureSize.getWidth() != 0 && oldFigureSize.getHeight() != 0
113                         && ((oldFigureSize.getWidth() != size[0]) || (oldFigureSize.getHeight() != size[1]))
114                         && ((Boolean) GraphicController.getController().getProperty(component.getId(), __GO_AUTORESIZE__))
115                    ) {
116                     Integer[] axesSize = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_AXES_SIZE__);
117                     Integer[] newAxesSize = {axesSize[0] + deltaFigureX, axesSize[1] + deltaFigureY};
118                     GraphicController.getController().setProperty(component.getId(), __GO_AXES_SIZE__, newAxesSize);
119                 }
120                 break;
121             case __GO_POSITION__ :
122                 Integer[] position = (Integer[]) value;
123                 SwingScilabWindow.allScilabWindows.get(component.getParentWindowId()).setPosition(new Position(position[0], position[1]));
124                 break;
125             case __GO_AXES_SIZE__ :
126                 Integer[] axesSize = (Integer[]) value;
127                 Dimension oldAxesSize = component.getContentPane().getSize();
128                 if ( oldAxesSize.getWidth() != 0 && oldAxesSize.getHeight() != 0
129                         && ((oldAxesSize.getWidth() != axesSize[0]) || (oldAxesSize.getHeight() != axesSize[1]))
130                         && ((Boolean) GraphicController.getController().getProperty(component.getId(), __GO_AUTORESIZE__))
131                    ) {
132                     // TODO manage tabs when there are docked (do not change the window size if more than one tab docked)
133                     int deltaX = axesSize[0] - (int) oldAxesSize.getWidth();
134                     int deltaY = axesSize[1] - (int) oldAxesSize.getHeight();
135                     Size parentWindowSize = SwingScilabWindow.allScilabWindows.get(component.getParentWindowId()).getDims();
136                     SwingScilabWindow.allScilabWindows.get(component.getParentWindowId()).setDims(
137                         new Size(parentWindowSize.getWidth() + deltaX, parentWindowSize.getHeight() + deltaY));
138                     Integer figureSize[] = {parentWindowSize.getWidth() + deltaX, parentWindowSize.getHeight() + deltaY};
139                     GraphicController.getController().setProperty(component.getId(), __GO_SIZE__, figureSize);
140                 }
141                 break;
142             case __GO_INFO_MESSAGE__ :
143                 if (component.getInfoBar() != null) {
144                     component.getInfoBar().setText((String) value);
145                 }
146                 break;
147             case __GO_EVENTHANDLER_ENABLE__ :
148                 Boolean enabled = (Boolean) GraphicController.getController().getProperty(component.getId(), __GO_EVENTHANDLER_ENABLE__);
149                 component. setEventHandlerEnabled(enabled);
150                 break;
151             case __GO_EVENTHANDLER_NAME__ :
152                 String eventHandlerName = (String) GraphicController.getController().getProperty(component.getId(), __GO_EVENTHANDLER_NAME__);
153                 component.setEventHandler(eventHandlerName);
154                 break;
155             case __GO_VISIBLE__ :
156                 component.getContentPane().setVisible((Boolean) value);
157                 if (component.getParentWindow().getNbDockedObjects() == 1) {
158                     component.getParentWindow().setVisible((Boolean) value);
159                 }
160                 break;
161             case __GO_INFOBAR_VISIBLE__ :
162                 component.getInfoBar().setVisible((Boolean) value);
163                 break;
164             case __GO_TOOLBAR_VISIBLE__ :
165                 component.getToolBar().setVisible((Boolean) value);
166                 break;
167             case __GO_MENUBAR_VISIBLE__ :
168                 component.getMenuBar().setVisible((Boolean) value);
169                 break;
170             case __GO_RESIZE__ :
171                 component.getParentWindow().setResizable((Boolean) value);
172                 break;
173             case __GO_LAYOUT__ :
174                 LayoutType newLayout = LayoutType.intToEnum((Integer) value);
175                 switch (newLayout) {
176                     case BORDER : {
177                         Integer[] padding = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_BORDER_OPT_PADDING__);
178                         component.getWidgetPane().setLayout(new BorderLayout(padding[0], padding[1]));
179                         component.getWidgetPane().setLayout(new BorderLayout());
180                         break;
181                     }
182                     case GRIDBAG : {
183                         component.getWidgetPane().setLayout(new GridBagLayout());
184                         break;
185                     }
186                     case GRID : {
187                         Integer[] padding = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_GRID_OPT_PADDING__);
188                         Integer[] grid = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_GRID_OPT_GRID__);
189                         if (grid[0] == 0 && grid[1] == 0) {
190                             grid[0] = 1;
191                         }
192                         component.getWidgetPane().setLayout(new GridLayout(grid[0], grid[1], padding[0], padding[1]));
193                         break;
194                     }
195                     case NONE :
196                     default:
197                         component.getWidgetPane().setLayout(null);
198                         break;
199                 }
200                 break;
201             case __GO_GRID_OPT_PADDING__ :
202             case __GO_GRID_OPT_GRID__ : {
203                 Integer layout = (Integer) GraphicController.getController().getProperty(component.getId(), __GO_LAYOUT__);
204                 LayoutType layoutType = LayoutType.intToEnum(layout);
205
206                 if (layoutType != LayoutType.GRID) {
207                     break;
208                 }
209
210                 Integer[] padding = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_GRID_OPT_PADDING__);
211                 Integer[] grid = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_GRID_OPT_GRID__);
212                 if (grid[0] == 0 && grid[1] == 0) {
213                     grid[0] = 1;
214                 }
215                 component.getWidgetPane().setLayout(new GridLayout(grid[0], grid[1], padding[0], padding[1]));
216                 break;
217             }
218             case __GO_BORDER_OPT_PADDING__ : {
219                 Integer layout = (Integer) GraphicController.getController().getProperty(component.getId(), __GO_LAYOUT__);
220                 LayoutType layoutType = LayoutType.intToEnum(layout);
221
222                 if (layoutType != LayoutType.BORDER) {
223                     break;
224                 }
225
226                 Integer[] padding = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_BORDER_OPT_PADDING__);
227                 component.getWidgetPane().setLayout(new BorderLayout(padding[0], padding[1]));
228                 component.getWidgetPane().setLayout(new BorderLayout());
229             }
230         }
231     }
232
233     /**
234      * Update the title of the Tab
235      * @param figureName figure_name property
236      * @param figureId figure_id property
237      */
238     private static void updateTitle(SwingScilabPanel component, String figureName, Integer figureId) {
239         if ((figureName != null) && (figureId != null)) {
240             String figureTitle = figureName.replaceFirst("%d", figureId.toString());
241             component.setName(figureTitle);
242         }
243     }
244
245     /**
246      * Update the menus callbacks when they are linked to the figure ID
247      * @param children the children UID
248      * @param parentFigureId the figure ID
249      */
250     private static void updateChildrenCallbacks(Integer[] children, int parentFigureId) {
251         for (int kChild = 0; kChild < children.length; kChild++) {
252             Integer childType = (Integer) GraphicController.getController().getProperty(children[kChild], __GO_TYPE__);
253             if (childType != null && (
254                         childType == __GO_UIMENU__
255                         || childType == __GO_UIPARENTMENU__
256                         || childType == __GO_UICHILDMENU__
257                         || childType == __GO_UICHECKEDMENU__)) {
258                 String cb = (String) GraphicController.getController().getProperty(children[kChild], __GO_CALLBACK__);
259                 SwingView.getFromId(children[kChild]).update(__GO_CALLBACK__, replaceFigureID(cb, parentFigureId));
260                 Integer[] menuChildren = (Integer[]) GraphicController.getController().getProperty(children[kChild], __GO_CHILDREN__);
261                 updateChildrenCallbacks(menuChildren, parentFigureId);
262             }
263         }
264     }
265
266     /**
267      * Replace pattern [SCILAB_FIGURE_ID] by the figure index
268      * @param initialString string read in XML file
269      * @param parentFigureId the figure ID
270      * @return callback string
271      */
272     private static String replaceFigureID(String initialString, Integer parentFigureId) {
273         return initialString.replaceAll("\\[SCILAB_FIGURE_ID\\]", Integer.toString(parentFigureId));
274     }
275
276     /**
277      * Add a SwingViewObject (from SwingView.java) to container and returns its index
278      * @param member the member to add
279      */
280     protected static void addMember(SwingScilabPanel component, SwingViewObject member) {
281         //member.get
282         Uicontrol uicontrol = (Uicontrol) GraphicModel.getModel().getObjectFromId(member.getId());
283         if (component.getWidgetPane().getLayout() instanceof BorderLayout) {
284             switch (uicontrol.getBorderPositionAsEnum()) {
285                 case BOTTOM:
286                     component.getWidgetPane().add((Component) member, BorderLayout.SOUTH);
287                     break;
288                 case TOP:
289                     component.getWidgetPane().add((Component) member, BorderLayout.NORTH);
290                     break;
291                 case LEFT:
292                     component.getWidgetPane().add((Component) member, BorderLayout.WEST);
293                     break;
294                 case RIGHT:
295                     component.getWidgetPane().add((Component) member, BorderLayout.EAST);
296                     break;
297                 case CENTER:
298                     component.getWidgetPane().add((Component) member, BorderLayout.CENTER);
299                     break;
300                 default:
301                     break;
302             }
303         } else if (component.getWidgetPane().getLayout() instanceof GridBagLayout) {
304             GridBagConstraints constraints = new GridBagConstraints();
305
306             // Grid
307             Integer[] grid = uicontrol.getGridBagGrid();
308             constraints.gridx = grid[0];
309             constraints.gridy = grid[1];
310             constraints.gridwidth = grid[2];
311             constraints.gridheight = grid[3];
312
313             // Weight
314             Double[] weight = uicontrol.getGridBagWeight();
315             constraints.weightx = weight[0];
316             constraints.weighty = weight[1];
317
318             // Anchor
319             switch (uicontrol.getGridBagAnchorAsEnum()) {
320                 case LEFT :
321                     constraints.anchor = GridBagConstraints.EAST;
322                     break;
323                 case UPPER :
324                     constraints.anchor = GridBagConstraints.NORTH;
325                     break;
326                 case LOWER:
327                     constraints.anchor = GridBagConstraints.SOUTH;
328                     break;
329                 case LOWER_LEFT:
330                     constraints.anchor = GridBagConstraints.SOUTHEAST;
331                     break;
332                 case LOWER_RIGHT:
333                     constraints.anchor = GridBagConstraints.SOUTHWEST;
334                     break;
335                 case RIGHT:
336                     constraints.anchor = GridBagConstraints.WEST;
337                     break;
338                 case UPPER_LEFT:
339                     constraints.anchor = GridBagConstraints.NORTHEAST;
340                     break;
341                 case UPPER_RIGHT:
342                     constraints.anchor = GridBagConstraints.NORTHWEST;
343                     break;
344                 case CENTER :
345                 default :
346                     constraints.anchor = GridBagConstraints.CENTER;
347                     break;
348             }
349
350             // Fill
351             switch (uicontrol.getGridBagFillAsEnum()) {
352                 case BOTH :
353                     constraints.fill = GridBagConstraints.BOTH;
354                     break;
355                 case HORIZONTAL:
356                     constraints.fill = GridBagConstraints.HORIZONTAL;
357                     break;
358                 case VERTICAL:
359                     constraints.fill = GridBagConstraints.VERTICAL;
360                     break;
361                 case NONE:
362                 default:
363                     constraints.fill = GridBagConstraints.NONE;
364                     break;
365             }
366
367             // Insets
368             // TODO : add Insets
369
370             // Padding
371             Integer[] padding = uicontrol.getGridBagPadding();
372             constraints.ipadx = padding[0];
373             constraints.ipady = padding[1];
374
375             component.getWidgetPane().add((Component) member, constraints);
376             component.getWidgetPane().revalidate();
377         } else {
378             if (member instanceof SwingScilabFrame) {
379                 component.getWidgetPane().add((Component) member, JLayeredPane.FRAME_CONTENT_LAYER);
380             } else {
381                 component.getWidgetPane().add((Component) member, JLayeredPane.DEFAULT_LAYER + 1);
382             }
383         }
384     }
385     
386     protected static void  removeMember(SwingScilabPanel component,SwingViewObject member) {
387         component.getWidgetPane().remove((Component) member);
388     }
389 }