Package edu.stanford.genetics.treeview

Source Code of edu.stanford.genetics.treeview.ViewFrame

/* BEGIN_HEADER                                              Java TreeView
*
* $Author: alokito $
* $RCSfile: ViewFrame.java,v $
* $Revision: 1.37 $
* $Date: 2009-08-26 11:48:27 $
* $Name:  $
*
* This file is part of Java TreeView
* Copyright (C) 2001-2003 Alok Saldanha, All Rights Reserved. Modified by Alex Segal 2004/08/13. Modifications Copyright (C) Lawrence Berkeley Lab.
*
* This software is provided under the GNU GPL Version 2. In particular,
*
* 1) If you modify a source file, make a comment in it containing your name and the date.
* 2) If you distribute a modified version, you must do it under the GPL 2.
* 3) Developers are encouraged but not required to notify the Java TreeView maintainers at alok@genome.stanford.edu when they make a useful addition. It would be nice if significant contributions could be merged into the main distribution.
*
* A full copy of the license can be found in gpl.txt or online at
*
* http://www.gnu.org/licenses/gpl.txt *
* END_HEADER
*/

package edu.stanford.genetics.treeview;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;

import edu.stanford.genetics.treeview.core.FileMru;
import edu.stanford.genetics.treeview.core.HeaderFinder;
import edu.stanford.genetics.treeview.model.DataModelWriter;
import edu.stanford.genetics.treeview.model.ReorderedDataModel;





/**
*  Any frame that wants to contain MainPanels must extend this.
*
* @author     Alok Saldanha <alok@genome.stanford.edu>
* @version    @version $Revision: 1.37 $ $Date: 2009-08-26 11:48:27 $
*/
public abstract class ViewFrame extends JFrame implements Observer {
  // must override in subclass...
  /**
   *  This is to ensure that we can observe the MainPanels when they change.
   *
   * @param  observable  The MainPanel or other thing which changed.
   * @param  object      Generally null.
   */
  public abstract void update(Observable observable, Object object);


  /**
   * This routine should return any instances of the plugin
   * of the indicated name (i.e. it will loop over all instantiated
   * MainPanel calling their getName() properties, find all that are
   * equal to the indicated string, and return all matching ones
   */
  public abstract MainPanel[] getMainPanelsByName(String name);
 
  /**
   *
   * @return all mainPanels managed by this viewFrame
   */
  public abstract MainPanel[] getMainPanels();
 
  /**
   *  Sets up a <code>FileMru</code> using a particular config node.
   * This <code>FileMru</code> can later be edited or used to show a mru menu.
   *
   * @param  fileMruNode  Node which will be bound to the FileMru
   */
  protected void setupFileMru(ConfigNode fileMruNode) {
    fileMru = new FileMru();
    fileMru.bindConfig(fileMruNode);
    try {
      fileMru.removeMoved();
    } catch (Exception e) {
      LogBuffer.println("problem checking MRU in ViewFrame constructor: " + e.toString());
      e.printStackTrace();
    }

    fileMru.addObserver(this);
    fileMru.notifyObservers();//sends us message
  }


  /**
   *  Centers the frame onscreen.
   *
   * @param  rectangle  A rectangle describing the outlines of the screen.
   */
  private void center(Rectangle rectangle) {
    Dimension dimension  = getSize();
    setLocation((rectangle.width - dimension.width) / 3 + rectangle.x, (rectangle.height - dimension.height) / 3 + rectangle.y);
  }


  /**  Determines dimension of screen and centers frame onscreen. */
  public void centerOnscreen() {
    // trying this for mac...
    Toolkit toolkit      = Toolkit.getDefaultToolkit();
    Dimension dimension  = toolkit.getScreenSize();
    Rectangle rectangle  = new Rectangle(dimension);

    // XXX should drag out of global config
    setSize(rectangle.width * 3 / 4, rectangle.height * 4 / 5);
    center(rectangle);
  }


  /**  Sets a listener on self, so taht we can grab focus when activated, and close ourselves when closed.*/
  private void setupWindowListener() {
    setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
    addWindowListener(
      new WindowAdapter() {
        public void windowActivated(WindowEvent windowEvent) {
          setWindowActive(true);
        }


        public void windowClosing(WindowEvent windowEvent) {
          closeWindow();
        }


        public void windowDeactivated(WindowEvent windowEvent) {
          setWindowActive(false);
        }
      });
  }


  /**
   *  Constructor for the ViewFrame object
   * Sets title and window listeners
   *
   * @param  title  Title for the viewframe.
   */
  public ViewFrame(String title) {
    super(title);
    setupWindowListener();
  }


  /**  construts an untitled <code>ViewFrame</code> */
  public ViewFrame() {
    super();
    setupWindowListener();
  }


  /**
   *  Keep track of when active, so that clicks don't get passed through too much.
   *
   * @param  flag  The new windowActive value
   */
  protected void setWindowActive(boolean flag) {
    windowActive = flag;
  }


  /**
   *  Keep track of when active, so that clicks don't get passed through too much.
   *
   * @return    True if window is active.
   */
  public boolean windowActive() {
    return windowActive;
  }


  /**  Keep track of when active, so that clicks don't get passed through too much. */
  private boolean windowActive;


  /**  close window cleanly.
  * causes documentConfig to be stored.
  */
  public void closeWindow() {
    try {
      DataModel dataModel  = getDataModel();
      if (dataModel != null) {
          if (dataModel.getModified()) {
            int option = JOptionPane.showConfirmDialog(this, "DataModel is modified. Do you wish to save?");
            switch (option) {
              case JOptionPane.YES_OPTION:
                  DataModelWriter writer = new DataModelWriter(getDataModel());
                writer.writeIncremental(getDataModel().getFileSet());
                break;
              case JOptionPane.CANCEL_OPTION:
                return;
              case JOptionPane.NO_OPTION:
                break;
            }
          }       
       
        ConfigNode documentConfig  = dataModel.getDocumentConfigRoot();
        if (documentConfig != null) {
          documentConfig.store();
        }
      }
    } catch (Exception e) {
      System.out.println("ViewFrame.closeWindow() Got exception: " + e);
    }
    System.out.println("ViewFrame.dispose");
    dispose();
  }


  /**
   *  required by all <code>ModelPanel</code>s
   *
   * @return   The shared TreeSelection object for genes.
   */
  public TreeSelectionI getGeneSelection() {
    return geneSelection;
  }
  protected void setGeneSelection(TreeSelectionI newSelection) {
    geneSelection = newSelection;
  }

  /**
   *  required by all <code>ModelPanel</code>s
   *
   * @return   The shared TreeSelection object for arrays.
   */
  public TreeSelectionI getArraySelection() {
    return arraySelection;
  }
  protected void setArraySelection(TreeSelectionI newSelection) {
    arraySelection = newSelection;
  }

  /**
   *  used by data model to signal completion of loading.
   * The <code>ViewFrame</code> will react by reconfiguring it's widgets.
   *
   * @param  b  The new loaded value
   */
  public abstract void setLoaded(boolean b);


  /**
   *  returns special nodata value.
   *  generally, just cribs from the <code>DataModel</code>
   *
   * @return    A special double which means nodata available.
   */

  public abstract double noData();


  /**
   *  returns the UrlPresets for the views to make use of when configuring linking
   *  for genes
   *
   * @return    The shared <code>UrlPresets</code> object for genes
   */
  public abstract UrlPresets getGeneUrlPresets();


  /**
   *  returns the UrlPresets for the views to make use of when configuring linking
   *  for arrays
   *
   * @return    The shared <code>UrlPresets</code> object for arrays
   */
  public abstract UrlPresets getArrayUrlPresets();

  /**
   *  Gets the loaded attribute of the ViewFrame object
   *
   * @return    True if there is currently a model loaded.
   */
  public abstract boolean getLoaded();


  /**
   *  Gets the shared <code>DataModel</code>
   *
   * @return    Gets the shared <code>DataModel</code>
   */
  public abstract DataModel getDataModel();

  /**
   *  Sets the shared <code>DataModel</code>
   *
   * @return    Sets the shared <code>DataModel</code>
   * @throws LoadException
   */
  public abstract void setDataModel(DataModel model);

  /**
   *  Should scroll all MainPanels in this view frame to the specified gene.
   *  The index provided is respect to the TreeSelection object.
   *
   * @param  i  gene index in model to scroll the mainpanel to.
   */
  public abstract void scrollToGene(int i);
  public abstract void scrollToArray(int i);

  /**  The shared selection objects */
  TreeSelectionI geneSelection = null;
  TreeSelectionI arraySelection = null;
  public void deselectAll() {
    geneSelection.deselectAllIndexes();
    arraySelection.deselectAllIndexes();
  }
  /***
  * This routine causes all data views to
  * select and scroll to a particular gene.
  */
  public void seekGene(int i) {
    geneSelection.deselectAllIndexes();
    geneSelection.setIndex(i, true);
    geneSelection.notifyObservers();
    scrollToGene(i);
    }
  /***
  * This routine causes all data views to
  * select and scroll to a particular array.
  */
  public void seekArray(int i) {
    arraySelection.deselectAllIndexes();
    arraySelection.setIndex(i, true);
    arraySelection.notifyObservers();
    scrollToGene(i);
    }
 
  /**
  * This routine extends the selected range to include the index
  * i.
  */
  public void extendRange(int i) {
    if (geneSelection.getMinIndex() == -1)
    seekGene(i);
    geneSelection.setIndex(i, true);
    geneSelection.notifyObservers();

    scrollToGene(i);
    }
 
    public boolean geneIsSelected(int i) {
    return getGeneSelection().isIndexSelected(i);
    }


  /**
   *  url linking support
   *
   * @param  i  index of gene who's url you would like to display.
   */
  public void displayURL(int i) {
    displayURL(getUrl(i));
  }


  /**
   *  Gets the url for a particular gene.
   *
   * @param  i  index of the gene, for the gene's <code>UrlExtractor</code>
   * @return    A string representation of the url
   */
  public String getUrl(int i) {
    if (urlExtractor == null) {
      return null;
    }
    return urlExtractor.getUrl(i);
  }


  /**
   *  Gets the url for a particular array.
   *
   * @param  i  index of the array, for the array's <code>UrlExtractor</code>
   * @return    A string representation of the url
   */
  public String getArrayUrl(int i) {
    if (arrayUrlExtractor == null) {
      return null;
    }
    return arrayUrlExtractor.getUrl(i);
  }


  /**
   *  Pops up a browser window with the specified url
   *
   * @param  string  String representation of the url.
   */
  public void displayURL(String string) {
    if (string == null) {
      return;
    }
    try {
      if (browserControl == null) {
        browserControl = BrowserControl.getBrowserControl();
      }
      browserControl.displayURL(string);
    } catch (MalformedURLException e) {
      String message = new StringBuffer("Problem loading url: ").append(e).toString();
      LogBuffer.println(message);
      e.printStackTrace();
      JOptionPane.showMessageDialog(this,message);
    } catch (IOException e) {
      String message = new StringBuffer("Could not load url: ").append(e).toString();
      LogBuffer.println(message);
      e.printStackTrace();
      JOptionPane.showMessageDialog(this,message);
    }

  }


  /**
   *  Gets the UrlExtractor for the arrays.
   *
   * This object is used to convert a given array index into a url string. It can be configured to do this in multiple ways.
   *
   * @return    The UrlExtractor for the arrays
   */
  public UrlExtractor getArrayUrlExtractor() {
    return arrayUrlExtractor;
  }


  /**
   *  Gets the UrlExtractor for the genes.
   *
   * This object is used to convert a given gene index into a url string. It can be configured to do this in multiple ways.
   *
   * @return    The UrlExtractor for the genes
   */
  public UrlExtractor getUrlExtractor() {
    return urlExtractor;
  }


  /**
   *  Sets the arrayUrlExtractor attribute of the ViewFrame object
   *
   * @param  ue  The new arrayUrlExtractor value
   */
  public void setArrayUrlExtractor(UrlExtractor ue) {
    arrayUrlExtractor = ue;
  }


  /**
   *  Sets the urlExtractor attribute of the ViewFrame object
   *
   * @param  ue  The new urlExtractor value
   */
  public void setUrlExtractor(UrlExtractor ue) {
    urlExtractor = ue;
  }

  abstract public HeaderFinder getGeneFinder();

/**
* Open a dialog which allows the user to select a new data file
*
* @return The fileset corresponding to the dataset.
*/
     protected FileSet offerSelection()
   throws LoadException
   {
     FileSet fileSet1; // will be chosen...
    
     JFileChooser fileDialog = new JFileChooser();
     setupFileDialog(fileDialog);
     int retVal = fileDialog.showOpenDialog(this);
     if (retVal == JFileChooser.APPROVE_OPTION) {
       File chosen = fileDialog.getSelectedFile();
      
       fileSet1 = new FileSet(chosen.getName(), chosen.getParent()+File.separator);
/*      
       // check existing file nodes...
       ConfigNode aconfigNode[] = fileMru.getConfigs();
       for (int i = 0; i < aconfigNode.length; i++) {
         FileSet fileSet2 = new FileSet(aconfigNode[i]);
         if (fileSet2.equals(fileSet1)) {
           LogPanel.println("Found Existing node in MRU list for " + fileSet1);
           return fileSet2;
         }
       }
*/
     } else {
       throw new LoadException("File Dialog closed without selection...", LoadException.NOFILE);
     }
    
      /* Don't enforce suffixes...
     // see if we match at all...
     try {
       if (!ff.accept(null, fileSet1.getCdt()))
         throw new LoadException(fileSet1.getCdt() +
         " did not end in .cdt or .pcl", LoadException.EXT);
     } catch (NullPointerException e) {
       throw new LoadException(e + ",most likely, no file selected so cdt is null", LoadException.NOFILE);
     }
     */

      /*
      ConfigNode configNode = fileMru.createSubNode();
      fileMru.setLast(configNode);
      FileSet fileSet3 = new FileSet(configNode);
      fileSet3.copyState(fileSet1);
      fileMru.notifyObservers();
      */
     return fileSet1;
   }

   protected void setupFileDialog(JFileChooser fileDialog) {
    CdtFilter ff = new CdtFilter();
    try {
      fileDialog.addChoosableFileFilter(ff);
      // will fail on pre-1.3 swings
      fileDialog.setAcceptAllFileFilterUsed(true);
    } catch (Exception e) {
      // hmm... I'll just assume that there's no accept all.
      fileDialog.addChoosableFileFilter(new javax.swing.filechooser.FileFilter() {
        public boolean accept (File f) {
          return true;
        }
        public String getDescription () {
          return "All Files";
        }
      });
    }
    fileDialog.setFileFilter(ff);
    fileDialog.setFileSelectionMode(JFileChooser.FILES_ONLY);
    String string = fileMru.getMostRecentDir();
    if (string != null) {
      fileDialog.setCurrentDirectory(new File(string));
    }
   }
  
  
  /**
   *  Rebuild a particular window menu.
   *
   * @param  windows  the list of windows to add elements to.
   *
   * Add a menu item for each window which grants that window the foreground when selected.
   */
   public void rebuildWindowMenu(Vector windows) {
     synchronized (menubar) {
       menubar.setMenu(TreeviewMenuBarI.windowMenu);
       menubar.removeAll();

       int max  = windows.size();
       for (int i = 0; i < max; i++) {
         if (i > 8) {
           break;
         }// just want first 9 windows...
         addFocusItem(windows,i);
       }
       menubar.addSeparator();

       menubar.addMenuItem("New Window", new ActionListener() {
         public void actionPerformed(ActionEvent actionEvent)
         {
           createNewFrame().setVisible(true);
         }
       });
       menubar.setAccelerator(KeyEvent.VK_N);
       menubar.setMnemonic(KeyEvent.VK_N);

       menubar.addMenuItem("Close Window", new ActionListener() {
         public void actionPerformed(ActionEvent actionEvent) {
           closeWindow();
         }
       });
       menubar.setAccelerator(KeyEvent.VK_W);
       menubar.setMnemonic(KeyEvent.VK_W);
     }
   }
  
   /**
   * currenlty, only the concrete subclass has a reference to the application, and hence can create new frames.
   * perhaps this will change if I add an interface for the App classes.
   */
   public ViewFrame createNewFrame() {
     return getApp().openNew();
   }
  
   public abstract TreeViewApp getApp();
   /**
   *  Constructs a MenuItem which causes the i'th window to be moved to the front.
   *
   * @param  windows  a list of windows
   * @param  i  which window to move to the front.
   * @return    a menuItem which focuses the i'th window, or null if more than 9 windows.
   */
   private void addFocusItem(Vector windows, int i) {
     int p1                  = i + 1;
     if (p1 > 9) {
       return;
     }
     final ViewFrame source  = (ViewFrame) windows.elementAt(i);
     String name;
     if (source.getLoaded()) {
       name = source.getDataModel().getName();
     } else {
       name = "Not Loaded";
     }
     menubar.addMenuItem(name, new ActionListener() {
       public void actionPerformed(ActionEvent e) {
         source.toFront();
       }
     });
     menubar.setAccelerator(getKey(p1));
   }
  
  
   /**
   *  Gets the key corresponding to a particular number.
   *
   * @param  i  The number
   * @return    The VK_blah key value
   */
   protected int getKey(int i) {
     switch (i) {
      case 0:
        return KeyEvent.VK_0;
        case 1:
        return KeyEvent.VK_1;
      case 2:
        return KeyEvent.VK_2;
      case 3:
        return KeyEvent.VK_3;
      case 4:
        return KeyEvent.VK_4;
      case 5:
        return KeyEvent.VK_5;
      case 6:
        return KeyEvent.VK_6;
      case 7:
        return KeyEvent.VK_7;
      case 8:
        return KeyEvent.VK_8;
      case 9:
        return KeyEvent.VK_9;
     }
     return 0;
   }
  
    public void showSubDataModel(int[] indexes, String source, String name) {
      if (indexes.length == 0) {
        JOptionPane.showMessageDialog(this, "No Genes to show summary of!");
        return;
      }
      showSubDataModel(indexes, null, source, name);
    }
    public void showSubDataModel(int[] geneIndexes,int[] arrayIndexes, String source, String name) {
        ReorderedDataModel dataModel = new ReorderedDataModel(getDataModel(), geneIndexes,  arrayIndexes);
        if (source != null) dataModel.setSource(source);
        if (name != null) dataModel.setName(name);
        ViewFrame window = getApp().openNew();
        window.setDataModel(dataModel);
        window.setLoaded(true);
        window.setVisible(true);
      }  
  
   /**  The global most recently used object. */
   protected FileMru fileMru;
   /**  allows opening of urls in external browser */
   protected BrowserControl browserControl = null;
   /**  url extractor for genes */
   private UrlExtractor urlExtractor;
   /**  url extractor for arrays */
   private UrlExtractor arrayUrlExtractor;
   protected TreeviewMenuBarI menubar;
  

}
TOP

Related Classes of edu.stanford.genetics.treeview.ViewFrame

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.