From b5c0f129b44aab3456b488053ddcb4d93f0f01cc Mon Sep 17 00:00:00 2001
From: Tim Molter <tim.molter@gmail.com>
Date: Sun, 3 Feb 2013 18:45:08 +0100
Subject: [PATCH] added save-as dialog to XChart panel to save plots

---
 .../java/com/xeiam/xchart/XChartPanel.java    | 172 ++++++++++++++++++
 1 file changed, 172 insertions(+)

diff --git a/xchart/src/main/java/com/xeiam/xchart/XChartPanel.java b/xchart/src/main/java/com/xeiam/xchart/XChartPanel.java
index 76688bd8..374d857a 100644
--- a/xchart/src/main/java/com/xeiam/xchart/XChartPanel.java
+++ b/xchart/src/main/java/com/xeiam/xchart/XChartPanel.java
@@ -18,11 +18,27 @@ package com.xeiam.xchart;
 import java.awt.Dimension;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.io.File;
+import java.io.IOException;
 
+import javax.swing.AbstractAction;
+import javax.swing.JFileChooser;
+import javax.swing.JMenuItem;
 import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.KeyStroke;
+import javax.swing.filechooser.FileFilter;
 
 /**
  * A Swing JPanel that contains a Chart
+ * <p>
+ * Right-click + Save As... or ctrl+S pops up a Save As dialog box for saving the chart as a JPeg or PNG file.
  * 
  * @author timmolter
  */
@@ -39,6 +55,13 @@ public class XChartPanel extends JPanel {
 
     this.chart = chart;
 
+    // Right-click listener for saving chart
+    this.addMouseListener(new PopUpMenuClickListener());
+
+    // Control+S key listener for saving chart
+    KeyStroke ctrlS = KeyStroke.getKeyStroke(KeyEvent.VK_S, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
+    this.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(ctrlS, "save");
+    this.getActionMap().put("save", new SaveAction());
   }
 
   @Override
@@ -54,4 +77,153 @@ public class XChartPanel extends JPanel {
 
     return new Dimension(chart.width, chart.height);
   }
+
+  private class SaveAction extends AbstractAction {
+
+    public SaveAction() {
+
+      super("save");
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent e) {
+
+      showSaveAsDialog();
+    }
+  }
+
+  private void showSaveAsDialog() {
+
+    JFileChooser fileChooser = new JFileChooser();
+    fileChooser.addChoosableFileFilter(new JPGSaveFilter());
+    fileChooser.addChoosableFileFilter(new PNGSaveFilter());
+    fileChooser.setAcceptAllFileFilterUsed(false);
+
+    if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
+
+      if (fileChooser.getSelectedFile() != null) {
+        File theFileToSave = fileChooser.getSelectedFile();
+        try {
+          if (fileChooser.getFileFilter() == null) {
+            BitmapEncoder.savePNG(chart, theFileToSave.getCanonicalPath().toString());
+          } else if (fileChooser.getFileFilter().getDescription().equals("*.jpg,*.JPG")) {
+            BitmapEncoder.saveJPG(chart, theFileToSave.getCanonicalPath().toString() + ".jpg", 1.0f);
+          } else if (fileChooser.getFileFilter().getDescription().equals("*.png,*.PNG")) {
+            BitmapEncoder.savePNG(chart, theFileToSave.getCanonicalPath().toString() + ".png");
+          }
+        } catch (IOException e) {
+          e.printStackTrace();
+        }
+      }
+
+    }
+  }
+
+  private class JPGSaveFilter extends FileFilter {
+
+    @Override
+    public boolean accept(File f) {
+
+      if (f.isDirectory()) {
+        return false;
+      }
+
+      String s = f.getName();
+
+      return s.endsWith(".jpg") || s.endsWith(".JPG");
+    }
+
+    @Override
+    public String getDescription() {
+
+      return "*.jpg,*.JPG";
+    }
+
+  }
+
+  private class PNGSaveFilter extends FileFilter {
+
+    @Override
+    public boolean accept(File f) {
+
+      if (f.isDirectory()) {
+        return false;
+      }
+
+      String s = f.getName();
+
+      return s.endsWith(".png") || s.endsWith(".PNG");
+    }
+
+    @Override
+    public String getDescription() {
+
+      return "*.png,*.PNG";
+    }
+
+  }
+
+  private class PopUpMenuClickListener extends MouseAdapter {
+
+    @Override
+    public void mousePressed(MouseEvent e) {
+
+      if (e.isPopupTrigger()) {
+        doPop(e);
+      }
+    }
+
+    @Override
+    public void mouseReleased(MouseEvent e) {
+
+      if (e.isPopupTrigger()) {
+        doPop(e);
+      }
+    }
+
+    private void doPop(MouseEvent e) {
+
+      XChartPanelPopupMenu menu = new XChartPanelPopupMenu();
+      menu.show(e.getComponent(), e.getX(), e.getY());
+    }
+  }
+
+  private class XChartPanelPopupMenu extends JPopupMenu {
+
+    JMenuItem saveAsMenuItem;
+
+    public XChartPanelPopupMenu() {
+
+      saveAsMenuItem = new JMenuItem("Save As...");
+      saveAsMenuItem.addMouseListener(new MouseListener() {
+
+        @Override
+        public void mouseReleased(MouseEvent e) {
+
+          showSaveAsDialog();
+        }
+
+        @Override
+        public void mousePressed(MouseEvent e) {
+
+        }
+
+        @Override
+        public void mouseExited(MouseEvent e) {
+
+        }
+
+        @Override
+        public void mouseEntered(MouseEvent e) {
+
+        }
+
+        @Override
+        public void mouseClicked(MouseEvent e) {
+
+        }
+      });
+      add(saveAsMenuItem);
+    }
+  }
 }
-- 
GitLab