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.DefaultComboBoxModel;
45 import javax.swing.JComboBox;
46 import javax.swing.JOptionPane;
47 import javax.swing.UIManager;
48 import javax.swing.UnsupportedLookAndFeelException;
50 import net.pterodactylus.jsite.core.Core;
51 import net.pterodactylus.jsite.core.CoreListener;
52 import net.pterodactylus.jsite.core.JSiteException;
53 import net.pterodactylus.jsite.core.Node;
54 import net.pterodactylus.jsite.core.Project;
55 import net.pterodactylus.jsite.i18n.I18n;
56 import net.pterodactylus.jsite.i18n.gui.I18nAction;
57 import net.pterodactylus.util.image.IconLoader;
58 import net.pterodactylus.util.io.Closer;
59 import net.pterodactylus.util.logging.Logging;
60 import net.pterodactylus.util.logging.LoggingListener;
63 * The Swing user interface.
65 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
67 public class SwingInterface implements CoreListener, LoggingListener, PropertyChangeListener {
70 private static final Logger logger = Logging.getLogger(SwingInterface.class.getName());
72 /** The application core. */
73 private final Core core;
75 /** The configuration directory. */
76 private final String configDirectory;
78 /** The main window. */
79 private MainWindow mainWindow;
82 private Executor threadPool = Executors.newCachedThreadPool();
84 /** The logger window. */
85 private LogWindow logWindow;
87 /** The “configure” action. */
88 private I18nAction configureAction;
90 /** The “import config” action. */
91 private I18nAction importConfigAction;
93 /** The “quit” action. */
94 private I18nAction quitAction;
96 /** The “add node” action. */
97 private I18nAction addNodeAction;
99 /** All node menu items. */
100 private Map<Node, I18nAction> nodeConnectActions = Collections.synchronizedMap(new HashMap<Node, I18nAction>());
102 /** All node disconnect actions. */
103 private Map<Node, I18nAction> nodeDisconnectActions = Collections.synchronizedMap(new HashMap<Node, I18nAction>());
105 /** All node edit actions. */
106 private Map<Node, I18nAction> nodeEditActions = Collections.synchronizedMap(new HashMap<Node, I18nAction>());
108 /** All node removal actions. */
109 private Map<Node, I18nAction> nodeDeleteActions = Collections.synchronizedMap(new HashMap<Node, I18nAction>());
111 /** All lanugage menu items. */
112 private List<I18nAction> languageActions = new ArrayList<I18nAction>();
114 /** The “about” action. */
115 private I18nAction helpAboutAction;
117 /** The “add project” action. */
118 private I18nAction addProjectAction;
120 /** The “insert project” actions. */
121 private Map<Project, I18nAction> insertProjectActions = new HashMap<Project, I18nAction>();
123 /** The “clone project” actions. */
124 private Map<Project, I18nAction> cloneProjectActions = new HashMap<Project, I18nAction>();
126 /** The “delete project” actions. */
127 private Map<Project, I18nAction> deleteProjectActions = new HashMap<Project, I18nAction>();
129 /** The “about” dialog. */
130 private AboutDialog aboutDialog;
132 /** The configuration dialog. */
133 private ConfigurationDialog configurationDialog;
135 /** The node editor dialog. */
136 private AddNodeDialog addNodeDialog;
138 /** The list of all defined nodes. */
139 private List<Node> nodeList = Collections.synchronizedList(new ArrayList<Node>());
141 /** The list of all projects. */
142 private List<Project> projectList = Collections.synchronizedList(new ArrayList<Project>());
148 /** The advanced mode. */
149 private boolean advancedMode;
151 /** Whether to antialias the GUI. */
152 private boolean antialias;
154 /** The control font. */
155 private String controlFont;
157 /** The user font. */
158 private String userFont;
160 /** The class name of the look and feel. */
161 private String lookAndFeel;
163 /** X coordinate of the main window. */
164 private int mainWindowX = -1;
166 /** Y coordinate of the main window. */
167 private int mainWindowY = -1;
169 /** Width of the main window. */
170 private int mainWindowWidth = -1;
172 /** Height of the main window. */
173 private int mainWindowHeight = -1;
176 * Creates a new swing interface.
179 * The core to operate on
180 * @param configDirectory
181 * The directory the configuration is stored in
183 public SwingInterface(Core core, String configDirectory) {
185 this.configDirectory = configDirectory;
186 I18n.setLocale(Locale.ENGLISH);
188 if (lookAndFeel != null) {
190 UIManager.setLookAndFeel(lookAndFeel);
191 } catch (ClassNotFoundException cnfe1) {
192 logger.log(Level.WARNING, "could not load look and feel", cnfe1);
193 } catch (InstantiationException ie1) {
194 logger.log(Level.WARNING, "could not load look and feel", ie1);
195 } catch (IllegalAccessException iae1) {
196 logger.log(Level.WARNING, "could not load look and feel", iae1);
197 } catch (UnsupportedLookAndFeelException ulafe1) {
198 logger.log(Level.WARNING, "could not load look and feel", ulafe1);
202 System.setProperty("swing.aatext", "true");
204 if (controlFont != null) {
205 System.setProperty("swing.plaf.metal.controlFont", controlFont);
207 if (userFont != null) {
208 System.setProperty("swing.plaf.metal.userFont", userFont);
212 mainWindow = new MainWindow(this);
213 mainWindow.setAdvancedMode(advancedMode);
214 if ((mainWindowX != -1) && (mainWindowY != -1) && (mainWindowWidth != -1) && (mainWindowHeight != -1)) {
215 mainWindow.setLocation(mainWindowX, mainWindowY);
216 mainWindow.setSize(mainWindowWidth, mainWindowHeight);
218 logWindow = new LogWindow();
226 * Returns the core that is controlled by the Swing interface.
235 * Returns the main window of the Swing interface.
237 * @return The main window
239 MainWindow getMainWindow() {
244 * Returns whether the advanced mode is activated.
246 * @return <code>true</code> if the advanced mode is activated,
247 * <code>false</code> if the simple mode is activated
249 boolean isAdvancedMode() {
254 * Returns the “configure” action.
256 * @return The “configure” action
258 I18nAction getConfigureAction() {
259 return configureAction;
263 * Returns the “import config” action.
265 * @return The “import config” action
267 I18nAction getImportConfigAction() {
268 return importConfigAction;
272 * Returns the “quit” action.
274 * @return The “quit” action
276 I18nAction getQuitAction() {
281 * Returns the “add node” action.
283 * @return The “add node” action
285 I18nAction getAddNodeAction() {
286 return addNodeAction;
290 * Returns the “connect to node” action for the given node.
293 * The node go get the “connect” action for
294 * @return The “connect to node” action
296 I18nAction getNodeConnectAction(Node node) {
297 return nodeConnectActions.get(node);
301 * Returns the “disconnect from node” action for the given node.
304 * The node go get the “disconnect” action for
305 * @return The “disconnect from node” action
307 I18nAction getNodeDisconnectAction(Node node) {
308 return nodeDisconnectActions.get(node);
312 * Returns the “edit node” action for the given node.
316 * @return The “edit node” action
318 I18nAction getNodeEditAction(Node node) {
319 return nodeEditActions.get(node);
323 * Returns the “delete node” action for the given node.
327 * @return The “delete node” action
329 I18nAction getNodeDeleteAction(Node node) {
330 return nodeDeleteActions.get(node);
334 * Returns all language actions.
336 * @return All language actions
338 List<I18nAction> getLanguageActions() {
339 return languageActions;
343 * Returns the “about” action.
345 * @return The “about” action
347 I18nAction getHelpAboutAction() {
348 return helpAboutAction;
352 * Returns the “add project” action.
354 * @return The “add project” action
356 I18nAction getAddProjectAction() {
357 return addProjectAction;
361 * Returns the “insert project” action for the given project.
364 * The project to get the “insert project” action for
365 * @return The “insert project” action
367 I18nAction getInsertProjectAction(Project project) {
368 return insertProjectActions.get(project);
372 * Returns the “clone project” action for the given project.
375 * The project to get the “clone project” action for
376 * @return The “clone project” action
378 I18nAction getCloneProjectAction(Project project) {
379 return cloneProjectActions.get(project);
383 * Returns the “delete project” action for the given project.
386 * The project to get the “delete project” action for
387 * @return The “delete project” action
389 I18nAction getDeleteProjectAction(Project project) {
390 return deleteProjectActions.get(project);
394 * Returns all currently configured nodes.
396 * @return All configured nodes
398 List<Node> getNodes() {
403 * Returns a list of all projects.
405 * @return All projects
407 List<Project> getProjects() {
412 * Returns the thread pool used for off-thread processes.
414 * @return The thread pool
416 Executor getThreadPool() {
433 * Loads the configuration of the interface.
435 private void loadConfig() {
436 /* initialize default stuff. */
438 /* now read config. */
439 File configFile = new File(configDirectory, "swing-interface.properties");
440 if (!configFile.exists() || !configFile.canRead() || !configFile.isFile()) {
441 System.err.println("could not find “" + configFile.getAbsolutePath() + "”!");
444 Properties configProperties = new Properties();
445 FileInputStream configInputStream = null;
447 configInputStream = new FileInputStream(configFile);
448 configProperties.load(configInputStream);
449 } catch (IOException ioe1) {
450 System.err.println("could not load config, " + ioe1.getMessage());
452 Closer.close(configInputStream);
454 if (configProperties.containsKey("advancedMode")) {
455 advancedMode = Boolean.valueOf(configProperties.getProperty("advancedMode"));
457 if (configProperties.containsKey("antialias")) {
458 antialias = Boolean.valueOf(configProperties.getProperty("antialias"));
460 if (configProperties.containsKey("controlFont")) {
461 controlFont = configProperties.getProperty("controlFont");
463 if (configProperties.containsKey("userFont")) {
464 userFont = configProperties.getProperty("userFont");
466 if (configProperties.containsKey("lookAndFeel")) {
467 lookAndFeel = configProperties.getProperty("lookAndFeel");
469 if (configProperties.containsKey("language")) {
470 I18n.setLocale(new Locale(configProperties.getProperty("language")));
472 if (configProperties.containsKey("mainWindowX")) {
473 mainWindowX = Integer.valueOf(configProperties.getProperty("mainWindowX"));
475 if (configProperties.containsKey("mainWindowY")) {
476 mainWindowY = Integer.valueOf(configProperties.getProperty("mainWindowY"));
478 if (configProperties.containsKey("mainWindowWidth")) {
479 mainWindowWidth = Integer.valueOf(configProperties.getProperty("mainWindowWidth"));
481 if (configProperties.containsKey("mainWindowHeight")) {
482 mainWindowHeight = Integer.valueOf(configProperties.getProperty("mainWindowHeight"));
487 * Saves the configuration.
489 private void saveConfig() {
490 File configDirectory = new File(this.configDirectory);
491 if (!configDirectory.exists()) {
492 if (!configDirectory.mkdirs()) {
493 System.err.println("could not create “" + this.configDirectory + "”!");
497 if (!configDirectory.exists() || !configDirectory.isDirectory() || !configDirectory.canWrite()) {
498 System.err.println("can not access “" + this.configDirectory + "”!");
501 File configFile = new File(configDirectory, "swing-interface.properties");
502 Properties configProperties = new Properties();
503 configProperties.setProperty("advancedMode", String.valueOf(advancedMode));
504 configProperties.setProperty("antialias", String.valueOf(antialias));
505 if (controlFont != null) {
506 configProperties.setProperty("controlFont", controlFont);
508 if (userFont != null) {
509 configProperties.setProperty("userFont", userFont);
511 if (lookAndFeel != null) {
512 configProperties.setProperty("lookAndFeel", lookAndFeel);
514 configProperties.setProperty("language", I18n.getLocale().getLanguage());
515 configProperties.setProperty("mainWindowX", String.valueOf(mainWindowX));
516 configProperties.setProperty("mainWindowY", String.valueOf(mainWindowY));
517 configProperties.setProperty("mainWindowWidth", String.valueOf(mainWindowWidth));
518 configProperties.setProperty("mainWindowHeight", String.valueOf(mainWindowHeight));
519 FileOutputStream configOutputStream = null;
521 configOutputStream = new FileOutputStream(configFile);
522 configProperties.store(configOutputStream, "configuration of swing interface");
523 } catch (IOException ioe1) {
524 System.err.println("could not save config, " + ioe1.getMessage());
526 Closer.close(configOutputStream);
531 * Initializes all actions.
533 private void initActions() {
534 configureAction = new I18nAction("mainWindow.menu.jSite.configure", IconLoader.loadIcon("/preferences-system.png")) {
539 @SuppressWarnings("synthetic-access")
540 public void actionPerformed(ActionEvent actionEvent) {
544 importConfigAction = new I18nAction("mainWindow.menu.jSite.importConfig") {
549 @SuppressWarnings("synthetic-access")
550 public void actionPerformed(ActionEvent actionEvent) {
554 quitAction = new I18nAction("mainWindow.menu.jSite.quit", IconLoader.loadIcon("/system-log-out.png")) {
559 @SuppressWarnings("synthetic-access")
560 public void actionPerformed(ActionEvent actionEvent) {
564 List<Locale> availableLanguages = I18n.findAvailableLanguages();
565 for (final Locale locale : availableLanguages) {
566 String language = locale.getLanguage();
567 I18nAction languageAction = new I18nAction("general.language." + language, IconLoader.loadIcon("/flag-" + language + ".png")) {
569 @SuppressWarnings("synthetic-access")
570 public void actionPerformed(ActionEvent e) {
571 changeLanguage(locale, this);
575 if (I18n.getLocale().getLanguage().equals(language)) {
576 languageAction.setEnabled(false);
578 languageActions.add(languageAction);
580 addNodeAction = new I18nAction("mainWindow.menu.node.item.addNode", IconLoader.loadIcon("/node-new.png")) {
585 @SuppressWarnings("synthetic-access")
586 public void actionPerformed(ActionEvent actionEvent) {
590 helpAboutAction = new I18nAction("mainWindow.menu.help.item.about") {
595 @SuppressWarnings("synthetic-access")
596 public void actionPerformed(ActionEvent actionEvent) {
600 addProjectAction = new I18nAction("mainWindow.button.addProject") {
605 @SuppressWarnings("synthetic-access")
606 public void actionPerformed(ActionEvent actionEvent) {
613 * Initializes all child dialogs.
615 private void initDialogs() {
616 aboutDialog = new AboutDialog(this);
617 configurationDialog = new ConfigurationDialog(this);
618 addNodeDialog = new AddNodeDialog(mainWindow);
626 * Shows the configuration dialog.
628 private void configure() {
629 configurationDialog.setAdvancedMode(advancedMode);
630 configurationDialog.setAntialias(antialias);
631 configurationDialog.setControlFont(controlFont);
632 configurationDialog.setUserFont(userFont);
633 configurationDialog.setLookAndFeel(lookAndFeel);
634 configurationDialog.setVisible(true);
635 if (!configurationDialog.wasCancelled()) {
636 advancedMode = configurationDialog.isAdvancedMode();
637 if (!advancedMode && (nodeList.size() > 1)) {
638 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.message"), I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.title"), JOptionPane.WARNING_MESSAGE);
640 mainWindow.setAdvancedMode(advancedMode);
641 antialias = configurationDialog.isAntialias();
642 controlFont = configurationDialog.getControlFont();
643 userFont = configurationDialog.getUserFont();
644 lookAndFeel = configurationDialog.getLookAndFeel();
650 * Imports old jSite configuration.
652 private void importConfig() {
659 private void quit() {
662 mainWindowX = mainWindow.getX();
663 mainWindowY = mainWindow.getY();
664 mainWindowWidth = mainWindow.getWidth();
665 mainWindowHeight = mainWindow.getHeight();
673 private void addNode() {
674 addNodeDialog.setNodeName(I18n.get(nodeList.isEmpty() ? "general.defaultNode.name" : "general.newNode.name"));
675 addNodeDialog.setNodeHostname("localhost");
676 addNodeDialog.setNodePort(9481);
677 addNodeDialog.setVisible(true);
678 if (!addNodeDialog.wasCancelled()) {
679 Node newNode = new Node();
680 newNode.setName(addNodeDialog.getNodeName());
681 newNode.setHostname(addNodeDialog.getNodeHostname());
682 newNode.setPort(addNodeDialog.getNodePort());
684 core.addNode(newNode);
685 } catch (UnknownHostException e) {
686 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.hostnameUnresolvable.message"), I18n.get("mainWindow.error.hostnameUnresolvable.title"), JOptionPane.ERROR_MESSAGE);
692 * Edits the given node.
697 private void editNode(Node node) {
698 addNodeDialog.setNodeName(node.getName());
699 addNodeDialog.setNodeHostname(node.getHostname());
700 addNodeDialog.setNodePort(node.getPort());
701 addNodeDialog.setVisible(true);
702 if (!addNodeDialog.wasCancelled()) {
703 node.setName(addNodeDialog.getNodeName());
704 node.setHostname(addNodeDialog.getNodeHostname());
705 node.setPort(addNodeDialog.getNodePort());
710 * Deletes the given node.
715 private void deleteNode(Node node) {
716 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);
717 if (option == JOptionPane.OK_OPTION) {
718 core.removeNode(node);
723 * Connects to the node.
726 * The node to connect to
728 private void nodeConnect(final Node node) {
729 threadPool.execute(new Runnable() {
734 @SuppressWarnings("synthetic-access")
736 logger.log(Level.INFO, "connecting to node “" + node.getName() + "”…");
737 core.connectToNode(node);
743 * Disconnects from the node.
746 * The node to disconnect from
748 private void nodeDisconnect(Node node) {
749 logger.log(Level.INFO, "disconnecting from node “" + node.getName() + "”…");
750 core.disconnectFromNode(node);
754 * Changes the language of the interface. This method also disables the
755 * action for the newly set language and enables all others.
759 * @param languageAction
760 * The action that triggered the change
762 private void changeLanguage(Locale newLocale, I18nAction languageAction) {
763 for (I18nAction i18nAction : languageActions) {
764 i18nAction.setEnabled(i18nAction != languageAction);
766 I18n.setLocale(newLocale);
770 * Shows the “about” dialog.
772 private void helpAbout() {
773 aboutDialog.setVisible(true);
779 private void addProject() {
781 core.createProject();
782 } catch (JSiteException jse1) {
783 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.projectCreationFailed.message", jse1.getMessage()), I18n.get("mainWindow.error.projectCreationFailed.title"), JOptionPane.ERROR_MESSAGE);
784 } catch (IOException e) {
785 /* TODO - add i18n */
786 JOptionPane.showMessageDialog(mainWindow, I18n.get(""), I18n.get(""), JOptionPane.ERROR_MESSAGE);
791 * Inserts the given project.
794 * The project to insert
796 private void insertProject(Project project) {
797 Node targetNode = project.getNode();
798 if (targetNode == null) {
799 JComboBox nodeComboBox = new JComboBox();
800 for (Node node : nodeList) {
801 ((DefaultComboBoxModel) nodeComboBox.getModel()).addElement(node.getName() + " (" + node.getHostname() + ":" + node.getPort() + ")");
803 int selectedOption = JOptionPane.showConfirmDialog(mainWindow, new Object[] { I18n.get("nodeSelectionDialog.selectNode.text"), nodeComboBox }, I18n.get("nodeSelectionDialog.noNodeSelected.text"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
804 if (selectedOption == JOptionPane.CANCEL_OPTION) {
807 int selectedNodeIndex = nodeComboBox.getSelectedIndex();
808 logger.log(Level.FINE, "selected node index: " + selectedNodeIndex);
809 targetNode = nodeList.get(selectedNodeIndex);
811 logger.log(Level.INFO, "Inserting project “" + project.getName() + "” to node “" + targetNode.getName() + "”...");
812 if (!core.isNodeConnected(targetNode)) {
813 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.nodeNotConnected.message", targetNode.getName()), I18n.get("mainWindow.error.nodeNotConnected.title", targetNode.getName()), JOptionPane.ERROR_MESSAGE);
816 core.insertProject(targetNode, project);
823 * The project to clone
825 private void cloneProject(Project project) {
826 core.cloneProject(project);
833 * The project to delete
835 private void deleteProject(Project project) {
836 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);
837 if (choice == JOptionPane.NO_OPTION) {
840 core.removeProject(project);
844 // INTERFACE CoreListener
850 public void loadingProjectsDone(String directory) {
851 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectLoadingDone"));
852 for (Project project : core.getProjects()) {
853 projectAdded(project, false);
860 public void loadingProjectsFailed(String directory, Throwable throwable) {
861 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.projectLoadingFailed.message", directory), I18n.get("mainWindow.error.projectLoadingFailed.title"), JOptionPane.ERROR_MESSAGE);
867 public void savingProjectsDone(String directory) {
868 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectSavingDone"));
874 public void savingProjectsFailed(String directory, Throwable throwabled) {
881 public void projectAdded(Project project) {
882 project.setName(I18n.get("general.newProject.name"));
883 project.setDescription(I18n.get("general.newProject.description", new Date()));
884 projectAdded(project, true);
889 * @param switchToProject
891 private void projectAdded(final Project project, boolean switchToProject) {
892 insertProjectActions.put(project, new I18nAction("mainWindow.button.insertProject") {
897 @SuppressWarnings("synthetic-access")
898 public void actionPerformed(ActionEvent actionEvent) {
899 insertProject(project);
902 cloneProjectActions.put(project, new I18nAction("mainWindow.button.cloneProject") {
907 @SuppressWarnings("synthetic-access")
908 public void actionPerformed(ActionEvent actionEvent) {
909 cloneProject(project);
912 deleteProjectActions.put(project, new I18nAction("mainWindow.button.deleteProject") {
917 @SuppressWarnings("synthetic-access")
918 public void actionPerformed(ActionEvent actionEvent) {
919 deleteProject(project);
922 projectList.add(project);
923 mainWindow.addProject(project, switchToProject);
929 public void projectCloned(Project clonedProject, Project projectClone) {
930 projectAdded(projectClone, true);
936 public void projectRemoved(Project project) {
937 mainWindow.removeProject(project);
938 cloneProjectActions.remove(project);
939 deleteProjectActions.remove(project);
945 public void loadingNodesDone(String directory) {
946 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.loadingNodesDone"));
952 public void loadingNodesFailed(String directory, Throwable throwable) {
959 public void savingNodesDone(String directory) {
960 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.savingNodesDone"));
966 public void savingNodesFailed(String directory, Throwable throwable) {
973 public void coreLoaded() {
974 mainWindow.setVisible(true);
975 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreLoaded"));
981 public void coreStopped() {
982 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreStopped"));
988 public void nodeAdded(final Node node) {
989 logger.log(Level.INFO, "node added: " + node);
991 node.addPropertyChangeListener(this);
992 logger.log(Level.FINE, "nodeList.size(): " + nodeList.size());
993 nodeConnectActions.put(node, new I18nAction("mainWindow.menu.node.item.connect") {
998 @SuppressWarnings("synthetic-access")
999 public void actionPerformed(ActionEvent e) {
1003 nodeDisconnectActions.put(node, new I18nAction("mainWindow.menu.node.item.disconnect") {
1008 @SuppressWarnings("synthetic-access")
1009 public void actionPerformed(ActionEvent e) {
1010 nodeDisconnect(node);
1013 nodeDisconnectActions.get(node).setEnabled(false);
1014 nodeEditActions.put(node, new I18nAction("mainWindow.menu.node.item.edit") {
1019 @SuppressWarnings("synthetic-access")
1020 public void actionPerformed(ActionEvent actionEvent) {
1024 nodeDeleteActions.put(node, new I18nAction("mainWindow.menu.node.item.remove") {
1029 @SuppressWarnings("synthetic-access")
1030 public void actionPerformed(ActionEvent actionEvent) {
1034 mainWindow.addNode(node);
1040 public void nodeRemoved(Node node) {
1041 logger.log(Level.INFO, "node removed: " + node);
1042 nodeList.remove(node);
1043 node.removePropertyChangeListener(this);
1044 nodeConnectActions.remove(node);
1045 nodeDisconnectActions.remove(node);
1046 nodeEditActions.remove(node);
1047 nodeDeleteActions.remove(node);
1048 mainWindow.removeNode(node);
1054 public void nodeConnecting(Node node) {
1055 nodeConnectActions.get(node).setEnabled(false);
1056 nodeEditActions.get(node).setEnabled(false);
1057 nodeDeleteActions.get(node).setEnabled(false);
1058 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectingToNode", node.getName(), node.getHostname(), node.getPort()));
1064 public void nodeConnected(Node node) {
1065 nodeDisconnectActions.get(node).setEnabled(true);
1066 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectedToNode", node.getName(), node.getHostname(), node.getPort()));
1067 mainWindow.setOnline(node);
1073 public void nodeConnectionFailed(Node node, Throwable cause) {
1074 nodeConnectActions.get(node).setEnabled(true);
1075 nodeEditActions.get(node).setEnabled(true);
1076 nodeDeleteActions.get(node).setEnabled(true);
1077 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectionToNodeFailed", node.getName(), node.getHostname(), node.getPort(), (cause != null) ? cause.getMessage() : "no reason given"));
1078 mainWindow.setError(node);
1079 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);
1085 public void nodeDisconnected(Node node, Throwable throwable) {
1086 nodeDisconnectActions.get(node).setEnabled(false);
1087 nodeConnectActions.get(node).setEnabled(true);
1088 nodeEditActions.get(node).setEnabled(true);
1089 nodeDeleteActions.get(node).setEnabled(true);
1090 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.disconnectedFromNode", node.getName(), node.getHostname(), node.getPort()));
1091 mainWindow.setOffline(node);
1095 * @see net.pterodactylus.jsite.core.CoreListener#projectInsertStarted(net.pterodactylus.jsite.core.Project)
1097 public void projectInsertStarted(Project project) {
1098 mainWindow.projectInsertStarted(project);
1102 * @see net.pterodactylus.jsite.core.CoreListener#projectInsertProgressed(net.pterodactylus.jsite.core.Project,
1103 * int, int, int, int, int, boolean)
1105 public void projectInsertProgressed(Project project, int totalBlocks, int requiredBlocks, int successfulBlocks, int failedBlocks, int fatallyFailedBlocks, boolean finalizedTotal) {
1106 mainWindow.projectInsertProgressed(project, totalBlocks, requiredBlocks, successfulBlocks, failedBlocks, fatallyFailedBlocks, finalizedTotal);
1110 * @see net.pterodactylus.jsite.core.CoreListener#projectInsertGeneratedURI(net.pterodactylus.jsite.core.Project,
1113 public void projectInsertGeneratedURI(Project project, String uri) {
1114 mainWindow.projectInsertGeneratedURI(project);
1118 * @see net.pterodactylus.jsite.core.CoreListener#projectInsertFinished(net.pterodactylus.jsite.core.Project,
1121 public void projectInsertFinished(Project project, boolean success) {
1122 mainWindow.projectInsertFinished(project, success);
1126 // INTERFACE LoggingListener
1132 public void logged(LogRecord logRecord) {
1133 logWindow.logged(logRecord);
1137 // INTERFACE PropertyChangeListener
1143 public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
1144 /* do not react to anything (yet). */