View Javadoc

1   // Copyright 2003-2005, FreeHEP.
2   package hep.wired.heprep.plugin;
3   
4   import java.awt.*;
5   import java.awt.event.*;
6   import java.io.*;
7   import java.net.*;
8   import java.util.*;
9   import java.util.List;
10  import javax.swing.*;
11  import javax.swing.event.*;
12  import javax.swing.filechooser.*;
13  
14  import org.jdom.Element;
15  
16  import org.xml.sax.SAXException;
17  
18  import org.freehep.application.mdi.PageContext;
19  import org.freehep.application.mdi.PageEvent;
20  import org.freehep.application.mdi.PageListener;
21  import org.freehep.application.mdi.ManagedPage;
22  import org.freehep.application.Application;
23  import org.freehep.application.studio.Plugin;
24  import org.freehep.application.studio.Studio;
25  import org.freehep.record.loop.event.RecordLoopListener;
26  import org.freehep.record.loop.event.LoopEvent;
27  import org.freehep.record.loop.event.LoopProgressEvent;
28  import org.freehep.record.source.EndOfSourceException;
29  import org.freehep.record.loop.SequentialRecordLoop;
30  import org.freehep.record.source.SequentialRecordSource;
31  import org.freehep.graphics2d.VectorGraphics;
32  import org.freehep.xml.menus.XMLMenuBuilder;
33  import org.freehep.swing.layout.TableLayout;
34  import org.freehep.util.Value;
35  import org.freehep.util.FreeHEPLookup;
36  import org.freehep.util.UserProperties;
37  import org.freehep.util.images.ImageHandler;
38  import org.freehep.util.commanddispatcher.CommandProcessor;
39  import org.freehep.xml.io.XMLIO;
40  import org.freehep.xml.io.XMLIOManager;
41  import org.freehep.xml.io.XMLIOFactory;
42  import org.freehep.xml.io.XMLIORegistry;
43  
44  import hep.graphics.heprep.HepRepConverter;
45  import hep.graphics.heprep.HepRepConversionException;
46  import hep.graphics.heprep.HepRepProvider;
47  import hep.graphics.heprep.HepRepViewer;
48  import hep.graphics.heprep.HepRep;
49  import hep.graphics.heprep.HepRepType;
50  import hep.graphics.heprep.HepRepTypeTree;
51  import hep.graphics.heprep.ref.DefaultHepRep;
52  import hep.graphics.heprep.util.HepRepUtil;
53  
54  import org.freehep.jas.plugin.xmlio.XMLPluginIO;
55  
56  import hep.wired.image.WiredBaseImage;
57  import hep.wired.plot.WiredPlot;
58  import hep.wired.plugin.WiredPage;
59  import hep.wired.plugin.WiredXMLIOFactory;
60  import hep.wired.services.GraphicsPanel;
61  import hep.wired.services.InteractionHandler;
62  import hep.wired.services.RecordPlot;
63  import hep.wired.util.WiredRegistry;
64  
65  import hep.wired.heprep.graphicspanel.ControlPanel;
66  import hep.wired.heprep.graphicspanel.HepRepPanel;
67  import hep.wired.heprep.graphicspanel.HepRepGraphicsMode;
68  import hep.wired.heprep.services.GraphicsMode;
69  import hep.wired.heprep.services.Projection;
70  import hep.wired.heprep.image.WiredImage;
71  import hep.wired.heprep.interaction.HepRepInfoPanel;
72  import hep.wired.heprep.interaction.InteractionPanel;
73  import hep.wired.heprep.interaction.VariablePanel;
74  import hep.wired.heprep.tree.TreePanel;
75  import hep.wired.heprep.tree.TreePanelListener;
76  import hep.wired.heprep.util.NullGraphics2D;
77  import hep.wired.heprep.interaction.Interaction;
78  import hep.wired.heprep.interaction.Picking;
79  import hep.wired.heprep.interaction.Variables;
80  import hep.wired.heprep.projection.VariableProjection;
81  import hep.wired.heprep.projection.CompositeProjection;
82  
83  /***
84   * Defines the plugin for use in JAS3.
85   *
86   * @author Mark Donszelmann
87   * @version $Id: WiredPlugin.java 2183 2005-08-03 22:11:23Z duns $
88   */
89  public class WiredPlugin extends Plugin
90         implements HepRepViewer, XMLPluginIO {
91  
92      private static final Icon defaultIcon = WiredImage.getIcon("WiredIcon16.png");
93      private Icon wiredIcon;
94      private XMLMenuBuilder builder;
95      private WiredPluginCommandHandler pluginHandler;
96      private WiredGlobalCommandHandler globalHandler;
97      private Properties user;
98      private Value viewNo;
99  
100     private PlotHandler plotHandler = new PlotHandler();
101 
102     private PageListener pageHandler = new PageHandler();    
103     private PageContext currentPageContext;
104     
105     private PageContext controlContext;
106     
107     private ControlPanel interactionAndTreePanel;
108     private ControlPanel interactionPanel;
109     private ControlPanel infoPanel;
110     private ControlPanel treePanel;
111     private ControlPanel variablePanel;
112 
113     private Collection/*PageContext*/ eventPlots = new ArrayList();
114 
115     private LoopHandler loopHandler = new LoopHandler();
116     private SequentialRecordLoop loop;
117     private Collection/*PageContext*/ loopPlots = new ArrayList();
118     
119     private InteractionHandler interactionHandler;
120 
121     private static WiredPlugin plugin;
122 
123     public WiredPlugin() {
124         plugin = this;
125 
126         viewNo = new Value();
127         viewNo.set(1);
128         pluginHandler = new WiredPluginCommandHandler(viewNo);
129         globalHandler = new WiredGlobalCommandHandler();
130     }
131 
132     public static WiredPlugin getPlugin() {
133         return plugin;
134     }
135 
136     protected void init() throws SAXException, IOException {
137         Studio application = getApplication();
138         WiredRegistry.add(this);
139     
140         user = application.getUserProperties();
141 
142         // NOTE, should just be done in save/restore but that seems too late.
143         addXMLIOFactories(null);
144 
145         builder = application.getXMLMenuBuilder();
146         URL xml = getClass().getResource("WiredPlugin.menus");
147         try {
148             builder.build(xml);
149         } catch (org.xml.sax.SAXParseException e) {
150             System.out.println(e);
151             System.out.println("at line: "+e.getLineNumber()+" column: "+e.getColumnNumber());
152             throw e;
153         }
154 
155         // FIXME to be re-added when merge of toolbars exist
156 /* WIRED-291
157         application.addToolBar(builder.getToolBar("actionToolBar"), "Action Toolbar");
158         application.addToolBar(builder.getToolBar("interactionToolBar2D"), "2D Interaction Toolbar");
159         application.addToolBar(builder.getToolBar("interactionToolBar3D"), "3D Interaction Toolbar");
160         application.addToolBar(builder.getToolBar("qualityToolBar"), "Quality Toolbar");
161 */
162 
163         application.getCommandTargetManager().add(pluginHandler);
164     }
165 
166     protected void postInit() {
167         // subscribe to loop here since the plugins load in undefined order
168         loop = (SequentialRecordLoop)WiredRegistry.lookup(SequentialRecordLoop.class);
169         if (loop != null) {
170             loop.addRecordLoopListener(loopHandler);
171         } else {
172             System.out.println("Could not find SequentialRecordLoop");
173         }
174     }
175 
176     public WiredPage createWiredView(String name, HepRep event) {
177         checkHepRep(event);
178 
179         WiredPlot wiredPlot = new WiredPlot(name, new HepRepPanel(new HepRepGraphicsMode(false)));        
180         WiredPage wiredPage = new WiredPage(name, wiredPlot, null);
181         
182         wiredPlot.addChangeListener(plotHandler);
183         wiredPlot.setRecord(event);
184         
185         return wiredPage;
186     }
187 
188     public void showWired(WiredPage wiredPage, Icon icon, boolean attachToLoop) {
189         wiredIcon = (icon == null) ? defaultIcon : icon;
190 
191         PageContext context = getApplication().getPageManager().openPage(wiredPage, wiredPage.getName(), wiredIcon);
192         context.addPageListener(pageHandler);
193 
194         if (attachToLoop) {
195             loopPlots.add(context);
196         } else {
197             eventPlots.add(context);
198         }
199                 
200         if (attachToLoop && (loop != null)) {
201             try {
202                 SequentialRecordSource source = loop.getRecordSource();
203                 if (source != null) loopHandler.setRecord(source.getCurrentRecord());
204             } catch (Exception e) {
205                 // ok, no current record;
206             }
207         }
208 
209         ControlPanel currentControl = getControl();
210         setControl(getControl() != null ? getControl() : getInteractionPanel());
211         setInteractionHandler(getControl().getInteractionHandler());
212 
213         // FIXME: JAS-226 this should be called by studio
214         pageHandler.pageChanged(new PageEvent(context, PageEvent.PAGESELECTED));
215     }
216 
217     public int getNumberOfPlots() {
218         return loopPlots.size()+eventPlots.size();
219     }
220 
221     public void setInteractionHandler(InteractionHandler handler) {
222         interactionHandler = handler;
223         
224         ControlPanel panel = getControl();
225         if ((panel != null) && (interactionHandler != null)) panel.setInteractionHandler(interactionHandler);
226         
227         for (Iterator contexts = loopPlots.iterator(); contexts.hasNext(); ) {
228             PageContext context = (PageContext)contexts.next();
229             WiredPage page = (WiredPage)context.getPage();
230             RecordPlot plot = page.getRecordPlot();
231             plot.setInteractionHandler(handler);
232             page.setChanged();
233         }
234 
235         for (Iterator contexts = eventPlots.iterator(); contexts.hasNext(); ) {
236             PageContext context = (PageContext)contexts.next();
237             WiredPage page = (WiredPage)context.getPage();
238             RecordPlot plot = page.getRecordPlot();
239             plot.setInteractionHandler(handler);
240             page.setChanged();
241         }        
242     }
243     
244     public InteractionHandler getInteractionHandler() {
245         return interactionHandler;
246     }
247 
248     // Handles events as a HepRepViewer
249     public void display(HepRep event) {
250         try {
251             String name = null;
252             String path = null;
253             // FIXME: when HEPREP-13 is implemented
254             if (event instanceof DefaultHepRep) {
255                 name = ((DefaultHepRep)event).getProperty("transient.filename");
256                 path = ((DefaultHepRep)event).getProperty("transient.path");
257             }
258             if (name == null) name = "Fixed View";
259             if (path == null) path = "Unknown Source";
260 
261             checkHepRep(event);
262 
263             // FIXME: use path as tooltip, when possible            
264             showWired(createWiredView(name, event), null, false);
265         } catch (Throwable e) {
266             getApplication().error("HepRep invalid", e);
267         }
268     }
269 
270     public PageContext getCurrentPageContext() {
271         return currentPageContext;
272     }
273 
274     public void setControl(ControlPanel control) {  
275         getControlPage().setControl(control);
276     }
277         
278     /*** 
279      * return null if no control page is available 
280      */
281     public ControlPanel getControl() {
282         if (controlContext == null) return null;
283         return getControlPage().getControl();
284     }
285     
286     private ControlPage getControlPage() {
287         if (controlContext == null) {            
288             controlContext = getApplication().getControlManager().openPage(new ControlPage(), "WIRED", wiredIcon);
289         }
290         return (ControlPage)controlContext.getPage();
291     }
292 
293     public InteractionPanel getInteractionPanel() {
294         if (interactionPanel == null) {
295             interactionPanel = Interaction.getInstance().getPanel();
296         }
297         return (InteractionPanel)interactionPanel;
298     }
299  
300     public HepRepInfoPanel getHepRepInfoPanel() {
301         if (infoPanel == null) {
302             infoPanel = Picking.getInstance().getPanel();
303         }
304         return (HepRepInfoPanel)infoPanel;
305     }
306 
307     public VariablePanel getVariablePanel() {
308         if (variablePanel == null) {
309             variablePanel = Variables.getInstance().getPanel();
310             ((VariablePanel)variablePanel).addChangeListener(new ChangeListener() {
311                 public void stateChanged(ChangeEvent event) {
312                     if (currentPageContext != null) {
313                         WiredPage page = (WiredPage)currentPageContext.getPage();
314                         RecordPlot plot = page.getRecordPlot();
315                         plot.repaint();
316                     }
317                 }
318             });
319         }
320         return (VariablePanel)variablePanel;
321     }
322 
323     public TreePanel getTreePanel() {
324         if (treePanel == null) {
325             treePanel = new TreePanel();
326         }
327         return (TreePanel)treePanel;
328     }
329 
330     private HepRepPanel checkHepRepPanel;
331     private VectorGraphics checkHepRepGraphics;
332 
333     public void checkHepRep(HepRep heprep) { 
334         // patch the HepRep for a bug with DrawAs values in GEANT4-xxx (only in Geant4.7.1)
335         patchG471bug(heprep);                                          
336         
337         // check if the heprep is correct
338         if (checkHepRepPanel == null) {
339             checkHepRepGraphics = new NullGraphics2D();
340             checkHepRepPanel = new HepRepPanel(new HepRepGraphicsMode(true));
341         }
342         checkHepRepPanel.setRecord(heprep);
343         checkHepRepPanel.draw(checkHepRepGraphics, true, null, null, false);
344     }
345     
346     //FIXME, WIRED-391 duplicate from WiredBase
347     private void addXMLIOFactories(XMLIORegistry registry) {
348         addXMLIOFactory(registry, GraphicsMode.class);
349         addXMLIOFactory(registry, HepRepPanel.class);
350 
351         addXMLIOFactoryForService(registry, Projection.class);
352     }
353 
354     //FIXME, WIRED-391 duplicate from WiredBase
355     private void addXMLIOFactory(XMLIORegistry registry, Class cls) {
356         if ((registry == null) || (registry.getXMLIOFactory(cls) == null)) {
357             WiredRegistry.add(new WiredXMLIOFactory(cls));
358         } 
359     }
360 
361     //FIXME, WIRED-391 duplicate from WiredBase
362     private void addXMLIOFactoryForService(XMLIORegistry registry, Class service) {
363         Set allClasses = WiredRegistry.allClasses(service);
364         for (Iterator i = allClasses.iterator(); i.hasNext(); ) {
365             addXMLIOFactory(registry, (Class)i.next());
366         }
367     }
368     
369 //
370 // XMLPluginIO
371 //
372     public void save(XMLIOManager manager,
373                      org.jdom.Element el) {
374         addXMLIOFactories(manager.getXMLIORegistry());
375         for (Iterator i=loopPlots.iterator(); i.hasNext(); ) {
376             PageContext pageContext = (PageContext)i.next();
377             Component page = pageContext.getPage();
378             if (page instanceof XMLIO) {
379                 Element pageNode = manager.save((XMLIO)page);
380                 pageNode.setAttribute("attachToLoop", Boolean.toString(true));
381                 el.addContent(pageNode);
382             }
383         }
384         for (Iterator i=eventPlots.iterator(); i.hasNext(); ) {
385             PageContext pageContext = (PageContext)i.next();
386             Component page = pageContext.getPage();
387             if (page instanceof XMLIO) el.addContent(manager.save((XMLIO)page));
388         }            
389     }
390     
391     public int restore(int level,
392                        XMLIOManager manager,
393                        org.jdom.Element el) {
394 //        System.out.println("Restoring WiredPlugin at "+level);
395         if (level == RESTORE_PLOTS_IN_PAGES) {
396             for (Iterator i = el.getChildren().iterator(); i.hasNext(); ) {
397                 Element pageNode = (Element)i.next();
398                 WiredPage page = (WiredPage)manager.restore(pageNode);
399                 boolean attachToLoop = Boolean.getBoolean(pageNode.getAttributeValue("attachToLoop", "true"));
400                 showWired(page, null, attachToLoop);
401                 // rename page
402 //                page.setName("View "+viewNo.getInt());
403                 viewNo.set(viewNo.getInt()+1);
404             }
405             
406             return RESTORE_DONE;                    
407         } else {
408             addXMLIOFactories(manager.getXMLIORegistry());
409             return RESTORE_PLOTS_IN_PAGES;
410         }
411     }
412     
413     public List getVariables() {
414         List variables = new ArrayList();
415         
416         if (currentPageContext == null) return variables;
417         
418         Component page = currentPageContext.getPage();
419         if (page instanceof WiredPage) {
420             WiredPage wiredPage = (WiredPage)page;
421             RecordPlot plot = wiredPage.getRecordPlot();
422             GraphicsPanel panel = plot.getGraphicsPanel();
423             if (panel instanceof HepRepPanel) {
424                 HepRepPanel heprepPanel = (HepRepPanel)panel;
425             
426                 // graphicsmode variables
427                 HepRepGraphicsMode mode = (HepRepGraphicsMode)heprepPanel.getGraphicsMode();
428                 variables.addAll(mode.getVariables());
429                 
430                 // projection variables
431                 variables.addAll(getVariables(heprepPanel.getProjection()));
432             }
433         }
434               
435         return variables;
436     }
437     
438     private List getVariables(Projection projection) {
439         List variables = new ArrayList();
440         if (projection instanceof VariableProjection) {
441             variables.addAll(((VariableProjection)projection).getVariables());
442         } else if (projection instanceof CompositeProjection) {
443             CompositeProjection composite = (CompositeProjection)projection;
444             for (Iterator i = composite.getProjections().iterator(); i.hasNext(); ) {
445                 variables.addAll(getVariables((Projection)i.next()));
446             }
447         }
448         return variables;
449     }
450     
451     class PlotHandler implements ChangeListener {
452         public void stateChanged(ChangeEvent event) {
453             if (controlContext != null) controlContext.requestShow();
454         }
455     }
456        
457     class PageHandler implements PageListener {
458         
459         public void pageChanged(PageEvent event) {
460 //            System.err.println(event);
461             switch (event.getID()) {
462                 case PageEvent.PAGESELECTED: {
463                     currentPageContext = event.getPageContext();
464                     getApplication().getCommandTargetManager().add(globalHandler);
465                     WiredPage page = (WiredPage)currentPageContext.getPage();
466                     RecordPlot plot = page.getRecordPlot();
467                     if (plot instanceof WiredPlot) {
468                         WiredPlot wiredPlot = (WiredPlot)plot;
469                         getTreePanel().setTreeToPlot(wiredPlot);
470                         getHepRepInfoPanel().setInfo((HepRep)wiredPlot.getRecord());
471                         getInteractionPanel().update();
472                         getVariablePanel().update();
473                         
474                         // make sure interaction handler is valid
475                         if (!wiredPlot.supports(getInteractionHandler())) {
476                             setInteractionHandler(null);
477                         }
478                     }
479                     if (controlContext != null) controlContext.requestShow();
480                     break;
481                 }
482                 case PageEvent.PAGEDESELECTED: {
483                     getApplication().getCommandTargetManager().remove(globalHandler);
484                     getTreePanel().setTreeToPlot(null);
485                     getHepRepInfoPanel().setInfo((HepRep)null);
486                     getVariablePanel().setVariables(null);
487                     currentPageContext = null;
488                     break;
489                 }
490                 case PageEvent.PAGECLOSED: {
491 //                  plot.destroy();
492                     PageContext context = event.getPageContext();
493                     eventPlots.remove(context);
494                     loopPlots.remove(context);
495                     WiredPage page = (WiredPage)context.getPage();
496                     RecordPlot plot = page.getRecordPlot();
497                     plot.setRecord(null);
498                     plot.setInteractionHandler(null);
499                     plot.removeChangeListener(plotHandler);
500                     currentPageContext = null;
501     
502                     // close all wired info
503                     if (getNumberOfPlots() == 0) {
504                         if (controlContext != null) {
505                             controlContext.close();
506                             controlContext = null;    
507                         }
508 // NOTE WIRED-458, needed to disable setting to NULL, further investigation needed.
509 // When this setting is on, opening one wired view, closing it and opening a new one 
510 // does not reinsert the tree in the right place...
511 //                        treePanel = null;
512                     }                    
513                     break;
514                 }
515                 default:
516                     break;
517             }
518             
519             pluginHandler.setChanged();
520             globalHandler.setChanged();
521         }
522     }
523         
524     // Handles events coming from a recordloop. All loopPlots will be updated.
525     class LoopHandler implements RecordLoopListener {
526         
527         public void loopBeginning(LoopEvent loopEvent) {
528         }
529 
530         public void loopEnded(LoopEvent loopEvent) {
531             SequentialRecordLoop loop = (SequentialRecordLoop) loopEvent.getSource();
532             SequentialRecordSource source = loop.getRecordSource();
533             if (source != null) {
534                 Object record = null;
535                 try {
536                     record = source.getCurrentRecord();
537                 } catch (EndOfSourceException e) {
538                     return;
539                 } catch (Throwable t) {
540                     getApplication().error("Exception...", t);
541                     return;
542                 }
543     
544                 try {
545                     setRecord(record);
546                 } catch (Throwable e) {
547                     getApplication().error("HepRep invalid", e);
548                 }
549             }
550         }
551 
552         void setRecord(Object record) {
553             if (record == null) {
554                 setRecord((HepRep)null);
555                 return;
556             }
557             
558             // convert to heprep...
559             FreeHEPLookup registry = ((Studio)Application.getApplication()).getLookup();
560             try {
561                 HepRepProvider converter = HepRepUtil.getHepRepProvider(registry, record);
562                 if (converter != null) {
563                     setRecord(converter.convert(record));
564                     return;
565                 }
566                  
567                 // for backward compatibility
568                 HepRepConverter oldConverter = HepRepUtil.getHepRepConverter(registry, record.getClass());
569                 if (oldConverter != null) {
570                     setRecord(oldConverter.convert(record));
571                     return;
572                 }
573             } catch (HepRepConversionException e) {
574             }
575 // Note: since we get all records from any record source, we should ignore if we cannot convert it to HepRep
576 //            getApplication().error("WiredPlugin: Cannot convert record '"+record+"' of class: "+record.getClass());
577         }
578         
579         void setRecord(HepRep heprep) {        
580             if (heprep == null) return;
581 
582             checkHepRep(heprep);
583 
584             // patch the HepRep for a bug with DrawAs values in GEANT4-60 (only in Geant4.7.1)
585             patchG471bug(heprep);                                          
586                               
587             // check if we display somewhere
588             Iterator contexts = loopPlots.iterator();
589 // Removed as requested for WIRED-449
590 //            if (!contexts.hasNext()) {
591 //                pluginHandler.onNewWired4();
592 //                contexts = loopPlots.iterator();
593 //            }
594            
595             // Tell all the plots to switch to the new event         
596             while (contexts.hasNext()) {
597                 PageContext context = (PageContext)contexts.next();
598                 WiredPage page = (WiredPage)context.getPage();
599                 RecordPlot plot = page.getRecordPlot();
600                 plot.setRecord(heprep);
601                 
602                 // set the tree to the current page 
603                 if ((context == currentPageContext) && (plot instanceof WiredPlot)) {
604                     getTreePanel().setTreeToPlot((WiredPlot)plot);
605                     getHepRepInfoPanel().setInfo(heprep);
606                 }
607                 
608                 // bring to front if no wired loopplot is current
609 // Removed as requested for WIRED-449
610 //                if ((currentPageContext == null) || !loopPlots.contains(currentPageContext)) context.requestShow();
611                 
612                 page.setChanged();
613             }            
614         }
615 
616         public void loopReset(LoopEvent loopEvent) {
617         }
618     
619         public void progress(LoopProgressEvent loopProgressEvent) {
620         }
621     }
622 
623     // patch the HepRep for a bug with DrawAs values in GEANT4-60 (only in Geant4.7.1)
624     private void patchG471bug(HepRep heprep) {
625         if (heprep == null) return;
626         
627         Collection typeTrees = heprep.getTypeTreeList();
628         for (Iterator i=typeTrees.iterator(); i.hasNext(); ) {
629             HepRepTypeTree typeTree = (HepRepTypeTree)i.next();
630             patchG471bug(typeTree.getTypeList());  
631         }
632     }
633     
634     // patch the HepRep for a bug with DrawAs values in GEANT4-60 (only in Geant4.7.1)
635     private void patchG471bug(Collection/*<HepRepType>*/ typeList) {
636         for (Iterator i=typeList.iterator(); i.hasNext(); ) {
637             HepRepType type = (HepRepType)i.next();
638             if (type.getName().equals("*Face")) {
639                 type.addAttValue("DrawAs", "Polygon");
640             }
641             patchG471bug(type.getTypeList());
642         }
643     }
644 
645     // Control Panel to disable close button if WIRED views exist.
646     class ControlPage extends JPanel implements ManagedPage {
647 
648         private final JTabbedPane handler;
649         
650         private ControlPanel control;
651 
652         ControlPage() {
653             setLayout(new BorderLayout());
654             handler = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.WRAP_TAB_LAYOUT);
655             add(getInteractionPanel());
656             add(getHepRepInfoPanel());
657             add(getVariablePanel());
658 
659             handler.addChangeListener(new ChangeListener() {
660                 public void stateChanged(ChangeEvent event) {
661                     setControl((ControlPanel)handler.getSelectedComponent());
662                 }
663             });
664             add(handler, BorderLayout.CENTER);            
665         }
666         
667         void add(ControlPanel control) {
668             handler.addTab(control.getName(), control.getIcon(), control, control.getToolTipText());
669         }
670         
671         ControlPanel getControl() {
672             return control;
673         }
674         
675         void setControl(ControlPanel control) {
676             this.control = control;
677             
678             if (control != null) {
679                 InteractionHandler interactionHandler = control.getInteractionHandler();
680                 if (interactionHandler != null) setInteractionHandler(interactionHandler);
681             
682                 handler.setSelectedComponent(control);
683             }
684             pluginHandler.setChanged();
685         }
686         
687         //
688         // ManagedPage interface
689         //
690         public boolean close() {
691             return getNumberOfPlots() == 0;
692         }
693 
694         public void setPageContext(PageContext context) {
695         }
696 
697         public void pageSelected() {
698         }
699 
700         public void pageDeselected() {
701         }
702 
703         public void pageIconized() {
704         }
705 
706         public void pageDeiconized() {
707         }
708 
709         public void pageClosed() {
710             controlContext = null;               
711         }
712     }
713 
714     
715 }
716