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;
24 import java.io.FileInputStream;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.Date;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Locale;
34 import java.util.Properties;
35 import java.util.concurrent.Executor;
36 import java.util.concurrent.Executors;
37 import java.util.logging.Level;
38 import java.util.logging.LogRecord;
39 import java.util.logging.Logger;
41 import javax.swing.AbstractAction;
42 import javax.swing.Action;
43 import javax.swing.JOptionPane;
44 import javax.swing.UIManager;
45 import javax.swing.UnsupportedLookAndFeelException;
47 import net.pterodactylus.jsite.core.Core;
48 import net.pterodactylus.jsite.core.CoreListener;
49 import net.pterodactylus.jsite.core.NoNodeException;
50 import net.pterodactylus.jsite.core.Node;
51 import net.pterodactylus.jsite.core.Project;
52 import net.pterodactylus.jsite.core.Request;
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>
66 public class SwingInterface implements CoreListener, LoggingListener {
69 private static final Logger logger = Logging.getLogger(SwingInterface.class.getName());
71 /** The application core. */
72 private final Core core;
74 /** The configuration directory. */
75 private final String configDirectory;
77 /** The main window. */
78 private MainWindow mainWindow;
81 private Executor threadPool = Executors.newCachedThreadPool();
83 /** The logger window. */
84 private LogWindow logWindow;
86 /** The “configure” action. */
87 private I18nAction configureAction;
89 /** The “import config” action. */
90 private I18nAction importConfigAction;
92 /** The “quit” action. */
93 private I18nAction quitAction;
95 /** The “manage nodes” action. */
96 private I18nAction manageNodesAction;
98 /** The “connect to node” (simple mode) action. */
99 private I18nAction nodeConnectAction;
101 /** The “disconnect from node” (simple mode) action. */
102 private I18nAction nodeDisconnectAction;
104 /** All node menu items. */
105 private List<Action> nodeConnectActions = Collections.synchronizedList(new ArrayList<Action>());
107 /** Mapping from nodes to node connect actions. */
108 private Map<Node, Action> nodeNodeConnectActions = Collections.synchronizedMap(new HashMap<Node, Action>());
110 /** Mapping from node connect actions to nodes. */
111 private Map<Action, Node> nodeConnectActionNodes = Collections.synchronizedMap(new HashMap<Action, Node>());
113 /** All node disconnect actions. */
114 private List<Action> nodeDisconnectActions = Collections.synchronizedList(new ArrayList<Action>());
116 /** Mapping from nodes to node disconnect actions. */
117 private Map<Node, Action> nodeNodeDisconnectActions = Collections.synchronizedMap(new HashMap<Node, Action>());
119 /** Mapping from node disconnect actions to nodes. */
120 private Map<Action, Node> nodeDisconnectActionNodes = Collections.synchronizedMap(new HashMap<Action, Node>());
122 /** The node manager dialog. */
123 private ManageNodesDialog manageNodesDialog;
125 /** All lanugage menu items. */
126 private List<I18nAction> languageActions = new ArrayList<I18nAction>();
128 /** The “about” action. */
129 private I18nAction helpAboutAction;
131 /** The “add project” action. */
132 private I18nAction addProjectAction;
134 /** The “clone project” action. */
135 private I18nAction cloneProjectAction;
137 /** The “delete project” action. */
138 private I18nAction deleteProjectAction;
140 /** The “about” dialog. */
141 private AboutDialog aboutDialog;
143 /** The configuration dialog. */
144 private ConfigurationDialog configurationDialog;
146 /** The list of all defined nodes. */
147 private List<Node> nodeList = Collections.synchronizedList(new ArrayList<Node>());
149 /** The request table model. */
150 private RequestTableModel requestTableModel = new RequestTableModel();
156 /** The advanced mode. */
157 private boolean advancedMode;
159 /** Whether to antialias the GUI. */
160 private boolean antialias;
162 /** The control font. */
163 private String controlFont;
165 /** The user font. */
166 private String userFont;
168 /** The class name of the look and feel. */
169 private String lookAndFeel;
171 /** X coordinate of the main window. */
172 private int mainWindowX = -1;
174 /** Y coordinate of the main window. */
175 private int mainWindowY = -1;
177 /** Width of the main window. */
178 private int mainWindowWidth = -1;
180 /** Height of the main window. */
181 private int mainWindowHeight = -1;
184 * Creates a new swing interface.
187 * The core to operate on
188 * @param configDirectory
189 * The directory the configuration is stored in
191 public SwingInterface(Core core, String configDirectory) {
193 this.configDirectory = configDirectory;
194 I18n.setLocale(Locale.ENGLISH);
196 if (lookAndFeel != null) {
198 UIManager.setLookAndFeel(lookAndFeel);
199 } catch (ClassNotFoundException cnfe1) {
200 logger.log(Level.WARNING, "could not load look and feel", cnfe1);
201 } catch (InstantiationException ie1) {
202 logger.log(Level.WARNING, "could not load look and feel", ie1);
203 } catch (IllegalAccessException iae1) {
204 logger.log(Level.WARNING, "could not load look and feel", iae1);
205 } catch (UnsupportedLookAndFeelException ulafe1) {
206 logger.log(Level.WARNING, "could not load look and feel", ulafe1);
210 System.setProperty("swing.aatext", "true");
212 if (controlFont != null) {
213 System.setProperty("swing.plaf.metal.controlFont", controlFont);
215 if (userFont != null) {
216 System.setProperty("swing.plaf.metal.userFont", userFont);
220 mainWindow = new MainWindow(this);
221 mainWindow.setAdvancedMode(advancedMode);
222 if ((mainWindowX != -1) && (mainWindowY != -1) && (mainWindowWidth != -1) && (mainWindowHeight != -1)) {
223 mainWindow.setLocation(mainWindowX, mainWindowY);
224 mainWindow.setSize(mainWindowWidth, mainWindowHeight);
226 logWindow = new LogWindow();
234 * Returns the core that is controlled by the Swing interface.
243 * Returns the main window of the Swing interface.
245 * @return The main window
247 MainWindow getMainWindow() {
252 * Returns whether the advanced mode is activated.
254 * @return <code>true</code> if the advanced mode is activated,
255 * <code>false</code> if the simple mode is activated
257 boolean isAdvancedMode() {
262 * Returns the “configure” action.
264 * @return The “configure” action
266 I18nAction getConfigureAction() {
267 return configureAction;
271 * Returns the “import config” action.
273 * @return The “import config” action
275 I18nAction getImportConfigAction() {
276 return importConfigAction;
280 * Returns the “quit” action.
282 * @return The “quit” action
284 I18nAction getQuitAction() {
289 * Returns the “manage nodes” action.
291 * @return The “manage nodes” action
293 I18nAction getManageNodesAction() {
294 return manageNodesAction;
298 * Returns the “connect to node” action.
300 * @return The “connect to node” action
302 I18nAction getNodeConnectAction() {
303 return nodeConnectAction;
307 * Returns all “connect node” actions.
309 * @return All “connect node” actions
311 List<Action> getNodeConnectActions() {
312 return nodeConnectActions;
316 * Returns the “disconnect from node” action.
318 * @return The “disconnect from node” action
320 I18nAction getNodeDisconnectAction() {
321 return nodeDisconnectAction;
325 * Returns all “disconnect node” actions.
327 * @return All “disconnect node” action
329 List<Action> getNodeDisconnectActions() {
330 return nodeDisconnectActions;
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 “clone project” action.
363 * @return The “clone project” action
365 I18nAction getCloneProjectAction() {
366 return cloneProjectAction;
370 * Returns the “delete project” action.
372 * @return The “delete project” action
374 I18nAction getDeleteProjectAction() {
375 return deleteProjectAction;
379 * Returns the request table model.
381 * @return The request table model
383 RequestTableModel getRequestTableModel() {
384 return requestTableModel;
400 * Loads the configuration of the interface.
402 private void loadConfig() {
403 /* initialize default stuff. */
405 /* now read config. */
406 File configFile = new File(configDirectory, "swing-interface.properties");
407 if (!configFile.exists() || !configFile.canRead() || !configFile.isFile()) {
408 System.err.println("could not find “" + configFile.getAbsolutePath() + "”!");
411 Properties configProperties = new Properties();
412 FileInputStream configInputStream = null;
414 configInputStream = new FileInputStream(configFile);
415 configProperties.load(configInputStream);
416 } catch (IOException ioe1) {
417 System.err.println("could not load config, " + ioe1.getMessage());
419 Closer.close(configInputStream);
421 if (configProperties.containsKey("advancedMode")) {
422 advancedMode = Boolean.valueOf(configProperties.getProperty("advancedMode"));
424 if (configProperties.containsKey("antialias")) {
425 antialias = Boolean.valueOf(configProperties.getProperty("antialias"));
427 if (configProperties.containsKey("controlFont")) {
428 controlFont = configProperties.getProperty("controlFont");
430 if (configProperties.containsKey("userFont")) {
431 userFont = configProperties.getProperty("userFont");
433 if (configProperties.containsKey("lookAndFeel")) {
434 lookAndFeel = configProperties.getProperty("lookAndFeel");
436 if (configProperties.containsKey("language")) {
437 I18n.setLocale(new Locale(configProperties.getProperty("language")));
439 if (configProperties.containsKey("mainWindowX")) {
440 mainWindowX = Integer.valueOf(configProperties.getProperty("mainWindowX"));
442 if (configProperties.containsKey("mainWindowY")) {
443 mainWindowY = Integer.valueOf(configProperties.getProperty("mainWindowY"));
445 if (configProperties.containsKey("mainWindowWidth")) {
446 mainWindowWidth = Integer.valueOf(configProperties.getProperty("mainWindowWidth"));
448 if (configProperties.containsKey("mainWindowHeight")) {
449 mainWindowHeight = Integer.valueOf(configProperties.getProperty("mainWindowHeight"));
454 * Saves the configuration.
456 private void saveConfig() {
457 File configDirectory = new File(this.configDirectory);
458 if (!configDirectory.exists()) {
459 if (!configDirectory.mkdirs()) {
460 System.err.println("could not create “" + this.configDirectory + "”!");
464 if (!configDirectory.exists() || !configDirectory.isDirectory() || !configDirectory.canWrite()) {
465 System.err.println("can not access “" + this.configDirectory + "”!");
468 File configFile = new File(configDirectory, "swing-interface.properties");
469 Properties configProperties = new Properties();
470 configProperties.setProperty("advancedMode", String.valueOf(advancedMode));
471 configProperties.setProperty("antialias", String.valueOf(antialias));
472 if (controlFont != null) {
473 configProperties.setProperty("controlFont", controlFont);
475 if (userFont != null) {
476 configProperties.setProperty("userFont", userFont);
478 if (lookAndFeel != null) {
479 configProperties.setProperty("lookAndFeel", lookAndFeel);
481 configProperties.setProperty("language", I18n.getLocale().getLanguage());
482 configProperties.setProperty("mainWindowX", String.valueOf(mainWindowX));
483 configProperties.setProperty("mainWindowY", String.valueOf(mainWindowY));
484 configProperties.setProperty("mainWindowWidth", String.valueOf(mainWindowWidth));
485 configProperties.setProperty("mainWindowHeight", String.valueOf(mainWindowHeight));
486 FileOutputStream configOutputStream = null;
488 configOutputStream = new FileOutputStream(configFile);
489 configProperties.store(configOutputStream, "configuration of swing interface");
490 } catch (IOException ioe1) {
491 System.err.println("could not save config, " + ioe1.getMessage());
493 Closer.close(configOutputStream);
498 * Initializes all actions.
500 private void initActions() {
501 configureAction = new I18nAction("mainWindow.menu.jSite.configure", IconLoader.loadIcon("/preferences-system.png")) {
506 @SuppressWarnings("synthetic-access")
507 public void actionPerformed(ActionEvent actionEvent) {
511 importConfigAction = new I18nAction("mainWindow.menu.jSite.importConfig") {
516 @SuppressWarnings("synthetic-access")
517 public void actionPerformed(ActionEvent actionEvent) {
521 quitAction = new I18nAction("mainWindow.menu.jSite.quit", IconLoader.loadIcon("/system-log-out.png")) {
526 @SuppressWarnings("synthetic-access")
527 public void actionPerformed(ActionEvent actionEvent) {
531 manageNodesAction = new I18nAction("mainWindow.menu.node.item.manageNodes") {
536 @SuppressWarnings("synthetic-access")
537 public void actionPerformed(ActionEvent actionEvent) {
541 nodeConnectAction = new I18nAction("mainWindow.menu.node.item.connect", false) {
543 @SuppressWarnings("synthetic-access")
544 public void actionPerformed(ActionEvent actionEvent) {
545 List<Node> nodes = core.getNodes();
546 if (nodes.isEmpty()) {
549 nodeConnect(nodes.get(0));
553 nodeDisconnectAction = new I18nAction("mainWindow.menu.node.item.disconnect", false) {
558 @SuppressWarnings("synthetic-access")
559 public void actionPerformed(ActionEvent e) {
560 List<Node> nodes = core.getNodes();
561 if (nodes.isEmpty()) {
564 nodeDisconnect(nodes.get(0));
567 rebuildNodeActions(core.getNodes());
568 List<Locale> availableLanguages = I18n.findAvailableLanguages();
569 for (final Locale locale: availableLanguages) {
570 I18nAction languageAction = new I18nAction("general.language." + locale.getLanguage()) {
572 @SuppressWarnings("synthetic-access")
573 public void actionPerformed(ActionEvent e) {
574 changeLanguage(locale, this);
578 if (I18n.getLocale().getLanguage().equals(locale.getLanguage())) {
579 languageAction.setEnabled(false);
581 languageActions.add(languageAction);
583 helpAboutAction = new I18nAction("mainWindow.menu.help.item.about") {
588 @SuppressWarnings("synthetic-access")
589 public void actionPerformed(ActionEvent actionEvent) {
593 addProjectAction = new I18nAction("mainWindow.button.addProject") {
598 @SuppressWarnings("synthetic-access")
599 public void actionPerformed(ActionEvent actionEvent) {
603 cloneProjectAction = new I18nAction("mainWindow.button.cloneProject") {
608 @SuppressWarnings("synthetic-access")
609 public void actionPerformed(ActionEvent actionEvent) {
613 deleteProjectAction = new I18nAction("mainWindow.button.deleteProject") {
618 @SuppressWarnings("synthetic-access")
619 public void actionPerformed(ActionEvent actionEvent) {
626 * Initializes all child dialogs.
628 private void initDialogs() {
629 manageNodesDialog = new ManageNodesDialog(this);
630 aboutDialog = new AboutDialog(this);
631 configurationDialog = new ConfigurationDialog(this);
639 * Shows the configuration dialog.
641 private void configure() {
642 configurationDialog.setAdvancedMode(advancedMode);
643 configurationDialog.setAntialias(antialias);
644 configurationDialog.setControlFont(controlFont);
645 configurationDialog.setUserFont(userFont);
646 configurationDialog.setLookAndFeel(lookAndFeel);
647 configurationDialog.setVisible(true);
648 if (!configurationDialog.wasCancelled()) {
649 advancedMode = configurationDialog.isAdvancedMode();
650 if (!advancedMode && (nodeList.size() > 1)) {
651 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.message"), I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.title"), JOptionPane.WARNING_MESSAGE);
653 mainWindow.setAdvancedMode(advancedMode);
654 antialias = configurationDialog.isAntialias();
655 controlFont = configurationDialog.getControlFont();
656 userFont = configurationDialog.getUserFont();
657 lookAndFeel = configurationDialog.getLookAndFeel();
663 * Imports old jSite configuration.
665 private void importConfig() {
672 private void quit() {
675 mainWindowX = mainWindow.getX();
676 mainWindowY = mainWindow.getY();
677 mainWindowWidth = mainWindow.getWidth();
678 mainWindowHeight = mainWindow.getHeight();
684 * Rebuilds all node connect and disconnect actions.
689 private void rebuildNodeActions(List<Node> nodes) {
690 logger.fine("rebuilding node actions…");
691 nodeConnectActions.clear();
692 nodeNodeConnectActions.clear();
693 nodeConnectActionNodes.clear();
694 nodeDisconnectActions.clear();
695 nodeNodeDisconnectActions.clear();
696 nodeDisconnectActionNodes.clear();
697 for (Node node: nodes) {
698 logger.finer("adding node “" + node + "” to menus");
699 Action nodeConnectAction = new AbstractAction(node.getName()) {
704 @SuppressWarnings("synthetic-access")
705 public void actionPerformed(ActionEvent e) {
706 Node node = nodeConnectActionNodes.get(this);
710 nodeConnectActions.add(nodeConnectAction);
711 nodeConnectActionNodes.put(nodeConnectAction, node);
712 nodeNodeConnectActions.put(node, nodeConnectAction);
713 Action nodeDisconnectAction = new AbstractAction(node.getName()) {
718 @SuppressWarnings("synthetic-access")
719 public void actionPerformed(ActionEvent e) {
720 Node node = nodeDisconnectActionNodes.get(this);
721 nodeDisconnect(node);
724 // nodeDisconnectActions.add(nodeDisconnectAction);
725 nodeDisconnectActionNodes.put(nodeDisconnectAction, node);
726 nodeNodeDisconnectActions.put(node, nodeDisconnectAction);
731 * Pops up the “manage nodes” dialog.
733 private void manageNodes() {
735 manageNodesDialog.setNodeList(nodeList);
736 manageNodesDialog.setVisible(true);
737 nodeList = manageNodesDialog.getNodeList();
738 rebuildNodeActions(nodeList);
739 mainWindow.refreshNodeMenuItems();
741 if (nodeList.isEmpty()) {
742 Node newNode = new Node();
743 newNode.setName(I18n.get("general.defaultNode.name"));
744 newNode.setHostname("localhost");
745 newNode.setPort(9481);
746 nodeList.add(newNode);
748 Node firstNode = nodeList.get(0);
749 EditNodeDialog editNodeDialog = manageNodesDialog.getEditNodeDialog();
750 editNodeDialog.setNodeName(firstNode.getName());
751 editNodeDialog.setNodeHostname(firstNode.getHostname());
752 editNodeDialog.setNodePort(firstNode.getPort());
753 editNodeDialog.setVisible(true);
754 if (!editNodeDialog.wasCancelled()) {
755 firstNode.setName(editNodeDialog.getNodeName());
756 firstNode.setHostname(editNodeDialog.getNodeHostname());
757 firstNode.setPort(editNodeDialog.getNodePort());
758 /* TODO - give to core. */
764 * Connects to the node.
767 * The node to connect to
769 private void nodeConnect(final Node node) {
770 threadPool.execute(new Runnable() {
775 @SuppressWarnings("synthetic-access")
777 logger.log(Level.INFO, "connecting to node “" + node.getName() + "”…");
778 core.connectToNode(node);
784 * Disconnects from the node.
787 * The node to disconnect from
789 private void nodeDisconnect(Node node) {
790 logger.log(Level.INFO, "disconnecting from node “" + node.getName() + "”…");
791 core.disconnectFromNode(node);
795 * Changes the language of the interface. This method also disables the
796 * action for the newly set language and enables all others.
800 * @param languageAction
801 * The action that triggered the change
803 private void changeLanguage(Locale newLocale, I18nAction languageAction) {
804 for (I18nAction i18nAction: languageActions) {
805 i18nAction.setEnabled(i18nAction != languageAction);
807 I18n.setLocale(newLocale);
811 * Shows the “about” dialog.
813 private void helpAbout() {
814 aboutDialog.setVisible(true);
820 private void addProject() {
822 Project project = core.createProject();
823 mainWindow.addProject(project);
824 project.setName(I18n.get("general.newProject.name"));
825 project.setDescription(I18n.get("general.newProject.description", new Date()));
826 } catch (NoNodeException nne1) {
827 /* TODO - add i18n */
828 JOptionPane.showMessageDialog(mainWindow, I18n.get(""), I18n.get(""), JOptionPane.ERROR_MESSAGE);
829 } catch (IOException e) {
830 /* TODO - add i18n */
831 JOptionPane.showMessageDialog(mainWindow, I18n.get(""), I18n.get(""), JOptionPane.ERROR_MESSAGE);
838 private void cloneProject() {
845 private void deleteProject() {
850 // INTERFACE CoreListener
856 public void loadingProjectsDone(String directory) {
857 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectLoadingDone"));
858 for (Project project: core.getProjects()) {
859 mainWindow.addProject(project);
866 public void loadingProjectsFailed(String directory, Throwable throwable) {
867 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.projectLoadingFailed.message", directory), I18n.get("mainWindow.error.projectLoadingFailed.title"), JOptionPane.ERROR_MESSAGE);
873 public void savingProjectsDone(String directory) {
874 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectSavingDone"));
880 public void savingProjectsFailed(String directory, Throwable throwabled) {
887 public void loadingNodesDone(String directory) {
888 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.loadingNodesDone"));
894 public void loadingNodesFailed(String directory, Throwable throwable) {
901 public void savingNodesDone(String directory) {
902 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.savingNodesDone"));
908 public void savingNodesFailed(String directory, Throwable throwable) {
915 public void coreLoaded() {
916 mainWindow.setVisible(true);
917 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreLoaded"));
923 public void coreStopped() {
924 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreStopped"));
930 public void nodeAdded(Node node) {
931 logger.log(Level.INFO, "node added: " + node);
933 logger.log(Level.FINE, "nodeList.size(): " + nodeList.size());
934 manageNodesDialog.setNodeList(nodeList);
935 rebuildNodeActions(nodeList);
936 mainWindow.refreshNodeMenuItems();
942 public void nodeRemoved(Node node) {
943 logger.log(Level.INFO, "node removed: " + node);
944 nodeList.remove(node);
945 rebuildNodeActions(nodeList);
946 mainWindow.refreshNodeMenuItems();
952 public void nodeConnecting(Node node) {
953 Action nodeConnectAction = nodeNodeConnectActions.get(node);
954 nodeConnectActions.remove(nodeConnectAction);
955 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectingToNode", node.getName(), node.getHostname(), node.getPort()));
956 mainWindow.refreshNodeMenuItems();
962 public void nodeConnected(Node node) {
963 Action nodeDisconnectAction = nodeNodeDisconnectActions.get(node);
964 nodeDisconnectActions.add(nodeDisconnectAction);
965 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectedToNode", node.getName(), node.getHostname(), node.getPort()));
966 mainWindow.refreshNodeMenuItems();
972 public void nodeConnectionFailed(Node node, Throwable cause) {
973 Action nodeConnectAction = nodeNodeConnectActions.get(node);
974 nodeConnectActions.add(nodeConnectAction);
975 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectionToNodeFailed", node.getName(), node.getHostname(), node.getPort(), (cause != null) ? cause.getMessage() : "no reason given"));
976 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);
977 mainWindow.refreshNodeMenuItems();
983 public void nodeDisconnected(Node node, Throwable throwable) {
984 Action nodeConnectAction = nodeNodeConnectActions.get(node);
985 nodeConnectActions.add(nodeConnectAction);
986 Action nodeDisconnectAction = nodeNodeDisconnectActions.get(node);
987 nodeDisconnectActions.remove(nodeDisconnectAction);
988 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.disconnectedFromNode", node.getName(), node.getHostname(), node.getPort()));
989 mainWindow.refreshNodeMenuItems();
995 public void requestAdded(Request request) {
996 logger.log(Level.INFO, "request added to node: " + request + ", " + request.getNode());
997 /* TODO - implement */
998 requestTableModel.addRequest(request);
1004 public void requestProgressed(Request request) {
1005 /* TODO - update table model */
1009 * @see net.pterodactylus.jsite.core.CoreListener#requestRemoved(net.pterodactylus.jsite.core.Request)
1011 public void requestRemoved(Request request) {
1012 requestTableModel.removeRequest(request);
1016 // INTERFACE LoggingListener
1022 public void logged(LogRecord logRecord) {
1023 logWindow.logged(logRecord);