package jalview.appletgui; import java.awt.event.*; import java.awt.*; public class OverviewPanel extends Panel implements Runnable { Image miniMe; AlignViewport av; AlignmentPanel ap; float scalew = 1f; float scaleh = 1f; public int width, sequencesHeight; int graphHeight=30; int boxX=-1, boxY=-1, boxWidth=-1, boxHeight=-1; boolean resizing = false; Frame nullFrame; public OverviewPanel(AlignmentPanel ap) { this.av = ap.av; this.ap = ap; setLayout(null); nullFrame = new Frame(); nullFrame.addNotify(); // scale the initial size of overviewpanel to shape of alignment float initialScale = (float)av.alignment.getWidth()/(float)av.alignment.getHeight(); if(av.alignment.getWidth() > av.alignment.getHeight()) { // wider width = 400; sequencesHeight = (int)(400f/initialScale); } else { // taller width = (int)(400f*initialScale); sequencesHeight = 300; if(width<120) width = 120; } setSize (new Dimension(width, sequencesHeight+graphHeight)); addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent evt) { if( getSize().width!=width || getSize().height!=sequencesHeight+graphHeight) { updateOverviewImage(); } } }); addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent evt) { doMouseDragged(evt);} }); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent evt) { doMousePressed(evt);} public void mouseReleased(MouseEvent evt) { doMouseReleased(evt);} }); updateOverviewImage(); } public void doMousePressed(MouseEvent evt) { boxX = evt.getX(); boxY = evt.getY(); checkValid(); repaint(); } public void doMouseReleased(MouseEvent evt) { boxX = evt.getX(); boxY = evt.getY(); checkValid(); if(!resizing) ap.setScrollValues( (int)(boxX/scalew/av.getCharWidth()), (int)(boxY/scaleh/av.getCharHeight()) ); } public void doMouseDragged(MouseEvent evt) { boxX = evt.getX(); boxY = evt.getY(); checkValid(); if(!resizing) ap.setScrollValues( (int)(boxX/scalew/av.getCharWidth()), (int)(boxY/scaleh/av.getCharHeight()) ); repaint(); ap.repaint(); } void checkValid() { if (boxY < 0) boxY = 0; if (boxY > sequencesHeight - boxHeight) boxY = sequencesHeight - boxHeight+1; if (boxX < 0) boxX = 0; if (boxX > width - boxWidth) boxX = width - boxWidth; } public void updateOverviewImage() { if(resizing) { return; } resizing = true; Thread thread = new Thread(this); thread.start(); repaint(); } public void run() { miniMe = null; int alwidth = av.alignment.getWidth(); int alheight = av.alignment.getHeight(); if(getSize().width>0 && getSize().height>0) { width = getSize().width; sequencesHeight = getSize().height - graphHeight; } setSize (new Dimension(width, sequencesHeight+graphHeight)); int fullsizeWidth = alwidth * av.getCharWidth(); int fullsizeHeight = alheight * av.getCharHeight(); scalew = (float) width / (float) fullsizeWidth; scaleh = (float) sequencesHeight / (float) fullsizeHeight; miniMe = nullFrame.createImage(width, sequencesHeight + graphHeight); Graphics mg = miniMe.getGraphics(); Image consensus = nullFrame.createImage(fullsizeWidth, 60); Graphics g = consensus.getGraphics(); ap.annotationPanel.drawGraph(g, av.conservation, fullsizeWidth, 60); mg.drawImage(consensus, 0, sequencesHeight, width, sequencesHeight + graphHeight, 0, 0, fullsizeWidth, 60, this); boolean oldRenderGaps = av.renderGaps; try{ // We'll have to draw the full size alignment in chunks, as an image of the // whole alignment requires too much memory // Max size depends on the font size, the following is a // guess at a size which works int maxSize = 2000 / av.getFont().getSize(); Image block; int blockx=0, blocky=0, blockw=0, blockh=0, eRes=0, eSeq=0; av.setRenderGaps(false); for(int sRes=0, chunkx=0; sResalwidth) eRes = alwidth; for(int sSeq=0, chunky=0; sSeqalheight) eSeq = alheight; blocky = 0; blockx = (int)((float)sRes/(float)alwidth * width); block = nullFrame.createImage((eRes-sRes)*av.charWidth, (eSeq-sSeq)*av.charHeight); g = block.getGraphics(); ap.seqPanel.seqCanvas.drawPanel(g, sRes, eRes, sSeq, eSeq, sRes, sSeq, 0); blockh = (int)( (float)(eSeq-sSeq)/(float)alheight * sequencesHeight )+1 ; blockw = (int)( (float)(eRes-sRes)/(float)alwidth * width )+1; blocky += (int) ((float)sSeq/(float)alheight* sequencesHeight); mg.drawImage(block, blockx, blocky , blockx + blockw, blocky + blockh, 0, 0, block.getWidth(null),block.getHeight(null), this); block = null; } } }catch(OutOfMemoryError error) { System.out.println("out of memory"); } av.setRenderGaps(oldRenderGaps); resizing = false; setBoxPosition(); } public void setBoxPosition() { boxX = (int) (av.getStartRes() * av.getCharWidth() * scalew); boxY = (int) (av.getStartSeq() * av.getCharHeight() * scaleh); boxWidth = (int) ((av.getEndRes()-av.getStartRes()+1)* av.getCharWidth() * scalew) ; boxHeight = (int) (av.getEndSeq() * av.getCharHeight() * scaleh) - boxY; repaint(); } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { if(resizing) { g.setColor(Color.white); g.fillRect(0, 0, getSize().width, getSize().height); g.setColor(Color.black); g.setFont(new Font("Verdana", Font.BOLD, 15)); g.drawString("Recalculating", 5, sequencesHeight/2); g.drawString("Overview.....", 5, sequencesHeight/2 +20); } else { if(miniMe!=null) g.drawImage(miniMe, 0,0,this); g.setColor(Color.red); g.drawRect(boxX, boxY, boxWidth, boxHeight); g.drawRect(boxX+1, boxY+1, boxWidth-2, boxHeight-2); } } }