SummaryTimeCanvas.java

Go to the documentation of this file.
00001 package edu.rice.cs.hpc.traceviewer.summary;
00002 
00003 import java.util.Iterator;
00004 import java.util.Set;
00005 import java.util.TreeMap;
00006 
00007 import org.eclipse.core.commands.ExecutionException;
00008 import org.eclipse.core.commands.operations.IOperationHistoryListener;
00009 import org.eclipse.core.commands.operations.OperationHistoryEvent;
00010 import org.eclipse.core.commands.operations.OperationHistoryFactory;
00011 import org.eclipse.jface.window.DefaultToolTip;
00012 import org.eclipse.jface.window.ToolTip;
00013 import org.eclipse.swt.SWT;
00014 import org.eclipse.swt.events.PaintEvent;
00015 import org.eclipse.swt.graphics.Color;
00016 import org.eclipse.swt.graphics.GC;
00017 import org.eclipse.swt.graphics.Image;
00018 import org.eclipse.swt.graphics.ImageData;
00019 import org.eclipse.swt.graphics.Point;
00020 import org.eclipse.swt.graphics.RGB;
00021 import org.eclipse.swt.graphics.Rectangle;
00022 import org.eclipse.swt.widgets.Composite;
00023 import org.eclipse.swt.widgets.Control;
00024 import org.eclipse.swt.widgets.Event;
00025 
00026 import edu.rice.cs.hpc.traceviewer.operation.BufferRefreshOperation;
00027 import edu.rice.cs.hpc.traceviewer.operation.TraceOperation;
00028 import edu.rice.cs.hpc.traceviewer.operation.ZoomOperation;
00029 import edu.rice.cs.hpc.traceviewer.painter.AbstractTimeCanvas;
00030 import edu.rice.cs.hpc.traceviewer.painter.ImageTraceAttributes;
00031 import edu.rice.cs.hpc.traceviewer.spaceTimeData.Frame;
00032 import edu.rice.cs.hpc.traceviewer.spaceTimeData.Position;
00033 import edu.rice.cs.hpc.traceviewer.spaceTimeData.SpaceTimeDataController;
00034 import edu.rice.cs.hpc.traceviewer.data.util.Constants;
00035 import edu.rice.cs.hpc.traceviewer.data.util.Debugger;
00036 
00037 /******************************************************************
00038  * 
00039  * Canvas class for summary view
00040  *
00041  ******************************************************************/
00042 public class SummaryTimeCanvas extends AbstractTimeCanvas 
00043 implements IOperationHistoryListener
00044 {   
00045     private SpaceTimeDataController dataTraces = null;
00046     private TreeMap<Integer, Integer> mapStatistics;
00047     private int totPixels;
00048     private ImageData detailData;
00049     private boolean needToRedraw = false;
00050     private ToolTip tooltip;
00051     
00052     /**********************************
00053      * Construct a summary canvas without background nor scrollbar
00054      * 
00055      * @param composite
00056      **********************************/
00057     public SummaryTimeCanvas(Composite composite)
00058     {
00059         super(composite, SWT.NO_BACKGROUND);
00060         
00061         OperationHistoryFactory.getOperationHistory().addOperationHistoryListener(this);
00062         
00063         // ------------------------------------------------------------------------------------------
00064         // setup tooltip information about the percentage of the color appointed by the mouse
00065         // ------------------------------------------------------------------------------------------
00066         tooltip = new SummaryTooltip(this) ;
00067         tooltip.deactivate();
00068     }
00069     
00070     @Override
00071     public void paintControl(PaintEvent event)
00072     {
00073         super.paintControl(event);
00074         if (needToRedraw) {
00075             refreshWithCondition();
00076             needToRedraw = false;
00077         }
00078     }
00079     
00080     /****
00081      * called to be notify when the canvas is visible and needs to be activated
00082      * 
00083      * @param isActivated
00084      */
00085     public void activate(boolean isActivated)
00086     {
00087         needToRedraw = isActivated;
00088     }
00089 
00090     private void refreshWithCondition()
00091     {
00092         if (imageBuffer == null){
00093             // ------------------------------------------------------------------------
00094             // ------------------------------------------------------------------------
00095             if (detailData != null) {
00096                 rebuffer(detailData);
00097                 return;
00098             }
00099         }
00100         
00101         // ------------------------------------------------------------------------
00102         // we need to avoid repainting if the size of the image buffer is not the same
00103         // as the image of the canvas. This case happens when the view is resize while
00104         // it's in hidden state, and then it turns visible. 
00105         // this will cause misalignment in the view
00106         // ------------------------------------------------------------------------
00107         final Rectangle r1 = imageBuffer.getBounds();
00108         final Rectangle r2 = getClientArea();
00109         
00110         if (!(r1.height == r2.height && r1.width == r2.width))
00111         {
00112             rebuffer(detailData);
00113             return;
00114         }
00115     }
00116     
00117     
00118     
00119     
00120     /*****
00121      * rebuffers the data in the summary time canvas and then asks receiver to paint it again
00122      *****/
00123     private void rebuffer(ImageData detailData)
00124     {
00125         // store the original image data for further usage such as when the painting is needed.
00126         this.detailData = detailData;
00127         
00128         if (detailData == null || !isVisible())
00129             return;
00130 
00131         // ------------------------------------------------------------------------------------------
00132         // let use GC instead of ImageData since GC allows us to draw lines and rectangles
00133         // ------------------------------------------------------------------------------------------
00134         if (imageBuffer != null) {
00135             imageBuffer.dispose();
00136         }
00137         final int viewWidth = getBounds().width;
00138         final int viewHeight = getBounds().height;
00139 
00140         if (viewWidth == 0 || viewHeight == 0)
00141             return;
00142 
00143         imageBuffer = new Image(getDisplay(), viewWidth, viewHeight);
00144         GC buffer = new GC(imageBuffer);
00145         buffer.setBackground(Constants.COLOR_WHITE);
00146         buffer.fillRectangle(0, 0, viewWidth, viewHeight);
00147         
00148         float yScale = (float)viewHeight / (float)detailData.height;
00149         float xScale = ((float)viewWidth / (float)detailData.width);
00150         int xOffset = 0;
00151 
00152         mapStatistics = new TreeMap<Integer, Integer>();
00153         
00154         //---------------------------------------------------------------------------
00155         // needs to be optimized:
00156         // for every pixel along the width, check the pixel, group them based on color,
00157         //   count the amount of each group, and draw the pixel
00158         //---------------------------------------------------------------------------
00159         for (int x = 0; x < detailData.width; ++x)
00160         {
00161             //---------------------------------------------------------------------------
00162             // use tree map to sort the key of color map
00163             // without sort, it can be confusing
00164             //---------------------------------------------------------------------------
00165             TreeMap<Integer, Integer> sortedColorMap = new TreeMap<Integer, Integer>();
00166 
00167             for (int y = 0; y < detailData.height; ++y)
00168             {
00169                 int pixelValue = detailData.getPixel(x,y);
00170                 if (sortedColorMap.containsKey(pixelValue))
00171                     sortedColorMap.put( pixelValue , sortedColorMap.get(pixelValue)+1 );
00172                 else
00173                     sortedColorMap.put( pixelValue , 1);
00174             }
00175             Set<Integer> set = sortedColorMap.keySet();
00176             int yOffset = viewHeight;
00177             
00178             int h = 0;
00179             //---------------------------------------------------------------------------
00180             // draw the line of a specific color with a specific length from bottom to the top
00181             // note: the coordinates 0,0 starts from the top-left corner !
00182             //---------------------------------------------------------------------------
00183             for (Iterator<Integer> it = set.iterator(); it.hasNext(); ) 
00184             {
00185                 final Integer pixel = it.next();
00186                 final RGB rgb = detailData.palette.getRGB(pixel);
00187                 final Color c = new Color(getDisplay(), rgb);
00188                 final Integer numCounts = sortedColorMap.get(pixel);
00189                 final int height = Math.round(numCounts * yScale);
00190                 
00191                 buffer.setBackground(c);
00192                 
00193                 // if this is the last color, we should draw from the current position to the end
00194                 // this may not be the best solution, but the round-up in height variable may give
00195                 // empty spaces if the number of colors are not a height's divisor.
00196                 
00197                 if (it.hasNext())
00198                     buffer.fillRectangle(xOffset, yOffset-height, (int) Math.max(1, xScale), height);
00199                 else
00200                     buffer.fillRectangle(xOffset, 0, (int) Math.max(1, xScale), viewHeight-h);
00201                 yOffset -= height;
00202                 c.dispose();
00203                 
00204                 // accumulate the statistics of this pixel
00205                 Integer val = mapStatistics.get(pixel);
00206                 Integer acc = (val==null?  numCounts : val + numCounts);
00207                 mapStatistics.put(pixel, acc);
00208                 
00209                 h += height;
00210             }
00211             xOffset = Math.round(xOffset + xScale);
00212         }
00213         totPixels = detailData.width * detailData.height;
00214 
00215         buffer.dispose();
00216         
00217         tooltip.activate();
00218 
00219         redraw();
00220     }
00221     
00222     /****
00223      * main method to decide whether we want to create a new buffer or just to
00224      * redraw the canvas
00225      * 
00226      * @param _detailData : new data
00227      */
00228     private void refresh(ImageData detailData)
00229     {
00230         super.init();       
00231         rebuffer(detailData);
00232     }
00233     
00234     /********
00235      * set the new database
00236      * @param data
00237      ********/
00238     public void updateData(SpaceTimeDataController data)
00239     {
00240         dataTraces = data;
00241         needToRedraw = true; // new data
00242         setVisible(true);
00243     }
00244 
00245     
00246     /*****
00247      * get the number of pixel per time unit
00248      * @return
00249      */
00250     private double getScalePixelsPerTime()
00251     {
00252         final int viewWidth = getClientArea().width;
00253 
00254         return (double)viewWidth / (double)getNumTimeDisplayed();
00255     }
00256     
00257     /******
00258      * get the time interval displayed on the canvas
00259      * @return
00260      */
00261     private long getNumTimeDisplayed()
00262     {
00263         return (dataTraces.getAttributes().getTimeInterval());
00264     }
00265 
00266 
00267     /******************************************************************
00268      * 
00269      * Customized tooltip for summary canvas
00270      *
00271      ******************************************************************/
00272     private class SummaryTooltip extends DefaultToolTip
00273     {
00274         public SummaryTooltip(Control control) {
00275             super(control);
00276         }
00277 
00278         @Override
00279         /*
00280          * (non-Javadoc)
00281          * @see org.eclipse.jface.window.DefaultToolTip#getText(org.eclipse.swt.widgets.Event)
00282          */
00283         protected String getText(Event event) {
00284             if (mapStatistics != null ) 
00285             {
00286                 // ------------------------------------------------
00287                 // copy the area pointed by the mouse to an image
00288                 // ------------------------------------------------
00289                 final Image image = new Image(event.display, 1, 1);
00290                 GC gc = new GC(SummaryTimeCanvas.this);
00291                 gc.copyArea(image, event.x, event.y);
00292                 final ImageData data = image.getImageData();
00293                 gc.dispose();
00294                 
00295                 // ------------------------------------------------
00296                 // get the pixel of the image 
00297                 // ------------------------------------------------
00298                 int pixel = data.getPixel(0, 0); 
00299                 image.dispose();
00300 
00301                 // ------------------------------------------------
00302                 // get the number of counts of this pixel
00303                 // ------------------------------------------------
00304                 Integer stat = mapStatistics.get(pixel);
00305                 
00306                 if (stat != null) {
00307                     // ------------------------------------------------
00308                     // compute the percentage
00309                     // ------------------------------------------------
00310                     float percent = (float)100.0 * ((float)stat / (float) totPixels);
00311                     if (percent > 0) {
00312                         final String percent_str = String.format("%.2f %%", percent);
00313                         return percent_str;
00314                     }
00315                 }
00316             }
00317             return null;
00318         }
00319         
00320         @Override
00321         /*
00322          * (non-Javadoc)
00323          * @see org.eclipse.jface.window.ToolTip#getLocation(org.eclipse.swt.graphics.Point, org.eclipse.swt.widgets.Event)
00324          */
00325         public Point getLocation(Point tipSize, Event event) {
00326             return SummaryTimeCanvas.this.toDisplay(event.x + 5, event.y - 15);
00327         }
00328     }
00329     
00330     //---------------------------------------------------------------------------------------
00331     // Override methods
00332     //---------------------------------------------------------------------------------------
00333 
00334 
00335     @Override
00336     public void historyNotification(final OperationHistoryEvent event) {
00337         // we are not interested with other operation
00338         if (event.getOperation().hasContext(BufferRefreshOperation.context)) {
00339             if (event.getEventType() == OperationHistoryEvent.DONE) {
00340                 Debugger.printDebug(1, "STC attributes: ");
00341                 getDisplay().syncExec(new Runnable() {
00342                     @Override
00343                     public void run() {
00344                         BufferRefreshOperation operation = (BufferRefreshOperation) event.getOperation();
00345                         refresh(operation.getImageData());
00346                     }
00347                 });
00348             }
00349         }
00350     }
00351 
00352     @Override
00353     protected void changePosition(Point point) {
00354         // TODO Auto-generated method stub
00355         
00356     }
00357 
00358     @Override
00359     protected void changeRegion(Rectangle region) 
00360     {
00361         final ImageTraceAttributes attributes = dataTraces.getAttributes();
00362         
00363         long timeBegin   = attributes.getTimeBegin();
00364         int left = region.x;
00365         int right = region.width + region.x;
00366         
00367         long topLeftTime = timeBegin + (long)(left / getScalePixelsPerTime());
00368         long bottomRightTime = timeBegin + (long)(right / getScalePixelsPerTime());
00369         
00370         final Position position = attributes.getPosition();
00371         
00372         final Frame frame = new Frame(topLeftTime, bottomRightTime,
00373                 attributes.getProcessBegin(), attributes.getProcessEnd(),
00374                 attributes.getDepth(), position.time, position.process );
00375         try {
00376             TraceOperation.getOperationHistory().execute(
00377                     new ZoomOperation("Time zoom in", frame), 
00378                     null, null);
00379         } catch (ExecutionException e) {
00380             e.printStackTrace();
00381         }
00382 
00383     }
00384 }

Generated on 5 May 2015 for HPCVIEWER by  doxygen 1.6.1