60 import org.eclipse.swt.widgets.Composite;
61 import org.eclipse.swt.widgets.Control;
62 import org.eclipse.swt.widgets.Display;
63 import org.eclipse.swt.widgets.Event;
64 import org.eclipse.swt.widgets.Listener;
65 import org.openjdk.jmc.common.IDisplayable;
66 import org.openjdk.jmc.common.unit.IQuantity;
67 import org.openjdk.jmc.ui.UIPlugin;
68 import org.openjdk.jmc.ui.accessibility.FocusTracker;
69 import org.openjdk.jmc.ui.charts.IChartInfoVisitor;
70 import org.openjdk.jmc.ui.charts.IXDataRenderer;
71 import org.openjdk.jmc.ui.charts.XYChart;
72 import org.openjdk.jmc.ui.common.util.Environment;
73 import org.openjdk.jmc.ui.common.util.Environment.OSType;
74 import org.openjdk.jmc.ui.handlers.MCContextMenuManager;
75
76 public class ChartCanvas extends Canvas {
77 private int lastMouseX = -1;
78 private int lastMouseY = -1;
79 private List<Rectangle2D> highlightRects;
80
81 private class Selector extends MouseAdapter implements MouseMoveListener, MouseTrackListener {
82
83 int selectionStartX = -1;
84 int selectionStartY = -1;
85 boolean selectionIsClick = false;
86
87 @Override
88 public void mouseDown(MouseEvent e) {
89 /*
90 * On Mac OS X, CTRL + left mouse button can be used to trigger a context menu. (This is
91 * for historical reasons when the primary input device on Macs were a mouse with a
92 * single physical button. All modern Macs have other means to bring up the context
93 * menu, typically a two finger tap.)
94 *
95 * Although I think it would be best to check that this MouseEvent does not cause a
96 * platform specific popup trigger, like java.awt.event.MouseEvent.isPopupTrigger() for
97 * AWT, SWT doesn't seem to have something as simple. It has the MenuDetectEvent, but
98 * the order in relation to this MouseEvent is unspecified.
99 *
135 }
136
137 @Override
138 public void mouseUp(MouseEvent e) {
139 if (selectionStartX >= 0 && (e.button == 1)) {
140 updateSelectionState(e);
141 selectionStartX = -1;
142 selectionStartY = -1;
143 if (selectionListener != null) {
144 selectionListener.run();
145 }
146 }
147 }
148
149 @Override
150 public void mouseEnter(MouseEvent e) {
151 }
152
153 @Override
154 public void mouseExit(MouseEvent e) {
155 clearHighlightRects();
156 }
157
158 @Override
159 public void mouseHover(MouseEvent e) {
160 }
161 }
162
163 class Painter implements PaintListener {
164
165 @Override
166 public void paintControl(PaintEvent e) {
167 Rectangle rect = getClientArea();
168 if (awtNeedsRedraw || !awtCanvas.hasImage(rect.width, rect.height)) {
169 Graphics2D g2d = awtCanvas.getGraphics(rect.width, rect.height);
170 g2d.setColor(Color.WHITE);
171 g2d.fillRect(0, 0, rect.width, rect.height);
172 Point adjusted = translateDisplayToImageCoordinates(rect.width, rect.height);
173 render(g2d, adjusted.x, adjusted.y);
174 if (highlightRects != null) {
374 * the provided y coordinate
375 * @return a Point that represents the (x,y) coordinates in the chart's coordinate space
376 */
377 private Point translateDisplayToImageCoordinates(int x, int y) {
378 int xImage = (int) Math.round(x / xScale);
379 int yImage = (int) Math.round(y / yScale);
380 return new Point(xImage, yImage);
381 }
382
383 /**
384 * Translates a display x coordinate into an image x coordinate for the chart.
385 *
386 * @param x
387 * the provided display x coordinate
388 * @return the x coordinate in the chart's coordinate space
389 */
390 private int translateDisplayToImageXCoordinates(int x) {
391 return (int) Math.round(x / xScale);
392 }
393
394 private void updateHighlightRects() {
395 List<Rectangle2D> newRects = new ArrayList<>();
396 infoAt(new IChartInfoVisitor.Adapter() {
397 @Override
398 public void visit(IBucket bucket) {
399 newRects.add(bucket.getTarget());
400 }
401
402 @Override
403 public void visit(IPoint point) {
404 Point2D target = point.getTarget();
405 newRects.add(new Rectangle2D.Double(target.getX(), target.getY(), 0, 0));
406 }
407
408 @Override
409 public void visit(ISpan span) {
410 newRects.add(span.getTarget());
411 }
412
413 @Override
414 public void visit(ITick tick) {
415 Point2D target = tick.getTarget();
416 newRects.add(new Rectangle2D.Double(target.getX(), target.getY(), 0, 0));
417 }
418
419 @Override
420 public void visit(ILane lane) {
421 // FIXME: Do we want this highlighted?
422 }
423 }, lastMouseX, lastMouseY);
424 // Attempt to reduce flicker by avoiding unnecessary updates.
425 if (!newRects.equals(highlightRects)) {
426 highlightRects = newRects;
427 redraw();
428 }
429 }
430
431 private void clearHighlightRects() {
432 if (highlightRects != null) {
433 highlightRects = null;
434 redraw();
435 }
436 }
437
438 private void handleWheelEvent(int stateMask, int x, int count) {
439 // SWT.MOD1 is CMD on OS X and CTRL elsewhere.
440 if ((stateMask & SWT.MOD1) != 0) {
441 pan(count * 3);
|
60 import org.eclipse.swt.widgets.Composite;
61 import org.eclipse.swt.widgets.Control;
62 import org.eclipse.swt.widgets.Display;
63 import org.eclipse.swt.widgets.Event;
64 import org.eclipse.swt.widgets.Listener;
65 import org.openjdk.jmc.common.IDisplayable;
66 import org.openjdk.jmc.common.unit.IQuantity;
67 import org.openjdk.jmc.ui.UIPlugin;
68 import org.openjdk.jmc.ui.accessibility.FocusTracker;
69 import org.openjdk.jmc.ui.charts.IChartInfoVisitor;
70 import org.openjdk.jmc.ui.charts.IXDataRenderer;
71 import org.openjdk.jmc.ui.charts.XYChart;
72 import org.openjdk.jmc.ui.common.util.Environment;
73 import org.openjdk.jmc.ui.common.util.Environment.OSType;
74 import org.openjdk.jmc.ui.handlers.MCContextMenuManager;
75
76 public class ChartCanvas extends Canvas {
77 private int lastMouseX = -1;
78 private int lastMouseY = -1;
79 private List<Rectangle2D> highlightRects;
80 private String activeScopeName;
81
82 private class Selector extends MouseAdapter implements MouseMoveListener, MouseTrackListener {
83
84 int selectionStartX = -1;
85 int selectionStartY = -1;
86 boolean selectionIsClick = false;
87
88 @Override
89 public void mouseDown(MouseEvent e) {
90 /*
91 * On Mac OS X, CTRL + left mouse button can be used to trigger a context menu. (This is
92 * for historical reasons when the primary input device on Macs were a mouse with a
93 * single physical button. All modern Macs have other means to bring up the context
94 * menu, typically a two finger tap.)
95 *
96 * Although I think it would be best to check that this MouseEvent does not cause a
97 * platform specific popup trigger, like java.awt.event.MouseEvent.isPopupTrigger() for
98 * AWT, SWT doesn't seem to have something as simple. It has the MenuDetectEvent, but
99 * the order in relation to this MouseEvent is unspecified.
100 *
136 }
137
138 @Override
139 public void mouseUp(MouseEvent e) {
140 if (selectionStartX >= 0 && (e.button == 1)) {
141 updateSelectionState(e);
142 selectionStartX = -1;
143 selectionStartY = -1;
144 if (selectionListener != null) {
145 selectionListener.run();
146 }
147 }
148 }
149
150 @Override
151 public void mouseEnter(MouseEvent e) {
152 }
153
154 @Override
155 public void mouseExit(MouseEvent e) {
156 resetActiveScopeName();
157 clearHighlightRects();
158 }
159
160 @Override
161 public void mouseHover(MouseEvent e) {
162 }
163 }
164
165 class Painter implements PaintListener {
166
167 @Override
168 public void paintControl(PaintEvent e) {
169 Rectangle rect = getClientArea();
170 if (awtNeedsRedraw || !awtCanvas.hasImage(rect.width, rect.height)) {
171 Graphics2D g2d = awtCanvas.getGraphics(rect.width, rect.height);
172 g2d.setColor(Color.WHITE);
173 g2d.fillRect(0, 0, rect.width, rect.height);
174 Point adjusted = translateDisplayToImageCoordinates(rect.width, rect.height);
175 render(g2d, adjusted.x, adjusted.y);
176 if (highlightRects != null) {
376 * the provided y coordinate
377 * @return a Point that represents the (x,y) coordinates in the chart's coordinate space
378 */
379 private Point translateDisplayToImageCoordinates(int x, int y) {
380 int xImage = (int) Math.round(x / xScale);
381 int yImage = (int) Math.round(y / yScale);
382 return new Point(xImage, yImage);
383 }
384
385 /**
386 * Translates a display x coordinate into an image x coordinate for the chart.
387 *
388 * @param x
389 * the provided display x coordinate
390 * @return the x coordinate in the chart's coordinate space
391 */
392 private int translateDisplayToImageXCoordinates(int x) {
393 return (int) Math.round(x / xScale);
394 }
395
396 public String getActiveScopeName() {
397 return this.activeScopeName;
398 }
399
400 public void resetActiveScopeName() {
401 this.activeScopeName = null;
402 }
403
404 public void setActiveScopeName(String name) {
405 this.activeScopeName = name;
406 }
407
408 private void updateHighlightRects() {
409 List<Rectangle2D> newRects = new ArrayList<>();
410 infoAt(new IChartInfoVisitor.Adapter() {
411 @Override
412 public void visit(IBucket bucket) {
413 newRects.add(bucket.getTarget());
414 }
415
416 @Override
417 public void visit(IPoint point) {
418 Point2D target = point.getTarget();
419 newRects.add(new Rectangle2D.Double(target.getX(), target.getY(), 0, 0));
420 }
421
422 @Override
423 public void visit(ISpan span) {
424 newRects.add(span.getTarget());
425 }
426
427 @Override
428 public void visit(ITick tick) {
429 Point2D target = tick.getTarget();
430 newRects.add(new Rectangle2D.Double(target.getX(), target.getY(), 0, 0));
431 }
432
433 @Override
434 public void visit(ILane lane) {
435 // FIXME: Do we want this highlighted?
436 }
437
438 @Override
439 public boolean enterScope(String context, boolean fullyShown) {
440 setActiveScopeName(context);
441 return false;
442 }
443 }, lastMouseX, lastMouseY);
444 // Attempt to reduce flicker by avoiding unnecessary updates.
445 if (!newRects.equals(highlightRects)) {
446 highlightRects = newRects;
447 redraw();
448 }
449 }
450
451 private void clearHighlightRects() {
452 if (highlightRects != null) {
453 highlightRects = null;
454 redraw();
455 }
456 }
457
458 private void handleWheelEvent(int stateMask, int x, int count) {
459 // SWT.MOD1 is CMD on OS X and CTRL elsewhere.
460 if ((stateMask & SWT.MOD1) != 0) {
461 pan(count * 3);
|