set missing insets/margins in SwingView
[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_UI_ICON__;
39 import static org.scilab.modules.graphic_objects.graphicObject.GraphicObjectProperties.__GO_VISIBLE__;
40
41 import java.awt.BorderLayout;
42 import java.awt.Component;
43 import java.awt.Dimension;
44 import java.awt.GridBagConstraints;
45 import java.awt.GridBagLayout;
46 import java.awt.GridLayout;
47 import java.awt.Insets;
48 import java.awt.image.BufferedImage;
49 import java.io.File;
50 import java.io.IOException;
51
52 import javax.imageio.ImageIO;
53 import javax.swing.ImageIcon;
54 import javax.swing.JLayeredPane;
55
56 import org.scilab.modules.commons.gui.FindIconHelper;
57 import org.scilab.modules.graphic_objects.figure.Figure;
58 import org.scilab.modules.graphic_objects.figure.Figure.BarType;
59 import org.scilab.modules.graphic_objects.graphicController.GraphicController;
60 import org.scilab.modules.graphic_objects.graphicModel.GraphicModel;
61 import org.scilab.modules.graphic_objects.uicontrol.Uicontrol;
62 import org.scilab.modules.graphic_objects.utils.LayoutType;
63 import org.scilab.modules.gui.SwingView;
64 import org.scilab.modules.gui.SwingViewObject;
65 import org.scilab.modules.gui.bridge.frame.SwingScilabFrame;
66 import org.scilab.modules.gui.bridge.frame.SwingScilabScrollableFrame;
67 import org.scilab.modules.gui.bridge.window.SwingScilabWindow;
68 import org.scilab.modules.gui.events.callback.ScilabCloseCallBack;
69 import org.scilab.modules.gui.toolbar.ToolBar;
70 import org.scilab.modules.gui.utils.Position;
71 import org.scilab.modules.gui.utils.Size;
72 import org.scilab.modules.gui.utils.ToolBarBuilder;
73
74 public class SwingScilabCommonPanel {
75
76     public static final String GRAPHICS_TOOLBAR_DESCRIPTOR = System.getenv("SCI") + "/modules/gui/etc/graphics_toolbar.xml";
77
78     /**
79      * Update the tab after a modification of its properties
80      * @param property the property name
81      * @param value the property value
82      * @see org.scilab.modules.gui.SwingViewObject#update(java.lang.String, java.lang.Object)
83      */
84     protected static void update(SwingScilabPanel component, int property, Object value) {
85         String name;
86         Integer figureId;
87         switch (property) {
88             case  __GO_NAME__ :
89                 name = ((String) value);
90                 figureId = (Integer) GraphicController.getController().getProperty(component.getId(), __GO_ID__);
91                 updateTitle(component, name, figureId);
92                 break;
93             case __GO_ID__ :
94                 /* Update title */
95                 figureId = ((Integer) value);
96                 Figure localFigure = (Figure) GraphicController.getController().getObjectFromId(component.getId());
97                 name = localFigure.getName();
98                 updateTitle(component, name, figureId);
99
100                 /** Update tool bar */
101                 if (localFigure.getToolbarAsEnum() == BarType.FIGURE) {
102                     SwingScilabWindow parentWindow = SwingScilabWindow.allScilabWindows.get(component.getParentWindowId());
103                     ToolBar toolbar = ToolBarBuilder.buildToolBar(GRAPHICS_TOOLBAR_DESCRIPTOR, figureId);
104                     toolbar.setVisible(localFigure.getToolbarVisible());
105                     component.setToolBar(toolbar);
106                     parentWindow.addToolBar(toolbar);
107                 }
108
109                 /* Update callback */
110                 String closingCommand =
111                     "if (get_figure_handle(" + figureId + ") <> []) then"
112                     +      "  if (get(get_figure_handle(" + figureId + "), 'event_handler_enable') == 'on') then"
113                     +      "    execstr(get(get_figure_handle(" + figureId + "), 'event_handler')+'(" + figureId + ", -1, -1, -1000)', 'errcatch', 'm');"
114                     +      "  end;"
115                     +      "  delete(get_figure_handle(" + figureId + "));"
116                     +      "end;";
117                 component.setCallback(null);
118                 component.setCallback(ScilabCloseCallBack.create(component.getId(), closingCommand));
119                 /* Update menus callback */
120                 Integer[] children = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_CHILDREN__);
121                 updateChildrenCallbacks(children, figureId);
122                 break;
123             case __GO_SIZE__ :
124                 Integer[] size = (Integer[]) value;
125                 SwingScilabWindow figure = SwingScilabWindow.allScilabWindows.get(component.getParentWindowId());
126                 Size oldFigureSize = figure.getDims();
127                 figure.setDims(new Size(size[0], size[1]));
128                 int deltaFigureX = size[0] - oldFigureSize.getWidth();
129                 int deltaFigureY = size[1] - oldFigureSize.getHeight();
130                 if ( oldFigureSize.getWidth() != 0 && oldFigureSize.getHeight() != 0
131                         && ((oldFigureSize.getWidth() != size[0]) || (oldFigureSize.getHeight() != size[1]))
132                         && ((Boolean) GraphicController.getController().getProperty(component.getId(), __GO_AUTORESIZE__))
133                    ) {
134                     Integer[] axesSize = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_AXES_SIZE__);
135                     Integer[] newAxesSize = {axesSize[0] + deltaFigureX, axesSize[1] + deltaFigureY};
136                     GraphicController.getController().setProperty(component.getId(), __GO_AXES_SIZE__, newAxesSize);
137                 }
138                 break;
139             case __GO_POSITION__ :
140                 Integer[] position = (Integer[]) value;
141                 SwingScilabWindow.allScilabWindows.get(component.getParentWindowId()).setPosition(new Position(position[0], position[1]));
142                 break;
143             case __GO_AXES_SIZE__ :
144                 Integer[] axesSize = (Integer[]) value;
145                 Dimension oldAxesSize = component.getContentPane().getSize();
146                 if ( oldAxesSize.getWidth() != 0 && oldAxesSize.getHeight() != 0
147                         && ((oldAxesSize.getWidth() != axesSize[0]) || (oldAxesSize.getHeight() != axesSize[1]))
148                         && ((Boolean) GraphicController.getController().getProperty(component.getId(), __GO_AUTORESIZE__))
149                    ) {
150                     // TODO manage tabs when there are docked (do not change the window size if more than one tab docked)
151                     int deltaX = axesSize[0] - (int) oldAxesSize.getWidth();
152                     int deltaY = axesSize[1] - (int) oldAxesSize.getHeight();
153                     Size parentWindowSize = SwingScilabWindow.allScilabWindows.get(component.getParentWindowId()).getDims();
154                     SwingScilabWindow.allScilabWindows.get(component.getParentWindowId()).setDims(
155                         new Size(parentWindowSize.getWidth() + deltaX, parentWindowSize.getHeight() + deltaY));
156                     Integer figureSize[] = {parentWindowSize.getWidth() + deltaX, parentWindowSize.getHeight() + deltaY};
157                     GraphicController.getController().setProperty(component.getId(), __GO_SIZE__, figureSize);
158                 }
159                 break;
160             case __GO_INFO_MESSAGE__ :
161                 if (component.getInfoBar() != null) {
162                     component.getInfoBar().setText((String) value);
163                 }
164                 break;
165             case __GO_EVENTHANDLER_ENABLE__ :
166                 Boolean enabled = (Boolean) GraphicController.getController().getProperty(component.getId(), __GO_EVENTHANDLER_ENABLE__);
167                 component. setEventHandlerEnabled(enabled);
168                 break;
169             case __GO_EVENTHANDLER_NAME__ :
170                 String eventHandlerName = (String) GraphicController.getController().getProperty(component.getId(), __GO_EVENTHANDLER_NAME__);
171                 component.setEventHandler(eventHandlerName);
172                 break;
173             case __GO_VISIBLE__ :
174                 component.getContentPane().setVisible((Boolean) value);
175                 if (component.getParentWindow().getNbDockedObjects() == 1) {
176                     component.getParentWindow().setVisible((Boolean) value);
177                 }
178                 break;
179             case __GO_INFOBAR_VISIBLE__ :
180                 component.getInfoBar().setVisible((Boolean) value);
181                 break;
182             case __GO_TOOLBAR_VISIBLE__ :
183                 component.getToolBar().setVisible((Boolean) value);
184                 break;
185             case __GO_MENUBAR_VISIBLE__ :
186                 component.getMenuBar().setVisible((Boolean) value);
187                 break;
188             case __GO_RESIZE__ :
189                 component.getParentWindow().setResizable((Boolean) value);
190                 break;
191             case __GO_LAYOUT__ :
192                 LayoutType newLayout = LayoutType.intToEnum((Integer) value);
193                 switch (newLayout) {
194                     case BORDER : {
195                         Integer[] padding = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_BORDER_OPT_PADDING__);
196                         component.getWidgetPane().setLayout(new BorderLayout(padding[0], padding[1]));
197                         component.getWidgetPane().setLayout(new BorderLayout());
198                         break;
199                     }
200                     case GRIDBAG : {
201                         component.getWidgetPane().setLayout(new GridBagLayout());
202                         break;
203                     }
204                     case GRID : {
205                         Integer[] padding = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_GRID_OPT_PADDING__);
206                         Integer[] grid = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_GRID_OPT_GRID__);
207                         Integer[] localGrid = new Integer[] {0, 0};
208                         localGrid[0] = grid[0];
209                         localGrid[1] = grid[1];
210
211                         if (localGrid[0] == 0 && localGrid[1] == 0) {
212                             localGrid[0] = 1;
213                         }
214
215                         component.getWidgetPane().setLayout(new GridLayout(localGrid[0], localGrid[1], padding[0], padding[1]));
216                         break;
217                     }
218                     case NONE :
219                     default:
220                         component.getWidgetPane().setLayout(null);
221                         break;
222                 }
223                 break;
224             case __GO_GRID_OPT_PADDING__ :
225             case __GO_GRID_OPT_GRID__ : {
226                 Integer layout = (Integer) GraphicController.getController().getProperty(component.getId(), __GO_LAYOUT__);
227                 LayoutType layoutType = LayoutType.intToEnum(layout);
228
229                 if (layoutType != LayoutType.GRID) {
230                     break;
231                 }
232
233                 Integer[] padding = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_GRID_OPT_PADDING__);
234
235                 Integer[] grid = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_GRID_OPT_GRID__);
236                 Integer[] localGrid = new Integer[] {0, 0};
237                 localGrid[0] = grid[0];
238                 localGrid[1] = grid[1];
239
240                 if (localGrid[0] == 0 && localGrid[1] == 0) {
241                     localGrid[0] = 1;
242                 }
243
244                 component.getWidgetPane().setLayout(new GridLayout(localGrid[0], localGrid[1], padding[0], padding[1]));
245                 break;
246             }
247             case __GO_BORDER_OPT_PADDING__ : {
248                 Integer layout = (Integer) GraphicController.getController().getProperty(component.getId(), __GO_LAYOUT__);
249                 LayoutType layoutType = LayoutType.intToEnum(layout);
250
251                 if (layoutType != LayoutType.BORDER) {
252                     break;
253                 }
254
255                 Integer[] padding = (Integer[]) GraphicController.getController().getProperty(component.getId(), __GO_BORDER_OPT_PADDING__);
256                 component.getWidgetPane().setLayout(new BorderLayout(padding[0], padding[1]));
257                 component.getWidgetPane().setLayout(new BorderLayout());
258                 break;
259             }
260             case __GO_UI_ICON__ : {
261                 File file = new File((String)value);
262                 if (file.exists() == false) {
263                     String filename = FindIconHelper.findImage((String)value);
264                     file = new File(filename);
265                 }
266
267                 try {
268                     BufferedImage icon = ImageIO.read(file);
269                     component.getParentWindow().setIconImage(new ImageIcon(icon).getImage());
270                 } catch (IOException e) {
271                 }
272                 break;
273             }
274         }
275     }
276
277     /**
278      * Update the title of the Tab
279      * @param figureName figure_name property
280      * @param figureId figure_id property
281      */
282     private static void updateTitle(SwingScilabPanel component, String figureName, Integer figureId) {
283         if ((figureName != null) && (figureId != null)) {
284             String figureTitle = figureName.replaceFirst("%d", figureId.toString());
285             component.setName(figureTitle);
286         }
287     }
288
289     /**
290      * Update the menus callbacks when they are linked to the figure ID
291      * @param children the children UID
292      * @param parentFigureId the figure ID
293      */
294     private static void updateChildrenCallbacks(Integer[] children, int parentFigureId) {
295         for (int kChild = 0; kChild < children.length; kChild++) {
296             Integer childType = (Integer) GraphicController.getController().getProperty(children[kChild], __GO_TYPE__);
297             if (childType != null && (
298                         childType == __GO_UIMENU__
299                         || childType == __GO_UIPARENTMENU__
300                         || childType == __GO_UICHILDMENU__
301                         || childType == __GO_UICHECKEDMENU__)) {
302                 String cb = (String) GraphicController.getController().getProperty(children[kChild], __GO_CALLBACK__);
303                 SwingView.getFromId(children[kChild]).update(__GO_CALLBACK__, replaceFigureID(cb, parentFigureId));
304                 Integer[] menuChildren = (Integer[]) GraphicController.getController().getProperty(children[kChild], __GO_CHILDREN__);
305                 updateChildrenCallbacks(menuChildren, parentFigureId);
306             }
307         }
308     }
309
310     /**
311      * Replace pattern [SCILAB_FIGURE_ID] by the figure index
312      * @param initialString string read in XML file
313      * @param parentFigureId the figure ID
314      * @return callback string
315      */
316     private static String replaceFigureID(String initialString, Integer parentFigureId) {
317         return initialString.replaceAll("\\[SCILAB_FIGURE_ID\\]", Integer.toString(parentFigureId));
318     }
319
320     /**
321      * Add a SwingViewObject (from SwingView.java) to container and returns its index
322      * @param member the member to add
323      */
324     protected static void addMember(SwingScilabPanel component, SwingViewObject member) {
325         //member.get
326         Uicontrol uicontrol = (Uicontrol) GraphicModel.getModel().getObjectFromId(member.getId());
327         if (component.getWidgetPane().getLayout() instanceof BorderLayout) {
328             switch (uicontrol.getBorderPositionAsEnum()) {
329                 case BOTTOM:
330                     component.getWidgetPane().add((Component) member, BorderLayout.SOUTH);
331                     break;
332                 case TOP:
333                     component.getWidgetPane().add((Component) member, BorderLayout.NORTH);
334                     break;
335                 case LEFT:
336                     component.getWidgetPane().add((Component) member, BorderLayout.WEST);
337                     break;
338                 case RIGHT:
339                     component.getWidgetPane().add((Component) member, BorderLayout.EAST);
340                     break;
341                 case CENTER:
342                     component.getWidgetPane().add((Component) member, BorderLayout.CENTER);
343                     break;
344                 default:
345                     break;
346             }
347
348             Integer[] preferredSize = uicontrol.getBorderPreferredSize();
349             if (preferredSize[0].equals(-1) == false && preferredSize[1].equals(-1) == false) {
350                 ((Component) member).setPreferredSize(new Dimension(preferredSize[0], preferredSize[1]));
351             }
352         } else if (component.getWidgetPane().getLayout() instanceof GridBagLayout) {
353             GridBagConstraints constraints = new GridBagConstraints();
354
355             // Grid
356             Integer[] grid = uicontrol.getGridBagGrid();
357             constraints.gridx = grid[0];
358             constraints.gridy = grid[1];
359             constraints.gridwidth = grid[2];
360             constraints.gridheight = grid[3];
361
362             // Weight
363             Double[] weight = uicontrol.getGridBagWeight();
364             constraints.weightx = weight[0];
365             constraints.weighty = weight[1];
366
367             // Anchor
368             switch (uicontrol.getGridBagAnchorAsEnum()) {
369                 case LEFT :
370                     constraints.anchor = GridBagConstraints.EAST;
371                     break;
372                 case UPPER :
373                     constraints.anchor = GridBagConstraints.NORTH;
374                     break;
375                 case LOWER:
376                     constraints.anchor = GridBagConstraints.SOUTH;
377                     break;
378                 case LOWER_LEFT:
379                     constraints.anchor = GridBagConstraints.SOUTHEAST;
380                     break;
381                 case LOWER_RIGHT:
382                     constraints.anchor = GridBagConstraints.SOUTHWEST;
383                     break;
384                 case RIGHT:
385                     constraints.anchor = GridBagConstraints.WEST;
386                     break;
387                 case UPPER_LEFT:
388                     constraints.anchor = GridBagConstraints.NORTHEAST;
389                     break;
390                 case UPPER_RIGHT:
391                     constraints.anchor = GridBagConstraints.NORTHWEST;
392                     break;
393                 case CENTER :
394                 default :
395                     constraints.anchor = GridBagConstraints.CENTER;
396                     break;
397             }
398
399             // Fill
400             switch (uicontrol.getGridBagFillAsEnum()) {
401                 case BOTH :
402                     constraints.fill = GridBagConstraints.BOTH;
403                     break;
404                 case HORIZONTAL:
405                     constraints.fill = GridBagConstraints.HORIZONTAL;
406                     break;
407                 case VERTICAL:
408                     constraints.fill = GridBagConstraints.VERTICAL;
409                     break;
410                 case NONE:
411                 default:
412                     constraints.fill = GridBagConstraints.NONE;
413                     break;
414             }
415
416             // Insets
417             Double[] margins = uicontrol.getMargins();
418             constraints.insets = new Insets(
419                 margins[0].intValue(), margins[1].intValue(),
420                 margins[2].intValue(), margins[3].intValue());
421
422             // Padding
423             Integer[] padding = uicontrol.getGridBagPadding();
424             constraints.ipadx = padding[0];
425             constraints.ipady = padding[1];
426
427             Integer[] preferredSize = uicontrol.getGridBagPreferredSize();
428             if (preferredSize[0].equals(-1) == false && preferredSize[1].equals(-1) == false) {
429                 ((Component) member).setPreferredSize(new Dimension(preferredSize[0], preferredSize[1]));
430             }
431
432             component.getWidgetPane().add((Component) member, constraints);
433             component.getWidgetPane().revalidate();
434         } else {
435             if (member instanceof SwingScilabScrollableFrame || member instanceof SwingScilabFrame) {
436                 component.getWidgetPane().add((Component) member, JLayeredPane.FRAME_CONTENT_LAYER);
437             } else {
438                 component.getWidgetPane().add((Component) member, JLayeredPane.DEFAULT_LAYER + 1);
439             }
440         }
441     }
442
443     protected static void  removeMember(SwingScilabPanel component, SwingViewObject member) {
444         component.getWidgetPane().remove((Component) member);
445     }
446 }