Java tutorial
/* * Copyright 2015 Fondazione Istituto Italiano di Tecnologia. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package it.iit.genomics.cru.igb.bundles.mi.view; import com.affymetrix.common.CommonUtils; import edu.uci.ics.jung.algorithms.layout.FRLayout; import edu.uci.ics.jung.algorithms.layout.Layout; import edu.uci.ics.jung.graph.Graph; import edu.uci.ics.jung.graph.SparseMultigraph; import edu.uci.ics.jung.graph.util.EdgeType; import edu.uci.ics.jung.visualization.VisualizationViewer; import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; import edu.uci.ics.jung.visualization.control.ModalGraphMouse; import edu.uci.ics.jung.visualization.renderers.Renderer; import it.iit.genomics.cru.igb.bundles.commons.business.IGBLogger; import it.iit.genomics.cru.igb.bundles.commons.view.LogPanel; import it.iit.genomics.cru.igb.bundles.mi.business.MIResult; import static it.iit.genomics.cru.igb.bundles.mi.business.MIResult.HTML_SCORE_0; import static it.iit.genomics.cru.igb.bundles.mi.business.MIResult.HTML_SCORE_1; import static it.iit.genomics.cru.igb.bundles.mi.business.MIResult.HTML_SCORE_2; import static it.iit.genomics.cru.igb.bundles.mi.business.MIResult.HTML_SCORE_3; import it.iit.genomics.cru.igb.bundles.mi.commons.MIBundleConfiguration; import it.iit.genomics.cru.igb.bundles.mi.commons.MICommons; import it.iit.genomics.cru.igb.bundles.mi.model.TaxonColorer; import it.iit.genomics.cru.igb.bundles.mi.query.MIQuery; import it.iit.genomics.cru.structures.model.MoleculeEntry; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Desktop; import java.awt.Dimension; import java.awt.HeadlessException; import java.awt.Paint; import java.awt.Shape; import java.awt.Stroke; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.AffineTransform; import java.awt.geom.Area; import java.awt.geom.Ellipse2D; import java.awt.geom.FlatteningPathIterator; import java.awt.geom.GeneralPath; import java.awt.geom.PathIterator; import java.awt.geom.Rectangle2D; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import javax.swing.AbstractButton; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ButtonGroup; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JSplitPane; import javax.swing.JTextPane; import javax.swing.filechooser.FileFilter; import org.apache.commons.collections15.Transformer; import org.apache.commons.httpclient.util.URIUtil; import org.lorainelab.igb.services.IgbService; /** * * @author Arnaud Ceol * * Panel to display all results of a query. */ public class MIResultPanel extends JPanel { private static final long serialVersionUID = 1L; private final IGBLogger igbLogger; private MITable miTable; private StructuresPanel structures; private final JSplitPane resultBox; private String label; private TaxonColorer colorer; private final static String HTML_CHECKBOX_STRUCTURE = "<html><font color=\"green\"><b>S</b></font>ructure/model</html>"; private final static String HTML_CHECKBOX_PHYSICAL = "<html><font color=\"red\"><b>P</b></font>hysical</html>"; private final static String HTML_CHECKBOX_ASSOCIATION = "<html><font color=\"orange\"><b>A</b></font>ssociation</html>"; private final static String HTML_CHECKBOX_ENZYMATIC = "<html><font color=\"blue\"><b>E</b></font>nzymatic</html>"; private final static String HTML_CHECKBOX_OTHER = "<html><font color=\"pink\"><b>O</b></font>ther</html>"; private final static String HTML_CHECKBOX_UNSPECIFIED = "<html><font color=\"black\"><b>U</b></font>nspecified</html>"; public MIResultPanel(IgbService service, String summary, List<MIResult> results, String label, MIQuery query) { setLayout(new BorderLayout()); this.label = label; igbLogger = IGBLogger.getInstance(label); colorer = TaxonColorer.getColorer(query.getTaxid()); Box menuBox = new Box(BoxLayout.X_AXIS); Box buttonBox = new Box(BoxLayout.Y_AXIS); Box buttonBox1 = new Box(BoxLayout.X_AXIS); Box buttonBox3 = new Box(BoxLayout.X_AXIS); buttonBox.add(buttonBox1); buttonBox.add(buttonBox3); JTextPane querySummary = new JTextPane(); querySummary.setContentType("text/html"); querySummary.setEditable(false); querySummary.setText(summary); menuBox.add(querySummary); menuBox.add(buttonBox); final JFrame logFrame = new JFrame("MI Bundle Log"); logFrame.setVisible(false); Dimension preferredSize = new Dimension(800, 500); logFrame.setPreferredSize(preferredSize); logFrame.setMinimumSize(preferredSize); logFrame.add(new LogPanel(igbLogger)); JButton log = new JButton(); if (igbLogger.hasError()) { log.setBackground(Color.red); } log.setIcon(CommonUtils.getInstance().getIcon("16x16/actions/console.png")); log.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { logFrame.setVisible(true); } }); buttonBox1.add(log); JButton networkButton = new JButton(""); networkButton.setIcon(new ImageIcon(getClass().getResource("/network.jpg"))); networkButton.addActionListener(new DisplayNetworkActionListener()); buttonBox1.add(networkButton); buttonBox1.add(new JSeparator(JSeparator.VERTICAL)); buttonBox1.add(new JLabel("Save: ")); JButton exportButton = new JButton("text"); exportButton.setIcon(CommonUtils.getInstance().getIcon("16x16/actions/save.png")); exportButton.addActionListener(new ExportActionListener()); if (false == MICommons.testVersion) { buttonBox1.add(exportButton); } JButton exportXgmmlButton = new JButton("xgmml"); exportXgmmlButton.setIcon(CommonUtils.getInstance().getIcon("16x16/actions/save.png")); exportXgmmlButton.addActionListener(new ExportXgmmlActionListener()); if (false == MICommons.testVersion) { buttonBox1.add(exportXgmmlButton); } buttonBox1.add(new JSeparator(JSeparator.VERTICAL)); buttonBox1.add(new JLabel("View structure: ")); structures = new StructuresPanel(service, label); buttonBox1.add(structures.getJmolButton()); buttonBox1.add(structures.getLinkButton()); // Filters ButtonGroup scoreGroup = new ButtonGroup(); JRadioButton scoreButton0 = new JRadioButton("<html>" + HTML_SCORE_0 + "</html>"); JRadioButton scoreButton1 = new JRadioButton("<html>" + HTML_SCORE_1 + "</html>"); JRadioButton scoreButton2 = new JRadioButton("<html>" + HTML_SCORE_2 + "</html>"); JRadioButton scoreButton3 = new JRadioButton("<html>" + HTML_SCORE_3 + "</html>"); scoreButton0.setSelected(true); ScoreListener scoreListener = new ScoreListener(); scoreButton0.addActionListener(scoreListener); scoreButton1.addActionListener(scoreListener); scoreButton2.addActionListener(scoreListener); scoreButton3.addActionListener(scoreListener); scoreGroup.add(scoreButton0); scoreGroup.add(scoreButton1); scoreGroup.add(scoreButton2); scoreGroup.add(scoreButton3); buttonBox1.add(new JSeparator(JSeparator.VERTICAL)); buttonBox1.add(new JLabel("Score: ")); buttonBox1.add(scoreButton0); buttonBox1.add(scoreButton1); buttonBox1.add(scoreButton2); buttonBox1.add(scoreButton3); buttonBox3.add(new JLabel("Interaction type: ")); JCheckBox EvidencePhysicalButton = new JCheckBox(HTML_CHECKBOX_PHYSICAL); JCheckBox EvidenceAssociationButton = new JCheckBox(HTML_CHECKBOX_ASSOCIATION); JCheckBox EvidenceEnzymaticButton = new JCheckBox(HTML_CHECKBOX_ENZYMATIC); JCheckBox EvidenceOtherButton = new JCheckBox(HTML_CHECKBOX_OTHER); JCheckBox EvidenceUnspecifiedButton = new JCheckBox(HTML_CHECKBOX_UNSPECIFIED); JCheckBox EvidenceStructureButton = new JCheckBox(HTML_CHECKBOX_STRUCTURE); EvidencePhysicalButton.setSelected(true); EvidenceAssociationButton.setSelected(true); EvidenceEnzymaticButton.setSelected(true); EvidenceOtherButton.setSelected(true); EvidenceUnspecifiedButton.setSelected(true); EvidenceStructureButton.setSelected(true); buttonBox3.add(EvidencePhysicalButton); buttonBox3.add(EvidenceAssociationButton); buttonBox3.add(EvidenceEnzymaticButton); buttonBox3.add(EvidenceOtherButton); buttonBox3.add(EvidenceUnspecifiedButton); buttonBox3.add(EvidenceStructureButton); EvidenceTypeListener evidenceListener = new EvidenceTypeListener(); EvidencePhysicalButton.addActionListener(evidenceListener); EvidenceAssociationButton.addActionListener(evidenceListener); EvidenceEnzymaticButton.addActionListener(evidenceListener); EvidenceOtherButton.addActionListener(evidenceListener); EvidenceUnspecifiedButton.addActionListener(evidenceListener); EvidenceStructureButton.addActionListener(evidenceListener); Box tableBox = new Box(BoxLayout.Y_AXIS); MITableModel model = new MITableModel(results); miTable = new MITable(model, service, query); miTable.setFillsViewportHeight(true); miTable.setStructuresPanel(structures); tableBox.add(miTable.getTableHeader()); tableBox.add(miTable); JScrollPane tableScroll = new JScrollPane(tableBox); tableScroll.setMinimumSize(new Dimension(800, 50)); tableScroll.setPreferredSize(new Dimension(800, 50)); tableScroll.setMaximumSize(new Dimension(Short.MAX_VALUE, Short.MAX_VALUE)); structures.setMinimumSize(new Dimension(200, 500)); structures.setPreferredSize(new Dimension(200, 500)); structures.setMaximumSize(new Dimension(200, Short.MAX_VALUE)); resultBox = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, tableScroll, structures); resultBox.setOneTouchExpandable(true); add(menuBox, BorderLayout.NORTH); add(resultBox, BorderLayout.CENTER); } public class PsicquicLinkActionListener implements ActionListener { PsicquicLinkActionListener() { } @Override public void actionPerformed(ActionEvent e) { try { if (false == miTable.getSelectedRow() >= 0) { JOptionPane.showMessageDialog(null, "Please select an interaction (row)."); return; } int modelRow = miTable.convertRowIndexToModel(miTable.getSelectedRow()); MIResult miResult = ((MITableModel) miTable.getModel()).getResult(modelRow); String query; String idA = miResult.getInteractor1().getUniprotAc(); String idB = miResult.getInteractor2().getUniprotAc(); if (false == idA.equals(idB)) { query = miResult.getPsicquicUrl() + "query/id:" + miResult.getInteractor1().getUniprotAc() + "* AND id:" + miResult.getInteractor2().getUniprotAc() + "*"; } else { query = miResult.getPsicquicUrl() + "query/idA:" + miResult.getInteractor1().getUniprotAc() + "* AND idB:" + miResult.getInteractor2().getUniprotAc() + "*"; } URI uri = new URI(URIUtil.encodeQuery(query)); Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null; if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) { desktop.browse(uri); } } catch (HeadlessException | URISyntaxException | IOException ex) { igbLogger.getLogger().error(null, ex); } } } public class ExportActionListener implements ActionListener { ExportActionListener() { } @Override public void actionPerformed(ActionEvent e) { igbLogger.info("Generate tab delimited code for query " + label); String header = "uniprot A\tgene A\tGenome Positions A\tResidues A" + "\tuniprot B\tgene B\tGenome Positions B\tResidues B" + "\tSelected regions A\tSelected regions B" + "\tSelected contact regions A\tSelected contact regions B" + "\tSelected contact AA A\tSelected contact AA B"; CustomFileChooser fileChooser = new CustomFileChooser( MIBundleConfiguration.getInstance().getExportFolder(), "txt", "tab-delimited file"); fileChooser.setDialogTitle("Save results"); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); fileChooser.setAcceptAllFileFilterUsed(false); if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) { File file = fileChooser.getSelectedFile(); String fileName = file.getPath(); String folder = file.getParentFile().getAbsolutePath(); if (false == folder.equals(MIBundleConfiguration.getInstance().getExportFolder())) { MIBundleConfiguration.getInstance().setExportFolder(folder); } try { try (FileWriter out = new FileWriter(file)) { out.append(header); for (int tableRow = 0; tableRow < miTable.getRowCount(); tableRow++) { int modelRow = miTable.convertRowIndexToModel(tableRow); MIResult miResult = ((MITableModel) miTable.getModel()).getResult(modelRow); out.append("\n" + miResult.toTab()); } out.flush(); } } catch (IOException e1) { JOptionPane.showMessageDialog(new JFrame(), "Fail to save the results in " + fileName, "Export error", JOptionPane.ERROR_MESSAGE); } } } } public class DisplayNetworkActionListener implements ActionListener { DisplayNetworkActionListener() { } private class EdgeInteraction { private boolean hasStructure; private boolean hasContactsA; private boolean hasContactsB; private String label; public EdgeInteraction(boolean hasStructure, boolean hasContactsA, boolean hasContactsB, String label) { this.hasStructure = hasStructure; this.hasContactsA = hasContactsA; this.hasContactsB = hasContactsB; this.label = label; } public boolean hasStructure() { return hasStructure; } public boolean hasContactsA() { return hasContactsA; } public boolean hasContactsB() { return hasContactsB; } public String getLabel() { return label; } } @Override public void actionPerformed(ActionEvent e) { Graph<MoleculeEntry, EdgeInteraction> graph = new SparseMultigraph<>(); for (int tableRow = 0; tableRow < miTable.getRowCount(); tableRow++) { int modelRow = miTable.convertRowIndexToModel(tableRow); MIResult miResult = ((MITableModel) miTable.getModel()).getResult(modelRow); EdgeInteraction edge = new EdgeInteraction(false == miResult.getInteractionStructures().isEmpty(), miResult.hasInterfaceOnStructureA(), miResult.hasInterfaceOnStructureB(), miResult.getTrackId()); graph.addEdge(edge, miResult.getInteractor1(), miResult.getInteractor2(), EdgeType.UNDIRECTED); } Layout<MoleculeEntry, EdgeInteraction> layout = new FRLayout(graph); layout.setSize(new Dimension(500, 600)); // sets the initial size of the space VisualizationViewer<MoleculeEntry, EdgeInteraction> vv = new VisualizationViewer<>(layout); vv.setPreferredSize(new Dimension(550, 650)); //Sets the viewing area size vv.setBackground(Color.WHITE); Transformer<MoleculeEntry, Paint> vertexPaint = new Transformer<MoleculeEntry, Paint>() { @Override public Paint transform(MoleculeEntry molecule) { return colorer.getColor(molecule.getTaxid()); } }; Transformer<EdgeInteraction, Paint> edgePaint = new Transformer<EdgeInteraction, Paint>() { @Override public Paint transform(EdgeInteraction interaction) { return interaction.hasStructure ? Color.BLACK : Color.GRAY; } }; final Stroke edgeStroke01 = new BasicStroke(); final float nodeSize = 20; final Stroke edgeStrokeBothContacts = new ShapeStroke(new Shape[] { new Ellipse2D.Float(0, 0, 10, 10) }, nodeSize, true, true); final Stroke edgeStrokeStartContacts = new ShapeStroke( new Shape[] { new Ellipse2D.Float(0, 0, 10, 10) }, nodeSize, true, false); final Stroke edgeStrokeEndContacts = new ShapeStroke(new Shape[] { new Ellipse2D.Float(0, 0, 10, 10) }, nodeSize, false, true); final Stroke edgeStrokeBothContact = new CompoundStroke(edgeStroke01, edgeStrokeBothContacts, CompoundStroke.ADD); final Stroke edgeStrokeStartContact = new CompoundStroke(edgeStroke01, edgeStrokeStartContacts, CompoundStroke.ADD); final Stroke edgeStrokeEndContact = new CompoundStroke(edgeStroke01, edgeStrokeEndContacts, CompoundStroke.ADD); Transformer<EdgeInteraction, Stroke> edgeStrokeTransformer = new Transformer<EdgeInteraction, Stroke>() { @Override public Stroke transform(EdgeInteraction s) { if (s.hasContactsA && s.hasContactsB) { return edgeStrokeBothContact; } if (s.hasContactsA) { return edgeStrokeStartContact; } if (s.hasContactsB) { return edgeStrokeEndContact; } return edgeStroke01; } }; Transformer<MoleculeEntry, String> moleculeLabeller = new Transformer<MoleculeEntry, String>() { @Override public String transform(MoleculeEntry s) { return s.getGeneName() != null ? s.getGeneName() : s.getUniprotAc(); } }; vv.getRenderContext().setVertexFillPaintTransformer(vertexPaint); vv.getRenderContext().setEdgeDrawPaintTransformer(edgePaint); vv.getRenderContext().setEdgeStrokeTransformer(edgeStrokeTransformer); vv.getRenderContext().setVertexLabelTransformer(moleculeLabeller); vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR); DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse(); graphMouse.setMode(ModalGraphMouse.Mode.PICKING); vv.setGraphMouse(graphMouse); JFrame frame = new JFrame("Network " + label); frame.getContentPane().add(vv); frame.pack(); frame.setVisible(true); } } public class ExportXgmmlActionListener implements ActionListener { ExportXgmmlActionListener() { } @Override public void actionPerformed(ActionEvent e) { igbLogger.info("Generate xgmml code for query " + label); // default file name CustomFileChooser fileChooser = new CustomFileChooser( MIBundleConfiguration.getInstance().getExportFolder(), "xgmml", "eXtensible Graph Markup and Modeling Language"); fileChooser.setDialogTitle("Save results"); fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY); fileChooser.setAcceptAllFileFilterUsed(false); if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) { File file = fileChooser.getSelectedFile(); String folder = file.getParentFile().getAbsolutePath(); if (false == folder.equals(MIBundleConfiguration.getInstance().getExportFolder())) { MIBundleConfiguration.getInstance().setExportFolder(folder); } String export = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + "\n<graph label=\"" + label + "\"" + "\nxmlns:dc=\"http://purl.org/dc/elements/1.1/\"" + "\nxmlns:xlink=\"http://www.w3.org/1999/xlink\"" + "\nxmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"" + "\nxmlns:cy=\"http://www.cytoscape.org\"" + "\nxmlns=\"http://www.cs.rpi.edu/XGMML\"" + "\ndirected=\"0\">"; String xgmmlEdges = ""; ArrayList<String> interactors = new ArrayList<>(); for (int tableRow = 0; tableRow < miTable.getRowCount(); tableRow++) { int modelRow = miTable.convertRowIndexToModel(tableRow); MIResult miResult = ((MITableModel) miTable.getModel()).getResult(modelRow); xgmmlEdges += "\n" + miResult.toXgmml(); if (false == interactors.contains(miResult.getContainerId1())) { interactors.add(miResult.getContainerId1()); export += "\n" + "<node id=\"" + miResult.getContainerId1() + "\" label=\"" + miResult.getInteractor1().getGeneName() + "\"><att type=\"string\" name=\"uniprotAcc\" value=\"" + miResult.getInteractor1().getUniprotAc() + "\"/><att type=\"integer\" name=\"numRegions\" value=\"" + miResult.getResiduesA().size() + "\"/><att type=\"string\" name=\"species\" value=\"" + miResult.getInteractor1().getOrganism() + "\"/></node>"; } if (false == interactors.contains(miResult.getContainerId2())) { interactors.add(miResult.getContainerId1()); export += "\n" + "<node id=\"" + miResult.getContainerId2() + "\" label=\"" + miResult.getInteractor2().getGeneName() + "\"><att type=\"string\" name=\"uniprotAcc\" value=\"" + miResult.getInteractor2().getUniprotAc() + "\"/><att type=\"integer\" name=\"numRegions\" value=\"" + miResult.getResiduesB().size() + "\"/><att type=\"string\" name=\"species\" value=\"" + miResult.getInteractor2().getOrganism() + "\"/></node>"; } } export += xgmmlEdges; export += "\n</graph>"; String fileName = file.getPath(); try { try (FileWriter out = new FileWriter(file)) { out.append(export); out.flush(); } } catch (IOException e1) { JOptionPane.showMessageDialog(new JFrame(), "Fail to save the results in " + fileName, "Export error", JOptionPane.ERROR_MESSAGE); } } } } public class FileTypeFilter extends FileFilter { private final String extension; private final String description; public FileTypeFilter(String extension, String description) { this.extension = extension; this.description = description; } @Override public boolean accept(File file) { if (file.isDirectory()) { return true; } return file.getName().endsWith(extension); } @Override public String getDescription() { return description + String.format(" (*%s)", extension); } } /** * The divider location should be set after the component has become * visible. */ @Override public void setVisible(boolean aFlag) { super.setVisible(aFlag); resultBox.setDividerLocation((int) resultBox.getParent().getParent().getWidth() * 4 / 5); //.setDividerLocation((int) (resultBox.getWidth() - structures.getWidth())); } public static class ShapeStroke implements Stroke { private Shape shapes[]; private float advance; private final boolean repeat = true; private final AffineTransform t = new AffineTransform(); private static final float FLATNESS = 1; private boolean start; private boolean end; public ShapeStroke(Shape shapes, float advance, boolean start, boolean end) { this(new Shape[] { shapes }, advance, start, end); } public ShapeStroke(Shape shapes[], float advance, boolean start, boolean end) { this.advance = advance; this.shapes = new Shape[shapes.length]; this.start = start; this.end = end; for (int i = 0; i < this.shapes.length; i++) { Rectangle2D bounds = shapes[i].getBounds2D(); t.setToTranslation(-bounds.getCenterX(), -bounds.getCenterY()); this.shapes[i] = t.createTransformedShape(shapes[i]); } } @Override public Shape createStrokedShape(Shape shape) { GeneralPath result = new GeneralPath(); if (false == start && false == end) { return result; } PathIterator it = new FlatteningPathIterator(shape.getPathIterator(null), FLATNESS); float points[] = new float[6]; float moveX = 0, moveY = 0; float lastX = 0, lastY = 0; float thisX = 0, thisY = 0; int type = 0; boolean first = false; Shape secondLast = null; Shape lastShape = null; float firstX = 0; float firstY = 0; float next = 0; int currentShape = 0; int length = shapes.length; float factor = 1; boolean firstDrawn = false; while (currentShape < length && !it.isDone()) { type = it.currentSegment(points); switch (type) { case PathIterator.SEG_MOVETO: moveX = lastX = points[0]; moveY = lastY = points[1]; result.moveTo(moveX, moveY); if (false == first) { firstX = lastX; firstY = lastY; } first = true; next = 0; //break; case PathIterator.SEG_CLOSE: points[0] = moveX; points[1] = moveY; // Fall into.... case PathIterator.SEG_LINETO: thisX = points[0]; thisY = points[1]; float dx = thisX - lastX; float dy = thisY - lastY; float distance = (float) Math.sqrt(dx * dx + dy * dy); float sdx = thisX - firstX; float sdy = thisY - firstY; if (distance >= next) { float r = 1.0f / distance; float angle = (float) Math.atan2(dy, dx); while (currentShape < length && distance >= next) { float x = lastX + next * dx * r; float y = lastY + next * dy * r; t.setToTranslation(x, y); t.rotate(angle); Shape s = t.createTransformedShape(shapes[currentShape]); if (lastShape == null) { secondLast = s; } else { secondLast = lastShape; } lastShape = s; float d = (float) Math.sqrt(sdx * sdx + sdy * sdy); if (start && d > advance && false == firstDrawn) { result.append(s, false); firstDrawn = true; if (false == end) { return result; } } next += advance; currentShape++; if (repeat) { currentShape %= length; } } } next -= distance; first = false; lastX = thisX; lastY = thisY; break; } it.next(); } if (end) { result.append(secondLast, false); } return result; } } public static class CompoundStroke implements Stroke { public final static int ADD = 0; public final static int SUBTRACT = 1; public final static int INTERSECT = 2; public final static int DIFFERENCE = 3; private final Stroke stroke1, stroke2; private final int operation; public CompoundStroke(Stroke stroke1, Stroke stroke2, int operation) { this.stroke1 = stroke1; this.stroke2 = stroke2; this.operation = operation; } @Override public Shape createStrokedShape(Shape shape) { Area area1 = new Area(stroke1.createStrokedShape(shape)); Area area2 = new Area(stroke2.createStrokedShape(shape)); switch (operation) { case ADD: area1.add(area2); break; case SUBTRACT: area1.subtract(area2); break; case INTERSECT: area1.intersect(area2); break; case DIFFERENCE: area1.exclusiveOr(area2); break; } return area1; } } class ScoreListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { switch (e.getActionCommand()) { case "<html>" + HTML_SCORE_0 + "</html>": miTable.setScoreLimit(0); break; case "<html>" + HTML_SCORE_1 + "</html>": miTable.setScoreLimit(1); break; case "<html>" + HTML_SCORE_2 + "</html>": miTable.setScoreLimit(2); break; case "<html>" + HTML_SCORE_3 + "</html>": miTable.setScoreLimit(3); break; } } } class EvidenceTypeListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { AbstractButton abstractButton = (AbstractButton) e.getSource(); switch (e.getActionCommand()) { case HTML_CHECKBOX_PHYSICAL: miTable.setShowPhysical(abstractButton.isSelected()); break; case HTML_CHECKBOX_ASSOCIATION: miTable.setShowAssociations(abstractButton.isSelected()); break; case HTML_CHECKBOX_ENZYMATIC: miTable.setShowEnzymatic(abstractButton.isSelected()); break; case HTML_CHECKBOX_OTHER: miTable.setShowOther(abstractButton.isSelected()); break; case HTML_CHECKBOX_UNSPECIFIED: miTable.setShowUnspecified(abstractButton.isSelected()); break; case HTML_CHECKBOX_STRUCTURE: miTable.setShowStructure(abstractButton.isSelected()); break; } } } public static void main(String[] args) { MIResultPanel p = new MIResultPanel(null, "test", new ArrayList<MIResult>(), "test", new MIQuery()); JFrame f = new JFrame(); f.setSize(1024, 800); f.add(p); f.show(); } }