DepthTimeCanvas.java

Go to the documentation of this file.
00001 package edu.rice.cs.hpc.traceviewer.depth;
00002 
00003 import java.util.concurrent.ExecutorService;
00004 import java.util.concurrent.Executors;
00005 
00006 import org.eclipse.core.commands.ExecutionException;
00007 import org.eclipse.core.commands.operations.IOperationHistoryListener;
00008 import org.eclipse.core.commands.operations.IUndoableOperation;
00009 import org.eclipse.core.commands.operations.OperationHistoryEvent;
00010 import org.eclipse.core.runtime.jobs.IJobChangeEvent;
00011 import org.eclipse.core.runtime.jobs.IJobChangeListener;
00012 import org.eclipse.swt.SWT;
00013 import org.eclipse.swt.events.DisposeEvent;
00014 import org.eclipse.swt.events.DisposeListener;
00015 import org.eclipse.swt.events.PaintEvent;
00016 import org.eclipse.swt.graphics.GC;
00017 import org.eclipse.swt.graphics.Image;
00018 import org.eclipse.swt.graphics.Point;
00019 import org.eclipse.swt.graphics.Rectangle;
00020 import org.eclipse.swt.widgets.Composite;
00021 import edu.rice.cs.hpc.common.ui.Util;
00022 import edu.rice.cs.hpc.traceviewer.operation.BufferRefreshOperation;
00023 import edu.rice.cs.hpc.traceviewer.operation.PositionOperation;
00024 import edu.rice.cs.hpc.traceviewer.operation.TraceOperation;
00025 import edu.rice.cs.hpc.traceviewer.operation.ZoomOperation;
00026 import edu.rice.cs.hpc.traceviewer.painter.AbstractTimeCanvas;
00027 import edu.rice.cs.hpc.traceviewer.painter.BaseViewPaint;
00028 import edu.rice.cs.hpc.traceviewer.painter.ISpaceTimeCanvas;
00029 import edu.rice.cs.hpc.traceviewer.painter.ImageTraceAttributes;
00030 import edu.rice.cs.hpc.traceviewer.spaceTimeData.Frame;
00031 import edu.rice.cs.hpc.traceviewer.spaceTimeData.Position;
00032 import edu.rice.cs.hpc.traceviewer.spaceTimeData.SpaceTimeDataController;
00033 import edu.rice.cs.hpc.traceviewer.util.Utility;
00034 import edu.rice.cs.hpc.traceviewer.data.util.Constants;
00035 import edu.rice.cs.hpc.traceviewer.data.util.Debugger;
00036 
00038 public class DepthTimeCanvas extends AbstractTimeCanvas 
00039 implements IOperationHistoryListener, ISpaceTimeCanvas
00040 {   
00041     final private ExecutorService threadExecutor;
00042 
00043     private SpaceTimeDataController stData;
00044     private int currentProcess = Integer.MIN_VALUE;
00045     private boolean needToRedraw = false;
00046 
00047     /********************
00048      * constructor to create this canvas
00049      * 
00050      * @param composite : the parent composite
00051      */
00052     public DepthTimeCanvas(Composite composite)
00053     {
00054         super(composite, SWT.NONE);
00055         
00056         threadExecutor = Executors.newFixedThreadPool( Utility.getNumThreads(0) ); 
00057         addDisposeListener( new DisposeListener() {
00058             
00059             @Override
00060             public void widgetDisposed(DisposeEvent e) {
00061                 dispose();              
00062             }
00063         });
00064     }
00065     
00066     /****
00067      * new data update
00068      * @param _stData
00069      */
00070     public void updateView(SpaceTimeDataController stData)
00071     {
00072         super.init();
00073         setVisible(true);
00074         
00075         if (this.stData == null) {
00076             // just initialize once
00077             TraceOperation.getOperationHistory().addOperationHistoryListener(this);
00078         }
00079         this.stData = stData;       
00080     }
00081     
00082     /*
00083      * (non-Javadoc)
00084      * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
00085      */
00086     public void paintControl(PaintEvent event)
00087     {
00088         if (this.stData == null)
00089             return;
00090         
00091         if (needToRedraw) {
00092             refreshWithCondition();
00093             
00094             // set the flag that we don't need to redraw again
00095             needToRedraw = false;
00096         }
00097         super.paintControl(event);
00098         
00099         final long topLeftPixelX = Math.round(stData.getAttributes().getTimeBegin()*getScalePixelsPerTime());
00100         final int viewHeight     = getClientArea().height;
00101 
00102         //--------------------
00103         //draws cross hairs
00104         //--------------------
00105         
00106         event.gc.setBackground(Constants.COLOR_WHITE);
00107         event.gc.setAlpha(240);
00108         
00109         long selectedTime = stData.getAttributes().getFrame().position.time;
00110         
00111         int topPixelCrossHairX = (int)(Math.round(selectedTime*getScalePixelsPerTime())-2-topLeftPixelX);
00112         event.gc.fillRectangle(topPixelCrossHairX,0,4,viewHeight);
00113         
00114         final int maxDepth = stData.getMaxDepth();
00115         final int depth    = stData.getAttributes().getDepth();
00116         
00117         final int width    = depth*viewHeight/maxDepth+viewHeight/(2*maxDepth);
00118         event.gc.fillRectangle(topPixelCrossHairX-8,width-1,20,4);
00119     }
00120     
00121     
00122     /***
00123      * force to refresh the content of the canvas. 
00124      */
00125     public void refresh() 
00126     {
00127         rebuffer();
00128     }
00129     
00130     public void activate(boolean isActivated)
00131     {
00132         this.needToRedraw = isActivated;
00133     }
00134     
00135     /****
00136      *  refresh only if the size of the buffer doesn't match with the size of the canvas
00137      */
00138     private void refreshWithCondition() 
00139     {
00140         if (imageBuffer == null) {
00141             if (stData != null) {
00142                 rebuffer();
00143             }
00144             return;
00145         }
00146         
00147         // ------------------------------------------------------------------------
00148         // we need to avoid repainting if the size of the image buffer is not the same
00149         // as the image of the canvas. This case happens when the view is resize while
00150         // it's in hidden state, and then it turns visible. 
00151         // this will cause misalignment in the view
00152         // ------------------------------------------------------------------------
00153         
00154         final Rectangle r1 = imageBuffer.getBounds();
00155         final Rectangle r2 = getClientArea();
00156         
00157         if (!(r1.height == r2.height && r1.width == r2.width))
00158         {
00159             // the size if not the same, we need to recompute and repaint again
00160             rebuffer();
00161         }
00162     }
00163     
00164     
00165     public double getScalePixelsPerTime()
00166     {
00167         final int viewWidth = getClientArea().width;
00168 
00169         return (double)viewWidth / (double)getNumTimeDisplayed();
00170     }
00171 
00172     public double getScalePixelsPerRank() {
00173         final Rectangle r = this.getClientArea();
00174         return Math.max(r.height/(double)stData.getMaxDepth(), 1);
00175     }
00176 
00177     
00178     //---------------------------------------------------------------------------------------
00179     // PRIVATE METHODS
00180     //---------------------------------------------------------------------------------------
00181 
00182     private long getNumTimeDisplayed()
00183     {
00184         return (stData.getAttributes().getTimeInterval());
00185     }
00186     
00187     
00188     /************
00189      * method to repaint the canvas
00190      * this method can be costly, please do not call this unless the data has changed
00191      * 
00192      */
00193     private void rebuffer()
00194     {
00195         if (stData == null || !isVisible())
00196             return;
00197 
00198         final ImageTraceAttributes attributes = stData.getAttributes();
00199         final Frame frame = attributes.getFrame();
00200 
00201         // store the current process so that we don't need to rebuffer every time
00202         // we change the position within the same process
00203         currentProcess = frame.position.process;
00204 
00205         final Rectangle rb = getBounds();
00206         
00207         final int viewWidth  = rb.width;
00208         final int viewHeight = rb.height;
00209 
00210         if (viewWidth>0 && viewHeight>0) {
00211             if (imageBuffer != null) {
00212                 imageBuffer.dispose();
00213             }
00214             //paints the current screen
00215             imageBuffer = new Image(getDisplay(), viewWidth, viewHeight);
00216         } else {
00217             // empty canvas to view
00218             return;
00219         }
00220         final GC bufferGC = new GC(imageBuffer);
00221         bufferGC.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
00222         bufferGC.fillRectangle(0,0,viewWidth,viewHeight);
00223         
00224         attributes.numPixelsDepthV = viewHeight;
00225         
00226         Debugger.printDebug(1, "DTC rebuffering " + attributes);
00227         
00228         BaseViewPaint depthPaint = new DepthViewPaint(Util.getActiveWindow(), bufferGC, 
00229                 stData, attributes, true, this, threadExecutor);
00230         
00231         depthPaint.setUser(true);
00232         depthPaint.addJobChangeListener(new DepthJobListener(bufferGC));
00233         depthPaint.schedule();
00234     }
00235 
00236     /*
00237      * (non-Javadoc)
00238      * @see org.eclipse.swt.widgets.Widget#dispose()
00239      */
00240     public void dispose()
00241     {
00242         threadExecutor.shutdown();
00243         super.dispose();
00244     }
00245 
00246 
00247     @Override
00248     /*
00249      * (non-Javadoc)
00250      * @see org.eclipse.core.commands.operations.IOperationHistoryListener#historyNotification(org.eclipse.core.commands.operations.OperationHistoryEvent)
00251      */
00252     public void historyNotification(final OperationHistoryEvent event) {
00253         
00254         if (event.getEventType() == OperationHistoryEvent.DONE) 
00255         {
00256             final IUndoableOperation operation = event.getOperation();
00257 
00258             if (operation.hasContext(BufferRefreshOperation.context)) {
00259                 // this event includes if there's a change of colors definition, so everyone needs
00260                 // to refresh the content
00261                 super.init();
00262                 rebuffer();
00263                 
00264             } else if (operation.hasContext(PositionOperation.context)) {
00265                 PositionOperation opPos = (PositionOperation) operation;
00266                 Position position = opPos.getPosition();
00267                 if (position.process == currentProcess)
00268                 {
00269                     // changing cursor position within the same process
00270                     redraw();
00271                 } else {
00272                     // different process, we need to repaint every thing
00273                     rebuffer();
00274                 }
00275             }
00276         }
00277     }
00278 
00279     @Override
00280     protected void changePosition(Point point) {
00281         long closeTime = stData.getAttributes().getTimeBegin() + (long)(point.x / getScalePixelsPerTime());
00282         
00283         Position currentPosition = stData.getAttributes().getPosition();
00284         Position newPosition = new Position(closeTime, currentPosition.process);
00285             
00286         try {
00287             TraceOperation.getOperationHistory().execute(
00288                     new PositionOperation(newPosition), 
00289                     null, null);
00290         } catch (ExecutionException e) {
00291             e.printStackTrace();
00292         }
00293         
00294     }
00295 
00296     @Override
00297     protected void changeRegion(Rectangle region) 
00298     {
00299         final ImageTraceAttributes attributes = stData.getAttributes();
00300 
00301         long topLeftTime     = attributes.getTimeBegin() + (long)(region.x / getScalePixelsPerTime());
00302         long bottomRightTime = attributes.getTimeBegin() + (long)((region.width+region.x) / getScalePixelsPerTime());
00303         
00304         final Frame oldFrame    = attributes.getFrame();
00305         final Position position = oldFrame.position;
00306         
00307         Frame frame = new Frame(topLeftTime, bottomRightTime,
00308                 attributes.getProcessBegin(), attributes.getProcessEnd(),
00309                 attributes.getDepth(), position.time, position.process);
00310         try {
00311             TraceOperation.getOperationHistory().execute(
00312                     new ZoomOperation("Time zoom out", frame), 
00313                     null, null);
00314         } catch (ExecutionException e) {
00315             e.printStackTrace();
00316         }
00317     }
00318     
00319     private class DepthJobListener implements IJobChangeListener
00320     {
00321         final private GC bufferGC;
00322         
00323         public DepthJobListener(GC bufferGC)
00324         {
00325             this.bufferGC = bufferGC;
00326         }
00327         
00328         @Override
00329         public void sleeping(IJobChangeEvent event) {}
00330         
00331         @Override
00332         public void scheduled(IJobChangeEvent event) {}
00333         
00334         @Override
00335         public void running(IJobChangeEvent event) {}
00336         
00337         @Override
00338         public void done(IJobChangeEvent event) {
00339             bufferGC.dispose();             
00340             redraw();
00341         }
00342         
00343         @Override
00344         public void awake(IJobChangeEvent event) {}
00345         
00346         @Override
00347         public void aboutToRun(IJobChangeEvent event) {}
00348 
00349     }
00350 }

Generated on 5 May 2015 for HPCVIEWER by  doxygen 1.6.1