/* * The MIT License (MIT) * * Copyright (c) 2007-2015 Broad Institute * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.broad.igv.ui.panel; import org.apache.log4j.Logger; import org.broad.igv.exceptions.DataLoadException; import org.broad.igv.renderer.DataRange; import org.broad.igv.track.*; import org.broad.igv.ui.IGV; import org.broad.igv.ui.MessageCollection; import org.broad.igv.ui.util.MessageUtils; import org.broad.igv.util.HttpUtils; import org.broad.igv.util.ResourceLocator; import java.awt.*; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.dnd.*; import java.io.File; import java.util.*; import java.util.List; /** * @author jrobinso * @date Sep 8, 2010 */ public class DataPanelContainer extends TrackPanelComponent implements Paintable { private static Logger log = Logger.getLogger(DataPanelContainer.class); TrackPanel parent; public DataPanelContainer(TrackPanel trackPanel) { super(trackPanel); DropTarget target = new DropTarget(this, new FileDropTargetListener(trackPanel)); setDropTarget(target); target.setActive(true); this.setLayout(new DataPanelLayout()); this.parent = trackPanel; createDataPanels(); } public void createDataPanels() { removeAll(); for (ReferenceFrame f : FrameManager.getFrames()) { if (f.isVisible()) { DataPanel dp = new DataPanel(f, this); add(dp); } } invalidate(); } @Override public void setBackground(Color color) { super.setBackground(color); for (Component c : this.getComponents()) { if (c instanceof DataPanel) { c.setBackground(color); } } } public Collection<TrackGroup> getTrackGroups() { TrackPanel dataTrackView = (TrackPanel) getParent(); return dataTrackView.getGroups(); } public int getVisibleHeight() { TrackPanel dataTrackView = (TrackPanel) getParent(); return dataTrackView.getVisibleRect().height; } public void setCurrentTool(RegionOfInterestTool regionOfInterestTool) { for (Component c : this.getComponents()) { if (c instanceof DataPanel) { ((DataPanel) c).setCurrentTool(regionOfInterestTool); } } } /** * Paint to an offscreen graphic, e.g. a graphic for an image or svg file. * * @param g * @param rect */ public void paintOffscreen(Graphics2D g, Rectangle rect) { // Get the components of the sort by X position. Component[] components = getComponents(); Arrays.sort(components, new Comparator<Component>() { public int compare(Component component, Component component1) { return component.getX() - component1.getX(); } }); for (Component c : this.getComponents()) { if (c instanceof DataPanel) { Graphics2D g2d = (Graphics2D) g.create(); Rectangle clipRect = new Rectangle(c.getBounds()); clipRect.height = rect.height; g2d.setClip(clipRect); g2d.translate(c.getX(), 0); ((DataPanel) c).paintOffscreen(g2d, rect); } } //super.paintBorder(g); } @Override protected void paintChildren(Graphics g) { autoscale(); super.paintChildren(g); if (IGV.getInstance().isRulerEnabled()) { int start = MouseInfo.getPointerInfo().getLocation().x - getLocationOnScreen().x; g.setColor(Color.BLACK); g.drawLine(start, 0, start, getHeight()); } } private class FileDropTargetListener implements DropTargetListener { private TrackPanel panel; public FileDropTargetListener(TrackPanel dataPanel) { panel = dataPanel; } public void dragEnter(DropTargetDragEvent event) { if (!isDragAcceptable(event)) { event.rejectDrag(); return; } } public void dragExit(DropTargetEvent event) { } public void dragOver(DropTargetDragEvent event) { // you can provide visual feedback here } public void dropActionChanged(DropTargetDragEvent event) { if (!isDragAcceptable(event)) { event.rejectDrag(); return; } } public void drop(DropTargetDropEvent event) { if (!isDropAcceptable(event)) { event.rejectDrop(); return; } event.acceptDrop(DnDConstants.ACTION_COPY); Transferable transferable = event.getTransferable(); MessageCollection messages = new MessageCollection(); try { List<File> files = (List<File>) transferable.getTransferData(DataFlavor.javaFileListFlavor); for (File file : files) { try { ResourceLocator locator = new ResourceLocator(file.getAbsolutePath()); IGV.getInstance().load(locator, panel); } catch (DataLoadException de) { messages.append(de.getMessage()); } } String obj = transferable.getTransferData(DataFlavor.stringFlavor).toString(); if (HttpUtils.isRemoteURL(obj)) { IGV.getInstance().load(new ResourceLocator(obj), panel); } if (messages != null && !messages.isEmpty()) { log.error(messages.getFormattedMessage()); MessageUtils.showMessage(messages.getFormattedMessage()); } } catch (Exception e) { String obj = null; try { obj = transferable.getTransferData(DataFlavor.stringFlavor).toString(); if (HttpUtils.isRemoteURL(obj)) { IGV.getInstance().load(new ResourceLocator(obj), panel); } } catch (Exception e1) { log.error(e1); if (messages != null && !messages.isEmpty()) { MessageUtils.showMessage(messages.getFormattedMessage()); } } } IGV.getMainFrame().repaint(); event.dropComplete(true); } public boolean isDragAcceptable(DropTargetDragEvent event) { // usually, you // check the // available // data flavors // here // in this program, we accept all flavors return (event.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0; } public boolean isDropAcceptable(DropTargetDropEvent event) { // usually, you // check the // available // data flavors // here // in this program, we accept all flavors return (event.getDropAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0; } } private void autoscale() { final Collection<Track> trackList = IGV.getInstance().getAllTracks(); Map<String, List<Track>> autoscaleGroups = new HashMap<String, List<Track>>(); for (Track track : trackList) { if (!track.isVisible()) continue; String asGroup = track.getAttributeValue(AttributeManager.GROUP_AUTOSCALE); if (asGroup != null) { if (!autoscaleGroups.containsKey(asGroup)) { autoscaleGroups.put(asGroup, new ArrayList<Track>()); } if (track instanceof MergedTracks) { for (Track mt : ((MergedTracks) track).getMemberTracks()) { autoscaleGroups.get(asGroup).add(track); } } else { autoscaleGroups.get(asGroup).add(track); } } else if (track.getAutoScale()) { if (track instanceof MergedTracks) { for (Track mt : ((MergedTracks) track).getMemberTracks()) { autoscaleGroup(Arrays.asList(mt)); } } else { autoscaleGroup(Arrays.asList(track)); } } } if (autoscaleGroups.size() > 0) { for (List<Track> tracks : autoscaleGroups.values()) { autoscaleGroup(tracks); } } } private void autoscaleGroup(List<Track> trackList) { List<ReferenceFrame> frames = FrameManager.isGeneListMode() ? FrameManager.getFrames() : Arrays.asList(FrameManager.getDefaultFrame()); List<Range> inViewRanges = new ArrayList<Range>(); synchronized (trackList) { for (Track track : trackList) { if (track instanceof ScalableTrack) { for (ReferenceFrame frame : frames) { Range range = ((ScalableTrack) track).getInViewRange(frame); if (range != null) { inViewRanges.add(range); } } } } if (inViewRanges.size() > 0) { Range inter = computeScale(inViewRanges); for (Track track : trackList) { DataRange dr = track.getDataRange(); float min = Math.min(0, inter.min); float base = Math.max(min, dr.getBaseline()); float max = inter.max; // Pathological case where min ~= max (no data in view) if (max - min <= (2 * Float.MIN_VALUE)) { max = min + 1; } DataRange newDR = new DataRange(min, base, max, dr.isDrawBaseline()); newDR.setType(dr.getType()); track.setDataRange(newDR); } } } } public static Range computeScale(List<Range> ranges) { float min = 0; float max = 0; if (ranges.size() > 0) { max = ranges.get(0).max; min = ranges.get(0).min; for (int i = 1; i < ranges.size(); i++) { Range r = ranges.get(i); max = Math.max(r.max, max); min = Math.min(r.min, min); } } return new Range(min, max); } }