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 “clone project” actions. */
119 private Map<Project, I18nAction> cloneProjectActions = new HashMap<Project, I18nAction>();
121 /** The “delete project” actions. */
122 private Map<Project, I18nAction> deleteProjectActions = new HashMap<Project, I18nAction>();
124 /** The “about” dialog. */
125 private AboutDialog aboutDialog;
127 /** The configuration dialog. */
128 private ConfigurationDialog configurationDialog;
130 /** The node editor dialog. */
131 private AddNodeDialog addNodeDialog;
133 /** The list of all defined nodes. */
134 private List<Node> nodeList = Collections.synchronizedList(new ArrayList<Node>());
136 /** The list of all projects. */
137 private List<Project> projectList = Collections.synchronizedList(new ArrayList<Project>());
143 /** The advanced mode. */
144 private boolean advancedMode;
146 /** Whether to antialias the GUI. */
147 private boolean antialias;
149 /** The control font. */
150 private String controlFont;
152 /** The user font. */
153 private String userFont;
155 /** The class name of the look and feel. */
156 private String lookAndFeel;
158 /** X coordinate of the main window. */
159 private int mainWindowX = -1;
161 /** Y coordinate of the main window. */
162 private int mainWindowY = -1;
164 /** Width of the main window. */
165 private int mainWindowWidth = -1;
167 /** Height of the main window. */
168 private int mainWindowHeight = -1;
171 * Creates a new swing interface.
174 * The core to operate on
175 * @param configDirectory
176 * The directory the configuration is stored in
178 public SwingInterface(Core core, String configDirectory) {
180 this.configDirectory = configDirectory;
181 I18n.setLocale(Locale.ENGLISH);
183 if (lookAndFeel != null) {
185 UIManager.setLookAndFeel(lookAndFeel);
186 } catch (ClassNotFoundException cnfe1) {
187 logger.log(Level.WARNING, "could not load look and feel", cnfe1);
188 } catch (InstantiationException ie1) {
189 logger.log(Level.WARNING, "could not load look and feel", ie1);
190 } catch (IllegalAccessException iae1) {
191 logger.log(Level.WARNING, "could not load look and feel", iae1);
192 } catch (UnsupportedLookAndFeelException ulafe1) {
193 logger.log(Level.WARNING, "could not load look and feel", ulafe1);
197 System.setProperty("swing.aatext", "true");
199 if (controlFont != null) {
200 System.setProperty("swing.plaf.metal.controlFont", controlFont);
202 if (userFont != null) {
203 System.setProperty("swing.plaf.metal.userFont", userFont);
207 mainWindow = new MainWindow(this);
208 mainWindow.setAdvancedMode(advancedMode);
209 if ((mainWindowX != -1) && (mainWindowY != -1) && (mainWindowWidth != -1) && (mainWindowHeight != -1)) {
210 mainWindow.setLocation(mainWindowX, mainWindowY);
211 mainWindow.setSize(mainWindowWidth, mainWindowHeight);
213 logWindow = new LogWindow();
221 * Returns the core that is controlled by the Swing interface.
230 * Returns the main window of the Swing interface.
232 * @return The main window
234 MainWindow getMainWindow() {
239 * Returns whether the advanced mode is activated.
241 * @return <code>true</code> if the advanced mode is activated,
242 * <code>false</code> if the simple mode is activated
244 boolean isAdvancedMode() {
249 * Returns the “configure” action.
251 * @return The “configure” action
253 I18nAction getConfigureAction() {
254 return configureAction;
258 * Returns the “import config” action.
260 * @return The “import config” action
262 I18nAction getImportConfigAction() {
263 return importConfigAction;
267 * Returns the “quit” action.
269 * @return The “quit” action
271 I18nAction getQuitAction() {
276 * Returns the “add node” action.
278 * @return The “add node” action
280 I18nAction getAddNodeAction() {
281 return addNodeAction;
285 * Returns the “connect to node” action for the given node.
288 * The node go get the “connect” action for
289 * @return The “connect to node” action
291 I18nAction getNodeConnectAction(Node node) {
292 return nodeConnectActions.get(node);
296 * Returns the “disconnect from node” action for the given node.
299 * The node go get the “disconnect” action for
300 * @return The “disconnect from node” action
302 I18nAction getNodeDisconnectAction(Node node) {
303 return nodeDisconnectActions.get(node);
307 * Returns the “edit node” action for the given node.
311 * @return The “edit node” action
313 I18nAction getNodeEditAction(Node node) {
314 return nodeEditActions.get(node);
318 * Returns the “delete node” action for the given node.
322 * @return The “delete node” action
324 I18nAction getNodeDeleteAction(Node node) {
325 return nodeDeleteActions.get(node);
329 * Returns all language actions.
331 * @return All language actions
333 List<I18nAction> getLanguageActions() {
334 return languageActions;
338 * Returns the “about” action.
340 * @return The “about” action
342 I18nAction getHelpAboutAction() {
343 return helpAboutAction;
347 * Returns the “add project” action.
349 * @return The “add project” action
351 I18nAction getAddProjectAction() {
352 return addProjectAction;
356 * Returns the “clone project” action for the given project.
359 * The project to get the “clone project” action for
360 * @return The “clone project” action
362 I18nAction getCloneProjectAction(Project project) {
363 return cloneProjectActions.get(project);
367 * Returns the “delete project” action for the given project.
370 * The project to get the “delete project” action for
371 * @return The “delete project” action
373 I18nAction getDeleteProjectAction(Project project) {
374 return deleteProjectActions.get(project);
378 * Returns all currently configured nodes.
380 * @return All configured nodes
382 List<Node> getNodes() {
387 * Returns a list of all projects.
389 * @return All projects
391 List<Project> getProjects() {
396 * Returns the thread pool used for off-thread processes.
398 * @return The thread pool
400 Executor getThreadPool() {
417 * Loads the configuration of the interface.
419 private void loadConfig() {
420 /* initialize default stuff. */
422 /* now read config. */
423 File configFile = new File(configDirectory, "swing-interface.properties");
424 if (!configFile.exists() || !configFile.canRead() || !configFile.isFile()) {
425 System.err.println("could not find “" + configFile.getAbsolutePath() + "”!");
428 Properties configProperties = new Properties();
429 FileInputStream configInputStream = null;
431 configInputStream = new FileInputStream(configFile);
432 configProperties.load(configInputStream);
433 } catch (IOException ioe1) {
434 System.err.println("could not load config, " + ioe1.getMessage());
436 Closer.close(configInputStream);
438 if (configProperties.containsKey("advancedMode")) {
439 advancedMode = Boolean.valueOf(configProperties.getProperty("advancedMode"));
441 if (configProperties.containsKey("antialias")) {
442 antialias = Boolean.valueOf(configProperties.getProperty("antialias"));
444 if (configProperties.containsKey("controlFont")) {
445 controlFont = configProperties.getProperty("controlFont");
447 if (configProperties.containsKey("userFont")) {
448 userFont = configProperties.getProperty("userFont");
450 if (configProperties.containsKey("lookAndFeel")) {
451 lookAndFeel = configProperties.getProperty("lookAndFeel");
453 if (configProperties.containsKey("language")) {
454 I18n.setLocale(new Locale(configProperties.getProperty("language")));
456 if (configProperties.containsKey("mainWindowX")) {
457 mainWindowX = Integer.valueOf(configProperties.getProperty("mainWindowX"));
459 if (configProperties.containsKey("mainWindowY")) {
460 mainWindowY = Integer.valueOf(configProperties.getProperty("mainWindowY"));
462 if (configProperties.containsKey("mainWindowWidth")) {
463 mainWindowWidth = Integer.valueOf(configProperties.getProperty("mainWindowWidth"));
465 if (configProperties.containsKey("mainWindowHeight")) {
466 mainWindowHeight = Integer.valueOf(configProperties.getProperty("mainWindowHeight"));
471 * Saves the configuration.
473 private void saveConfig() {
474 File configDirectory = new File(this.configDirectory);
475 if (!configDirectory.exists()) {
476 if (!configDirectory.mkdirs()) {
477 System.err.println("could not create “" + this.configDirectory + "”!");
481 if (!configDirectory.exists() || !configDirectory.isDirectory() || !configDirectory.canWrite()) {
482 System.err.println("can not access “" + this.configDirectory + "”!");
485 File configFile = new File(configDirectory, "swing-interface.properties");
486 Properties configProperties = new Properties();
487 configProperties.setProperty("advancedMode", String.valueOf(advancedMode));
488 configProperties.setProperty("antialias", String.valueOf(antialias));
489 if (controlFont != null) {
490 configProperties.setProperty("controlFont", controlFont);
492 if (userFont != null) {
493 configProperties.setProperty("userFont", userFont);
495 if (lookAndFeel != null) {
496 configProperties.setProperty("lookAndFeel", lookAndFeel);
498 configProperties.setProperty("language", I18n.getLocale().getLanguage());
499 configProperties.setProperty("mainWindowX", String.valueOf(mainWindowX));
500 configProperties.setProperty("mainWindowY", String.valueOf(mainWindowY));
501 configProperties.setProperty("mainWindowWidth", String.valueOf(mainWindowWidth));
502 configProperties.setProperty("mainWindowHeight", String.valueOf(mainWindowHeight));
503 FileOutputStream configOutputStream = null;
505 configOutputStream = new FileOutputStream(configFile);
506 configProperties.store(configOutputStream, "configuration of swing interface");
507 } catch (IOException ioe1) {
508 System.err.println("could not save config, " + ioe1.getMessage());
510 Closer.close(configOutputStream);
515 * Initializes all actions.
517 private void initActions() {
518 configureAction = new I18nAction("mainWindow.menu.jSite.configure", IconLoader.loadIcon("/preferences-system.png")) {
523 @SuppressWarnings("synthetic-access")
524 public void actionPerformed(ActionEvent actionEvent) {
528 importConfigAction = new I18nAction("mainWindow.menu.jSite.importConfig") {
533 @SuppressWarnings("synthetic-access")
534 public void actionPerformed(ActionEvent actionEvent) {
538 quitAction = new I18nAction("mainWindow.menu.jSite.quit", IconLoader.loadIcon("/system-log-out.png")) {
543 @SuppressWarnings("synthetic-access")
544 public void actionPerformed(ActionEvent actionEvent) {
548 List<Locale> availableLanguages = I18n.findAvailableLanguages();
549 for (final Locale locale : availableLanguages) {
550 String language = locale.getLanguage();
551 I18nAction languageAction = new I18nAction("general.language." + language, IconLoader.loadIcon("/flag-" + language + ".png")) {
553 @SuppressWarnings("synthetic-access")
554 public void actionPerformed(ActionEvent e) {
555 changeLanguage(locale, this);
559 if (I18n.getLocale().getLanguage().equals(language)) {
560 languageAction.setEnabled(false);
562 languageActions.add(languageAction);
564 addNodeAction = new I18nAction("mainWindow.menu.node.item.addNode", IconLoader.loadIcon("/node-new.png")) {
569 @SuppressWarnings("synthetic-access")
570 public void actionPerformed(ActionEvent actionEvent) {
574 helpAboutAction = new I18nAction("mainWindow.menu.help.item.about") {
579 @SuppressWarnings("synthetic-access")
580 public void actionPerformed(ActionEvent actionEvent) {
584 addProjectAction = new I18nAction("mainWindow.button.addProject") {
589 @SuppressWarnings("synthetic-access")
590 public void actionPerformed(ActionEvent actionEvent) {
597 * Initializes all child dialogs.
599 private void initDialogs() {
600 aboutDialog = new AboutDialog(this);
601 configurationDialog = new ConfigurationDialog(this);
602 addNodeDialog = new AddNodeDialog(mainWindow);
610 * Shows the configuration dialog.
612 private void configure() {
613 configurationDialog.setAdvancedMode(advancedMode);
614 configurationDialog.setAntialias(antialias);
615 configurationDialog.setControlFont(controlFont);
616 configurationDialog.setUserFont(userFont);
617 configurationDialog.setLookAndFeel(lookAndFeel);
618 configurationDialog.setVisible(true);
619 if (!configurationDialog.wasCancelled()) {
620 advancedMode = configurationDialog.isAdvancedMode();
621 if (!advancedMode && (nodeList.size() > 1)) {
622 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.message"), I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.title"), JOptionPane.WARNING_MESSAGE);
624 mainWindow.setAdvancedMode(advancedMode);
625 antialias = configurationDialog.isAntialias();
626 controlFont = configurationDialog.getControlFont();
627 userFont = configurationDialog.getUserFont();
628 lookAndFeel = configurationDialog.getLookAndFeel();
634 * Imports old jSite configuration.
636 private void importConfig() {
643 private void quit() {
646 mainWindowX = mainWindow.getX();
647 mainWindowY = mainWindow.getY();
648 mainWindowWidth = mainWindow.getWidth();
649 mainWindowHeight = mainWindow.getHeight();
657 private void addNode() {
658 addNodeDialog.setNodeName(I18n.get(nodeList.isEmpty() ? "general.defaultNode.name" : "general.newNode.name"));
659 addNodeDialog.setNodeHostname("localhost");
660 addNodeDialog.setNodePort(9481);
661 addNodeDialog.setVisible(true);
662 if (!addNodeDialog.wasCancelled()) {
663 Node newNode = new Node();
664 newNode.setName(addNodeDialog.getNodeName());
665 newNode.setHostname(addNodeDialog.getNodeHostname());
666 newNode.setPort(addNodeDialog.getNodePort());
668 core.addNode(newNode);
669 } catch (UnknownHostException e) {
670 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.hostnameUnresolvable.message"), I18n.get("mainWindow.error.hostnameUnresolvable.title"), JOptionPane.ERROR_MESSAGE);
676 * Edits the given node.
681 private void editNode(Node node) {
682 addNodeDialog.setNodeName(node.getName());
683 addNodeDialog.setNodeHostname(node.getHostname());
684 addNodeDialog.setNodePort(node.getPort());
685 addNodeDialog.setVisible(true);
686 if (!addNodeDialog.wasCancelled()) {
687 node.setName(addNodeDialog.getNodeName());
688 node.setHostname(addNodeDialog.getNodeHostname());
689 node.setPort(addNodeDialog.getNodePort());
694 * Deletes the given node.
699 private void deleteNode(Node node) {
700 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);
701 if (option == JOptionPane.OK_OPTION) {
702 core.removeNode(node);
707 * Connects to the node.
710 * The node to connect to
712 private void nodeConnect(final Node node) {
713 threadPool.execute(new Runnable() {
718 @SuppressWarnings("synthetic-access")
720 logger.log(Level.INFO, "connecting to node “" + node.getName() + "”…");
721 core.connectToNode(node);
727 * Disconnects from the node.
730 * The node to disconnect from
732 private void nodeDisconnect(Node node) {
733 logger.log(Level.INFO, "disconnecting from node “" + node.getName() + "”…");
734 core.disconnectFromNode(node);
738 * Changes the language of the interface. This method also disables the
739 * action for the newly set language and enables all others.
743 * @param languageAction
744 * The action that triggered the change
746 private void changeLanguage(Locale newLocale, I18nAction languageAction) {
747 for (I18nAction i18nAction : languageActions) {
748 i18nAction.setEnabled(i18nAction != languageAction);
750 I18n.setLocale(newLocale);
754 * Shows the “about” dialog.
756 private void helpAbout() {
757 aboutDialog.setVisible(true);
763 private void addProject() {
765 core.createProject();
766 } catch (JSiteException jse1) {
767 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.notConnected.message"), I18n.get("mainWindow.error.notConnected.title"), JOptionPane.ERROR_MESSAGE);
768 } catch (IOException e) {
769 /* TODO - add i18n */
770 JOptionPane.showMessageDialog(mainWindow, I18n.get(""), I18n.get(""), JOptionPane.ERROR_MESSAGE);
778 * The project to clone
780 private void cloneProject(Project project) {
781 core.cloneProject(project);
788 * The project to delete
790 private void deleteProject(Project project) {
791 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);
792 if (choice == JOptionPane.NO_OPTION) {
795 core.removeProject(project);
799 // INTERFACE CoreListener
805 public void loadingProjectsDone(String directory) {
806 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectLoadingDone"));
807 for (Project project : core.getProjects()) {
808 projectAdded(project, false);
815 public void loadingProjectsFailed(String directory, Throwable throwable) {
816 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.projectLoadingFailed.message", directory), I18n.get("mainWindow.error.projectLoadingFailed.title"), JOptionPane.ERROR_MESSAGE);
822 public void savingProjectsDone(String directory) {
823 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectSavingDone"));
829 public void savingProjectsFailed(String directory, Throwable throwabled) {
836 public void projectAdded(Project project) {
837 project.setName(I18n.get("general.newProject.name"));
838 project.setDescription(I18n.get("general.newProject.description", new Date()));
839 projectAdded(project, true);
844 * @param switchToProject
846 private void projectAdded(final Project project, boolean switchToProject) {
847 cloneProjectActions.put(project, new I18nAction("mainWindow.button.cloneProject") {
852 @SuppressWarnings("synthetic-access")
853 public void actionPerformed(ActionEvent actionEvent) {
854 cloneProject(project);
857 deleteProjectActions.put(project, new I18nAction("mainWindow.button.deleteProject") {
862 @SuppressWarnings("synthetic-access")
863 public void actionPerformed(ActionEvent actionEvent) {
864 deleteProject(project);
867 projectList.add(project);
868 mainWindow.addProject(project, switchToProject);
874 public void projectCloned(Project clonedProject, Project projectClone) {
875 projectAdded(projectClone, true);
881 public void projectRemoved(Project project) {
882 mainWindow.removeProject(project);
883 cloneProjectActions.remove(project);
884 deleteProjectActions.remove(project);
890 public void loadingNodesDone(String directory) {
891 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.loadingNodesDone"));
897 public void loadingNodesFailed(String directory, Throwable throwable) {
904 public void savingNodesDone(String directory) {
905 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.savingNodesDone"));
911 public void savingNodesFailed(String directory, Throwable throwable) {
918 public void coreLoaded() {
919 mainWindow.setVisible(true);
920 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreLoaded"));
926 public void coreStopped() {
927 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreStopped"));
933 public void nodeAdded(final Node node) {
934 logger.log(Level.INFO, "node added: " + node);
936 node.addPropertyChangeListener(this);
937 logger.log(Level.FINE, "nodeList.size(): " + nodeList.size());
938 nodeConnectActions.put(node, new I18nAction("mainWindow.menu.node.item.connect") {
943 @SuppressWarnings("synthetic-access")
944 public void actionPerformed(ActionEvent e) {
948 nodeDisconnectActions.put(node, new I18nAction("mainWindow.menu.node.item.disconnect") {
953 @SuppressWarnings("synthetic-access")
954 public void actionPerformed(ActionEvent e) {
955 nodeDisconnect(node);
958 nodeDisconnectActions.get(node).setEnabled(false);
959 nodeEditActions.put(node, new I18nAction("mainWindow.menu.node.item.edit") {
964 @SuppressWarnings("synthetic-access")
965 public void actionPerformed(ActionEvent actionEvent) {
969 nodeDeleteActions.put(node, new I18nAction("mainWindow.menu.node.item.remove") {
974 @SuppressWarnings("synthetic-access")
975 public void actionPerformed(ActionEvent actionEvent) {
979 mainWindow.addNode(node);
985 public void nodeRemoved(Node node) {
986 logger.log(Level.INFO, "node removed: " + node);
987 nodeList.remove(node);
988 node.removePropertyChangeListener(this);
989 nodeConnectActions.remove(node);
990 nodeDisconnectActions.remove(node);
991 nodeEditActions.remove(node);
992 nodeDeleteActions.remove(node);
993 mainWindow.removeNode(node);
999 public void nodeConnecting(Node node) {
1000 nodeConnectActions.get(node).setEnabled(false);
1001 nodeEditActions.get(node).setEnabled(false);
1002 nodeDeleteActions.get(node).setEnabled(false);
1003 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectingToNode", node.getName(), node.getHostname(), node.getPort()));
1009 public void nodeConnected(Node node) {
1010 nodeDisconnectActions.get(node).setEnabled(true);
1011 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectedToNode", node.getName(), node.getHostname(), node.getPort()));
1012 mainWindow.setOnline(node);
1018 public void nodeConnectionFailed(Node node, Throwable cause) {
1019 nodeConnectActions.get(node).setEnabled(true);
1020 nodeEditActions.get(node).setEnabled(true);
1021 nodeDeleteActions.get(node).setEnabled(true);
1022 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectionToNodeFailed", node.getName(), node.getHostname(), node.getPort(), (cause != null) ? cause.getMessage() : "no reason given"));
1023 mainWindow.setError(node);
1024 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);
1030 public void nodeDisconnected(Node node, Throwable throwable) {
1031 nodeDisconnectActions.get(node).setEnabled(false);
1032 nodeConnectActions.get(node).setEnabled(true);
1033 nodeEditActions.get(node).setEnabled(true);
1034 nodeDeleteActions.get(node).setEnabled(true);
1035 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.disconnectedFromNode", node.getName(), node.getHostname(), node.getPort()));
1036 mainWindow.setOffline(node);
1040 * @see net.pterodactylus.jsite.core.CoreListener#projectInsertStarted(net.pterodactylus.jsite.core.Project)
1042 public void projectInsertStarted(Project project) {
1043 mainWindow.projectInsertStarted(project);
1047 * @see net.pterodactylus.jsite.core.CoreListener#projectInsertProgressed(net.pterodactylus.jsite.core.Project,
1048 * int, int, int, int, int, boolean)
1050 public void projectInsertProgressed(Project project, int totalBlocks, int requiredBlocks, int successfulBlocks, int failedBlocks, int fatallyFailedBlocks, boolean finalizedTotal) {
1051 mainWindow.projectInsertProgressed(project, totalBlocks, requiredBlocks, successfulBlocks, failedBlocks, fatallyFailedBlocks, finalizedTotal);
1055 * @see net.pterodactylus.jsite.core.CoreListener#projectInsertGeneratedURI(net.pterodactylus.jsite.core.Project,
1058 public void projectInsertGeneratedURI(Project project, String uri) {
1059 mainWindow.projectInsertGeneratedURI(project);
1063 * @see net.pterodactylus.jsite.core.CoreListener#projectInsertFinished(net.pterodactylus.jsite.core.Project,
1066 public void projectInsertFinished(Project project, boolean success) {
1067 mainWindow.projectInsertFinished(project, success);
1071 // INTERFACE LoggingListener
1077 public void logged(LogRecord logRecord) {
1078 logWindow.logged(logRecord);
1082 // INTERFACE PropertyChangeListener
1088 public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
1089 /* do not react to anything (yet). */