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