/* * Copyright (C) 2008 Genome Research Limited * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * @author: Tim Carver */ package uk.ac.sanger.artemis.circular; import uk.ac.sanger.artemis.Feature; import javax.swing.*; import java.awt.geom.AffineTransform; import java.awt.geom.Line2D; import java.awt.*; import java.awt.datatransfer.*; import java.awt.event.*; import java.io.IOException; import java.util.Vector; import javax.swing.event.*; import java.awt.geom.Arc2D; public class Block implements Transferable { private static final long serialVersionUID = 1L; private DNADraw current_dna; private double angStart; private double angEnd; private Vector rect; private boolean drawLabel = false; final public static DataFlavor BLOCK = new DataFlavor(Block.class, "Block"); static DataFlavor blockFlavors[] = { BLOCK }; private String label; private int bstart; private int bend; private Feature feature; private Color colour; private float strokeSize; private boolean arrowHead; private boolean arrowTail; /** track to place the block on - as a fraction of the radii*/ private Track track; public Block(final String label, int bstart, int bend, Color colour, float strokeSize, Track track) { super(); this.label = label; this.bstart = bstart; this.bend = bend; this.colour = colour; this.strokeSize = strokeSize; this.track = track; } public Block(final String label, int bstart, int bend, Color colour, float strokeSize, Track fracRadii, DNADraw current_dna) { this(label, bstart, bend, colour, strokeSize, fracRadii); this.current_dna = current_dna; } protected void draw(Graphics2D g2) { if(current_dna.isCircular()) drawCircular(g2); else drawLinear(g2); } protected void showProperties(final JFrame f, final DNADraw draw, JButton delete) { // final JFrame f = new JFrame("Properties"); //set up menu bar JMenuBar menuBar = new JMenuBar(); JMenu fileMenu = new JMenu("File"); fileMenu.setMnemonic(KeyEvent.VK_F); menuBar.add(fileMenu); JMenuItem closeMenu = new JMenuItem("Close"); closeMenu.setAccelerator(KeyStroke.getKeyStroke( KeyEvent.VK_E, ActionEvent.CTRL_MASK)); closeMenu.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { f.dispose(); } }); fileMenu.add(closeMenu); //set up window f.setJMenuBar(menuBar); JPanel pane = (JPanel)f.getContentPane(); String markerLabel = getLabel(); int bstart = getBstart(); int bend = getBend(); Color colour = getColour(); float strokeSize = getStrokeSize(); boolean arrowHead = isArrowHead(); boolean arrowTail = isArrowTail(); Box bdown = Box.createVerticalBox(); pane.add(bdown); bdown.add(Box.createVerticalStrut(4)); Dimension d = new Dimension(200,30); Box bacross = Box.createHorizontalBox(); final JTextField annotation = new JTextField(); annotation.setPreferredSize(d); annotation.setMaximumSize(d); annotation.setText(markerLabel); annotation.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setLabel(annotation.getText()); if(draw != null) draw.repaint(); } }); bacross.add(annotation); bacross.add(new JLabel(" Label")); bacross.add(Box.createHorizontalGlue()); bdown.add(bacross); d = new Dimension(65,30); bacross = Box.createHorizontalBox(); final TextFieldInt start = new TextFieldInt(); start.setPreferredSize(d); start.setMaximumSize(d); start.setValue(bstart); start.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setBstart(start.getValue()); if(draw != null) draw.repaint(); } }); bacross.add(start); bacross.add(new JLabel(" Start")); bacross.add(Box.createHorizontalGlue()); bdown.add(bacross); bacross = Box.createHorizontalBox(); final TextFieldInt end = new TextFieldInt(); end.setPreferredSize(d); end.setMaximumSize(d); end.setValue(bend); end.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setBend(end.getValue()); if(draw != null) draw.repaint(); } }); bacross.add(end); bacross.add(new JLabel(" End")); bacross.add(Box.createHorizontalGlue()); bdown.add(bacross); //Set up the dialog that the button brings up. final JButton colourButton = GeneticMarker.setUpColorButton(colour); final JButton applyButton = new JButton("Apply"); applyButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { setColour(colourButton.getBackground()); setLabel(annotation.getText()); if(draw != null) draw.repaint(); } }); bacross = Box.createHorizontalBox(); bacross.add(new JLabel("Pick a Colour: ")); bacross.add(colourButton); bacross.add(applyButton); bacross.add(Box.createHorizontalGlue()); bdown.add(bacross); bacross = Box.createHorizontalBox(); final JSlider slider; if(strokeSize <= 25) slider = new JSlider(1,25,(int)strokeSize); else slider = new JSlider(1,25+(int)strokeSize,(int)strokeSize); bacross.add(slider); bacross.add(new JLabel(" Line width")); bacross.add(Box.createHorizontalGlue()); slider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { setStrokeSize((float)slider.getValue()); if(draw != null) draw.repaint(); } }); bacross.add(Box.createHorizontalGlue()); bdown.add(bacross); bacross = Box.createHorizontalBox(); bacross.add(new JLabel("Arrow :")); bacross.add(Box.createHorizontalGlue()); bdown.add(bacross); bacross = Box.createHorizontalBox(); final JRadioButton head = new JRadioButton("Head"); final JRadioButton tail = new JRadioButton("Tail"); final JRadioButton none = new JRadioButton("None"); head.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if(head.isSelected()) { setArrowHead(true); setArrowTail(false); } else { setArrowHead(false); setArrowTail(true); } if(draw != null) draw.repaint(); } }); bacross.add(head); tail.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if(tail.isSelected()) { setArrowTail(true); setArrowHead(false); } else { setArrowTail(false); setArrowHead(true); } if(draw != null) draw.repaint(); } }); bacross.add(tail); none.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if(none.isSelected()) { setArrowTail(false); setArrowHead(false); } if(draw != null) draw.repaint(); } }); bacross.add(none); bacross.add(Box.createHorizontalGlue()); bdown.add(bacross); bacross = Box.createHorizontalBox(); final JCheckBox label = new JCheckBox("Show Label", drawLabel); label.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { drawLabel = label.isSelected(); setLabel(annotation.getText()); draw.repaint(); } }); bacross.add(label); bacross.add(Box.createHorizontalGlue()); bdown.add(bacross); bacross = Box.createHorizontalBox(); bacross.add(delete); bacross.add(Box.createHorizontalGlue()); bdown.add(bacross); ButtonGroup group = new ButtonGroup(); group.add(head); group.add(tail); group.add(none); if(arrowHead) head.setSelected(true); else if(arrowTail) tail.setSelected(true); f.pack(); f.setVisible(true); } protected void drawLinear(final Graphics2D g2) { RenderingHints qualityHints = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); qualityHints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2.setRenderingHints(qualityHints); String markerLabel = getLabel(); int bstart = getBstart(); int bend = getBend(); FontMetrics fm = g2.getFontMetrics(); g2.setColor(getColour()); //int shift = (int)getTrack().getPosition(); int basesPerLine = current_dna.getBasesPerLine(); int lineNumberStart = Math.round((float)(bstart-1)/((float)basesPerLine) + 0.5f)-1; int lineNumberEnd = Math.round((float)(bend-1)/((float)basesPerLine) + 0.5f)-1; float singleBaseWidth = current_dna.getSingleBaseWidth(); int borderWidth2 = current_dna.getBorderWidth2(); int borderHeight2 = current_dna.getBorderHeight2(); int ypos = (int) ( (lineNumberStart*current_dna.getLineHeight()) - (strokeSize/2.f) - ((1-track.getPosition())*current_dna.getLineHeight()) + borderHeight2+current_dna.getLineHeight()); int xstart = (int) ((bstart-(lineNumberStart*basesPerLine))*singleBaseWidth)+borderWidth2; int xend = (int) ((bend-(lineNumberEnd*basesPerLine))*singleBaseWidth)+borderWidth2; if(rect == null) rect = new Vector(); BasicStroke basicstroke; if(bstart == bend) { // SNP / variation feature basicstroke = new BasicStroke( 1.f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); g2.setStroke(basicstroke); g2.drawLine(xstart,ypos,xstart,(int) (ypos+strokeSize)); Rectangle r = new Rectangle(); r.setLocation(xstart,ypos); r.setSize(current_dna.getWidth()-borderWidth2-xstart,2); rect.add(r); return; } basicstroke = new BasicStroke( strokeSize, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER); g2.setStroke(basicstroke); if(arrowTail) { int[] xPoints = {xstart+(int)strokeSize,xstart+(int)strokeSize,xstart}; int[] yPoints = {ypos+(int)strokeSize,ypos-(int)strokeSize,ypos}; xstart+=strokeSize/2; g2.fillPolygon(xPoints,yPoints,3); } Rectangle r; if(lineNumberEnd > lineNumberStart) { g2.drawLine(xstart,ypos,current_dna.getWidth()-borderWidth2,ypos); r = new Rectangle(); r.setLocation(xstart,ypos); r.setSize(current_dna.getWidth()-borderWidth2-xstart,(int)strokeSize); rect.add(r); for(int i=lineNumberStart+1; i y_origin) angDegrees = (180 - angDegrees); else if(x < x_origin && y < y_origin) angDegrees = (angDegrees + 180); else if(x > x_origin && y < y_origin) angDegrees = (360 - angDegrees); angDegrees = angDegrees - DNADraw.THETA; if(angDegrees > 360) angDegrees-=360; if( angDegrees >= -angStart-.05 && angDegrees <= -(angStart+angEnd-0.05) ) { double len = Math.sqrt(Math.pow((y_origin - y), 2) + Math.pow((x_origin - x), 2)); //double rat = (len / dradii); /*System.out.println(getLabel() + " " + getFeature().getIDString()); System.out.println("ANGLE " + angDegrees ); System.out.println("START " + angStart + " " + angStart); System.out.println("END " + (angStart + angEnd) + " " + angEnd);*/ double trackPos = track.getPosition()*dradii; if(len <= trackPos+(track.getSize()/2.f) && len >= trackPos-(track.getSize()/2.f)) return true; } } else { for(int i=0; i