00001 package org.swtchart.ext;
00002
00003 import org.eclipse.jface.preference.PreferenceDialog;
00004 import org.eclipse.jface.preference.PreferenceManager;
00005 import org.eclipse.jface.preference.PreferenceNode;
00006 import org.eclipse.swt.SWT;
00007 import org.eclipse.swt.events.PaintEvent;
00008 import org.eclipse.swt.events.PaintListener;
00009 import org.eclipse.swt.graphics.Point;
00010 import org.eclipse.swt.widgets.Composite;
00011 import org.eclipse.swt.widgets.Event;
00012 import org.eclipse.swt.widgets.FileDialog;
00013 import org.eclipse.swt.widgets.Menu;
00014 import org.eclipse.swt.widgets.MenuItem;
00015 import org.swtchart.Chart;
00016 import org.swtchart.IAxis;
00017 import org.swtchart.Range;
00018 import org.swtchart.IAxis.Direction;
00019 import org.swtchart.ext.internal.SelectionRectangle;
00020 import org.swtchart.ext.internal.properties.AxisPage;
00021 import org.swtchart.ext.internal.properties.AxisTickPage;
00022 import org.swtchart.ext.internal.properties.ChartPage;
00023 import org.swtchart.ext.internal.properties.GridPage;
00024 import org.swtchart.ext.internal.properties.LegendPage;
00025 import org.swtchart.ext.internal.properties.PropertiesResources;
00026 import org.swtchart.ext.internal.properties.SeriesLabelPage;
00027 import org.swtchart.ext.internal.properties.SeriesPage;
00028
00039 public class InteractiveChart extends Chart implements PaintListener {
00040
00042 private static final String[] EXTENSIONS = new String[] { "*.jpeg",
00043 "*.jpg", "*.png" };
00044
00046 protected SelectionRectangle selection;
00047
00049 private long clickedTime;
00050
00052 private PropertiesResources resources;
00053
00062 public InteractiveChart(Composite parent, int style) {
00063 super(parent, style);
00064 init();
00065 }
00066
00067 protected void resetSelection() {
00068 selection.dispose();
00069 }
00070
00074 private void init() {
00075 selection = new SelectionRectangle();
00076 resources = new PropertiesResources();
00077
00078 Composite plot = getPlotArea();
00079 plot.addListener(SWT.Resize, this);
00080 plot.addListener(SWT.MouseMove, this);
00081 plot.addListener(SWT.MouseDown, this);
00082 plot.addListener(SWT.MouseUp, this);
00083 plot.addListener(SWT.MouseWheel, this);
00084 plot.addListener(SWT.KeyDown, this);
00085
00086 plot.addPaintListener(this);
00087
00088 createMenuItems();
00089 }
00090
00094 private void createMenuItems() {
00095 Menu menu = new Menu(getPlotArea());
00096 getPlotArea().setMenu(menu);
00097
00098
00099 MenuItem menuItem = new MenuItem(menu, SWT.CASCADE);
00100 menuItem.setText(Messages.ADJUST_AXIS_RANGE_GROUP);
00101 Menu adjustAxisRangeMenu = new Menu(menuItem);
00102 menuItem.setMenu(adjustAxisRangeMenu);
00103
00104
00105 menuItem = new MenuItem(adjustAxisRangeMenu, SWT.PUSH);
00106 menuItem.setText(Messages.ADJUST_AXIS_RANGE);
00107 menuItem.addListener(SWT.Selection, this);
00108
00109
00110 menuItem = new MenuItem(adjustAxisRangeMenu, SWT.PUSH);
00111 menuItem.setText(Messages.ADJUST_X_AXIS_RANGE);
00112 menuItem.addListener(SWT.Selection, this);
00113
00114
00115 menuItem = new MenuItem(adjustAxisRangeMenu, SWT.PUSH);
00116 menuItem.setText(Messages.ADJUST_Y_AXIS_RANGE);
00117 menuItem.addListener(SWT.Selection, this);
00118
00119 menuItem = new MenuItem(menu, SWT.SEPARATOR);
00120
00121
00122 menuItem = new MenuItem(menu, SWT.CASCADE);
00123 menuItem.setText(Messages.ZOOMIN_GROUP);
00124 Menu zoomInMenu = new Menu(menuItem);
00125 menuItem.setMenu(zoomInMenu);
00126
00127
00128 menuItem = new MenuItem(zoomInMenu, SWT.PUSH);
00129 menuItem.setText(Messages.ZOOMIN);
00130 menuItem.addListener(SWT.Selection, this);
00131
00132
00133 menuItem = new MenuItem(zoomInMenu, SWT.PUSH);
00134 menuItem.setText(Messages.ZOOMIN_X);
00135 menuItem.addListener(SWT.Selection, this);
00136
00137
00138 menuItem = new MenuItem(zoomInMenu, SWT.PUSH);
00139 menuItem.setText(Messages.ZOOMIN_Y);
00140 menuItem.addListener(SWT.Selection, this);
00141
00142
00143 menuItem = new MenuItem(menu, SWT.CASCADE);
00144 menuItem.setText(Messages.ZOOMOUT_GROUP);
00145 Menu zoomOutMenu = new Menu(menuItem);
00146 menuItem.setMenu(zoomOutMenu);
00147
00148
00149 menuItem = new MenuItem(zoomOutMenu, SWT.PUSH);
00150 menuItem.setText(Messages.ZOOMOUT);
00151 menuItem.addListener(SWT.Selection, this);
00152
00153
00154 menuItem = new MenuItem(zoomOutMenu, SWT.PUSH);
00155 menuItem.setText(Messages.ZOOMOUT_X);
00156 menuItem.addListener(SWT.Selection, this);
00157
00158
00159 menuItem = new MenuItem(zoomOutMenu, SWT.PUSH);
00160 menuItem.setText(Messages.ZOOMOUT_Y);
00161 menuItem.addListener(SWT.Selection, this);
00162
00163 menuItem = new MenuItem(menu, SWT.SEPARATOR);
00164
00165
00166 menuItem = new MenuItem(menu, SWT.PUSH);
00167 menuItem.setText(Messages.SAVE_AS);
00168 menuItem.addListener(SWT.Selection, this);
00169
00170 menuItem = new MenuItem(menu, SWT.SEPARATOR);
00171
00172
00173 menuItem = new MenuItem(menu, SWT.PUSH);
00174 menuItem.setText(Messages.PROPERTIES);
00175 menuItem.addListener(SWT.Selection, this);
00176 }
00177
00178
00179
00180
00181 public void paintControl(PaintEvent e) {
00182 selection.draw(e.gc);
00183 }
00184
00185
00186
00187
00188 @Override
00189 public void handleEvent(Event event) {
00190 super.handleEvent(event);
00191
00192 switch (event.type) {
00193 case SWT.MouseMove:
00194 handleMouseMoveEvent(event);
00195 break;
00196 case SWT.MouseDown:
00197 handleMouseDownEvent(event);
00198 break;
00199 case SWT.MouseUp:
00200 handleMouseUpEvent(event);
00201 break;
00202 case SWT.MouseWheel:
00203 handleMouseWheel(event);
00204 break;
00205 case SWT.KeyDown:
00206 handleKeyDownEvent(event);
00207 break;
00208 case SWT.Selection:
00209 handleSelectionEvent(event);
00210 break;
00211 default:
00212 break;
00213 }
00214 }
00215
00216
00217
00218
00219 @Override
00220 public void dispose() {
00221 super.dispose();
00222 resources.dispose();
00223 }
00224
00231 private void handleMouseMoveEvent(Event event) {
00232 if (!selection.isDisposed()) {
00233 selection.setEndPoint(event.x, event.y);
00234 redraw();
00235 }
00236 }
00237
00244 private void handleMouseDownEvent(Event event) {
00245 if (event.button == 1) {
00246 clickedTime = System.currentTimeMillis();
00247 selection.setStartPoint(event.x, event.y);
00248 }
00249 }
00250
00257 private void handleMouseUpEvent(Event event) {
00258 if (event.button == 1 && System.currentTimeMillis() - clickedTime > 100) {
00259 for (IAxis axis : getAxisSet().getAxes()) {
00260 Point range = null;
00261 if ((getOrientation() == SWT.HORIZONTAL && axis.getDirection() == Direction.X)
00262 || (getOrientation() == SWT.VERTICAL && axis
00263 .getDirection() == Direction.Y)) {
00264 range = selection.getHorizontalRange();
00265 } else {
00266 range = selection.getVerticalRange();
00267 }
00268
00269 if (range != null && range.x != range.y) {
00270 setRange(range, axis);
00271 }
00272 }
00273 }
00274 selection.dispose();
00275 redraw();
00276 }
00277
00284 private void handleMouseWheel(Event event) {
00285 for (IAxis axis : getAxes(SWT.HORIZONTAL)) {
00286 double coordinate = axis.getDataCoordinate(event.x);
00287 if (event.count > 0) {
00288 axis.zoomIn(coordinate);
00289 } else {
00290 axis.zoomOut(coordinate);
00291 }
00292 }
00293
00294 for (IAxis axis : getAxes(SWT.VERTICAL)) {
00295 double coordinate = axis.getDataCoordinate(event.y);
00296 if (event.count > 0) {
00297 axis.zoomIn(coordinate);
00298 } else {
00299 axis.zoomOut(coordinate);
00300 }
00301 }
00302 redraw();
00303 }
00304
00311 private void handleKeyDownEvent(Event event) {
00312 if (event.keyCode == SWT.ARROW_DOWN) {
00313 if (event.stateMask == SWT.CTRL) {
00314 getAxisSet().zoomOut();
00315 } else {
00316 for (IAxis axis : getAxes(SWT.VERTICAL)) {
00317 axis.scrollDown();
00318 }
00319 }
00320 redraw();
00321 } else if (event.keyCode == SWT.ARROW_UP) {
00322 if (event.stateMask == SWT.CTRL) {
00323 getAxisSet().zoomIn();
00324 } else {
00325 for (IAxis axis : getAxes(SWT.VERTICAL)) {
00326 axis.scrollUp();
00327 }
00328 }
00329 redraw();
00330 } else if (event.keyCode == SWT.ARROW_LEFT) {
00331 for (IAxis axis : getAxes(SWT.HORIZONTAL)) {
00332 axis.scrollDown();
00333 }
00334 redraw();
00335 } else if (event.keyCode == SWT.ARROW_RIGHT) {
00336 for (IAxis axis : getAxes(SWT.HORIZONTAL)) {
00337 axis.scrollUp();
00338 }
00339 redraw();
00340 }
00341 }
00342
00350 private IAxis[] getAxes(int orientation) {
00351 IAxis[] axes;
00352 if (getOrientation() == orientation) {
00353 axes = getAxisSet().getXAxes();
00354 } else {
00355 axes = getAxisSet().getYAxes();
00356 }
00357 return axes;
00358 }
00359
00366 private void handleSelectionEvent(Event event) {
00367
00368 if (!(event.widget instanceof MenuItem)) {
00369 return;
00370 }
00371 MenuItem menuItem = (MenuItem) event.widget;
00372
00373 if (menuItem.getText().equals(Messages.ADJUST_AXIS_RANGE)) {
00374 getAxisSet().adjustRange();
00375 } else if (menuItem.getText().equals(Messages.ADJUST_X_AXIS_RANGE)) {
00376 for (IAxis axis : getAxisSet().getXAxes()) {
00377 axis.adjustRange();
00378 }
00379 } else if (menuItem.getText().equals(Messages.ADJUST_Y_AXIS_RANGE)) {
00380 for (IAxis axis : getAxisSet().getYAxes()) {
00381 axis.adjustRange();
00382 }
00383 } else if (menuItem.getText().equals(Messages.ZOOMIN)) {
00384 getAxisSet().zoomIn();
00385 } else if (menuItem.getText().equals(Messages.ZOOMIN_X)) {
00386 for (IAxis axis : getAxisSet().getXAxes()) {
00387 axis.zoomIn();
00388 }
00389 } else if (menuItem.getText().equals(Messages.ZOOMIN_Y)) {
00390 for (IAxis axis : getAxisSet().getYAxes()) {
00391 axis.zoomIn();
00392 }
00393 } else if (menuItem.getText().equals(Messages.ZOOMOUT)) {
00394 getAxisSet().zoomOut();
00395 } else if (menuItem.getText().equals(Messages.ZOOMOUT_X)) {
00396 for (IAxis axis : getAxisSet().getXAxes()) {
00397 axis.zoomOut();
00398 }
00399 } else if (menuItem.getText().equals(Messages.ZOOMOUT_Y)) {
00400 for (IAxis axis : getAxisSet().getYAxes()) {
00401 axis.zoomOut();
00402 }
00403 } else if (menuItem.getText().equals(Messages.SAVE_AS)) {
00404 openSaveAsDialog();
00405 } else if (menuItem.getText().equals(Messages.PROPERTIES)) {
00406 openPropertiesDialog();
00407 }
00408 redraw();
00409 }
00410
00414 private void openSaveAsDialog() {
00415 FileDialog dialog = new FileDialog(getShell(), SWT.SAVE);
00416 dialog.setText(Messages.SAVE_AS_DIALOG_TITLE);
00417 dialog.setFilterExtensions(EXTENSIONS);
00418
00419 String filename = dialog.open();
00420 if (filename == null) {
00421 return;
00422 }
00423
00424 int format;
00425 if (filename.endsWith(".jpg") || filename.endsWith(".jpeg")) {
00426 format = SWT.IMAGE_JPEG;
00427 } else if (filename.endsWith(".png")) {
00428 format = SWT.IMAGE_PNG;
00429 } else {
00430 format = SWT.IMAGE_UNDEFINED;
00431 }
00432
00433 if (format != SWT.IMAGE_UNDEFINED) {
00434 save(filename, format);
00435 }
00436 }
00437
00441 private void openPropertiesDialog() {
00442 PreferenceManager manager = new PreferenceManager();
00443
00444 final String chartTitle = "Chart";
00445 PreferenceNode chartNode = new PreferenceNode(chartTitle);
00446 chartNode.setPage(new ChartPage(this, resources, chartTitle));
00447 manager.addToRoot(chartNode);
00448
00449 final String legendTitle = "Legend";
00450 PreferenceNode legendNode = new PreferenceNode(legendTitle);
00451 legendNode.setPage(new LegendPage(this, resources, legendTitle));
00452 manager.addTo(chartTitle, legendNode);
00453
00454 final String xAxisTitle = "X Axis";
00455 PreferenceNode xAxisNode = new PreferenceNode(xAxisTitle);
00456 xAxisNode
00457 .setPage(new AxisPage(this, resources, Direction.X, xAxisTitle));
00458 manager.addTo(chartTitle, xAxisNode);
00459
00460 final String gridTitle = "Grid";
00461 PreferenceNode xGridNode = new PreferenceNode(gridTitle);
00462 xGridNode
00463 .setPage(new GridPage(this, resources, Direction.X, gridTitle));
00464 manager.addTo(chartTitle + "." + xAxisTitle, xGridNode);
00465
00466 final String tickTitle = "Tick";
00467 PreferenceNode xTickNode = new PreferenceNode(tickTitle);
00468 xTickNode.setPage(new AxisTickPage(this, resources, Direction.X,
00469 tickTitle));
00470 manager.addTo(chartTitle + "." + xAxisTitle, xTickNode);
00471
00472 final String yAxisTitle = "Y Axis";
00473 PreferenceNode yAxisNode = new PreferenceNode(yAxisTitle);
00474 yAxisNode
00475 .setPage(new AxisPage(this, resources, Direction.Y, yAxisTitle));
00476 manager.addTo(chartTitle, yAxisNode);
00477
00478 PreferenceNode yGridNode = new PreferenceNode(gridTitle);
00479 yGridNode
00480 .setPage(new GridPage(this, resources, Direction.Y, gridTitle));
00481 manager.addTo(chartTitle + "." + yAxisTitle, yGridNode);
00482
00483 PreferenceNode yTickNode = new PreferenceNode(tickTitle);
00484 yTickNode.setPage(new AxisTickPage(this, resources, Direction.Y,
00485 tickTitle));
00486 manager.addTo(chartTitle + "." + yAxisTitle, yTickNode);
00487
00488 final String seriesTitle = "Series";
00489 PreferenceNode plotNode = new PreferenceNode(seriesTitle);
00490 plotNode.setPage(new SeriesPage(this, resources, seriesTitle));
00491 manager.addTo(chartTitle, plotNode);
00492
00493 final String labelTitle = "Label";
00494 PreferenceNode labelNode = new PreferenceNode(labelTitle);
00495 labelNode.setPage(new SeriesLabelPage(this, resources, labelTitle));
00496 manager.addTo(chartTitle + "." + seriesTitle, labelNode);
00497
00498 PreferenceDialog dialog = new PreferenceDialog(getShell(), manager);
00499 dialog.create();
00500 dialog.getShell().setText("Properties");
00501 dialog.getTreeViewer().expandAll();
00502 dialog.open();
00503 }
00504
00513 private void setRange(Point range, IAxis axis) {
00514 if (range == null) {
00515 return;
00516 }
00517
00518 double min = axis.getDataCoordinate(range.x);
00519 double max = axis.getDataCoordinate(range.y);
00520
00521 axis.setRange(new Range(min, max));
00522 }
00523 }