00001 package edu.rice.cs.hpc.traceviewer.misc;
00002
00003 import org.eclipse.core.commands.ExecutionException;
00004 import org.eclipse.core.commands.operations.IOperationHistoryListener;
00005 import org.eclipse.core.commands.operations.IUndoableOperation;
00006 import org.eclipse.core.commands.operations.OperationHistoryEvent;
00007 import org.eclipse.core.commands.operations.OperationHistoryFactory;
00008 import org.eclipse.swt.SWT;
00009 import org.eclipse.swt.SWTException;
00010 import org.eclipse.swt.events.ControlAdapter;
00011 import org.eclipse.swt.events.ControlEvent;
00012 import org.eclipse.swt.events.DisposeEvent;
00013 import org.eclipse.swt.events.DisposeListener;
00014 import org.eclipse.swt.events.MouseEvent;
00015 import org.eclipse.swt.events.PaintEvent;
00016 import org.eclipse.swt.events.PaintListener;
00017 import org.eclipse.swt.graphics.Color;
00018 import org.eclipse.swt.graphics.GC;
00019 import org.eclipse.swt.graphics.Image;
00020 import org.eclipse.swt.graphics.Pattern;
00021 import org.eclipse.swt.graphics.Point;
00022 import org.eclipse.swt.graphics.Rectangle;
00023 import org.eclipse.swt.widgets.Composite;
00024 import edu.rice.cs.hpc.data.experiment.extdata.IBaseData;
00025 import edu.rice.cs.hpc.traceviewer.data.util.Debugger;
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.ITraceCanvas;
00030 import edu.rice.cs.hpc.traceviewer.painter.ImageTraceAttributes;
00031 import edu.rice.cs.hpc.traceviewer.painter.SpaceTimeCanvas;
00032 import edu.rice.cs.hpc.traceviewer.spaceTimeData.Frame;
00033 import edu.rice.cs.hpc.traceviewer.spaceTimeData.SpaceTimeDataController;
00034
00035
00036
00037
00038
00039
00040
00041 public class SpaceTimeMiniCanvas extends SpaceTimeCanvas
00042 implements ITraceCanvas, PaintListener, IOperationHistoryListener
00043 {
00045 private MouseState mouseState;
00046
00048 private Point mouseDown;
00049
00051 private Point mousePrevious;
00052
00054 private Point mouseUp;
00055
00057 private boolean insideBox;
00058
00059 private Rectangle view;
00060
00061 final private Color COMPLETELY_FILTERED_OUT_COLOR;
00062 final private Color NOT_FILTERED_OUT_COLOR;
00063 final private Color COLOR_BLACK, COLOR_GRAY;
00064
00069 private final Pattern PARTIALLY_FILTERED_PATTERN;
00070
00072 public SpaceTimeMiniCanvas(Composite _composite)
00073 {
00074 super(_composite);
00075
00076 mouseState = MouseState.ST_MOUSE_INIT;
00077 insideBox = true;
00078 view = new Rectangle(0, 0, 0, 0);
00079
00080
00081 COMPLETELY_FILTERED_OUT_COLOR = new Color(this.getDisplay(), 50,50,50);
00082 NOT_FILTERED_OUT_COLOR = getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY);
00083 COLOR_BLACK = getDisplay().getSystemColor(SWT.COLOR_BLACK);
00084 COLOR_GRAY = getDisplay().getSystemColor(SWT.COLOR_GRAY);
00085
00086
00087 PARTIALLY_FILTERED_PATTERN = createStripePattern();
00088
00089 addDisposeListener( new DisposeListener() {
00090
00091 @Override
00092 public void widgetDisposed(DisposeEvent e) {
00093 dispose();
00094 }
00095 });
00096 addControlListener( new ControlAdapter() {
00097
00098 @Override
00099 public void controlResized(ControlEvent e) {
00100 if (stData != null) {
00101 final Frame frame = stData.getAttributes().getFrame();
00102 setBox(frame);
00103 }
00104 }
00105 } );
00106 }
00107
00108
00109
00110
00111
00112 @Override
00113 public void dispose() {
00114 COMPLETELY_FILTERED_OUT_COLOR.dispose();
00115 PARTIALLY_FILTERED_PATTERN.dispose();
00116 }
00117
00118
00119
00120
00121
00122
00123 private Pattern createStripePattern() {
00124 Image image = new Image(getDisplay(), 15, 15);
00125 GC gc = new GC(image);
00126 gc.setBackground(NOT_FILTERED_OUT_COLOR);
00127 gc.fillRectangle(image.getBounds());
00128 gc.setForeground(COMPLETELY_FILTERED_OUT_COLOR);
00129
00130
00131 for (int i = 5; i < 15; i+= 5) {
00132 gc.drawLine(-5, i+5, i+5, -5);
00133 gc.drawLine(i-5, 20, 20, i-5);
00134 }
00135 gc.dispose();
00136 return new Pattern(getDisplay(), image);
00137 }
00138
00139
00140
00141
00142
00143
00144
00145 public void updateView(SpaceTimeDataController _stData)
00146 {
00147 setSpaceTimeData(_stData);
00148
00149 if (this.mouseState == MouseState.ST_MOUSE_INIT) {
00150 this.mouseState = MouseState.ST_MOUSE_NONE;
00151
00152 addMouseListener(this);
00153 addMouseMoveListener(this);
00154 addPaintListener(this);
00155
00156 OperationHistoryFactory.getOperationHistory().addOperationHistoryListener(this);
00157 }
00158 Rectangle r = this.getClientArea();
00159 view.x = 0;
00160 view.y = 0;
00161 view.height = r.height;
00162 view.width = r.width;
00163
00164 redraw();
00165 }
00166
00167
00168
00169
00170
00171 public void updateView()
00172 {
00173 final Frame frame = stData.getAttributes().getFrame();
00174 IBaseData baseData = stData.getBaseData();
00175
00176 int p1 = (int) Math.round( (frame.begProcess+baseData.getFirstIncluded()) * getScalePixelsPerRank() );
00177 int p2 = (int) Math.round( (frame.endProcess+baseData.getFirstIncluded()) * getScalePixelsPerRank() );
00178
00179 int t1 = (int) Math.round( frame.begTime * getScalePixelsPerTime() );
00180 int t2 = (int) Math.round( frame.endTime * getScalePixelsPerTime() );
00181
00182 int dp = Math.max(p2-p1, 1);
00183 int dt = Math.max(t2-t1, 1);
00184
00185 view.x = t1;
00186 view.y = p1;
00187 view.width = dt;
00188 view.height = dp;
00189
00190 redraw();
00191 }
00192
00194 public void paintControl(PaintEvent event)
00195 {
00196 if (this.stData == null)
00197 return;
00198
00199 final Rectangle clientArea = getClientArea();
00200
00201
00202
00203 event.gc.setBackground(COLOR_BLACK);
00204 event.gc.fillRectangle(clientArea);
00205
00206
00207
00208 final Frame frame = stData.getAttributes().getFrame();
00209 IBaseData baseData = stData.getBaseData();
00210
00211 int p1 = (int) Math.round( (baseData.getFirstIncluded()) * getScalePixelsPerRank() );
00212 int p2 = (int) Math.round( (baseData.getLastIncluded()+1) * getScalePixelsPerRank() );
00213
00214 int t1 = (int) Math.round( frame.begTime * getScalePixelsPerTime() );
00215 int t2 = (int) Math.round( frame.endTime * getScalePixelsPerTime() );
00216
00217 int dp = Math.max(p2-p1, 1);
00218 int dt = Math.max(t2-t1, 1);
00219
00220 if (baseData.isDenseBetweenFirstAndLast()){
00221 event.gc.setBackground(NOT_FILTERED_OUT_COLOR);
00222 } else {
00223 try{
00224 event.gc.setBackgroundPattern(PARTIALLY_FILTERED_PATTERN);
00225 }
00226 catch (SWTException e){
00227 System.out.println("Advanced graphics not supported");
00228 event.gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_RED));
00229 }
00230 }
00231
00232
00233 event.gc.fillRectangle(0, p1, getClientArea().width, dp);
00234
00235
00236 if (baseData.isDenseBetweenFirstAndLast()) {
00237
00238 p1 = (int) Math.round( (baseData.getFirstIncluded() + frame.begProcess )* getScalePixelsPerRank());
00239 p2 = (int) Math.round( (baseData.getFirstIncluded() + frame.endProcess )* getScalePixelsPerRank());
00240 dp = Math.max(1, p2 - p1);
00241
00242 event.gc.setBackground(COLOR_GRAY);
00243 event.gc.fillRectangle(t1, p1, dt, dp);
00244 }
00245
00246 if (insideBox) {
00247
00248 event.gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
00249 event.gc.fillRectangle(view);
00250 } else {
00251
00252 event.gc.setForeground(getDisplay().getSystemColor(SWT.COLOR_YELLOW));
00253 event.gc.drawRectangle(view);
00254 }
00255 }
00256
00257
00310 private void setBox(Frame frame)
00311 {
00312 if (this.stData == null)
00313 return;
00314
00315 view.x = (int)Math.round(frame.begTime * getScalePixelsPerTime());
00316 view.y = (int)Math.round(frame.begProcess * getScalePixelsPerRank());
00317
00318 int bottomRightPixelX = (int)Math.round(frame.endTime * getScalePixelsPerTime());
00319 int bottomRightPixelY = (int)Math.round(frame.endProcess * getScalePixelsPerRank());
00320
00321 view.width = Math.max(1, bottomRightPixelX-view.x);
00322 view.height = Math.max(1, bottomRightPixelY-view.y);
00323
00324 Debugger.printDebug(1, "STMC set view: " + view);
00325 insideBox = true;
00326 redraw();
00327 }
00328
00330 private void moveBox(Point mouseCurrent)
00331 {
00332
00333 int changeX = mouseCurrent.x-mousePrevious.x;
00334 int changeY = mouseCurrent.y-mousePrevious.y;
00335
00336
00337 view.x += changeX;
00338 view.y += changeY;
00339
00340
00341
00342 view.x = Math.max(view.x, 0);
00343 view.y = Math.max(view.y, getLowestY());
00344
00345
00346
00347
00348 checkRegion(view);
00349
00350 mousePrevious = mouseCurrent;
00351 }
00352
00353
00355 private void confirmNewRegion()
00356 {
00357 Point miniTopLeft = new Point( view.x, view.y);
00358 Point miniBottomRight = new Point( view.x+view.width, view.y+view.height);
00359
00360 final IBaseData data = stData.getBaseData();
00361
00362 long detailTopLeftTime = (long)(miniTopLeft.x/getScalePixelsPerTime());
00363 int detailTopLeftProcess = (int) Math.round( miniTopLeft.y/getScalePixelsPerRank() - data.getFirstIncluded());
00364
00365 long detailBottomRightTime = (long)(miniBottomRight.x / getScalePixelsPerTime());
00366 int detailBottomRightProcess = (int) Math.round( miniBottomRight.y/getScalePixelsPerRank()) - data.getFirstIncluded();
00367
00368
00369 if (detailBottomRightProcess-detailTopLeftProcess <= 0) {
00370 detailBottomRightProcess = detailTopLeftProcess + 1;
00371 }
00372
00373 final Frame originalFrame = stData.getAttributes().getFrame();
00374
00375
00376 Frame frame = new Frame( originalFrame );
00377 frame.set(detailTopLeftTime, detailBottomRightTime, detailTopLeftProcess, detailBottomRightProcess);
00378
00379 int totTraces = stData.getTotalTraceCount();
00380
00381 assert frame.begProcess >= 0 && frame.begProcess < totTraces :
00382 "incorrect beg rank: " + frame.begProcess + " should be in the range [0," +
00383 totTraces + "]";
00384
00385 assert frame.endProcess <= totTraces && frame.endProcess > 0 :
00386 "incorrect end rank: " + frame.endProcess + " should be in the range [ 0,"
00387 + totTraces + "]";
00388
00389
00390 if (!frame.equals(originalFrame))
00391 notifyRegionChangeOperation(frame);
00392 }
00393
00394
00395
00396
00397
00398
00399 private void notifyRegionChangeOperation( Frame frame )
00400 {
00401 try {
00402 TraceOperation.getOperationHistory().execute(
00403 new ZoomOperation("Change region", frame),
00404 null, null);
00405 } catch (ExecutionException e)
00406 {
00407 e.printStackTrace();
00408 }
00409 }
00410
00411
00412
00413
00414
00415
00416 private int getHighestY() {
00417
00418 final IBaseData baseData = stData.getBaseData();
00419 int highestRank = baseData.getLastIncluded()+1;
00420 return (int) Math.round(highestRank * getScalePixelsPerRank());
00421 }
00422
00423
00424
00425
00426
00427
00428
00429 private int getLowestY() {
00430 final IBaseData baseData = stData.getBaseData();
00431 final int lowestRank = baseData.getFirstIncluded();
00432 return (int) Math.round(lowestRank * getScalePixelsPerRank());
00433 }
00434
00436 private void adjustSelection(Point p1, Point p2)
00437 {
00438
00439
00440
00441 view.x = Math.max(0, Math.min(p1.x, p2.x) );
00442 view.y = Math.max(getLowestY(), Math.min(p1.y, p2.y) );
00443
00444 view.width = Math.abs( p1.x - p2.x );
00445 view.height = Math.abs( p1.y - p2.y );
00446
00447
00448
00449
00450 checkRegion(view);
00451 }
00452
00453
00454
00455
00456
00457
00458
00459 private void checkRegion(Rectangle region)
00460 {
00461 final Rectangle area = getClientArea();
00462
00463
00464 if ( region.x + region.width > area.width )
00465 region.x = area.width - region.width;
00466
00467
00468 int y_end = region.y + region.height;
00469 if ( y_end > area.height )
00470 region.y = area.height - region.height;
00471
00472 int highestY = getHighestY();
00473 int lowestY = getLowestY();
00474
00475
00476 if (y_end > highestY) {
00477 region.y = Math.max(highestY - region.height, lowestY);
00478
00479 final int maxHeight = highestY - lowestY;
00480 region.height = Math.min(region.height, maxHeight);
00481 }
00482
00483
00484 region.y = Math.min(region.y, highestY - 1);
00485 }
00486
00488 public double getScalePixelsPerTime()
00489 {
00490 return (double)getClientArea().width / (double)stData.getTimeWidth();
00491 }
00492
00494 public double getScalePixelsPerRank()
00495 {
00496 final IBaseData data = stData.getBaseData();
00497 final Rectangle area = getClientArea();
00498 return (double)area.height / (data.getNumberOfRanks());
00499 }
00500
00501
00502
00503
00504
00505
00506
00507
00508 public void mouseDown(MouseEvent e)
00509 {
00510 if (mouseState == MouseState.ST_MOUSE_NONE)
00511 {
00512 mouseState = MouseState.ST_MOUSE_DOWN;
00513 mouseDown = new Point(e.x,e.y);
00514 mousePrevious = new Point(e.x,e.y);
00515
00516 insideBox = ( mouseDown.x>=view.x &&
00517 mouseDown.x<=view.x+view.width &&
00518 mouseDown.y>=view.y &&
00519 mouseDown.y<=view.y+view.height );
00520 }
00521 }
00522
00523 public void mouseUp(MouseEvent e)
00524 {
00525 if (mouseState == MouseState.ST_MOUSE_DOWN)
00526 {
00527 mouseUp = new Point(e.x,e.y);
00528 mouseState = MouseState.ST_MOUSE_NONE;
00529 if (insideBox)
00530 {
00531 moveBox(mouseUp);
00532 confirmNewRegion();
00533 }
00534 else
00535 {
00536
00537
00538 if(Math.abs(mouseUp.x-mouseDown.x)>3 || Math.abs(mouseUp.y-mouseDown.y)>3)
00539 {
00540 adjustSelection(mouseDown, mouseUp);
00541 confirmNewRegion();
00542 }else {
00543 final ImageTraceAttributes attributes = stData.getAttributes();
00544
00545 setBox(attributes.getFrame());
00546 }
00547 }
00548 }
00549 }
00550
00551 public void mouseMove(MouseEvent e)
00552 {
00553 if(mouseState == MouseState.ST_MOUSE_DOWN)
00554 {
00555 Point mouseCurrent = new Point(e.x,e.y);
00556 if (insideBox)
00557 moveBox(mouseCurrent);
00558 else
00559 adjustSelection(mouseDown, mouseCurrent);
00560
00561 redraw();
00562 }
00563 }
00564
00565 @Override
00566 public void mouseDoubleClick(MouseEvent e) { }
00567
00568 @Override
00569
00570
00571
00572
00573 public void historyNotification(final OperationHistoryEvent event) {
00574 final IUndoableOperation operation = event.getOperation();
00575
00576 if (operation.hasContext(BufferRefreshOperation.context)) {
00577 final Frame frame = stData.getAttributes().getFrame();
00578 setBox(frame);
00579 }
00580 }
00581 }