/* BEGIN_HEADER Java TreeView
*
* $Author: alokito $
* $RCSfile: TextView.java,v $
* $Revision: 1.4 $
* $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.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Observable;
import javax.swing.JScrollPane;
import edu.stanford.genetics.treeview.ConfigNode;
import edu.stanford.genetics.treeview.HeaderInfo;
import edu.stanford.genetics.treeview.HeaderSummary;
import edu.stanford.genetics.treeview.ModelView;
import edu.stanford.genetics.treeview.TreeSelectionI;
import edu.stanford.genetics.treeview.UrlExtractor;
public class TextView extends ModelView implements FontSelectable,
KeyListener, AdjustmentListener,
MouseListener, MouseMotionListener {
public String[] getHints() {
String [] hints = {
"Click and drag to scroll",
};
return hints;
}
/**
* should really take a HeaderSummary instead of HeaderInfo, since the mapping should be managed by
* Dendroview so that the SummaryView can use the same HeaderSummary.
*/
public TextView(HeaderInfo hI, UrlExtractor uExtractor) {
super();
urlExtractor = uExtractor;
headerInfo = hI;
col = -1;
// could set up headerSummary...
int GIDIndex = headerInfo.getIndex("GID");
if (GIDIndex == -1) {
headerSummary.setIncluded(new int [] {1});
} else {
headerSummary.setIncluded(new int [] {2});
}
// int yorfIndex = headerInfo.getIndex("YORF");
// int nameIndex = headerInfo.getIndex("NAME");
addMouseListener(this);
addMouseMotionListener(this);
addKeyListener(this);
scrollPane = new JScrollPane(this);
scrollPane.setBorder(null);
panel = scrollPane;
}
public TextView(HeaderInfo hI, UrlExtractor uExtractor, int col) {
super();
urlExtractor = uExtractor;
headerInfo = hI;
this.col = col;
// could set up headerSummary...
int GIDIndex = headerInfo.getIndex("GID");
if (GIDIndex == -1) {
headerSummary.setIncluded(new int [] {1});
} else {
headerSummary.setIncluded(new int [] {2});
}
// int yorfIndex = headerInfo.getIndex("YORF");
// int nameIndex = headerInfo.getIndex("NAME");
addMouseListener(this);
addMouseMotionListener(this);
addKeyListener(this);
scrollPane = new JScrollPane(this);
scrollPane.setBorder(null);
panel = scrollPane;
}
public String viewName() { return "TextView";}
// I bet this isn't used anymore.
public MenuItem getFontMenuItem() {
MenuItem itema = new MenuItem("Gene Font...");
itema.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent actionEvent)
{
FontSelector fontSelector = new FontSelector
(TextView.this, "Select Fonts for Gene Info");
fontSelector.showDialog(viewFrame);
}
});
return itema;
}
// Canvas methods
public void updateBuffer(Graphics g) {
updateBuffer(g, offscreenSize);
}
public void updateBuffer(Image buf) {
Dimension offscreenSize = new Dimension(buf.getWidth(null), buf.getHeight(null));
updateBuffer(buf.getGraphics(), offscreenSize);
}
public void updateBuffer(Graphics g, Dimension offscreenSize) {
// clear the pallette...
g.setColor(Color.white);
g.fillRect(0,0, offscreenSize.width, offscreenSize.height);
g.setColor(Color.black);
if ((map.getMinIndex() >= 0) &&
(offscreenSize.height > 0)) {
int start = map.getIndex(0);
int end = map.getIndex(map.getUsedPixels());
g.setFont(new Font(face, style, size));
FontMetrics metrics = getFontMetrics(g.getFont());
int ascent = metrics.getAscent();
// draw backgrounds first...
int bgColorIndex = headerInfo.getIndex("BGCOLOR");
if (bgColorIndex > 0) {
Color back = g.getColor();
for (int j = start; j < end;j++) {
if ((geneSelection == null) || geneSelection.isIndexSelected(j)) {
String [] strings = headerInfo.getHeader(j);
try {
g.setColor(TreeColorer.getColor(strings[bgColorIndex]));
} catch (Exception e) {
// ignore
}
g.fillRect(0, map.getMiddlePixel(j) - ascent / 2, offscreenSize.width, ascent);
}
}
g.setColor(back);
}
// now, foreground text
int fgColorIndex = headerInfo.getIndex("FGCOLOR");
for (int j = start; j < end;j++) {
String out = null;
if(col == -1) {
out = headerSummary.getSummary(headerInfo, j);
} else {
String [] summaryArray = headerSummary.getSummaryArray(headerInfo, j);
if ((summaryArray != null) && (col < summaryArray.length))
out = summaryArray[col];
}
if (out != null) {
Color back = g.getColor();
if ((geneSelection == null) || geneSelection.isIndexSelected(j)) {
String [] strings = headerInfo.getHeader(j);
if (fgColorIndex > 0) {
g.setColor(TreeColorer.getColor(strings[fgColorIndex]));
}
g.drawString(out, 0, map.getMiddlePixel(j) + ascent / 2);
if (fgColorIndex > 0) g.setColor(back);
} else {
g.setColor(Color.gray);
g.drawString(out, 0, map.getMiddlePixel(j) + ascent / 2);
g.setColor(back);
}
}
}
} else { // some kind of blank default image?
// backG.drawString("Select something already!", 0, offscreenSize.height / 2 );
}
}
/**
* Set geneSelection
*
* @param geneSelection The TreeSelection which is set by selecting genes in the GlobalView
*/
public void setGeneSelection(TreeSelectionI geneSelection) {
if (this.geneSelection != null)
this.geneSelection.deleteObserver(this);
this.geneSelection = geneSelection;
this.geneSelection.addObserver(this);
}
public void setMap(MapContainer im) {
if (map != null) {
map.deleteObserver(this);
}
map = im;
if (map != null) map.addObserver(this);
}
/** This method is called when the selection is changed. It causes the component to
* recalculate it's width, and call repaint.
*/
private void selectionChanged() {
maxlength = 1;
FontMetrics fontMetrics = getFontMetrics(new Font(face, style, size));
int start = map.getIndex(0);
int end = map.getIndex(map.getUsedPixels());
for (int j = start; j < end;j++) {
int actualGene = j;
String out = headerSummary.getSummary(headerInfo, actualGene);
if (out == null) continue;
int length = fontMetrics.stringWidth(out);
if (maxlength < length) {
maxlength = length;
}
}
setPreferredSize(new Dimension(maxlength, map.getUsedPixels()));
revalidate();
repaint();
}
public UrlExtractor getUrlExtractor()
{
return urlExtractor;
}
// Observer
public void update(Observable o, Object arg) {
if (o == map) {
selectionChanged(); // gene locations changed
} else if (o == geneSelection) {
selectionChanged(); // which genes are selected changed
} else if(o == headerSummary) { // annotation selection changed
selectionChanged();
} else {
System.out.println("Textview got funny update!");
}
}
// MouseListener
public void mouseClicked(MouseEvent e) {
if (urlExtractor == null) return;
urlExtractor.setEnabled(true);
if (urlExtractor.isEnabled() == false) return;
// now, want mouse click to signal browser...
int index = map.getIndex(e.getY());
if (map.contains(index)) {
if(col != -1)
{
viewFrame.displayURL(urlExtractor.getUrl(index, headerInfo.getNames()[col]));
}
else
{
viewFrame.displayURL(urlExtractor.getUrl(index));
}
}
}
// MouseMotionListener
public void mousePressed(MouseEvent e) {
dragging = true;
}
public void mouseDragged(MouseEvent e) {
if (dragging) {
// int xoff = (e.getX() * (maxlength - offscreenSize.width)) / offscreenSize.width;
// adjustScrollbar(xoff);
}
}
public void mouseReleased(MouseEvent e) {
dragging = false;
}
// KeyListener
public void keyPressed(KeyEvent e) {
int xoff = 0;//scrollbar.getValue();
int c = e.getKeyCode();
switch (c) {
case KeyEvent.VK_UP:
break;
case KeyEvent.VK_DOWN:
break;
case KeyEvent.VK_LEFT:
xoff -= scrollstep; break;
case KeyEvent.VK_RIGHT:
xoff += scrollstep; break;
default:
return;
}
adjustScrollbar(xoff);
}
// AdjustmentListener
public void adjustmentValueChanged(AdjustmentEvent evt) {
offscreenValid = false;
repaint();
}
private void adjustScrollbar(int offset) {
// scrollbar.setValue(offset);
offscreenValid = false;
repaint();
}
//FontSelectable
public String getFace() {
return face;
}
public int getPoints() {
return size;
}
public int getStyle() {
return style;
}
public void setFace(String string) {
if ((face == null) ||(!face.equals(string))) {
face = string;
if (root != null)
root.setAttribute("face", face, d_face);
setFont(new Font(face, style, size));
repaint();
}
}
public void setPoints(int i) {
if (size != i) {
size = i;
if (root != null)
root.setAttribute("size", size, d_size);
setFont(new Font(face, style, size));
repaint();
}
}
public void setStyle(int i) {
if (style != i) {
style = i;
if (root != null)
root.setAttribute("style", style, d_style);
setFont(new Font(face, style, size));
repaint();
}
}
public void bindConfig(ConfigNode configNode)
{
root = configNode;
setFace(root.getAttribute("face", d_face));
setStyle(root.getAttribute("style", d_style));
setPoints(root.getAttribute("size", d_size));
getHeaderSummary().bindConfig(root.fetchOrCreate("GeneSummary"));
}
private final int scrollstep = 5;
private final String d_face = "Courier";
private final int d_style = 0;
private final int d_size = 12;
protected HeaderInfo headerInfo = null;
protected HeaderSummary headerSummary = new HeaderSummary();
/** Setter for headerSummary */
public void setHeaderSummary(HeaderSummary headerSummary) {
this.headerSummary = headerSummary;
}
/** Getter for headerSummary */
public HeaderSummary getHeaderSummary() {
return headerSummary;
}
private ConfigNode root = null;
private String face;
private int style;
private int size;
private TreeSelectionI geneSelection;
private MapContainer map;
private UrlExtractor urlExtractor;
private int maxlength = 0;
private int col;
private boolean dragging = false;
private JScrollPane scrollPane;
}