Package edu.stanford.genetics.treeview.plugin.dendroview

Source Code of edu.stanford.genetics.treeview.plugin.dendroview.ATRView

/* BEGIN_HEADER                                              Java TreeView
*
* $Author: alokito $
* $RCSfile: ATRView.java,v $
* $Revision: 1.2 $
* $Date: 2010-05-02 13:39:00 $
* $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.plugin.dendroview;

import java.awt.*;
import java.awt.event.*;
import java.util.Observable;

import javax.swing.JPanel;
import javax.swing.JScrollBar;

import edu.stanford.genetics.treeview.*;

/**
*  Draws an array tree to show the relations between arrays This object requires
*  a MapContainer to figure out the offsets for the arrays. Furthermore, it sets
*  up a scrollbar to scroll the tree, although there is currently no way to specify
*  how large you would like the scrollable area to be.
*
* @author     Alok Saldanha <alok@genome.stanford.edu>
* @version    $Revision: 1.2 $ $Date: 2010-05-02 13:39:00 $
*/

public class ATRView extends ModelViewBuffered implements
    MouseListener, KeyListener {
  /**  Constructor, sets up AWT components  */
  public ATRView() {
    super();

    panel = new JPanel();
    scrollbar = new JScrollBar(JScrollBar.VERTICAL, 0, 1, 0, 1);
    destRect = new Rectangle();

    panel.setLayout(new BorderLayout());
    panel.add(this, BorderLayout.CENTER);
    panel.add(scrollbar, BorderLayout.EAST);

    addMouseListener(this);
    addKeyListener(this);
  }


  private final static String[] hints = {
      "Click to select node",
      " - use arrow keys to navigate tree",
      };


  /*inherit description*/
  public String[] getHints() {
    return hints;
  }


  /**
   *  Set the selected node and redraw
   *
   * @param  n  The new node to be selected Does nothing if the node is already selected.
   */
  public void setSelectedNode(TreeDrawerNode n) {
    if (selectedNode == n) {
      return;
    }
    if (selectedNode != null) {
      drawer.paintSubtree(offscreenGraphics,
          xScaleEq, yScaleEq,
          destRect, selectedNode, false);
    }
    selectedNode = n;
    if (selectedNode != null) {
      if (xScaleEq != null) {
        drawer.paintSubtree(offscreenGraphics,
            xScaleEq, yScaleEq,
            destRect, selectedNode, true);
      }
    }

    if ((status != null) && hasMouse) {
      status.setMessages(getStatus());
    }
    synchMap();
    repaint();
  }

  /** make sure the selected array range reflects the selected node, if any. */
  private void synchMap() {
    if ((selectedNode != null) && (arraySelection != null)) {
      int start  = (int) (selectedNode.getLeftLeaf().getIndex());
      int end    = (int) (selectedNode.getRightLeaf().getIndex());
      arraySelection.deselectAllIndexes();
      arraySelection.setSelectedNode(selectedNode.getId());
      arraySelection.selectIndexRange(start, end);
      arraySelection.notifyObservers();
    }
       if ((status != null) && hasMouse)
       {status.setMessages(getStatus());}
  }



  /**
   *  Set  <code>TreeSelection</code> object which coordinates the shared selection state.
   *
   * @param  arraySelection  The <code>TreeSelection</code> which is set by selecting arrays in the
   *      </code>GlobalView</code>
   */
  public void setArraySelection(TreeSelectionI arraySelection) {
    if (this.arraySelection != null) {
      this.arraySelection.deleteObserver(this);
    }
    this.arraySelection = arraySelection;
    this.arraySelection.addObserver(this);
  }


  /**
   *  Set the drawer
   *
   * @param  d  The new drawer
   */
  public void setInvertedTreeDrawer(InvertedTreeDrawer d) {
    if (drawer != null) {
      drawer.deleteObserver(this);
    }
    drawer = d;
    drawer.addObserver(this);
  }


  /**
   *  Set the map.
   *      For the ATRView, this determines where the leaves of the tree will be.
   *
   * @param  m  The new map to be used for determining the spacing between indexes.
   */
  public void setMap(MapContainer m) {
    if (map != null) {
      map.deleteObserver(this);
    }
    map = m;
    map.addObserver(this);
  }




  /**
   *  expect updates to come from map, arraySelection and drawer
   *
   * @param  o    The observable which sent the update
   * @param  arg  Argument for this update, typically null.
   */
  public void update(Observable o, Object arg) {
    if (isEnabled() == false) {
      return;
    }

    if (o == map) {
      //      System.out.println("Got an update from map");
      offscreenValid = false;
      repaint();
    } else if (o == drawer) {
      //System.out.println("Got an update from drawer");
      offscreenValid = false;
      repaint();
    } else if (o == arraySelection) {
//      LogBuffer.println("got update from arraySelection "+o );
      TreeDrawerNode cand = null;
      if (arraySelection.getNSelectedIndexes() > 0) {
        // This clause selects the array node if only a single array is selected.
        if (arraySelection.getMinIndex() == arraySelection.getMaxIndex()) {
          cand = drawer.getLeaf(arraySelection.getMinIndex());
        }
        // this clause selects the root node if all arrays are selected.
        if (arraySelection.getMinIndex() == map.getMinIndex()) {
          if (arraySelection.getMaxIndex() == map.getMaxIndex()) {
            cand = drawer.getRootNode();
          }
        }
      }
      // Only notify observers if we're changing the selected node.
      if ((cand != null) && (cand.getId() != arraySelection.getSelectedNode())) {
        arraySelection.setSelectedNode(cand.getId());
        arraySelection.notifyObservers();
      } else {
        setSelectedNode(drawer.getNodeById(arraySelection.getSelectedNode()));
      }
    } else {
      System.out.println(viewName() + "Got an update from unknown " + o);
    }
  }


  /**
   *  Need to blit another part of the buffer to the screen when the scrollbar moves.
   *
   * @param  evt  The adjustment event generated by the scrollbar
   */
  public void adjustmentValueChanged(AdjustmentEvent evt) {
    repaint();
  }


  // method from ModelView
  /**
   *  Implements abstract method from ModelView. In this case, returns "ATRView"
   *
   * @return    name of this subclass of modelview
   */
  public String viewName() {
    return "ATRView";
  }

    // method from ModelView
  /**
   *  Gets the status attribute of the ATRView object The status is some information
   *  which the user might find useful.
   *
   * @return    The status value
   */
    public String[]  getStatus() {
      String [] status;
      if (selectedNode != null) {
        if (selectedNode.isLeaf()) {
          status = new String [2];
          status[0] = "Leaf Node " + selectedNode.getId();
          status[1] = "Pos " + selectedNode.getCorr();
        } else {
          int [] nameIndex = getHeaderSummary().getIncluded();
          status = new String [nameIndex.length * 2];
          HeaderInfo atrInfo = getViewFrame().getDataModel().getAtrHeaderInfo();
          String [] names = atrInfo.getNames();
          for (int i = 0; i < nameIndex.length; i++) {
            status[2*i] = names[nameIndex[i]] +":";
            status[2*i+1] = " " +atrInfo.getHeader(atrInfo.getHeaderIndex(selectedNode.getId()))[ nameIndex[i]];
          }
        }
      } else {
        status = new String [2];
        status[0] = "Select Node to ";
        status[1] = "view annotation.";
      }
      return status;
    }

  protected HeaderSummary headerSummary = new HeaderSummary();
  /** Setter for headerSummary */
  public void setHeaderSummary(HeaderSummary headerSummary) {
    this.headerSummary = headerSummary;
  }
  /** Getter for headerSummary */
  public HeaderSummary getHeaderSummary() {
    return headerSummary;
  }

  /*inherit description*/
  public void updateBuffer(Graphics g) {
    if (offscreenChanged == true) {
      offscreenValid = false;
    }
    if ((offscreenValid == false) && (drawer != null)) {
      map.setAvailablePixels(offscreenSize.width);

      // clear the pallette...
      g.setColor(Color.white);
      g.fillRect
          (0, 0, offscreenSize.width, offscreenSize.height);
      g.setColor(Color.black);

      //  calculate Scaling
      destRect.setBounds(0, 0, map.getUsedPixels(), offscreenSize.height);
      xScaleEq = new LinearTransformation
          (map.getIndex(destRect.x), destRect.x,
          map.getIndex(destRect.x + destRect.width),
          destRect.x + destRect.width);
      yScaleEq = new LinearTransformation
          (drawer.getCorrMin(), destRect.y,
          drawer.getCorrMax(), destRect.y + destRect.height);

      // draw
      drawer.paint(g,
          xScaleEq, yScaleEq,
          destRect, selectedNode);
    } else {
      //      System.out.println("didn't update buffer: valid = " + offscreenValid + " drawer = " + drawer);
    }
  }


  // Mouse Listener
  /**
   *  When a mouse is clicked, a node is selected.
   */
  public void mouseClicked(MouseEvent e) {
    if (isEnabled() == false) {
      return;
    }
    if (this == null) {
      return;
    }
    if (enclosingWindow().isActive() == false) {
      return;
    }
    if (drawer != null) {
      // the trick is translating back to the normalized space...
      setSelectedNode
          (drawer.getClosest(xScaleEq.inverseTransform(e.getX()),
          yScaleEq.inverseTransform(e.getY()),
      // weight must have correlation slope on top
          yScaleEq.getSlope() / xScaleEq.getSlope())
          );
    }
  }


  // method from KeyListener
  /**
   *  Arrow keys are used to change the selected node.
   *
   * up selects parent of current.
   * left selects left child.
   * right selects right child
   * down selects child with most descendants.
   *
   */
  public void keyPressed(KeyEvent e) {
    if (selectedNode == null) {
      return;
    }

    int c                = e.getKeyCode();
    switch (c) {
    case KeyEvent.VK_UP:
      selectParent();
    break;
    case KeyEvent.VK_LEFT:
      if (selectedNode.isLeaf() == false) {
        selectLeft();
      }
    break;
    case KeyEvent.VK_RIGHT:
      if (selectedNode.isLeaf() == false) {
        selectRight();
      }
    break;
    case KeyEvent.VK_DOWN:
      if (selectedNode.isLeaf() == false) {
        TreeDrawerNode right  = selectedNode.getRight();
        TreeDrawerNode left   = selectedNode.getLeft();
        if (right.getRange() > left.getRange()) {
          selectRight();
        } else {
          selectLeft();
        }
      }
    break;
    }
  }

   private void selectParent() {
       TreeDrawerNode current = selectedNode;
       selectedNode = current.getParent();
       if (selectedNode == null) {
         selectedNode = current;
         return;
       }
       if (current == selectedNode.getLeft())
         current = selectedNode.getRight();
       else
         current = selectedNode.getLeft();
       drawer.paintSubtree(offscreenGraphics,
      xScaleEq, yScaleEq,
      destRect, current, true);
       drawer.paintSingle(
         offscreenGraphics, xScaleEq, yScaleEq,
      destRect, selectedNode, true);
        
       synchMap();
       repaint();
     }
  
  private void selectRight() {
    if (selectedNode.isLeaf()) {
      return;
    }
    TreeDrawerNode current  = selectedNode;
    selectedNode = current.getRight();
    drawer.paintSingle(offscreenGraphics,
        xScaleEq, yScaleEq, destRect, current, false);
    drawer.paintSubtree(offscreenGraphics,
        xScaleEq, yScaleEq,
        destRect, current.getLeft(), false);
    synchMap();
    repaint();
  }


  private void selectLeft() {
    if (selectedNode.isLeaf()) {
      return;
    }
    TreeDrawerNode current  = selectedNode;
    selectedNode = current.getLeft();
    drawer.paintSingle(offscreenGraphics,
        xScaleEq, yScaleEq, destRect, current, false);
    drawer.paintSubtree(offscreenGraphics,
        xScaleEq, yScaleEq,
        destRect, current.getRight(), false);
    synchMap();
    repaint();
  }


  /**
   *  Key releases are ignored.
   *
   * @param  e  The keyevent
   */
  public void keyReleased(KeyEvent e) { }


  /**
   *  Key types are ignored.
   *
   * @param  e  the keypress.
   */
  public void keyTyped(KeyEvent e) { }


  private TreeSelectionI arraySelection;
  private LinearTransformation xScaleEq, yScaleEq;
  private MapContainer map;
  private JScrollBar scrollbar;
  private InvertedTreeDrawer drawer = null;
  private TreeDrawerNode selectedNode = null;
  private Rectangle destRect = null;
}
TOP

Related Classes of edu.stanford.genetics.treeview.plugin.dendroview.ATRView

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.