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