001/* 002 * Copyright (c) 2010 The Regents of the University of California. 003 * All rights reserved. 004 * 005 * '$Author: crawl $' 006 * '$Date: 2015-08-24 22:44:14 +0000 (Mon, 24 Aug 2015) $' 007 * '$Revision: 33630 $' 008 * 009 * Permission is hereby granted, without written agreement and without 010 * license or royalty fees, to use, copy, modify, and distribute this 011 * software and its documentation for any purpose, provided that the above 012 * copyright notice and the following two paragraphs appear in all copies 013 * of this software. 014 * 015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 019 * SUCH DAMAGE. 020 * 021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 026 * ENHANCEMENTS, OR MODIFICATIONS. 027 * 028 */ 029 030package org.kepler.gui; 031 032import java.awt.CardLayout; 033import java.awt.Component; 034import java.awt.Container; 035import java.awt.event.ActionEvent; 036import java.awt.event.ActionListener; 037import java.util.List; 038import java.util.Vector; 039import java.util.WeakHashMap; 040 041import javax.swing.JComboBox; 042import javax.swing.JComponent; 043import javax.swing.JLabel; 044import javax.swing.JPanel; 045import javax.swing.JTabbedPane; 046 047import org.apache.commons.logging.Log; 048import org.apache.commons.logging.LogFactory; 049import org.kepler.configuration.ConfigurationManager; 050import org.kepler.configuration.ConfigurationProperty; 051import org.kepler.gui.state.StateChangeMonitor; 052import org.kepler.gui.state.ViewStateChangeEvent; 053 054import ptolemy.actor.gui.PtolemyFrame; 055import ptolemy.actor.gui.TableauFrame; 056import ptolemy.kernel.util.NamedObj; 057 058/** 059 * The ViewManager keeps track of configured ViewPanes. 060 * 061 * @author Aaron Schultz 062 * 063 */ 064public class ViewManager { 065 066 private static final Log log = LogFactory.getLog(ViewManager.class 067 .getName()); 068 private static final boolean isDebugging = log.isDebugEnabled(); 069 070 //_viewPanes needs to be WeakReference because some of its elements might be GCed during Kepler GUI start. 071 //see bug: https://projects.ecoinformatics.org/ecoinfo/issues/5901 072 protected Vector<ViewPane> _viewPanes; 073 protected WeakHashMap<TableauFrame, JPanel> _viewAreas; 074 protected WeakHashMap<TableauFrame, JComboBox> _viewComboBoxes; 075 076 /** 077 * Constructor. 078 */ 079 public ViewManager() { 080 _viewPanes = new Vector<ViewPane>(); 081 _viewAreas = new WeakHashMap<TableauFrame, JPanel>(); 082 _viewComboBoxes = new WeakHashMap<TableauFrame, JComboBox>(); 083 } 084 085 /** 086 * Instantiate all of the ViewPanes that are specified in configuration.xml 087 * 088 * @param parent 089 */ 090 public void initializeViews(TableauFrame parent) { 091 try { 092 ViewPaneFactory VPfactory = (ViewPaneFactory) parent 093 .getConfiguration().getAttribute("ViewPaneFactory"); 094 if (VPfactory == null) { 095 VPfactory = new ViewPaneFactory(parent.getConfiguration(), 096 "ViewPaneFactory"); 097 } 098 099 if (VPfactory != null) { 100 boolean success = VPfactory.createViewPanes(parent); 101 if (!success) { 102 System.out 103 .println("error: ViewPane is null. " 104 + "This " 105 + "problem can be fixed by adding a viewPaneFactory " 106 + "property in the configuration.xml file."); 107 } 108 } else { 109 System.out.println("error: ViewPane is " + "null. This " 110 + "problem can be fixed by adding a viewPaneFactory " 111 + "property in the configuration.xml file."); 112 } 113 } catch (ptolemy.kernel.util.NameDuplicationException nde) { 114 115 } catch (Exception e) { 116 System.out.println("Could not create the ViewPaneFactory: " 117 + e.getMessage()); 118 e.printStackTrace(); 119 return; 120 } 121 122 // Create the view area and add all the viewpanes to it 123 JPanel viewArea = new JPanel(new CardLayout()); 124 Vector<ViewPane> frameViews = getFrameViews(parent); 125 String[] viewsList = new String[frameViews.size()]; 126 for (int i = 0; i < frameViews.size(); i++) { 127 ViewPane vp = frameViews.elementAt(i); 128 viewArea.add((Component) vp, vp.getViewName()); 129 viewsList[i] = vp.getViewName(); 130 if (isDebugging) 131 log.debug("add one element to viewsList:" + viewsList[i]); 132 } 133 134 try { 135 addConfiguredTabPanes(parent); 136 } catch (Exception e) { 137 e.printStackTrace(); 138 } 139 140 // while( e. hasMoreElements() ){ 141 // TableauFrame tableFrame = (TableauFrame)(e.nextElement()); 142 // System.out.println("getContainer in _viewAreas:"+ 143 // tableFrame.getTableau().getContainer()); 144 // System.out.println("isMaster in _viewAreas:"+ 145 // tableFrame.getTableau().isMaster()); 146 // if (tableFrame.getTableau().getContainer()==null && 147 // tableFrame.getTableau().isMaster()) 148 // { 149 // _viewAreas.remove(tableFrame); 150 // System.out.println("one element is in _viewAreas removed"); 151 // _viewComboBoxes.remove(tableFrame); 152 // System.out.println("one element is in _viewComboBoxes removed"); 153 // } 154 // 155 // } 156 157 _viewAreas.put(parent, viewArea); 158 if (isDebugging) { 159 log.debug("_viewAreas:" + _viewAreas.size()); 160 log.debug("_viewAreas key set:" + _viewAreas.keySet()); 161 } 162 163 164 165 JComboBox viewComboBox = new JComboBox(viewsList); 166 if (viewComboBox != null && viewComboBox.getItemCount() > 0) { 167 viewComboBox.setSelectedIndex(0); 168 viewComboBox.addActionListener(new ViewComboBoxListener()); 169 _viewComboBoxes.put(parent, viewComboBox); 170 if (isDebugging) 171 log.debug("_viewComboBoxes:" + _viewComboBoxes.size()); 172 } 173 174 } 175 176 public JPanel getViewArea(TableauFrame parent) { 177 return _viewAreas.get(parent); 178 } 179 180 /** 181 * Method to return a JComponent as a view selector. If there is only one 182 * view for the specified frame then an empty JLabel is returned otherwise a 183 * JComboBox is returned. 184 * 185 * @param parent 186 * @return JComponent 187 */ 188 public JComponent getViewSelector(TableauFrame parent) { 189 JComboBox c = getViewComboBox(parent); 190 if (c.getItemCount() == 1) { 191 // return new JLabel( c.getItemAt(0).toString() ); 192 return new JLabel(""); 193 } else { 194 return c; 195 } 196 } 197 198 /** 199 * Return a combo box that contains all of the views for the specified 200 * parent frame. 201 * 202 * @param parent 203 * @return JComboBox 204 */ 205 public JComboBox getViewComboBox(TableauFrame parent) { 206 return _viewComboBoxes.get(parent); 207 } 208 209 /** 210 * Set the JComboBox for a specific TableauFrame 211 * 212 * @param parent 213 * @param jcb 214 */ 215 public void setViewComboBox(TableauFrame parent, JComboBox jcb) { 216 _viewComboBoxes.put(parent, jcb); 217 } 218 219 public void showView(TableauFrame parent, String viewName) { 220 JPanel viewArea = _viewAreas.get(parent); 221 CardLayout cl = (CardLayout) (viewArea.getLayout()); 222 cl.show(viewArea, viewName); 223 NamedObj reference = ((PtolemyFrame) parent).getModel(); 224 ViewPane viewPane = getViewPane(parent, viewName); 225 StateChangeMonitor.getInstance().notifyStateChange( 226 new ViewStateChangeEvent((Component) viewPane, 227 ViewStateChangeEvent.SHOW_VIEW, reference, viewName)); 228 } 229 230 /** 231 * 232 */ 233 public void addCanvasToLocation(Component canvas, TableauFrame parent) 234 throws Exception { 235 ConfigurationProperty commonProperty = ConfigurationManager 236 .getInstance().getProperty( 237 ConfigurationManager.getModule("common")); 238 // get //canvasViewPaneLocation/viewPane 239 List<ConfigurationProperty> viewPaneList = commonProperty 240 .getProperties("canvasViewPaneLocation.viewPane"); 241 // for each viewPane 242 for (int i = 0; i < viewPaneList.size(); i++) { 243 ConfigurationProperty viewPaneProp = (ConfigurationProperty) viewPaneList 244 .get(i); 245 // get viewPane.name 246 String viewPaneName = viewPaneProp.getProperty("name").getValue(); 247 248 // ViewPane theViewPane = getViewPane(parent, viewPane.name); 249 ViewPane theViewPane = getViewPane(parent, viewPaneName); 250 // if theViewPane == null, throw exception 251 if (theViewPane == null) { 252 // Check for the case where the ViewPane *is* actually defined 253 // in configuration.xml, but it was not parsed from that file 254 // because it was specified along with a tableau filter, which 255 // the current tableau does not pass. 256 if (isInConfigurationFile(viewPaneName)) { 257 continue; 258 } 259 throw new Exception( 260 viewPaneName 261 + " ViewPane specified in " 262 + viewPaneProp.getModule() 263 + " configuration.xml" 264 + " was not found in the ViewManager." 265 + " Make sure you have specified this in the configuration.xml file."); 266 } 267 List<ConfigurationProperty> viewPaneLocationList = viewPaneProp 268 .getProperties("viewPaneLocation"); 269 // for each viewPane.viewPaneLocation 270 for (int j = 0; j < viewPaneLocationList.size(); j++) { 271 ConfigurationProperty viewPaneLocationProp = (ConfigurationProperty) viewPaneLocationList 272 .get(j); 273 // get viewPane.viewPaneLocation.name 274 String viewPaneLocationName = viewPaneLocationProp.getProperty( 275 "name").getValue(); 276 // if !theViewPane.hasLocation(viewPane.viewPaneLocation.name) 277 // throw exception 278 if (!theViewPane.hasLocation(viewPaneLocationName)) { 279 throw new Exception("The ViewPaneLocation, " 280 + viewPaneLocationName 281 + ", is not an available location of ViewPane, " 282 + viewPaneName); 283 } 284 // theViewPane.getLocationContainer(viewPane.viewPaneLocation.name).add("Workflow", 285 // canvas); 286 287 // see if the tab name for the canvas is specified 288 String canvasTabPaneName = "Workflow"; 289 ConfigurationProperty tabPaneProp = viewPaneProp 290 .getProperty("tabPanename"); 291 if (tabPaneProp != null) { 292 canvasTabPaneName = tabPaneProp.getValue(); 293 } 294 295 canvas.setName(canvasTabPaneName); 296 297 // add the canvas as the first tab in the view. 298 theViewPane.getLocationContainer(viewPaneLocationName).add( 299 canvas, 0); 300 301 // if the canvas is part of a tabbed pane, make sure it is 302 // selected 303 Component container = canvas.getParent(); 304 if (container instanceof JTabbedPane) { 305 ((JTabbedPane) container).setSelectedIndex(0); 306 } 307 } 308 } 309 } 310 311 private boolean isInConfigurationFile(String viewPaneName) { 312 if (viewPaneName == null) { 313 return false; 314 } 315 316 ConfigurationProperty guiProperty = ConfigurationManager.getInstance() 317 .getProperty(ConfigurationManager.getModule("gui")); 318 List<ConfigurationProperty> paneList = guiProperty 319 .getProperties("viewPaneFactory.viewPane"); 320 for (ConfigurationProperty property : paneList) { 321 ConfigurationProperty nameProperty = property.getProperty("name"); 322 if (nameProperty != null 323 && viewPaneName.equals(nameProperty.getValue())) { 324 return true; 325 } 326 } 327 return false; 328 } 329 330 /** 331 * Register a ViewPane with the ViewManager. ViewPanes must be subclasses of 332 * java.awt.Container 333 * 334 * @param vp 335 * @throws ClassCastException 336 */ 337 public void addViewPane(ViewPane vp) throws ClassCastException { 338 if (vp instanceof Container) { 339 340 // Iterator _viewPaneIt = _viewPanes.iterator(); 341 // while (_viewPaneIt.hasNext()) { 342 // ViewPane vpEle = (ViewPane)_viewPaneIt.next(); 343 // System.out.println("getContainer in _viewPanes:"+ 344 // vpEle.getParentFrame().getTableau().getContainer()); 345 // System.out.println("isMaster in _viewPanes:"+ 346 // vpEle.getParentFrame().getTableau().isMaster()); 347 // if (vpEle.getParentFrame().getTableau().getContainer()==null && 348 // vpEle.getParentFrame().getTableau().isMaster()) 349 // { 350 // _viewPanes.remove(vpEle); 351 // System.out.println("one element in _viewPanes is removed"); 352 // } 353 // 354 // } 355 356 // for (ViewPane vpEle : _viewPanes) 357 // { 358 // System.out.println("getContainer in _viewPanes:"+ 359 // vpEle.getParentFrame().getTableau().getContainer()); 360 // System.out.println("isMaster in _viewPanes:"+ 361 // vpEle.getParentFrame().getTableau().isMaster()); 362 // if (vpEle.getParentFrame().getTableau().getContainer()==null && 363 // vpEle.getParentFrame().getTableau().isMaster()) 364 // { 365 // _viewPanes.remove(vpEle); 366 // System.out.println("one element in _viewPanes is removed"); 367 // } 368 // } 369 370 _viewPanes.add(vp); 371 if (isDebugging) 372 log.debug("_viewPanes:" + _viewPanes.size()); 373 } else { 374 throw new ClassCastException(vp.getViewName() 375 + " ViewPane is not a subclass of java.awt.Container"); 376 } 377 } 378 379 /** 380 * Return a ViewPane reference for the given TableauFrame and viewName. 381 * 382 * @param parent 383 * @param viewName 384 * */ 385 public ViewPane getViewPane(TableauFrame parent, String viewName) { 386 viewName = viewName.trim(); 387 for (int i = 0; i < _viewPanes.size(); i++) { 388 ViewPane pane = _viewPanes.elementAt(i); 389 if (pane != null && pane.getParentFrame() == parent) { 390 if (pane.getViewName().equals(viewName)) { 391 if (pane instanceof Container) { 392 return pane; 393 } 394 } 395 } else if (pane == null) { 396 _viewPanes.removeElementAt(i); 397 i--; 398 } 399 } 400 return null; 401 } 402 403 /** 404 * Return a vector of ViewPane objects for the specified TableauFrame. 405 * 406 * @param parent 407 * */ 408 public Vector<ViewPane> getFrameViews(TableauFrame parent) { 409 Vector<ViewPane> frameViewPanes = new Vector<ViewPane>(); 410 for (int i = 0; i < _viewPanes.size(); i++) { 411 ViewPane pane = _viewPanes.elementAt(i); 412 if (pane != null && pane.getParentFrame() == parent) { 413 frameViewPanes.add(pane); 414 } else if (pane == null) { 415 _viewPanes.removeElementAt(i); 416 if (isDebugging) 417 log.debug("remove pane number " + i + " from _viewPanes because pane == null."); 418 i--; 419 } 420 421 } 422 return frameViewPanes; 423 } 424 425 /** 426 * Read in ViewPane locations of TabPanes from Config and add them. 427 * 428 * <viewPane> <name>example</name> 429 * <viewPaneLocation> <name>NORTH</name> <tabPane> 430 * <name>tabname</name> </tabPane> 431 * </viewPaneLocation> </viewPane> 432 * 433 * @throws Exception 434 */ 435 private void addConfiguredTabPanes(TableauFrame parent) throws Exception { 436 TabManager tabman = TabManager.getInstance(); 437 ConfigurationProperty commonProperty = ConfigurationManager 438 .getInstance().getProperty( 439 ConfigurationManager.getModule("common")); 440 441 // get the viewpanes 442 List<ConfigurationProperty> viewPaneList = commonProperty 443 .getProperties("viewPaneTabPanes.viewPane"); 444 // for each viewpane get the name 445 for (int i = 0; i < viewPaneList.size(); i++) { 446 ConfigurationProperty viewPaneProp = (ConfigurationProperty) viewPaneList 447 .get(i); 448 String viewPaneName = viewPaneProp.getProperty("name").getValue(); 449 // call getViewPane(parent, name) 450 ViewPane theViewPane = getViewPane(parent, viewPaneName); 451 // get the viewPaneLocation children of viewpane 452 List<ConfigurationProperty> viewPaneLocationList = viewPaneProp 453 .getProperties("viewPaneLocation"); 454 // for each viewpanelocation of viewpane 455 for (int j = 0; j < viewPaneLocationList.size(); j++) { 456 ConfigurationProperty viewPaneLocationProp = (ConfigurationProperty) viewPaneLocationList 457 .get(j); 458 // get viewpanelocation.name 459 String viewPaneLocationName = viewPaneLocationProp.getProperty( 460 "name").getValue(); 461 // check theViewPane.hasLocation(viewpanelocation.name) 462 if (theViewPane != null 463 && !theViewPane.hasLocation(viewPaneLocationName)) { 464 throw new Exception("The ViewPaneLocation, " 465 + viewPaneLocationName 466 + ", is not an available location of ViewPane, " 467 + viewPaneName); 468 } else if (theViewPane != null) { 469 // viewPaneContainer = 470 // theViewPane.getLocationContainer(viewpanelocation.name) 471 Container viewPaneContainer = theViewPane 472 .getLocationContainer(viewPaneLocationName); 473 List<ConfigurationProperty> tabPaneList = viewPaneLocationProp 474 .getProperties("tabPane"); 475 // for each tabpane in viewpanelocation 476 for (int k = 0; k < tabPaneList.size(); k++) { 477 ConfigurationProperty tabPaneProperty = (ConfigurationProperty) tabPaneList 478 .get(k); 479 // get the name of the tabpane 480 String tabPaneName = tabPaneProperty 481 .getProperty("name").getValue(); 482 // System.out.println("getting tab pane: " + 483 // tabPaneName); 484 TabPane theTabPane = tabman.getTab(parent, tabPaneName); 485 if (theTabPane == null) { 486 System.out 487 .println("ERROR: no tab named " 488 + tabPaneName 489 + " in the view " 490 + viewPaneName 491 + ". (Perhaps the tab's getTabName() does not match" 492 + " the name given in configuration.xml?)"); 493 } else { 494 viewPaneContainer.add(theTabPane.getTabName(), 495 (Component) theTabPane); 496 } 497 } 498 } 499 } 500 } 501 } 502 503 /** 504 * Method for getting an instance of this singleton class. 505 */ 506 public static ViewManager getInstance() { 507 return ViewManagerHolder.INSTANCE; 508 } 509 510 /** 511 * Method for remove . 512 */ 513 public void removeOpenFrame(TableauFrame parent) { 514 515 Object[] keyArray = _viewComboBoxes.keySet().toArray(); 516 for (int i = 0; i < keyArray.length; i++) { 517 if (keyArray[i] == null) { 518 if (isDebugging) 519 log.debug("keyArray[i] == null"); 520 } else { 521 TableauFrame tableauFrame = (TableauFrame) keyArray[i]; 522 if (isDebugging) { 523 log.debug("getContainer in _viewAreas:" 524 + tableauFrame.getTableau().getContainer()); 525 log.debug("isMaster in _viewAreas:" 526 + tableauFrame.getTableau().isMaster()); 527 } 528 // if (tableFrame.getTableau().getContainer()==null && 529 // tableFrame.getTableau().isMaster()) 530 if (tableauFrame == parent) { 531 _viewAreas.remove(tableauFrame); 532 _viewComboBoxes.remove(tableauFrame); 533 if (isDebugging) { 534 log.debug("one element is in _viewAreas removed:" + i); 535 log.debug("one element is in _viewComboBoxes removed:" 536 + i); 537 } 538 } 539 } 540 } 541 542 if (isDebugging) { 543 log.debug("the size of _viewAreas after removing:" 544 + _viewAreas.size()); 545 log.debug("the size of _viewComboBoxes after removing:" 546 + _viewComboBoxes.size()); 547 } 548 549 for (int i = 0; i < _viewPanes.size(); i++) { 550 ViewPane pane = _viewPanes.elementAt(i); 551 if (pane != null && pane.getParentFrame() == parent) { 552 pane.setParentFrame(null); 553 _viewPanes.removeElementAt(i); 554 if (isDebugging) 555 log.debug("one element is in _viewPanes removed:" + i); 556 i--; 557 } else if (pane == null) { 558 _viewPanes.removeElementAt(i); 559 if (isDebugging) 560 log.debug("one element is in _viewPanes removed 2:" + i); 561 i--; 562 } 563 564 } 565 566 if (isDebugging) 567 log.debug("the size of _viewPanes after removing:" 568 + _viewPanes.size()); 569 570 } 571 572 private static class ViewManagerHolder { 573 private static final ViewManager INSTANCE = new ViewManager(); 574 } 575 576 private class ViewComboBoxListener implements ActionListener { 577 578 /** Action for changing the view. */ 579 public void actionPerformed(ActionEvent e) { 580 Object c = e.getSource(); 581 if (c instanceof JComboBox) { 582 JComboBox jc = (JComboBox) c; 583 Object s = jc.getSelectedItem(); 584 if (s instanceof String) { 585 String viewName = (String) s; 586 // NOTE: we need to get the parent TableauFrame here instead 587 // of Window, since the detached toolbar is a Window. 588 TableauFrame frame = GUIUtil.getParentTableauFrame(jc); 589 if (frame == null) { 590 System.out 591 .println("ERROR: could not find parent tableau frame."); 592 } else { 593 showView(frame, viewName); 594 } 595 } 596 } 597 } 598 } 599}