2 * jSite2 - SwingInterface.java -
3 * Copyright © 2008 David Roden
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 package net.pterodactylus.jsite.gui;
22 import java.awt.event.ActionEvent;
23 import java.beans.PropertyChangeEvent;
24 import java.beans.PropertyChangeListener;
26 import java.io.FileInputStream;
27 import java.io.FileOutputStream;
28 import java.io.IOException;
29 import java.net.UnknownHostException;
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.Date;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Locale;
37 import java.util.Properties;
38 import java.util.concurrent.Executor;
39 import java.util.concurrent.Executors;
40 import java.util.logging.Level;
41 import java.util.logging.LogRecord;
42 import java.util.logging.Logger;
44 import javax.swing.JOptionPane;
45 import javax.swing.UIManager;
46 import javax.swing.UnsupportedLookAndFeelException;
48 import net.pterodactylus.jsite.core.Core;
49 import net.pterodactylus.jsite.core.CoreListener;
50 import net.pterodactylus.jsite.core.JSiteException;
51 import net.pterodactylus.jsite.core.Node;
52 import net.pterodactylus.jsite.core.Project;
53 import net.pterodactylus.jsite.i18n.I18n;
54 import net.pterodactylus.jsite.i18n.gui.I18nAction;
55 import net.pterodactylus.util.image.IconLoader;
56 import net.pterodactylus.util.io.Closer;
57 import net.pterodactylus.util.logging.Logging;
58 import net.pterodactylus.util.logging.LoggingListener;
61 * The Swing user interface.
63 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
65 public class SwingInterface implements CoreListener, LoggingListener, PropertyChangeListener {
68 private static final Logger logger = Logging.getLogger(SwingInterface.class.getName());
70 /** The application core. */
71 private final Core core;
73 /** The configuration directory. */
74 private final String configDirectory;
76 /** The main window. */
77 private MainWindow mainWindow;
80 private Executor threadPool = Executors.newCachedThreadPool();
82 /** The logger window. */
83 private LogWindow logWindow;
85 /** The “configure” action. */
86 private I18nAction configureAction;
88 /** The “import config” action. */
89 private I18nAction importConfigAction;
91 /** The “quit” action. */
92 private I18nAction quitAction;
94 /** The “add node” action. */
95 private I18nAction addNodeAction;
97 /** All node menu items. */
98 private Map<Node, I18nAction> nodeConnectActions = Collections.synchronizedMap(new HashMap<Node, I18nAction>());
100 /** All node disconnect actions. */
101 private Map<Node, I18nAction> nodeDisconnectActions = Collections.synchronizedMap(new HashMap<Node, I18nAction>());
103 /** All node edit actions. */
104 private Map<Node, I18nAction> nodeEditActions = Collections.synchronizedMap(new HashMap<Node, I18nAction>());
106 /** All node removal actions. */
107 private Map<Node, I18nAction> nodeDeleteActions = Collections.synchronizedMap(new HashMap<Node, I18nAction>());
109 /** All lanugage menu items. */
110 private List<I18nAction> languageActions = new ArrayList<I18nAction>();
112 /** The “about” action. */
113 private I18nAction helpAboutAction;
115 /** The “add project” action. */
116 private I18nAction addProjectAction;
118 /** The “insert project” actions. */
119 private Map<Project, I18nAction> insertProjectActions = new HashMap<Project, I18nAction>();
121 /** The “clone project” actions. */
122 private Map<Project, I18nAction> cloneProjectActions = new HashMap<Project, I18nAction>();
124 /** The “delete project” actions. */
125 private Map<Project, I18nAction> deleteProjectActions = new HashMap<Project, I18nAction>();
127 /** The “about” dialog. */
128 private AboutDialog aboutDialog;
130 /** The configuration dialog. */
131 private ConfigurationDialog configurationDialog;
133 /** The node editor dialog. */
134 private AddNodeDialog addNodeDialog;
136 /** The list of all defined nodes. */
137 private List<Node> nodeList = Collections.synchronizedList(new ArrayList<Node>());
139 /** The list of all projects. */
140 private List<Project> projectList = Collections.synchronizedList(new ArrayList<Project>());
146 /** The advanced mode. */
147 private boolean advancedMode;
149 /** Whether to antialias the GUI. */
150 private boolean antialias;
152 /** The control font. */
153 private String controlFont;
155 /** The user font. */
156 private String userFont;
158 /** The class name of the look and feel. */
159 private String lookAndFeel;
161 /** X coordinate of the main window. */
162 private int mainWindowX = -1;
164 /** Y coordinate of the main window. */
165 private int mainWindowY = -1;
167 /** Width of the main window. */
168 private int mainWindowWidth = -1;
170 /** Height of the main window. */
171 private int mainWindowHeight = -1;
174 * Creates a new swing interface.
177 * The core to operate on
178 * @param configDirectory
179 * The directory the configuration is stored in
181 public SwingInterface(Core core, String configDirectory) {
183 this.configDirectory = configDirectory;
184 I18n.setLocale(Locale.ENGLISH);
186 if (lookAndFeel != null) {
188 UIManager.setLookAndFeel(lookAndFeel);
189 } catch (ClassNotFoundException cnfe1) {
190 logger.log(Level.WARNING, "could not load look and feel", cnfe1);
191 } catch (InstantiationException ie1) {
192 logger.log(Level.WARNING, "could not load look and feel", ie1);
193 } catch (IllegalAccessException iae1) {
194 logger.log(Level.WARNING, "could not load look and feel", iae1);
195 } catch (UnsupportedLookAndFeelException ulafe1) {
196 logger.log(Level.WARNING, "could not load look and feel", ulafe1);
200 System.setProperty("swing.aatext", "true");
202 if (controlFont != null) {
203 System.setProperty("swing.plaf.metal.controlFont", controlFont);
205 if (userFont != null) {
206 System.setProperty("swing.plaf.metal.userFont", userFont);
210 mainWindow = new MainWindow(this);
211 mainWindow.setAdvancedMode(advancedMode);
212 if ((mainWindowX != -1) && (mainWindowY != -1) && (mainWindowWidth != -1) && (mainWindowHeight != -1)) {
213 mainWindow.setLocation(mainWindowX, mainWindowY);
214 mainWindow.setSize(mainWindowWidth, mainWindowHeight);
216 logWindow = new LogWindow();
224 * Returns the core that is controlled by the Swing interface.
233 * Returns the main window of the Swing interface.
235 * @return The main window
237 MainWindow getMainWindow() {
242 * Returns whether the advanced mode is activated.
244 * @return <code>true</code> if the advanced mode is activated,
245 * <code>false</code> if the simple mode is activated
247 boolean isAdvancedMode() {
252 * Returns the “configure” action.
254 * @return The “configure” action
256 I18nAction getConfigureAction() {
257 return configureAction;
261 * Returns the “import config” action.
263 * @return The “import config” action
265 I18nAction getImportConfigAction() {
266 return importConfigAction;
270 * Returns the “quit” action.
272 * @return The “quit” action
274 I18nAction getQuitAction() {
279 * Returns the “add node” action.
281 * @return The “add node” action
283 I18nAction getAddNodeAction() {
284 return addNodeAction;
288 * Returns the “connect to node” action for the given node.
291 * The node go get the “connect” action for
292 * @return The “connect to node” action
294 I18nAction getNodeConnectAction(Node node) {
295 return nodeConnectActions.get(node);
299 * Returns the “disconnect from node” action for the given node.
302 * The node go get the “disconnect” action for
303 * @return The “disconnect from node” action
305 I18nAction getNodeDisconnectAction(Node node) {
306 return nodeDisconnectActions.get(node);
310 * Returns the “edit node” action for the given node.
314 * @return The “edit node” action
316 I18nAction getNodeEditAction(Node node) {
317 return nodeEditActions.get(node);
321 * Returns the “delete node” action for the given node.
325 * @return The “delete node” action
327 I18nAction getNodeDeleteAction(Node node) {
328 return nodeDeleteActions.get(node);
332 * Returns all language actions.
334 * @return All language actions
336 List<I18nAction> getLanguageActions() {
337 return languageActions;
341 * Returns the “about” action.
343 * @return The “about” action
345 I18nAction getHelpAboutAction() {
346 return helpAboutAction;
350 * Returns the “add project” action.
352 * @return The “add project” action
354 I18nAction getAddProjectAction() {
355 return addProjectAction;
359 * Returns the “insert project” action for the given project.
362 * The project to get the “insert project” action for
363 * @return The “insert project” action
365 I18nAction getInsertProjectAction(Project project) {
366 return insertProjectActions.get(project);
370 * Returns the “clone project” action for the given project.
373 * The project to get the “clone project” action for
374 * @return The “clone project” action
376 I18nAction getCloneProjectAction(Project project) {
377 return cloneProjectActions.get(project);
381 * Returns the “delete project” action for the given project.
384 * The project to get the “delete project” action for
385 * @return The “delete project” action
387 I18nAction getDeleteProjectAction(Project project) {
388 return deleteProjectActions.get(project);
392 * Returns all currently configured nodes.
394 * @return All configured nodes
396 List<Node> getNodes() {
401 * Returns a list of all projects.
403 * @return All projects
405 List<Project> getProjects() {
410 * Returns the thread pool used for off-thread processes.
412 * @return The thread pool
414 Executor getThreadPool() {
431 * Loads the configuration of the interface.
433 private void loadConfig() {
434 /* initialize default stuff. */
436 /* now read config. */
437 File configFile = new File(configDirectory, "swing-interface.properties");
438 if (!configFile.exists() || !configFile.canRead() || !configFile.isFile()) {
439 System.err.println("could not find “" + configFile.getAbsolutePath() + "”!");
442 Properties configProperties = new Properties();
443 FileInputStream configInputStream = null;
445 configInputStream = new FileInputStream(configFile);
446 configProperties.load(configInputStream);
447 } catch (IOException ioe1) {
448 System.err.println("could not load config, " + ioe1.getMessage());
450 Closer.close(configInputStream);
452 if (configProperties.containsKey("advancedMode")) {
453 advancedMode = Boolean.valueOf(configProperties.getProperty("advancedMode"));
455 if (configProperties.containsKey("antialias")) {
456 antialias = Boolean.valueOf(configProperties.getProperty("antialias"));
458 if (configProperties.containsKey("controlFont")) {
459 controlFont = configProperties.getProperty("controlFont");
461 if (configProperties.containsKey("userFont")) {
462 userFont = configProperties.getProperty("userFont");
464 if (configProperties.containsKey("lookAndFeel")) {
465 lookAndFeel = configProperties.getProperty("lookAndFeel");
467 if (configProperties.containsKey("language")) {
468 I18n.setLocale(new Locale(configProperties.getProperty("language")));
470 if (configProperties.containsKey("mainWindowX")) {
471 mainWindowX = Integer.valueOf(configProperties.getProperty("mainWindowX"));
473 if (configProperties.containsKey("mainWindowY")) {
474 mainWindowY = Integer.valueOf(configProperties.getProperty("mainWindowY"));
476 if (configProperties.containsKey("mainWindowWidth")) {
477 mainWindowWidth = Integer.valueOf(configProperties.getProperty("mainWindowWidth"));
479 if (configProperties.containsKey("mainWindowHeight")) {
480 mainWindowHeight = Integer.valueOf(configProperties.getProperty("mainWindowHeight"));
485 * Saves the configuration.
487 private void saveConfig() {
488 File configDirectory = new File(this.configDirectory);
489 if (!configDirectory.exists()) {
490 if (!configDirectory.mkdirs()) {
491 System.err.println("could not create “" + this.configDirectory + "”!");
495 if (!configDirectory.exists() || !configDirectory.isDirectory() || !configDirectory.canWrite()) {
496 System.err.println("can not access “" + this.configDirectory + "”!");
499 File configFile = new File(configDirectory, "swing-interface.properties");
500 Properties configProperties = new Properties();
501 configProperties.setProperty("advancedMode", String.valueOf(advancedMode));
502 configProperties.setProperty("antialias", String.valueOf(antialias));
503 if (controlFont != null) {
504 configProperties.setProperty("controlFont", controlFont);
506 if (userFont != null) {
507 configProperties.setProperty("userFont", userFont);
509 if (lookAndFeel != null) {
510 configProperties.setProperty("lookAndFeel", lookAndFeel);
512 configProperties.setProperty("language", I18n.getLocale().getLanguage());
513 configProperties.setProperty("mainWindowX", String.valueOf(mainWindowX));
514 configProperties.setProperty("mainWindowY", String.valueOf(mainWindowY));
515 configProperties.setProperty("mainWindowWidth", String.valueOf(mainWindowWidth));
516 configProperties.setProperty("mainWindowHeight", String.valueOf(mainWindowHeight));
517 FileOutputStream configOutputStream = null;
519 configOutputStream = new FileOutputStream(configFile);
520 configProperties.store(configOutputStream, "configuration of swing interface");
521 } catch (IOException ioe1) {
522 System.err.println("could not save config, " + ioe1.getMessage());
524 Closer.close(configOutputStream);
529 * Initializes all actions.
531 private void initActions() {
532 configureAction = new I18nAction("mainWindow.menu.jSite.configure", IconLoader.loadIcon("/preferences-system.png")) {
537 @SuppressWarnings("synthetic-access")
538 public void actionPerformed(ActionEvent actionEvent) {
542 importConfigAction = new I18nAction("mainWindow.menu.jSite.importConfig") {
547 @SuppressWarnings("synthetic-access")
548 public void actionPerformed(ActionEvent actionEvent) {
552 quitAction = new I18nAction("mainWindow.menu.jSite.quit", IconLoader.loadIcon("/system-log-out.png")) {
557 @SuppressWarnings("synthetic-access")
558 public void actionPerformed(ActionEvent actionEvent) {
562 List<Locale> availableLanguages = I18n.findAvailableLanguages();
563 for (final Locale locale : availableLanguages) {
564 String language = locale.getLanguage();
565 I18nAction languageAction = new I18nAction("general.language." + language, IconLoader.loadIcon("/flag-" + language + ".png")) {
567 @SuppressWarnings("synthetic-access")
568 public void actionPerformed(ActionEvent e) {
569 changeLanguage(locale, this);
573 if (I18n.getLocale().getLanguage().equals(language)) {
574 languageAction.setEnabled(false);
576 languageActions.add(languageAction);
578 addNodeAction = new I18nAction("mainWindow.menu.node.item.addNode", IconLoader.loadIcon("/node-new.png")) {
583 @SuppressWarnings("synthetic-access")
584 public void actionPerformed(ActionEvent actionEvent) {
588 helpAboutAction = new I18nAction("mainWindow.menu.help.item.about") {
593 @SuppressWarnings("synthetic-access")
594 public void actionPerformed(ActionEvent actionEvent) {
598 addProjectAction = new I18nAction("mainWindow.button.addProject") {
603 @SuppressWarnings("synthetic-access")
604 public void actionPerformed(ActionEvent actionEvent) {
611 * Initializes all child dialogs.
613 private void initDialogs() {
614 aboutDialog = new AboutDialog(this);
615 configurationDialog = new ConfigurationDialog(this);
616 addNodeDialog = new AddNodeDialog(mainWindow);
624 * Shows the configuration dialog.
626 private void configure() {
627 configurationDialog.setAdvancedMode(advancedMode);
628 configurationDialog.setAntialias(antialias);
629 configurationDialog.setControlFont(controlFont);
630 configurationDialog.setUserFont(userFont);
631 configurationDialog.setLookAndFeel(lookAndFeel);
632 configurationDialog.setVisible(true);
633 if (!configurationDialog.wasCancelled()) {
634 advancedMode = configurationDialog.isAdvancedMode();
635 if (!advancedMode && (nodeList.size() > 1)) {
636 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.message"), I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.title"), JOptionPane.WARNING_MESSAGE);
638 mainWindow.setAdvancedMode(advancedMode);
639 antialias = configurationDialog.isAntialias();
640 controlFont = configurationDialog.getControlFont();
641 userFont = configurationDialog.getUserFont();
642 lookAndFeel = configurationDialog.getLookAndFeel();
648 * Imports old jSite configuration.
650 private void importConfig() {
657 private void quit() {
660 mainWindowX = mainWindow.getX();
661 mainWindowY = mainWindow.getY();
662 mainWindowWidth = mainWindow.getWidth();
663 mainWindowHeight = mainWindow.getHeight();
671 private void addNode() {
672 addNodeDialog.setNodeName(I18n.get(nodeList.isEmpty() ? "general.defaultNode.name" : "general.newNode.name"));
673 addNodeDialog.setNodeHostname("localhost");
674 addNodeDialog.setNodePort(9481);
675 addNodeDialog.setVisible(true);
676 if (!addNodeDialog.wasCancelled()) {
677 Node newNode = new Node();
678 newNode.setName(addNodeDialog.getNodeName());
679 newNode.setHostname(addNodeDialog.getNodeHostname());
680 newNode.setPort(addNodeDialog.getNodePort());
682 core.addNode(newNode);
683 } catch (UnknownHostException e) {
684 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.hostnameUnresolvable.message"), I18n.get("mainWindow.error.hostnameUnresolvable.title"), JOptionPane.ERROR_MESSAGE);
690 * Edits the given node.
695 private void editNode(Node node) {
696 addNodeDialog.setNodeName(node.getName());
697 addNodeDialog.setNodeHostname(node.getHostname());
698 addNodeDialog.setNodePort(node.getPort());
699 addNodeDialog.setVisible(true);
700 if (!addNodeDialog.wasCancelled()) {
701 node.setName(addNodeDialog.getNodeName());
702 node.setHostname(addNodeDialog.getNodeHostname());
703 node.setPort(addNodeDialog.getNodePort());
708 * Deletes the given node.
713 private void deleteNode(Node node) {
714 int option = JOptionPane.showConfirmDialog(mainWindow, I18n.get("mainWindow.question.deleteNode.message", node.getName()), I18n.get("mainWindow.question.deleteNode.title"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
715 if (option == JOptionPane.OK_OPTION) {
716 core.removeNode(node);
721 * Connects to the node.
724 * The node to connect to
726 private void nodeConnect(final Node node) {
727 threadPool.execute(new Runnable() {
732 @SuppressWarnings("synthetic-access")
734 logger.log(Level.INFO, "connecting to node “" + node.getName() + "”…");
735 core.connectToNode(node);
741 * Disconnects from the node.
744 * The node to disconnect from
746 private void nodeDisconnect(Node node) {
747 logger.log(Level.INFO, "disconnecting from node “" + node.getName() + "”…");
748 core.disconnectFromNode(node);
752 * Changes the language of the interface. This method also disables the
753 * action for the newly set language and enables all others.
757 * @param languageAction
758 * The action that triggered the change
760 private void changeLanguage(Locale newLocale, I18nAction languageAction) {
761 for (I18nAction i18nAction : languageActions) {
762 i18nAction.setEnabled(i18nAction != languageAction);
764 I18n.setLocale(newLocale);
768 * Shows the “about” dialog.
770 private void helpAbout() {
771 aboutDialog.setVisible(true);
777 private void addProject() {
779 core.createProject();
780 } catch (JSiteException jse1) {
781 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.notConnected.message"), I18n.get("mainWindow.error.notConnected.title"), JOptionPane.ERROR_MESSAGE);
782 } catch (IOException e) {
783 /* TODO - add i18n */
784 JOptionPane.showMessageDialog(mainWindow, I18n.get(""), I18n.get(""), JOptionPane.ERROR_MESSAGE);
792 * The project to clone
794 private void cloneProject(Project project) {
795 core.cloneProject(project);
802 * The project to delete
804 private void deleteProject(Project project) {
805 int choice = JOptionPane.showConfirmDialog(mainWindow, I18n.get("mainWindow.question.deleteProject.message", project.getName()), I18n.get("mainWindow.question.deleteProject.title"), JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
806 if (choice == JOptionPane.NO_OPTION) {
809 core.removeProject(project);
813 // INTERFACE CoreListener
819 public void loadingProjectsDone(String directory) {
820 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectLoadingDone"));
821 for (Project project : core.getProjects()) {
822 projectAdded(project, false);
829 public void loadingProjectsFailed(String directory, Throwable throwable) {
830 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.projectLoadingFailed.message", directory), I18n.get("mainWindow.error.projectLoadingFailed.title"), JOptionPane.ERROR_MESSAGE);
836 public void savingProjectsDone(String directory) {
837 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectSavingDone"));
843 public void savingProjectsFailed(String directory, Throwable throwabled) {
850 public void projectAdded(Project project) {
851 project.setName(I18n.get("general.newProject.name"));
852 project.setDescription(I18n.get("general.newProject.description", new Date()));
853 projectAdded(project, true);
858 * @param switchToProject
860 private void projectAdded(final Project project, boolean switchToProject) {
861 cloneProjectActions.put(project, new I18nAction("mainWindow.button.cloneProject") {
866 @SuppressWarnings("synthetic-access")
867 public void actionPerformed(ActionEvent actionEvent) {
868 cloneProject(project);
871 deleteProjectActions.put(project, new I18nAction("mainWindow.button.deleteProject") {
876 @SuppressWarnings("synthetic-access")
877 public void actionPerformed(ActionEvent actionEvent) {
878 deleteProject(project);
881 projectList.add(project);
882 mainWindow.addProject(project, switchToProject);
888 public void projectCloned(Project clonedProject, Project projectClone) {
889 projectAdded(projectClone, true);
895 public void projectRemoved(Project project) {
896 mainWindow.removeProject(project);
897 cloneProjectActions.remove(project);
898 deleteProjectActions.remove(project);
904 public void loadingNodesDone(String directory) {
905 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.loadingNodesDone"));
911 public void loadingNodesFailed(String directory, Throwable throwable) {
918 public void savingNodesDone(String directory) {
919 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.savingNodesDone"));
925 public void savingNodesFailed(String directory, Throwable throwable) {
932 public void coreLoaded() {
933 mainWindow.setVisible(true);
934 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreLoaded"));
940 public void coreStopped() {
941 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreStopped"));
947 public void nodeAdded(final Node node) {
948 logger.log(Level.INFO, "node added: " + node);
950 node.addPropertyChangeListener(this);
951 logger.log(Level.FINE, "nodeList.size(): " + nodeList.size());
952 nodeConnectActions.put(node, new I18nAction("mainWindow.menu.node.item.connect") {
957 @SuppressWarnings("synthetic-access")
958 public void actionPerformed(ActionEvent e) {
962 nodeDisconnectActions.put(node, new I18nAction("mainWindow.menu.node.item.disconnect") {
967 @SuppressWarnings("synthetic-access")
968 public void actionPerformed(ActionEvent e) {
969 nodeDisconnect(node);
972 nodeDisconnectActions.get(node).setEnabled(false);
973 nodeEditActions.put(node, new I18nAction("mainWindow.menu.node.item.edit") {
978 @SuppressWarnings("synthetic-access")
979 public void actionPerformed(ActionEvent actionEvent) {
983 nodeDeleteActions.put(node, new I18nAction("mainWindow.menu.node.item.remove") {
988 @SuppressWarnings("synthetic-access")
989 public void actionPerformed(ActionEvent actionEvent) {
993 mainWindow.addNode(node);
999 public void nodeRemoved(Node node) {
1000 logger.log(Level.INFO, "node removed: " + node);
1001 nodeList.remove(node);
1002 node.removePropertyChangeListener(this);
1003 nodeConnectActions.remove(node);
1004 nodeDisconnectActions.remove(node);
1005 nodeEditActions.remove(node);
1006 nodeDeleteActions.remove(node);
1007 mainWindow.removeNode(node);
1013 public void nodeConnecting(Node node) {
1014 nodeConnectActions.get(node).setEnabled(false);
1015 nodeEditActions.get(node).setEnabled(false);
1016 nodeDeleteActions.get(node).setEnabled(false);
1017 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectingToNode", node.getName(), node.getHostname(), node.getPort()));
1023 public void nodeConnected(Node node) {
1024 nodeDisconnectActions.get(node).setEnabled(true);
1025 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectedToNode", node.getName(), node.getHostname(), node.getPort()));
1026 mainWindow.setOnline(node);
1032 public void nodeConnectionFailed(Node node, Throwable cause) {
1033 nodeConnectActions.get(node).setEnabled(true);
1034 nodeEditActions.get(node).setEnabled(true);
1035 nodeDeleteActions.get(node).setEnabled(true);
1036 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectionToNodeFailed", node.getName(), node.getHostname(), node.getPort(), (cause != null) ? cause.getMessage() : "no reason given"));
1037 mainWindow.setError(node);
1038 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.nodeConnectionFailed.message", node.getName(), node.getHostname(), node.getPort(), (cause != null) ? cause.getMessage() : "no reason given"), I18n.get("mainWindow.error.nodeConnectionFailed.title"), JOptionPane.ERROR_MESSAGE);
1044 public void nodeDisconnected(Node node, Throwable throwable) {
1045 nodeDisconnectActions.get(node).setEnabled(false);
1046 nodeConnectActions.get(node).setEnabled(true);
1047 nodeEditActions.get(node).setEnabled(true);
1048 nodeDeleteActions.get(node).setEnabled(true);
1049 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.disconnectedFromNode", node.getName(), node.getHostname(), node.getPort()));
1050 mainWindow.setOffline(node);
1054 * @see net.pterodactylus.jsite.core.CoreListener#projectInsertStarted(net.pterodactylus.jsite.core.Project)
1056 public void projectInsertStarted(Project project) {
1057 mainWindow.projectInsertStarted(project);
1061 * @see net.pterodactylus.jsite.core.CoreListener#projectInsertProgressed(net.pterodactylus.jsite.core.Project,
1062 * int, int, int, int, int, boolean)
1064 public void projectInsertProgressed(Project project, int totalBlocks, int requiredBlocks, int successfulBlocks, int failedBlocks, int fatallyFailedBlocks, boolean finalizedTotal) {
1065 mainWindow.projectInsertProgressed(project, totalBlocks, requiredBlocks, successfulBlocks, failedBlocks, fatallyFailedBlocks, finalizedTotal);
1069 * @see net.pterodactylus.jsite.core.CoreListener#projectInsertGeneratedURI(net.pterodactylus.jsite.core.Project,
1072 public void projectInsertGeneratedURI(Project project, String uri) {
1073 mainWindow.projectInsertGeneratedURI(project);
1077 * @see net.pterodactylus.jsite.core.CoreListener#projectInsertFinished(net.pterodactylus.jsite.core.Project,
1080 public void projectInsertFinished(Project project, boolean success) {
1081 mainWindow.projectInsertFinished(project, success);
1085 // INTERFACE LoggingListener
1091 public void logged(LogRecord logRecord) {
1092 logWindow.logged(logRecord);
1096 // INTERFACE PropertyChangeListener
1102 public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
1103 /* do not react to anything (yet). */