Docking restoration: work in progress... (near the end)
[scilab.git] / scilab / modules / gui / src / java / org / scilab / modules / gui / bridge / tab / SwingScilabTab.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 20072008 - INRIA - Vincent Couvert
4  * Copyright (C) 2007 - INRIA - Bruno JOFRET
5  * Copyright (C) 2007 - INRIA - Marouane BEN JELLOUL
6  *
7  * This file must be used under the terms of the CeCILL.
8  * This source file is licensed as described in the file COPYING, which
9  * you should have received as part of this distribution.  The terms
10  * are also available at
11  * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
12  *
13  */
14
15 package org.scilab.modules.gui.bridge.tab;
16
17 import java.awt.Color;
18 import java.awt.Component;
19 import java.awt.Container;
20 import java.awt.Dimension;
21 import java.awt.Graphics;
22 import java.awt.Image;
23 import java.awt.Point;
24 import java.awt.event.FocusEvent;
25 import java.awt.event.FocusListener;
26 import java.lang.reflect.InvocationTargetException;
27 import java.util.ArrayList;
28 import java.util.Iterator;
29 import java.util.List;
30
31 import javax.swing.Action;
32 import javax.swing.ImageIcon;
33 import javax.swing.SwingUtilities;
34
35 import org.flexdock.docking.DockingConstants;
36 import org.flexdock.docking.DockingPort;
37 import org.flexdock.docking.event.DockingEvent;
38 import org.flexdock.docking.activation.ActiveDockableTracker;
39 import org.flexdock.docking.props.PropertyChangeListenerFactory;
40 import org.flexdock.view.Titlebar;
41 import org.flexdock.view.View;
42
43 import org.scilab.modules.gui.bridge.canvas.SwingScilabCanvasImpl;
44 import org.scilab.modules.gui.bridge.checkbox.SwingScilabCheckBox;
45 import org.scilab.modules.gui.bridge.console.SwingScilabConsole;
46 import org.scilab.modules.gui.bridge.editbox.SwingScilabEditBox;
47 import org.scilab.modules.gui.bridge.frame.SwingScilabFrame;
48 import org.scilab.modules.gui.bridge.helpbrowser.SwingScilabHelpBrowser;
49 import org.scilab.modules.gui.bridge.label.SwingScilabLabel;
50 import org.scilab.modules.gui.bridge.listbox.SwingScilabListBox;
51 import org.scilab.modules.gui.bridge.popupmenu.SwingScilabPopupMenu;
52 import org.scilab.modules.gui.bridge.pushbutton.SwingScilabPushButton;
53 import org.scilab.modules.gui.bridge.radiobutton.SwingScilabRadioButton;
54 import org.scilab.modules.gui.bridge.slider.SwingScilabSlider;
55 import org.scilab.modules.gui.bridge.tree.SwingScilabTree;
56 import org.scilab.modules.gui.bridge.window.SwingScilabWindow;
57 import org.scilab.modules.gui.canvas.Canvas;
58 import org.scilab.modules.gui.checkbox.CheckBox;
59 import org.scilab.modules.gui.console.Console;
60 import org.scilab.modules.gui.dockable.Dockable;
61 import org.scilab.modules.gui.editbox.EditBox;
62 import org.scilab.modules.gui.events.callback.CallBack;
63 import org.scilab.modules.gui.frame.Frame;
64 import org.scilab.modules.gui.helpbrowser.HelpBrowser;
65 import org.scilab.modules.gui.label.Label;
66 import org.scilab.modules.gui.listbox.ListBox;
67 import org.scilab.modules.gui.menubar.MenuBar;
68 import org.scilab.modules.gui.popupmenu.PopupMenu;
69 import org.scilab.modules.gui.pushbutton.PushButton;
70 import org.scilab.modules.gui.radiobutton.RadioButton;
71 import org.scilab.modules.gui.slider.Slider;
72 import org.scilab.modules.gui.tab.SimpleTab;
73 import org.scilab.modules.gui.tab.Tab;
74 import org.scilab.modules.gui.textbox.TextBox;
75 import org.scilab.modules.gui.toolbar.ToolBar;
76 import org.scilab.modules.gui.tree.Tree;
77 import org.scilab.modules.gui.utils.BarUpdater;
78 import org.scilab.modules.gui.utils.Position;
79 import org.scilab.modules.gui.utils.SciUndockingAction;
80 import org.scilab.modules.gui.utils.SciClosingAction;
81 import org.scilab.modules.gui.utils.Size;
82 import org.scilab.modules.gui.utils.WindowsConfigurationManager;
83
84 /**
85  * Swing implementation for Scilab tabs in GUIs
86  * This implementation uses FlexDock package
87  * @author Bruno JOFRET
88  * @author Vincent COUVERT
89  * @author Marouane BEN JELLOUL
90  * @author Jean-Baptiste SILVY
91  */
92 public class SwingScilabTab extends View implements SimpleTab, FocusListener {
93
94     private static final Image SCILAB_ICON = new ImageIcon(System.getenv("SCI") + "/modules/gui/images/icons/scilab.png").getImage();
95
96     private static final long serialVersionUID = 1L;
97
98     private static final int VIEWPORT_SIZE = 4;
99
100     private static final String UNDOCK = "undock";
101
102     static {
103         PropertyChangeListenerFactory.addFactory(new BarUpdater.UpdateBarFactory());
104     }
105
106     private int parentWindowId;
107     private String appNameOnClose;
108     private MenuBar menuBar;
109     private ToolBar toolBar;
110     private TextBox infoBar;
111
112     /** Contains the canvas and widgets */
113     private SwingScilabAxes contentPane;
114
115     /** Scroll the axes */
116     private ScilabScrollPane scrolling;
117
118     private Image icon;
119
120     /**
121      * Constructor
122      * @param name the name of the tab
123      * @param uuid an uuid to identify the tab
124      */
125     public SwingScilabTab(String name, String uuid) {
126         super(uuid, name, name);
127         //This button is "overloaded" when we add a callback
128         //this.addAction(DockingConstants.CLOSE_ACTION);
129         // Removed because make JOGL crash when "Unpin"
130         //this.addAction(DockingConstants.PIN_ACTION);
131         this.addAction(DockingConstants.ACTIVE_WINDOW);
132
133         // no need for an axes
134         contentPane = null;
135         scrolling = null;
136
137         this.setVisible(true);
138
139         getTitlebar().addFocusListener(this);
140         addFocusListener(this);
141         setCallback(null);
142     }
143
144     /**
145      * Create a graphic tab used to display a figure with 3D graphics and/or UIcontrols
146      * @param name name of the tab
147      * @param figureId id of the displayed figure
148      */
149     public SwingScilabTab(String name, int figureId) {
150         super(name, name, name);
151
152         // This button is "overloaded" when we add a callback
153         //this.addAction(DockingConstants.CLOSE_ACTION);
154         // Removed because make JOGL crash when "Unpin"
155         //this.addAction(DockingConstants.PIN_ACTION);
156         this.addAction(DockingConstants.ACTIVE_WINDOW);
157
158         // create the panel in which all the uiobjects will lie.
159         contentPane = new SwingScilabAxes(figureId);
160
161         // add it inside a JSCrollPane
162         scrolling = new SwingScilabScrollPane(contentPane);
163
164         // put in in the back of the tab
165         setContentPane(scrolling.getAsContainer());
166
167         this.setVisible(true);
168
169         getTitlebar().addFocusListener(this);
170         addFocusListener(this);
171         setCallback(null);
172     }
173
174     /**
175      * Constructor
176      * @param name the name of the tab (used to identify it)
177      */
178     public SwingScilabTab(String name) {
179         this(name, name);
180     }
181
182     public static void removeActions(SwingScilabTab tab) {
183         tab.setActionBlocked(DockingConstants.CLOSE_ACTION, true);
184         tab.setActionBlocked(UNDOCK, true);
185         tab.getTitlebar().revalidate();
186     }
187
188     public static void addActions(SwingScilabTab tab) {
189         tab.setActionBlocked(DockingConstants.CLOSE_ACTION, false);
190         tab.setActionBlocked(UNDOCK, false);
191         tab.getTitlebar().revalidate();
192     }
193
194     /**
195      * @param e the FocusEvent
196      */
197     public void focusGained(FocusEvent e) {
198         //ActiveDockableTracker.requestDockableActivation(this);
199         if (contentPane != null) {
200             contentPane.requestFocus();
201         } else if (getContentPane() != null) {
202             getContentPane().requestFocus();
203         } else {
204             SwingScilabTab.this.requestFocusInWindow();
205         }
206     }
207
208     /**
209      * Call when the tab restoration is ended.
210      */
211     public void endedRestoration() { }
212
213     /**
214      * @return the window icon associated with this tab
215      */
216     public Image getWindowIcon() {
217         if (icon == null) {
218             return SCILAB_ICON;
219         } else {
220             return icon;
221         }
222     }
223
224     /**
225      * @param the window icon associated with this tab
226      */
227     public void setWindowIcon(Image icon) {
228         this.icon = icon;
229     }
230
231     /**
232      * @param e the FocusEvent
233      */
234     public void focusLost(FocusEvent e) { }
235
236     /**
237      * {@inheritDoc}
238      */
239     public void dockingComplete(DockingEvent evt) {
240         super.dockingComplete(evt);
241         DockingPort port = evt.getNewDockingPort();
242         Iterator iter = port.getDockables().iterator();
243
244         if (port.getDockables().size() > 1) {
245             while (iter.hasNext()) {
246                 Object d = iter.next();
247                 if (d instanceof SwingScilabTab) {
248                     SwingScilabTab view = (SwingScilabTab) d;
249                     addActions(view);
250                 }
251             }
252         } else {
253             removeActions(this);
254         }
255     }
256
257     /**
258      * Sets the Name of a swing Scilab tab
259      * @param newTabName the Name of the tab
260      * @see org.scilab.modules.gui.tab.Tab#setName()
261      */
262     public void setName(String newTabName) {
263         setTitle(newTabName, true);
264         getTitlePane().repaint();
265         SwingUtilities.getAncestorOfClass(SwingScilabWindow.class, this).setName(newTabName);
266     }
267
268     /**
269      * @return the UUID of the parent window
270      */
271     public String getParentWindowUUID() {
272         return ((SwingScilabWindow) SwingUtilities.getAncestorOfClass(SwingScilabWindow.class, this)).getUUID();
273     }
274
275     /**
276      * Gets the title of a swing Scilab tab
277      * @return the title of the tab
278      * @see org.scilab.modules.gui.tab.Tab#getTitle()
279      */
280     public String getName() {
281         return this.getTitle();
282     }
283
284     /**
285      * Paint immediately this component
286      */
287     public void paintImmediately() {
288         // paint all
289         paintImmediately(0, 0, getWidth(), getHeight());
290     }
291
292     /**
293      * Draws a swing Scilab tab
294      * @see org.scilab.modules.gui.uielement.UIElement#draw()
295      */
296     public void draw() {
297         if (SwingUtilities.isEventDispatchThread()) {
298             setVisible(true);
299             paintImmediately();
300         } else {
301             try {
302                 SwingUtilities.invokeAndWait(new Runnable() {
303                         public void run() {
304                             setVisible(true);
305                             paintImmediately();
306                         }
307                     });
308             } catch (InterruptedException e) {
309                 e.printStackTrace();
310             } catch (InvocationTargetException e) {
311                 e.printStackTrace();
312             }
313         }
314
315     }
316
317     /**
318      * Gets the dimensions (width and height) of a swing Scilab tab
319      * @return the dimensions of the tab
320      * @see org.scilab.modules.gui.uielement.UIElement#getDims()
321      */
322     public Size getDims() {
323         return new Size(this.getSize().width, this.getSize().height);
324     }
325
326     /**
327      * Get the size for the axes
328      * @return size of the axes in pixels
329      */
330     public Size getAxesSize() {
331         return new Size(contentPane.getWidth(), contentPane.getHeight());
332     }
333
334     /**
335      * @param newSize new size to set for the axes
336      */
337     public void setAxesSize(Size newSize) {
338         contentPane.setSize(new Dimension(newSize.getWidth(), newSize.getHeight()));
339     }
340
341     /**
342      * Gets the position (X-coordinate and Y-coordinate) of a swing Scilab tab
343      * @return the position of the tab
344      * @see org.scilab.modules.gui.uielement.UIElement#getPosition()
345      */
346     public Position getPosition() {
347         return new Position(this.getX(), this.getY());
348     }
349
350     /**
351      * Sets the dimensions (width and height) of a swing Scilab tab
352      * @param newSize the dimensions we want to set to the tab
353      * @see org.scilab.modules.gui.uielement.UIElement#setDims(org.scilab.modules.gui.utils.Size)
354      */
355     public void setDims(Size newSize) {
356         this.setSize(newSize.getWidth(), newSize.getHeight());
357     }
358
359     /**
360      * Sets the position (X-coordinate and Y-coordinate) of a swing Scilab tab
361      * @param newPosition the position we want to set to the tab
362      * @see org.scilab.modules.gui.uielement.UIElement#setPosition(org.scilab.modules.gui.utils.Position)
363      */
364     public void setPosition(Position newPosition) {
365         this.setLocation(newPosition.getX(), newPosition.getY());
366     }
367
368     /**
369      * Add a member (dockable element) to container and returns its index
370      * @param member the member to add
371      * @return index of member in ArrayList
372      */
373     public int addMember(Canvas member) {
374         int result;
375
376         if (SwingScilabCanvasImpl.isGLCanvasEnabled()) {
377             int[] currentView = getViewingRegion();
378             final SwingScilabTab thisF = this;
379             try {
380                 SwingUtilities.invokeAndWait(new Runnable() {
381                         public void run() {
382                             scrolling = new AwtScilabScrollPane(contentPane, thisF);
383                             setContentPane(scrolling.getAsContainer());
384                             revalidate();
385
386                         }
387                     });
388             } catch (InterruptedException e) {
389                 e.printStackTrace();
390             } catch (InvocationTargetException e) {
391                 e.getCause().printStackTrace();
392             }
393             // set the canvas after doing every thing
394             result = contentPane.addMember(member);
395             // set the same viewport as before
396             setViewingRegion(currentView[0], currentView[1], currentView[2], currentView[2 + 1]);
397         } else {
398             result = contentPane.addMember(member);
399         }
400         return result;
401     }
402
403     /**
404      * We want to be able to remove directly a Canvas from a Tab.
405      * @param member canvas to remove
406      */
407     public void removeMember(Canvas member) {
408         contentPane.removeMember(member);
409         if (SwingScilabCanvasImpl.isGLCanvasEnabled()) {
410             try {
411                 SwingUtilities.invokeAndWait(new Runnable() {
412                         public void run() {
413                             scrolling = new SwingScilabScrollPane(contentPane);
414                             setContentPane(scrolling.getAsContainer());
415                             revalidate();
416                         }
417                     });
418             } catch (InterruptedException e) {
419                 e.printStackTrace();
420             } catch (InvocationTargetException e) {
421                 e.getCause().printStackTrace();
422             }
423         }
424     }
425
426     /**
427      * Add a member (dockable element) to container and returns its index
428      * @param member the member to add
429      * @return index of member in ArrayList
430      */
431     public int addMember(Console member) {
432         return this.addMember((SwingScilabConsole) member.getAsSimpleConsole());
433     }
434
435     /**
436      * Add a member (dockable element) to container and returns its index
437      * @param member the member to add
438      * @return index of member in ArrayList
439      */
440     private int addMember(SwingScilabConsole member) {
441         // replace the current content pane
442         this.setContentPane(member);
443         return this.getComponentZOrder(member);
444     }
445
446     /**
447      * Add a member (dockable element) to container and returns its index
448      * @param member the member to add
449      * @return index of member in ArrayList
450      */
451     public int addMember(HelpBrowser member) {
452         return this.addMember((SwingScilabHelpBrowser) member.getAsSimpleHelpBrowser());
453     }
454
455     /**
456      * Add a member (dockable element) to container and returns its index
457      * @param member the member to add
458      * @return index of member in ArrayList
459      */
460     private int addMember(SwingScilabHelpBrowser member) {
461         // replace the current content pane
462         this.setContentPane(member);
463         return this.getComponentZOrder(member);
464     }
465
466     /**
467      * Add a member (dockable element) to container and returns its index
468      * @param member the member to add
469      * @return index of member in ArrayList
470      */
471     public int addMember(Frame member) {
472         return this.addMember((SwingScilabFrame) member.getAsSimpleFrame());
473     }
474
475     /**
476      * Add a member (dockable element) to container and returns its index
477      * @param member the member to add
478      * @return index of member in ArrayList
479      */
480     private int addMember(SwingScilabFrame member) {
481         return contentPane.addFrame(member);
482     }
483
484     /**
485      * Remove a Frame from its container
486      * @param member the Frame to remove
487      */
488     public void removeMember(Frame member) {
489         this.removeMember((SwingScilabFrame) member.getAsSimpleFrame());
490     }
491
492     /**
493      * Remove a Frame from its container
494      * @param member the Frame to remove
495      */
496     private void removeMember(SwingScilabFrame member) {
497         contentPane.removeFrame(member);
498     }
499
500     /**
501      * Add a member (dockable element) to container and returns its index
502      * @param member the member to add
503      * @return index of member in ArrayList
504      */
505     public int addMember(PushButton member) {
506         return this.addMember((SwingScilabPushButton) member.getAsSimplePushButton());
507     }
508
509     /**
510      * Add a member (dockable element) to container and returns its index
511      * @param member the member to add
512      * @return index of member in ArrayList
513      */
514     private int addMember(SwingScilabPushButton member) {
515         int res = contentPane.addWidget(member);
516         repaint();
517         return res;
518     }
519
520     /**
521      * Remove a PushButton from its container
522      * @param member the PushButton to remove
523      */
524     public void removeMember(PushButton member) {
525         this.removeMember((SwingScilabPushButton) member.getAsSimplePushButton());
526     }
527
528     /**
529      * Remove a PushButton from its container
530      * @param member the PushButton to remove
531      */
532     private void removeMember(SwingScilabPushButton member) {
533         contentPane.remove(member);
534     }
535
536     /**
537      * Add a member (dockable element) to container and returns its index
538      * @param member the member to add
539      * @return index of member in ArrayList
540      */
541     public int addMember(EditBox member) {
542         return this.addMember((SwingScilabEditBox) member.getAsSimpleEditBox());
543     }
544
545     /**
546      * Add a member (dockable element) to container and returns its index
547      * @param member the member to add
548      * @return index of member in ArrayList
549      */
550     private int addMember(SwingScilabEditBox member) {
551         return contentPane.addWidget(member);
552     }
553
554     /**
555      * Remove an EditBox from its container
556      * @param member the EditBox to remove
557      */
558     public void removeMember(EditBox member) {
559         this.removeMember((SwingScilabEditBox) member.getAsSimpleEditBox());
560     }
561
562     /**
563      * Remove an EditBox from its container
564      * @param member the EditBox to remove
565      */
566     private void removeMember(SwingScilabEditBox member) {
567         contentPane.removeWidget(member);
568     }
569
570     /**
571      * Add a member (dockable element) to container and returns its index
572      * @param member the member to add
573      * @return index of member in ArrayList
574      */
575     public int addMember(Label member) {
576         return this.addMember((SwingScilabLabel) member.getAsSimpleLabel());
577     }
578
579     /**
580      * Add a member (dockable element) to container and returns its index
581      * @param member the member to add
582      * @return index of member in ArrayList
583      */
584     private int addMember(SwingScilabLabel member) {
585         return contentPane.addWidget(member);
586     }
587
588     /**
589      * Remove a Label from its container
590      * @param member the Label to remove
591      */
592     public void removeMember(Label member) {
593         this.removeMember((SwingScilabLabel) member.getAsSimpleLabel());
594     }
595
596     /**
597      * Remove a Label from its container
598      * @param member the Label to remove
599      */
600     private void removeMember(SwingScilabLabel member) {
601         contentPane.removeWidget(member);
602     }
603
604     /**
605      * Add a member (dockable element) to container and returns its index
606      * @param member the member to add
607      * @return index of member in ArrayList
608      */
609     public int addMember(CheckBox member) {
610         return this.addMember((SwingScilabCheckBox) member.getAsSimpleCheckBox());
611     }
612
613     /**
614      * Add a member (dockable element) to container and returns its index
615      * @param member the member to add
616      * @return index of member in ArrayList
617      */
618     private int addMember(SwingScilabCheckBox member) {
619         return contentPane.addWidget(member);
620     }
621
622     /**
623      * Remove a CheckBox from its container
624      * @param member the CheckBox to remove
625      */
626     public void removeMember(CheckBox member) {
627         this.removeMember((SwingScilabCheckBox) member.getAsSimpleCheckBox());
628     }
629
630     /**
631      * Remove a CheckBox from its container
632      * @param member the CheckBox to remove
633      */
634     private void removeMember(SwingScilabCheckBox member) {
635         contentPane.removeWidget(member);
636     }
637
638     /**
639      * Add a member (dockable element) to container and returns its index
640      * @param member the member to add
641      * @return index of member in ArrayList
642      */
643     public int addMember(RadioButton member) {
644         return this.addMember((SwingScilabRadioButton) member.getAsSimpleRadioButton());
645     }
646
647     /**
648      * Add a member (dockable element) to container and returns its index
649      * @param member the member to add
650      * @return index of member in ArrayList
651      */
652     private int addMember(SwingScilabRadioButton member) {
653         return contentPane.addWidget(member);
654     }
655
656     /**
657      * Remove a RadioButton from its container
658      * @param member the RadioButton to remove
659      */
660     public void removeMember(RadioButton member) {
661         this.removeMember((SwingScilabRadioButton) member.getAsSimpleRadioButton());
662     }
663
664     /**
665      * Remove a RadioButton from its container
666      * @param member the RadioButton to remove
667      */
668     private void removeMember(SwingScilabRadioButton member) {
669         contentPane.removeWidget(member);
670     }
671
672     /**
673      * Add a member (dockable element) to container and returns its index
674      * @param member the member to add
675      * @return index of member in ArrayList
676      */
677     public int addMember(Slider member) {
678         return this.addMember((SwingScilabSlider) member.getAsSimpleSlider());
679     }
680
681     /**
682      * Add a member (dockable element) to container and returns its index
683      * @param member the member to add
684      * @return index of member in ArrayList
685      */
686     private int addMember(SwingScilabSlider member) {
687         return contentPane.addWidget(member);
688     }
689
690     /**
691      * Remove a Slider from its container
692      * @param member the Slider to remove
693      */
694     public void removeMember(Slider member) {
695         this.removeMember((SwingScilabSlider) member.getAsSimpleSlider());
696     }
697
698     /**
699      * Remove a Slider from its container
700      * @param member the Slider to remove
701      */
702     private void removeMember(SwingScilabSlider member) {
703         contentPane.removeWidget(member);
704     }
705
706     /**
707      * Add a member (dockable element) to container and returns its index
708      * @param member the member to add
709      * @return index of member in ArrayList
710      */
711     public int addMember(ListBox member) {
712         return this.addMember((SwingScilabListBox) member.getAsSimpleListBox());
713     }
714
715     /**
716      * Add a member (dockable element) to container and returns its index
717      * @param member the member to add
718      * @return index of member in ArrayList
719      */
720     private int addMember(SwingScilabListBox member) {
721         return contentPane.addWidget(member);
722     }
723
724     /**
725      * Remove a ListBox from its container
726      * @param member the ListBox to remove
727      */
728     public void removeMember(ListBox member) {
729         this.removeMember((SwingScilabListBox) member.getAsSimpleListBox());
730     }
731
732     /**
733      * Remove a ListBox from its container
734      * @param member the ListBox to remove
735      */
736     private void removeMember(SwingScilabListBox member) {
737         contentPane.removeWidget(member);
738     }
739
740     /**
741      * Add a member (dockable element) to container and returns its index
742      * @param member the member to add
743      * @return index of member in ArrayList
744      */
745     public int addMember(PopupMenu member) {
746         return this.addMember((SwingScilabPopupMenu) member.getAsSimplePopupMenu());
747     }
748
749     /**
750      * Add a member (dockable element) to container and returns its index
751      * @param member the member to add
752      * @return index of member in ArrayList
753      */
754     private int addMember(SwingScilabPopupMenu member) {
755         return contentPane.addWidget(member);
756     }
757
758     /**
759      * Remove a PopupMenu from its container
760      * @param member the PopupMenu to remove
761      */
762     public void removeMember(PopupMenu member) {
763         this.removeMember((SwingScilabPopupMenu) member.getAsSimplePopupMenu());
764     }
765
766     /**
767      * Remove a PopupMenu from its container
768      * @param member the PopupMenu to remove
769      */
770     private void removeMember(SwingScilabPopupMenu member) {
771         contentPane.removeWidget(member);
772     }
773
774     /**
775      * Add a Tree member (dockable element) to container and returns its index
776      * @param member the member to add
777      * @return index of member in ArrayList
778      */
779     public int addMember(Tree member) {
780         return this.addMember((SwingScilabTree) member.getAsSimpleTree());
781     }
782
783     /**
784      * Add a Tree member (dockable element) to container and returns its index
785      * @param member the member to add
786      * @return index of member in ArrayList
787      */
788     public int addMember(SwingScilabTree member) {
789         return contentPane.addWidget(member.getAsComponent());
790     }
791
792     /**
793      * Add a Tree member (dockable element) to container and returns its index
794      * @param member the member to add
795      * @return index of member in ArrayList
796      */
797     public int addTree(SwingScilabTree member) {
798         this.setContentPane(member.getAsComponent());
799         return this.getComponentZOrder(member.getAsComponent());
800     }
801
802     /**
803      * Remove a PopupMenu from its container
804      * @param member the PopupMenu to remove
805      */
806     public void removeMember(Tree member) {
807         this.removeMember((SwingScilabTree) member.getAsSimpleTree());
808     }
809
810     /**
811      * Remove a PopupMenu from its container
812      * @param member the PopupMenu to remove
813      */
814     private void removeMember(SwingScilabTree member) {
815         contentPane.removeTree(member);
816     }
817
818     /**
819      * Add a member (dockable element) to container and returns its index
820      * @param member the member to add
821      * @return index of member in ArrayList
822      */
823     public int addMember(Dockable member) {
824         // TODO Auto-generated method stub
825         return 0;
826     }
827
828     /**
829      * Get the current status of the Tab in its parent
830      * @return true is the tab is the tab currently "on top" in its parent
831      */
832     public boolean isCurrentTab() {
833         // TODO should not always return TRUE
834         return true;
835     }
836
837     /**
838      * Get the parent window id for this tab
839      * @return the id of the parent window
840      */
841     public int getParentWindowId() {
842         return this.parentWindowId;
843     }
844
845     /**
846      * Set the parent window id for this tab
847      * @param id the id of the parent window
848      */
849     public void setParentWindowId(int id) {
850         this.parentWindowId = id;
851     }
852
853     /**
854      * Setter for MenuBar
855      * @param newMenuBar : the MenuBar to set.
856      * @see org.scilab.modules.gui.tab.SimpleTab#setMenuBar(org.scilab.modules.gui.menubar.MenuBar)
857      */
858     public void setMenuBar(MenuBar newMenuBar) {
859         this.menuBar = newMenuBar;
860     }
861
862
863     /**
864      * Getter for MenuBar
865      * @return MenuBar : the MenuBar associated to the Tab.
866      * @see org.scilab.modules.gui.tab.SimpleTab#getMenuBar()
867      */
868     public MenuBar getMenuBar() {
869         return this.menuBar;
870     }
871
872     /**
873      * Setter for ToolBar
874      * @param newToolBar : the ToolBar to set.
875      * @see org.scilab.modules.gui.tab.SimpleTab#setToolBar(org.scilab.modules.gui.toolbar.ToolBar)
876      */
877     public void setToolBar(ToolBar newToolBar) {
878         this.toolBar = newToolBar;
879     }
880
881     /**
882      * Getter for ToolBar
883      * @return ToolBar : the ToolBar associated to the Tab.
884      * @see org.scilab.modules.gui.tab.SimpleTab#getToolBar()
885      */
886     public ToolBar getToolBar() {
887         return this.toolBar;
888     }
889
890     /**
891      * Setter for InfoBar
892      * @param newInfoBar the InfoBar to set.
893      */
894     public void setInfoBar(TextBox newInfoBar) {
895         this.infoBar = newInfoBar;
896     }
897
898     /**
899      * Getter for InfoBar
900      * @return the InfoBar associated to the Tab.
901      */
902     public TextBox getInfoBar() {
903         return this.infoBar;
904     }
905
906     /**
907      * Set the callback of the tab
908      * @param callback the callback to set.
909      */
910     public void setCallback(CallBack callback) {
911         Action action;
912         if (callback != null) {
913             action = new SciClosingAction(this, callback);
914         } else {
915             action = new SciClosingAction(this);
916         }
917
918         action.putValue(Action.NAME, DockingConstants.CLOSE_ACTION);
919         ((Titlebar) getTitlePane()).removeAction(DockingConstants.CLOSE_ACTION);
920         addAction(action);
921
922         /* Undock button */
923         SciUndockingAction undockAction = new SciUndockingAction(this);
924         undockAction.putValue(Action.NAME, UNDOCK);
925         ((Titlebar) getTitlePane()).removeAction(UNDOCK);
926         addAction(undockAction);
927     }
928
929     /**
930      * Set this tab as the current tab of its parent Window
931      */
932     public void setCurrent() {
933         ActiveDockableTracker.requestDockableActivation(this);
934     }
935
936     /**
937      * Set the background color of the tab.
938      * @param red red channel of the color
939      * @param green green channel
940      * @param blue blue channel
941      */
942     public void setBackground(double red, double green, double blue) {
943         Color newColor = new Color((float) red, (float) green, (float) blue);
944         contentPane.setBackground(red, green, blue);
945         scrolling.setBackground(red, green, blue);
946         setBackground(newColor);
947     }
948
949     /**
950      * Get the part of the axes which is currently viewed
951      * @return [x,y,w,h] array
952      */
953     public int[] getViewingRegion() {
954         return scrolling.getViewingRegion();
955     }
956
957     /**
958      * Specify a new viewport for the axes
959      * For SwingScilabCanvas viewport can not be modified
960      * since it match the parent tab size
961      * @param posX X coordinate of upper left point of the viewport within the axes
962      * @param posY Y coordinate of upper left point of the viewport within the axes
963      * @param width width of the viewport
964      * @param height height of the viewport
965      */
966     public void setViewingRegion(int posX, int posY, int width, int height) {
967         // Check that the canvas can be resized
968         if (!scrolling.getAutoResizeMode()) {
969             // don't set viewport size here it should always fit parent tab size
970             // It seems that we must check the viewport size and positions
971             // to get coherent values, otherwise the setViewPosition hangs...
972             // there are three checks that must be performed for the two dimensions
973             // - be sure that viewport position is greater than 0.
974             // - if the viewport is larger than the canvas, then it can't be moved
975             // - if the viewport is smaller than the canvas, then it should remains
976             //   inside the canvas
977
978             int canvasWidth = contentPane.getWidth();
979             int canvasHeight = contentPane.getHeight();
980             int[] curViewedRegion = getViewingRegion();
981             int viewportPosX = curViewedRegion[0];
982             int viewPortPosY = curViewedRegion[1];
983             int viewportWidth = curViewedRegion[2];
984             int viewportHeight = curViewedRegion[VIEWPORT_SIZE - 1];
985
986             // use previous values as default ones
987             int realPosX = 0;
988             int realPosY = 0;
989
990
991             if (viewportWidth <= canvasWidth) {
992                 // viewport smaller than the canvas
993                 // check that the viewport stays in the canvas
994                 // the left most position is canvasWidth - viewporwidth
995                 realPosX = Math.min(posX, canvasWidth - viewportWidth);
996             } else {
997                 // viewport larger than the canvas
998                 // get previous position (should be 0)
999                 realPosX = viewportPosX;
1000             }
1001             // last check, greater than 0
1002             realPosX = Math.max(0, realPosX);
1003
1004             if (viewportHeight <= canvasHeight) {
1005                 realPosY = Math.min(posY, canvasHeight - viewportHeight);
1006             } else {
1007                 realPosY = viewPortPosY;
1008             }
1009             realPosY = Math.max(0, realPosY);
1010
1011             // must be called on the Swing thread otherwise some JOGL corruption may appear
1012             final Point realPos = new Point(realPosX, realPosY);
1013             try {
1014                 SwingUtilities.invokeAndWait(new Runnable() {
1015                         public void run() {
1016                             scrolling.setViewPosition(realPos.x, realPos.y);
1017                         }
1018                     });
1019             } catch (InterruptedException e) {
1020                 e.printStackTrace();
1021             } catch (InvocationTargetException e) {
1022                 e.getCause().printStackTrace();
1023             }
1024
1025
1026         }
1027     }
1028
1029     /**
1030      * Set the event handler of the Canvas
1031      * @param funName the name of the Scilab function to call
1032      */
1033     public void setEventHandler(String funName) {
1034         contentPane.setEventHandler(funName);
1035     }
1036
1037
1038     /**
1039      * Set the status of the event handler of the Canvas
1040      * @param status is true to set the event handler active
1041      */
1042     public void setEventHandlerEnabled(boolean status) {
1043         contentPane.setEventHandlerEnabled(status);
1044     }
1045
1046     /**
1047      * Specify whether the canvas should fit the parent tab size
1048      * (and consequently the scrollpane size) or not
1049      * @param onOrOff true to enable autoresize mode
1050      */
1051     public void setAutoResizeMode(boolean onOrOff) {
1052         scrolling.setAutoResizeMode(onOrOff);
1053     }
1054
1055     /**
1056      * @return whether the resize mode is on or off
1057      */
1058     public boolean getAutoResizeMode() {
1059         return scrolling.getAutoResizeMode();
1060     }
1061
1062     /**
1063      * Get the displacement in pixel that should be used for rotating axes
1064      * @param displacement out parameter, [x,y] array of displacement in pixels
1065      * @return true if the displacement recording continue, false otherwise
1066      */
1067     public boolean getRotationDisplacement(int[] displacement) {
1068         return contentPane.getRotationDisplacement(displacement);
1069     }
1070
1071     /**
1072      * Close the tab and disable it.
1073      */
1074     public void close() {
1075         getContentPane().removeAll();
1076         setMenuBar(null);
1077         setToolBar(null);
1078         setInfoBar(null);
1079         setTitlebar(null);
1080         removeAll();
1081         setActive(false);
1082
1083         scrolling = null;
1084         contentPane = null;
1085
1086         // without this children canvas are not released.
1087         Container dummyContainer = new Container();
1088         this.setContentPane(dummyContainer);
1089     }
1090
1091     /**
1092      * Asynchronous stop of rotation tracking.
1093      */
1094     public void stopRotationRecording() {
1095         contentPane.stopRotationRecording();
1096     }
1097
1098     /**
1099      * Redefine paint children to be sure that AWT components are well painted.
1100      *  @param g a Graphics
1101      */
1102     public void paintChildren(Graphics g) {
1103         Component[] children = getComponents();
1104         for (int i = 0; i < children.length; i++) {
1105             // AWT children don't draw themselves automatically
1106             // so force their draw
1107             if (!children[i].isLightweight()) {
1108                 children[i].paint(g);
1109             }
1110         }
1111         super.paintChildren(g);
1112     }
1113 }