/* jNetMap
*
* Created by rakudave <public@rakudave.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
package ch.rakudave.NetMap;
import java.awt.AWTException;
import java.awt.Color;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.MenuItem;
import java.awt.Point;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.Vector;
import javax.imageio.ImageIO;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.filechooser.FileNameExtensionFilter;
public class NetMap implements Runnable {
private JButton check;
private JProgressBar progress;
private JMenu recent;
private Thread t;
protected NetCanvas canvas;
protected JFrame f;
protected JTextField interval;
protected Vector<String> recentFiles;
protected String currentFile, password;
protected Preferences preferences;
protected Triggers triggers;
protected JMenuItem connect, disconnect, remove, settings, undo, redo;
protected JCheckBox showGrid, showLegend, showStats;
protected TrayIcon trayIcon;
protected final String version = "0.3.3.5";
public static void main(String[] args) {
new NetMap(args);
}
/**
* Create new jNetMap instance
*
* @param args command line arguments such as file to open
*/
public NetMap(final String[] args) {
preferences = new Preferences(this);
canvas = new NetCanvas(this, preferences);
check = new JButton("check now");
progress = new JProgressBar();
recent = new JMenu("Recent Files");
javax.swing.SwingUtilities.invokeLater(new Runnable() {public void run() {createGUI(args);}});
t = new Thread(this);
t.start();
Updater.checkForUpdates(this);
}
// create main window
private void createGUI(String[] args) {
f = new JFrame("jNetMap");
f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // let me handle that (ask to save)
f.setPreferredSize(new Dimension(800,700));
f.add(canvas);
// build the menu
JMenuBar menu = new JMenuBar();
JMenu file = new JMenu("File");
JMenuItem newFile = new JMenuItem("New");
newFile.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N,java.awt.Event.CTRL_MASK));
newFile.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {newFile();}});
JMenuItem open = new JMenuItem("Open");
open.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O,java.awt.Event.CTRL_MASK));
open.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {openFile(null);}});
JMenuItem save = new JMenuItem("Save");
save.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S,java.awt.Event.CTRL_MASK));
save.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {saveFile(currentFile);}});
JMenuItem saveas = new JMenuItem("Save As...");
saveas.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S,java.awt.Event.CTRL_MASK+java.awt.Event.SHIFT_MASK));
saveas.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {saveFile(null);}});
JMenuItem protect = new JMenuItem("Protect");
protect.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {newPassword();}});
JMenuItem export = new JMenuItem("Export Image");
export.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_E,java.awt.Event.CTRL_MASK));
export.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {imageExport();}});
JMenuItem exit = new JMenuItem("Exit");
exit.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Q,java.awt.Event.CTRL_MASK));
exit.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {destroy();}});
file.add(newFile);
file.add(open);
file.add(recent);
file.add(new JSeparator());
file.add(save);
file.add(saveas);
file.add(protect);
file.add(new JSeparator());
file.add(export);
file.add(new JSeparator());
file.add(exit);
JMenu edit = new JMenu("Edit");
JMenuItem addItem = new JMenuItem("Add Device");
addItem.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A,java.awt.Event.CTRL_MASK));
addItem.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {canvas.addItem(null);}});
JMenuItem addNote = new JMenuItem("Add Note");
addNote.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N,java.awt.Event.CTRL_MASK));
addNote.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {NetNote note = new NetNote("","",new Point(50,50)); canvas.notes.add(note); canvas.editNote(note);}});
undo = new JMenuItem("Undo");
undo.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Z,java.awt.Event.CTRL_MASK));
undo.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {canvas.undo();}});
undo.setEnabled(false);
redo = new JMenuItem("Redo");
redo.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Y,java.awt.Event.CTRL_MASK));
redo.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {canvas.redo();}});
redo.setEnabled(false);
connect = new JMenuItem("Connect");
connect.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_SPACE, 0));
connect.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {canvas.connect();}});
connect.setEnabled(false);
disconnect = new JMenuItem("Disconnect");
disconnect.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_BACK_SPACE, 0));
disconnect.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {canvas.disconnect();}});
disconnect.setEnabled(false);
remove = new JMenuItem("Remove");
remove.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_DELETE, 0));
remove.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {canvas.remove();}});
remove.setEnabled(false);
settings = new JMenuItem("Settings");
settings.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_ENTER, 0));
settings.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {canvas.settings();}});
settings.setEnabled(false);
JMenuItem bg = new JMenuItem("Add Background Image");
bg.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_B,java.awt.Event.CTRL_MASK));
bg.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {BackgroundImage img = new BackgroundImage(canvas); if (img.getPath() != null) canvas.backgroundImages.add(img);canvas.repaint();}});
JMenuItem rmbg = new JMenuItem("Remove All BG Images");
rmbg.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {canvas.backgroundImages.clear();canvas.repaint();canvas.updateHistory();}});
JMenuItem scan = new JMenuItem("Scan for Devices");
scan.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F,java.awt.Event.CTRL_MASK));
scan.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {new NetScan(canvas);}});
edit.add(addItem);
edit.add(addNote);
edit.add(new JSeparator());
edit.add(undo);
edit.add(redo);
edit.add(new JSeparator());
edit.add(connect);
edit.add(disconnect);
edit.add(remove);
edit.add(settings);
edit.add(new JSeparator());
edit.add(bg);
edit.add(rmbg);
edit.add(new JSeparator());
edit.add(scan);
JMenu view = new JMenu("View");
showGrid = new JCheckBox("Grid Mode", preferences.drawGrid);
showGrid.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {preferences.drawGrid = !preferences.drawGrid; canvas.repaint();}});
JMenuItem align = new JMenuItem("Align to Grid");
align.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_G,java.awt.Event.CTRL_MASK));
align.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {canvas.alignToGrid(null);}});
showLegend = new JCheckBox("Show Legend", preferences.drawLegend);
showLegend.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {preferences.drawLegend = !preferences.drawLegend; canvas.repaint();}});
showStats = new JCheckBox("Show Statistics", preferences.drawStats);
showStats.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {preferences.drawStats = !preferences.drawStats; canvas.repaint();}});
view.add(showGrid);
view.add(align);
view.add(new JSeparator());
view.add(showLegend);
view.add(showStats);
JMenu tools = new JMenu("Tools");
JMenuItem scanner = new JMenuItem("Port Scanner");
scanner.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P,java.awt.Event.CTRL_MASK));
scanner.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {if (canvas.selected.size() > 0) new PortProbe(canvas.selected.get(0).getIP()); else new PortProbe("127.0.0.1");}});
JMenuItem checkNow = new JMenuItem("Check Now");
checkNow.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_X,java.awt.Event.CTRL_MASK));
checkNow.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {t.interrupt();}});
JMenuItem resetCanvas = new JMenuItem("Reset Canvas");
resetCanvas.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R,java.awt.Event.CTRL_MASK));
resetCanvas.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {canvas.resetCanvas();}});
JMenuItem prefs = new JMenuItem("Preferences");
prefs.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_COMMA,java.awt.Event.CTRL_MASK));
prefs.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {preferences.showDialog();}});
tools.add(scanner);
tools.add(checkNow);
tools.add(resetCanvas);
tools.add(new JSeparator());
tools.add(prefs);
JMenu help = new JMenu("Help");
JMenuItem web = new JMenuItem("Documentation");
web.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {openURL("http://www.rakudave.ch/jnetmap#download");}});
JMenuItem bug = new JMenuItem("Report a Bug");
bug.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {showBugs();}});
JMenuItem about = new JMenuItem("About");
about.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {showAbout();}});
help.add(web);
help.add(bug);
help.add(new JSeparator());
help.add(about);
interval = new JTextField(preferences.pingInterval+"");
interval.setMaximumSize(new Dimension(30,20));
interval.setPreferredSize(new Dimension(30,20));
interval.setToolTipText("Floats are Ok");
check.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {t.interrupt();}});
check.setPreferredSize(new Dimension(100,20));
progress.setMaximumSize(new Dimension(100,20));
progress.setPreferredSize(new Dimension(100,20));
progress.setStringPainted(true);
progress.setVisible(false);
menu.add(file);
menu.add(edit);
menu.add(view);
menu.add(tools);
menu.add(help);
menu.add(Box.createHorizontalGlue());
menu.add(new JLabel("Ping interval: "));
menu.add(interval);
menu.add(new JLabel(" min "));
menu.add(check);
menu.add(progress);
menu.add(Box.createHorizontalStrut(5));
f.setJMenuBar(menu);
// done building menu
f.setIconImage(Icon.OTHER.getImage());
f.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent evt) {destroy();}});
f.pack();
if (preferences.rememberSize) f.setSize(preferences.windowSize);
if (preferences.rememberPosition) f.setLocation(preferences.windowPosition);
f.setVisible(true);
onLaunch(args);
addTrayIcon();
t.interrupt();
}
// infinite loop during runtime, ping all hosts, then sleep for x seconds
public void run() {
while (true) {
try {
try { // sleep for (one minute * the interval)
if (preferences.pingInterval <= 0) synchronized (t) {t.wait();} // stop for values <= 0 (for manual control)
else Thread.sleep((int)(60000*preferences.pingInterval));
} catch (InterruptedException e) {}
try {preferences.pingInterval = Float.parseFloat(interval.getText());} catch (Exception e) {} // try to parse ping interval
check.setVisible(false);
progress.setVisible(true);
canvas.resetStats();
for (NetItem item : canvas.items) {
if (item.getImageID() != 6) {
// ping mode:
if (item.getPort() == 70000) { // 70000 = ping, so that way old .netmap won't fail to load
try { // try to connect and set appropriate color
if (InetAddress.getByName(item.getIP()).isReachable(preferences.pingTimeout)) {
if (!item.getColor().equals(Color.green)) triggers.green(item);
canvas.setStatus(item, 1);
} else {
if (!item.getColor().equals(Color.red)) triggers.red(item);
canvas.setStatus(item, 3);
}
} catch (IOException e) {
if (!item.getColor().equals(Color.orange)) triggers.orange(item);
canvas.setStatus(item, 2);
}
// port mode:
} else {
try { // try to connect and set appropriate color
progress.setToolTipText("checking: "+item.getIP()+":"+item.getPort());
Socket sock = new Socket(item.getIP(), item.getPort());
sock.close();
if (!item.getColor().equals(Color.green)) triggers.green(item);
canvas.setStatus(item, 1);
} catch (UnknownHostException e) {
if (!item.getColor().equals(Color.orange)) triggers.orange(item);
canvas.setStatus(item, 2);
} catch (IOException e) {
if (!item.getColor().equals(Color.red)) triggers.red(item);
canvas.setStatus(item, 3);
}
}
progress.setValue(progress.getValue() + (100/canvas.items.size()));
}
}
// clean up
canvas.updateSwitches();
progress.setVisible(false);
check.setVisible(true);
progress.setValue(0);
progress.setToolTipText(null);
preferences.ignoreTriggers = false;
trayIcon.setToolTip("jNetMap - "+canvas.stats[1]+" up, "+canvas.stats[3]+" down");
} catch (Exception e) {}
}
}
private void showAbout() {
JOptionPane.showMessageDialog(f,
"jNetMap version "+version+"\n\n" +
"Created by rakudave <public@rakudave.ch>\n" +
"For more Information, visit www.rakudave.ch/jnetmap\n\n" +
"This program is free software; you can redistribute it and/or modify\n" +
"it under the terms of the GNU General Public License as published by\n" +
"the Free Software Foundation; either version 3 of the License, or\n" +
"(at your option) any later version.\n\n" +
"This program is distributed in the hope that it will be useful,\n" +
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" +
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" +
"GNU General Public License for more details.",
"About", JOptionPane.INFORMATION_MESSAGE);
}
private void showBugs() {
JOptionPane.showMessageDialog(f,
"Please write to \"bugs@rakudave.ch\" with \"jNetMap\" in the subject line.\n" +
"Also check for \"Known Issues\" on www.rakudave.ch/jnetmap#issues first.\n\n"+
"Thanks!",
"Report a Bug", JOptionPane.INFORMATION_MESSAGE);
}
/**
* Try to open a URL in the default browser.
* If this fails, show a message with the URL.
*
* @param URL to open in the default browser
*/
public void openURL(String URL) {
if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
if (desktop.isSupported(Desktop.Action.BROWSE)) {
try {
desktop.browse(new URI(URL));
} catch(Exception e) {
JOptionPane.showMessageDialog(f,
"Failed to launch your browser!\nLaunch your browser and enter \""+
URL+"\" into the navigation bar.",
"Error", JOptionPane.ERROR_MESSAGE);
}
}
}
}
/**
* Save items and lines to a file using an object stream
*
* @param path to the file. If this is <i>null</i>, show selection dialog
*/
public void saveFile(String path) {
if (path == null) {// display standard save dialog
JFileChooser chooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("jNetMap File (*.netmap)","netmap");
chooser.setFileFilter(filter);
int returnValue = chooser.showSaveDialog(f);
if (returnValue != JFileChooser.APPROVE_OPTION) return; // canceled
path = chooser.getSelectedFile().toString();
if (!path.matches("(.*).netmap")) path += ".netmap"; // add ending if not provided
} else if (password != null) { // ask for password if one exists
if (!Password.dialog(this, false)) return; // return if canceled (don't save)
}
File selectedFile = new File(path);
for (BackgroundImage img : canvas.backgroundImages) img.removeImage();
FileOutputStream out = null;
ObjectOutputStream obj = null;
try { // try to write two vectors to the file (items and lines)
out = new FileOutputStream(selectedFile);
obj = new ObjectOutputStream(out);
obj.writeObject(canvas.items);
obj.writeObject(canvas.lines);
obj.writeObject(password);
obj.writeObject(canvas.backgroundImages);
obj.writeObject(canvas.notes);
obj.close();
out.close();
currentFile = path;
canvas.updateHistory();
updateRecentDocuments(path);
f.setTitle("jNetMap - "+selectedFile);
} catch (Exception e) {
JOptionPane.showMessageDialog(f, "Failed to write "+selectedFile.getAbsolutePath(), "Error", JOptionPane.ERROR_MESSAGE);
}
canvas.repaint();
canvas.documentChanged = false;
}
/**
* Load items and lines from a file using an object stream
*
* @param path to read from. If this is <i>null</i>, show selection dialog
*/
@SuppressWarnings("unchecked")
public void openFile(String path) {
if (canvas.documentChanged) { // only prompt if something has changed
int option = JOptionPane.showConfirmDialog(f, "Do you wish to save the current map?", "Quit", JOptionPane.YES_NO_CANCEL_OPTION);
switch (option) {
case 0: // yes selected
saveFile(currentFile);
break;
case 2: // cancel selected
return;
default: // no/close selected
break;
}
}
File inFile = null;
if (path == null) { // check if a path was provided as an argument. If not, display a selection dialog
JFileChooser chooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("NetMap File (*.netmap)","netmap");
chooser.setFileFilter(filter);
if (chooser.showOpenDialog(f) != JFileChooser.APPROVE_OPTION) return;
path = chooser.getSelectedFile().getAbsolutePath();
inFile = chooser.getSelectedFile();
} else {
inFile = new File(path);
}
password = null;
FileInputStream in = null;
ObjectInputStream obj = null;
try { // try to read two vectors from the file
in = new FileInputStream(inFile);
obj = new ObjectInputStream(in);
canvas.items = (Vector<NetItem>) obj.readObject();
canvas.lines = ensureCompatibility((Vector<NetLine>) obj.readObject());
try {password = (String) obj.readObject();} catch (Exception e) {}
try {canvas.backgroundImages = (Vector<BackgroundImage>) obj.readObject();} catch (Exception e) {}
try {canvas.notes = (Vector<NetNote>) obj.readObject();} catch (Exception e) {}
in.close();
obj.close();
currentFile = path;
updateRecentDocuments(path);
for (BackgroundImage img : canvas.backgroundImages) img.reloadImage();
f.setTitle("jNetMap - "+path);
canvas.historyPosition = -1;
canvas.repaint();
canvas.updateHistory();
canvas.documentChanged = false;
} catch (Exception e) {
JOptionPane.showMessageDialog(f, "Failed to read "+path,"Error", JOptionPane.ERROR_MESSAGE);
}
}
// creates new file (prompt to save current), wipes the canvas
private void newFile() {
if (canvas.documentChanged) { // only prompt if something has changed
int option = JOptionPane.showConfirmDialog(f, "Do you wish to save this map?", "New File", JOptionPane.YES_NO_CANCEL_OPTION);
switch (option) {
case 0: // yes selected
saveFile(currentFile);
break;
case 2: // cancel selected
return;
default: // no/close selected
break;
}
}
canvas.clear();
currentFile = null;
password = null;
canvas.documentChanged = false;
f.setTitle("jNetMap");
}
// ensures that all NetLines are of type NetLine2
private Vector<NetLine2> ensureCompatibility(Vector<NetLine> lines) {
Vector<NetLine2> newLines = new Vector<NetLine2>(lines.size());
for (NetLine line : lines) newLines.add(new NetLine2(line));
return newLines;
}
private void newPassword() {
Password.dialog(this, true);
}
// prompt to save on exit
private void destroy() {
if (preferences.askToSave && canvas.documentChanged) { // only prompt if something has changed
int option = JOptionPane.showConfirmDialog(f, "Do you wish to save the current map?", "Quit", JOptionPane.YES_NO_CANCEL_OPTION);
switch (option) {
case 0: // yes selected
saveFile(currentFile);
preferences.save();
System.exit(0);
break;
case 2: // cancel selected
return;
default: // no/close selected
preferences.save();
System.exit(0);
break;
}
} else {
preferences.save();
System.exit(0);
}
}
// export the current canvas as a .png file
private void imageExport() {
boolean grid = preferences.drawGrid;
if (grid) preferences.drawGrid = false;
int width = 0, height = 0;
canvas.resetCanvas();
for (NetItem item : canvas.items) {
if (item.getPosition().x > width) width = item.getPosition().x;
if (item.getPosition().y > height) height = item.getPosition().y;
}
canvas.img = new BufferedImage(width+100, height+100, BufferedImage.TYPE_INT_RGB);
canvas.g2 = canvas.img.createGraphics();
canvas.exportPaint = true;
canvas.repaint();
JFileChooser chooser = new JFileChooser(); // display standard save dialog
FileNameExtensionFilter filter = new FileNameExtensionFilter("PNG File","png");
chooser.setFileFilter(filter);
int returnValue = chooser.showSaveDialog(f);
if (returnValue != JFileChooser.APPROVE_OPTION) {canvas.exportPaint = false; canvas.repaint(); return;}; // canceled
String path = chooser.getSelectedFile().toString();
if (!path.matches("(.*).png")) path += ".png"; // add ending if not provided
File selectedFile = new File(path);
try {
ImageIO.write(canvas.img, "png", selectedFile);
} catch (Exception e) {
JOptionPane.showMessageDialog(f, "Failed to write "+selectedFile.getAbsolutePath(), "Error", JOptionPane.ERROR_MESSAGE);
}
if (grid) preferences.drawGrid = true;
canvas.exportPaint = false;
canvas.repaint();
}
// remember 5 recent files, enter them into File > "Recent Files"
private void updateRecentDocuments(String path) {
if (path != null) {
if (!recentFiles.contains(path)) recentFiles.add(0,path);
if (recentFiles.size() > 5) recentFiles.remove(5);
}
recent.removeAll();
if (!preferences.history) return;
for (int i = 0; i < recentFiles.size(); i++) {
final String document = recentFiles.get(i);
JMenuItem item = new JMenuItem(document);
item.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {openFile(document);}});
recent.add(item);
}
if (recentFiles.size() > 0) {
JMenuItem clear = new JMenuItem("Clear History");
clear.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {recent.removeAll(); recentFiles.clear();}});
recent.add(new JSeparator());
recent.add(clear);
}
}
// what to do on startup (open file from argument, scan or display example)
private void onLaunch(String[] args) {
if (args.length == 1) { // check if we have to load a file passed as an argument
openFile(args[0]);
} else if (preferences.openLast && currentFile != null) {
openFile(currentFile);
} else if (preferences.askToScan) { // else load an example
int option = JOptionPane.showConfirmDialog(f, "Welcome to jNetMap!\nShould I scan your network?", "Welcome", JOptionPane.YES_NO_OPTION);
switch (option) {
case 0: // yes selected
new NetScan(canvas);
break;
default: // no selected
NetItem n1 = new NetItem(0,"127.0.0.1",70000,"example 1",new Point(251,301));
NetItem n2 = new NetItem(0,"localhost",70000,"example 2",new Point(451,301));
NetItem n3 = new NetItem(6,"",0,"",new Point(351,201));
canvas.items.add(n1);
canvas.items.add(n2);
canvas.items.add(n3);
canvas.lines.add(new NetLine2(n1,n3));
canvas.lines.add(new NetLine2(n2,n3));
canvas.stats[0] = 2; canvas.stats[4] = 2;
break;
}
}
}
private void addTrayIcon() {
if (preferences.trayIcon && SystemTray.isSupported()) {
PopupMenu popup = new PopupMenu();
MenuItem hide = new MenuItem("Show/Hide");
hide.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {if (f.isVisible()) f.setVisible(false); else f.setVisible(true);}});
MenuItem check = new MenuItem("Check Now");
check.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {t.interrupt();}});
MenuItem pref = new MenuItem("Preferences");
pref.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {preferences.showDialog();}});
MenuItem doc = new MenuItem("Documentation");
doc.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {openURL("http://www.rakudave.ch/jnetmap#download");}});
MenuItem exit = new MenuItem("Exit");
exit.addActionListener(new ActionListener() {@Override public void actionPerformed(ActionEvent e) {destroy();}});
popup.add(hide);
popup.addSeparator();
popup.add(check);
popup.add(pref);
popup.add(doc);
popup.addSeparator();
popup.add(exit);
trayIcon = new TrayIcon(Icon.OTHER.getImage(),"jNetMap", popup);
trayIcon.setImageAutoSize(true);
trayIcon.addMouseListener(new MouseListener() {
@Override public void mouseClicked(MouseEvent e) {if (f.isVisible()) f.setVisible(false); else f.setVisible(true);}
@Override public void mouseEntered(MouseEvent e) {}
@Override public void mouseExited(MouseEvent e) {}
@Override public void mousePressed(MouseEvent e) {}
@Override public void mouseReleased(MouseEvent e) {}
});
try {
SystemTray.getSystemTray().add(trayIcon);
} catch (AWTException e) {}
}
}
}