📄 chartpanel.java
字号:
return new Point(x, y);
}
/**
* Translates a screen location to a Java2D point.
*
* @param screenPoint the screen location.
*
* @return the Java2D coordinates.
*/
public Point2D translateScreenToJava2D(Point screenPoint) {
Insets insets = getInsets();
double x = (screenPoint.getX() - insets.left) / this.scaleX;
double y = (screenPoint.getY() - insets.top) / this.scaleY;
return new Point2D.Double(x, y);
}
/**
* Returns the chart entity at a given point.
* <P>
* This method will return null if there is (a) no entity at the given point, or
* (b) no entity collection has been generated.
*
* @param viewX the x-coordinate.
* @param viewY the y-coordinate.
*
* @return the chart entity (possibly null).
*/
public ChartEntity getEntityForPoint(int viewX, int viewY) {
Insets insets = getInsets();
double x = (viewX - insets.left) / scaleX;
double y = (viewY - insets.top) / scaleY;
EntityCollection entities = this.info.getEntityCollection();
return entities != null ? entities.getEntity(x, y) : null;
}
/**
* Sets the refresh buffer flag.
*
* @param flag <code>true</code> indicate, that the buffer should be refreshed.
*/
public void setRefreshBuffer(boolean flag) {
this.refreshBuffer = flag;
}
/** Working storage for available panel area after deducting insets. */
private Rectangle2D available = new Rectangle2D.Double();
/** Working storage for the chart area. */
private Rectangle2D chartArea = new Rectangle2D.Double();
/**
* Paints the component by drawing the chart to fill the entire component,
* but allowing for the insets (which will be non-zero if a border has been
* set for this component). To increase performance (at the expense of
* memory), an off-screen buffer image can be used.
*
* @param g the graphics device for drawing on.
*/
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g.create();
// first determine the size of the chart rendering area...
Dimension size = getSize();
Insets insets = getInsets();
available.setRect(insets.left, insets.top,
size.getWidth() - insets.left - insets.right,
size.getHeight() - insets.top - insets.bottom);
// work out if scaling is required...
boolean scale = false;
double drawWidth = available.getWidth();
double drawHeight = available.getHeight();
this.scaleX = 1.0;
this.scaleY = 1.0;
if (drawWidth < this.minimumDrawWidth) {
scaleX = drawWidth / minimumDrawWidth;
drawWidth = minimumDrawWidth;
scale = true;
}
else if (drawWidth > this.maximumDrawWidth) {
scaleX = drawWidth / maximumDrawWidth;
drawWidth = maximumDrawWidth;
scale = true;
}
if (drawHeight < this.minimumDrawHeight) {
scaleY = drawHeight / minimumDrawHeight;
drawHeight = minimumDrawHeight;
scale = true;
}
else if (drawHeight > this.maximumDrawHeight) {
scaleY = drawHeight / maximumDrawHeight;
drawHeight = maximumDrawHeight;
scale = true;
}
chartArea.setRect(0.0, 0.0, drawWidth, drawHeight);
// are we using the chart buffer?
if (useBuffer) {
// do we need to resize the buffer?
if ((chartBuffer == null) || (chartBufferWidth != available.getWidth())
|| (chartBufferHeight != available.getHeight())) {
chartBufferWidth = (int) available.getWidth();
chartBufferHeight = (int) available.getHeight();
chartBuffer = createImage(chartBufferWidth, chartBufferHeight);
refreshBuffer = true;
}
// do we need to redraw the buffer?
if (refreshBuffer) {
Rectangle2D bufferArea =
new Rectangle2D.Double(0, 0, chartBufferWidth, chartBufferHeight);
Graphics2D bufferG2 = (Graphics2D) chartBuffer.getGraphics();
if (scale) {
AffineTransform saved = bufferG2.getTransform();
AffineTransform st = AffineTransform.getScaleInstance(scaleX, scaleY);
bufferG2.transform(st);
chart.draw(bufferG2, chartArea, this.info);
bufferG2.setTransform(saved);
}
else {
chart.draw(bufferG2, bufferArea, this.info);
}
refreshBuffer = false;
}
// zap the buffer onto the panel...
g2.drawImage(chartBuffer, insets.left, insets.right, this);
}
// or redrawing the chart every time...
else {
AffineTransform saved = g2.getTransform();
g2.translate(insets.left, insets.right);
if (scale) {
AffineTransform st = AffineTransform.getScaleInstance(scaleX, scaleY);
g2.transform(st);
}
chart.draw(g2, chartArea, this.info);
g2.setTransform(saved);
}
this.verticalTraceLine = null;
this.horizontalTraceLine = null;
}
/**
* Receives notification of changes to the chart, and redraws the chart.
*
* @param event details of the chart change event.
*/
public void chartChanged(ChartChangeEvent event) {
this.refreshBuffer = true;
repaint();
}
/**
* Receives notification of a chart progress event.
*
* @param event the event.
*/
public void chartProgress(ChartProgressEvent event) {
// does nothing - override if necessary
}
/**
* Handles action events generated by the popup menu.
*
* @param event the event.
*/
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals(PROPERTIES_ACTION_COMMAND)) {
attemptEditChartProperties();
}
else if (command.equals(SAVE_ACTION_COMMAND)) {
try {
doSaveAs();
}
catch (IOException e) {
System.err.println("ChartPanel.doSaveAs: i/o exception = " + e.getMessage());
}
}
else if (command.equals(PRINT_ACTION_COMMAND)) {
createChartPrintJob();
}
else if (command.equals(ZOOM_IN_BOTH_ACTION_COMMAND)) {
zoomInBoth(this.zoomPoint.getX(), this.zoomPoint.getY());
}
else if (command.equals(ZOOM_IN_HORIZONTAL_ACTION_COMMAND)) {
zoomInHorizontal(this.zoomPoint.getX());
}
else if (command.equals(ZOOM_IN_VERTICAL_ACTION_COMMAND)) {
zoomInVertical(this.zoomPoint.getY());
}
else if (command.equals(ZOOM_OUT_BOTH_ACTION_COMMAND)) {
zoomOutBoth(this.zoomPoint.getX(), this.zoomPoint.getY());
}
else if (command.equals(ZOOM_OUT_HORIZONTAL_ACTION_COMMAND)) {
zoomOutHorizontal(this.zoomPoint.getX());
}
else if (command.equals(ZOOM_OUT_VERTICAL_ACTION_COMMAND)) {
zoomOutVertical(this.zoomPoint.getY());
}
else if (command.equals(AUTO_RANGE_BOTH_ACTION_COMMAND)) {
autoRangeBoth();
}
else if (command.equals(AUTO_RANGE_HORIZONTAL_ACTION_COMMAND)) {
autoRangeHorizontal();
}
else if (command.equals(AUTO_RANGE_VERTICAL_ACTION_COMMAND)) {
autoRangeVertical();
}
}
/**
* Handles a 'mouse entered' event.
* <P>
* This method does nothing, but is required for implementation of the MouseListener
* interface.
*
* @param e the mouse event.
*/
public void mouseEntered(MouseEvent e) {
// do nothing
}
/**
* Handles a 'mouse exited' event.
* <P>
* This method does nothing, but is required for implementation of the MouseListener
* interface.
*
* @param e the mouse event.
*/
public void mouseExited(MouseEvent e) {
// do nothing
}
/**
* Handles a 'mouse pressed' event.
* <P>
* This event is the popup trigger on Unix/Linux. For Windows, the popup
* trigger is the 'mouse released' event.
*
* @param e The mouse event.
*/
public void mousePressed(MouseEvent e) {
if (zoomRectangle == null) {
this.zoomPoint = RefineryUtilities.getPointInRectangle(e.getX(), e.getY(),
getScaledDataArea());
// check for popup trigger...
if (e.isPopupTrigger()) {
if (popup != null) {
displayPopupMenu(e.getX(), e.getY());
}
}
}
}
/**
* Handles a 'mouse released' event.
* <P>
* On Windows, we need to check if this is a popup trigger, but only if we
* haven't already been tracking a zoom rectangle.
*
* @param e Information about the event.
*/
public void mouseReleased(MouseEvent e) {
if (zoomRectangle != null) {
if (Math.abs(e.getX() - zoomPoint.getX()) >= MINIMUM_DRAG_ZOOM_SIZE) {
if (e.getX() < zoomPoint.getX() || e.getY() < zoomPoint.getY()) {
autoRangeBoth();
}
else {
double x, y, w, h;
Rectangle2D scaledDataArea = getScaledDataArea();
//for a mouseReleased event, (horizontalZoom || verticalZoom)
//will be true, so we can just test for either being false;
//otherwise both are true
if (!verticalZoom) {
x = zoomPoint.getX();
y = scaledDataArea.getMinY();
w = Math.min(zoomRectangle.getWidth(),
scaledDataArea.getMaxX() - zoomPoint.getX());
h = scaledDataArea.getHeight();
}
else if (!horizontalZoom) {
x = scaledDataArea.getMinX();
y = zoomPoint.getY();
w = scaledDataArea.getWidth();
h = Math.min(zoomRectangle.getHeight(),
scaledDataArea.getMaxY() - zoomPoint.getY());
}
else {
x = zoomPoint.getX();
y = zoomPoint.getY();
w = Math.min(zoomRectangle.getWidth(),
scaledDataArea.getMaxX() - zoomPoint.getX());
h = Math.min(zoomRectangle.getHeight(),
scaledDataArea.getMaxY() - zoomPoint.getY());
}
Rectangle2D zoomArea = new Rectangle2D.Double(x, y, w, h);
zoom(zoomArea);
}
this.zoomPoint = null;
this.zoomRectangle = null;
}
else {
Graphics2D g2 = (Graphics2D) getGraphics();
g2.setXORMode(java.awt.Color.gray);
if (fillZoomRectangle) {
g2.fill(zoomRectangle);
}
else {
g2.draw(zoomRectangle);
}
g2.dispose();
this.zoomRectangle = null;
}
}
else if (e.isPopupTrigger()) {
if (popup != null) {
displayPopupMenu(e.getX(), e.getY());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -