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.HashMap;
30 import java.util.List;
31 import java.util.Locale;
33 import java.util.Properties;
34 import java.util.concurrent.Executor;
35 import java.util.concurrent.Executors;
36 import java.util.logging.Level;
37 import java.util.logging.LogRecord;
38 import java.util.logging.Logger;
40 import javax.swing.AbstractAction;
41 import javax.swing.Action;
42 import javax.swing.JOptionPane;
43 import javax.swing.UIManager;
44 import javax.swing.UnsupportedLookAndFeelException;
46 import net.pterodactylus.jsite.core.Core;
47 import net.pterodactylus.jsite.core.CoreListener;
48 import net.pterodactylus.jsite.core.Node;
49 import net.pterodactylus.jsite.core.Project;
50 import net.pterodactylus.jsite.core.Request;
51 import net.pterodactylus.jsite.i18n.I18n;
52 import net.pterodactylus.jsite.i18n.gui.I18nAction;
53 import net.pterodactylus.util.image.IconLoader;
54 import net.pterodactylus.util.io.Closer;
55 import net.pterodactylus.util.logging.Logging;
56 import net.pterodactylus.util.logging.LoggingListener;
59 * The Swing user interface.
61 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
64 public class SwingInterface implements CoreListener, LoggingListener {
67 private static final Logger logger = Logging.getLogger(SwingInterface.class.getName());
69 /** The application core. */
70 private final Core core;
72 /** The configuration directory. */
73 private final String configDirectory;
75 /** The main window. */
76 private MainWindow mainWindow;
79 private Executor threadPool = Executors.newCachedThreadPool();
81 /** The logger window. */
82 private LogWindow logWindow;
84 /** The “configure” action. */
85 private I18nAction configureAction;
87 /** The “import config” action. */
88 private I18nAction importConfigAction;
90 /** The “quit” action. */
91 private I18nAction quitAction;
93 /** The “manage nodes” action. */
94 private I18nAction manageNodesAction;
96 /** The “connect to node” (simple mode) action. */
97 private I18nAction nodeConnectAction;
99 /** The “disconnect from node” (simple mode) action. */
100 private I18nAction nodeDisconnectAction;
102 /** All node menu items. */
103 private List<Action> nodeConnectActions = Collections.synchronizedList(new ArrayList<Action>());
105 /** Mapping from nodes to node connect actions. */
106 private Map<Node, Action> nodeNodeConnectActions = Collections.synchronizedMap(new HashMap<Node, Action>());
108 /** Mapping from node connect actions to nodes. */
109 private Map<Action, Node> nodeConnectActionNodes = Collections.synchronizedMap(new HashMap<Action, Node>());
111 /** All node disconnect actions. */
112 private List<Action> nodeDisconnectActions = Collections.synchronizedList(new ArrayList<Action>());
114 /** Mapping from nodes to node disconnect actions. */
115 private Map<Node, Action> nodeNodeDisconnectActions = Collections.synchronizedMap(new HashMap<Node, Action>());
117 /** Mapping from node disconnect actions to nodes. */
118 private Map<Action, Node> nodeDisconnectActionNodes = Collections.synchronizedMap(new HashMap<Action, Node>());
120 /** The node manager dialog. */
121 private ManageNodesDialog manageNodesDialog;
123 /** All lanugage menu items. */
124 private List<I18nAction> languageActions = new ArrayList<I18nAction>();
126 /** The “about” action. */
127 private I18nAction helpAboutAction;
129 /** The “add project” action. */
130 private I18nAction addProjectAction;
132 /** The “clone project” action. */
133 private I18nAction cloneProjectAction;
135 /** The “delete project” action. */
136 private I18nAction deleteProjectAction;
138 /** The “about” dialog. */
139 private AboutDialog aboutDialog;
141 /** The configuration dialog. */
142 private ConfigurationDialog configurationDialog;
144 /** The list of all defined nodes. */
145 private List<Node> nodeList = Collections.synchronizedList(new ArrayList<Node>());
147 /** The request table model. */
148 private RequestTableModel requestTableModel = new RequestTableModel();
154 /** The advanced mode. */
155 private boolean advancedMode;
157 /** Whether to antialias the GUI. */
158 private boolean antialias;
160 /** The control font. */
161 private String controlFont;
163 /** The user font. */
164 private String userFont;
166 /** The class name of the look and feel. */
167 private String lookAndFeel;
169 /** X coordinate of the main window. */
170 private int mainWindowX = -1;
172 /** Y coordinate of the main window. */
173 private int mainWindowY = -1;
175 /** Width of the main window. */
176 private int mainWindowWidth = -1;
178 /** Height of the main window. */
179 private int mainWindowHeight = -1;
182 * Creates a new swing interface.
185 * The core to operate on
186 * @param configDirectory
187 * The directory the configuration is stored in
189 public SwingInterface(Core core, String configDirectory) {
191 this.configDirectory = configDirectory;
192 I18n.setLocale(Locale.ENGLISH);
194 if (lookAndFeel != null) {
196 UIManager.setLookAndFeel(lookAndFeel);
197 } catch (ClassNotFoundException cnfe1) {
198 logger.log(Level.WARNING, "could not load look and feel", cnfe1);
199 } catch (InstantiationException ie1) {
200 logger.log(Level.WARNING, "could not load look and feel", ie1);
201 } catch (IllegalAccessException iae1) {
202 logger.log(Level.WARNING, "could not load look and feel", iae1);
203 } catch (UnsupportedLookAndFeelException ulafe1) {
204 logger.log(Level.WARNING, "could not load look and feel", ulafe1);
208 System.setProperty("swing.aatext", "true");
210 if (controlFont != null) {
211 System.setProperty("swing.plaf.metal.controlFont", controlFont);
213 if (userFont != null) {
214 System.setProperty("swing.plaf.metal.userFont", userFont);
218 mainWindow = new MainWindow(this);
219 mainWindow.setAdvancedMode(advancedMode);
220 if ((mainWindowX != -1) && (mainWindowY != -1) && (mainWindowWidth != -1) && (mainWindowHeight != -1)) {
221 mainWindow.setLocation(mainWindowX, mainWindowY);
222 mainWindow.setSize(mainWindowWidth, mainWindowHeight);
224 logWindow = new LogWindow();
232 * Returns the core that is controlled by the Swing interface.
241 * Returns the main window of the Swing interface.
243 * @return The main window
245 MainWindow getMainWindow() {
250 * Returns whether the advanced mode is activated.
252 * @return <code>true</code> if the advanced mode is activated,
253 * <code>false</code> if the simple mode is activated
255 boolean isAdvancedMode() {
260 * Returns the “configure” action.
262 * @return The “configure” action
264 I18nAction getConfigureAction() {
265 return configureAction;
269 * Returns the “import config” action.
271 * @return The “import config” action
273 I18nAction getImportConfigAction() {
274 return importConfigAction;
278 * Returns the “quit” action.
280 * @return The “quit” action
282 I18nAction getQuitAction() {
287 * Returns the “manage nodes” action.
289 * @return The “manage nodes” action
291 I18nAction getManageNodesAction() {
292 return manageNodesAction;
296 * Returns the “connect to node” action.
298 * @return The “connect to node” action
300 I18nAction getNodeConnectAction() {
301 return nodeConnectAction;
305 * Returns all “connect node” actions.
307 * @return All “connect node” actions
309 List<Action> getNodeConnectActions() {
310 return nodeConnectActions;
314 * Returns the “disconnect from node” action.
316 * @return The “disconnect from node” action
318 I18nAction getNodeDisconnectAction() {
319 return nodeDisconnectAction;
323 * Returns all “disconnect node” actions.
325 * @return All “disconnect node” action
327 List<Action> getNodeDisconnectActions() {
328 return nodeDisconnectActions;
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 “clone project” action.
361 * @return The “clone project” action
363 I18nAction getCloneProjectAction() {
364 return cloneProjectAction;
368 * Returns the “delete project” action.
370 * @return The “delete project” action
372 I18nAction getDeleteProjectAction() {
373 return deleteProjectAction;
377 * Returns the request table model.
379 * @return The request table model
381 RequestTableModel getRequestTableModel() {
382 return requestTableModel;
398 * Loads the configuration of the interface.
400 private void loadConfig() {
401 /* initialize default stuff. */
403 /* now read config. */
404 File configFile = new File(configDirectory, "swing-interface.properties");
405 if (!configFile.exists() || !configFile.canRead() || !configFile.isFile()) {
406 System.err.println("could not find “" + configFile.getAbsolutePath() + "”!");
409 Properties configProperties = new Properties();
410 FileInputStream configInputStream = null;
412 configInputStream = new FileInputStream(configFile);
413 configProperties.load(configInputStream);
414 } catch (IOException ioe1) {
415 System.err.println("could not load config, " + ioe1.getMessage());
417 Closer.close(configInputStream);
419 if (configProperties.containsKey("advancedMode")) {
420 advancedMode = Boolean.valueOf(configProperties.getProperty("advancedMode"));
422 if (configProperties.containsKey("antialias")) {
423 antialias = Boolean.valueOf(configProperties.getProperty("antialias"));
425 if (configProperties.containsKey("controlFont")) {
426 controlFont = configProperties.getProperty("controlFont");
428 if (configProperties.containsKey("userFont")) {
429 userFont = configProperties.getProperty("userFont");
431 if (configProperties.containsKey("lookAndFeel")) {
432 lookAndFeel = configProperties.getProperty("lookAndFeel");
434 if (configProperties.containsKey("language")) {
435 I18n.setLocale(new Locale(configProperties.getProperty("language")));
437 if (configProperties.containsKey("mainWindowX")) {
438 mainWindowX = Integer.valueOf(configProperties.getProperty("mainWindowX"));
440 if (configProperties.containsKey("mainWindowY")) {
441 mainWindowY = Integer.valueOf(configProperties.getProperty("mainWindowY"));
443 if (configProperties.containsKey("mainWindowWidth")) {
444 mainWindowWidth = Integer.valueOf(configProperties.getProperty("mainWindowWidth"));
446 if (configProperties.containsKey("mainWindowHeight")) {
447 mainWindowHeight = Integer.valueOf(configProperties.getProperty("mainWindowHeight"));
452 * Saves the configuration.
454 private void saveConfig() {
455 File configDirectory = new File(this.configDirectory);
456 if (!configDirectory.exists()) {
457 if (!configDirectory.mkdirs()) {
458 System.err.println("could not create “" + this.configDirectory + "”!");
462 if (!configDirectory.exists() || !configDirectory.isDirectory() || !configDirectory.canWrite()) {
463 System.err.println("can not access “" + this.configDirectory + "”!");
466 File configFile = new File(configDirectory, "swing-interface.properties");
467 Properties configProperties = new Properties();
468 configProperties.setProperty("advancedMode", String.valueOf(advancedMode));
469 configProperties.setProperty("antialias", String.valueOf(antialias));
470 if (controlFont != null) {
471 configProperties.setProperty("controlFont", controlFont);
473 if (userFont != null) {
474 configProperties.setProperty("userFont", userFont);
476 if (lookAndFeel != null) {
477 configProperties.setProperty("lookAndFeel", lookAndFeel);
479 configProperties.setProperty("language", I18n.getLocale().getLanguage());
480 configProperties.setProperty("mainWindowX", String.valueOf(mainWindowX));
481 configProperties.setProperty("mainWindowY", String.valueOf(mainWindowY));
482 configProperties.setProperty("mainWindowWidth", String.valueOf(mainWindowWidth));
483 configProperties.setProperty("mainWindowHeight", String.valueOf(mainWindowHeight));
484 FileOutputStream configOutputStream = null;
486 configOutputStream = new FileOutputStream(configFile);
487 configProperties.store(configOutputStream, "configuration of swing interface");
488 } catch (IOException ioe1) {
489 System.err.println("could not save config, " + ioe1.getMessage());
491 Closer.close(configOutputStream);
496 * Initializes all actions.
498 private void initActions() {
499 configureAction = new I18nAction("mainWindow.menu.jSite.configure", IconLoader.loadIcon("/preferences-system.png")) {
504 @SuppressWarnings("synthetic-access")
505 public void actionPerformed(ActionEvent actionEvent) {
509 importConfigAction = new I18nAction("mainWindow.menu.jSite.importConfig") {
514 @SuppressWarnings("synthetic-access")
515 public void actionPerformed(ActionEvent actionEvent) {
519 quitAction = new I18nAction("mainWindow.menu.jSite.quit", IconLoader.loadIcon("/system-log-out.png")) {
524 @SuppressWarnings("synthetic-access")
525 public void actionPerformed(ActionEvent actionEvent) {
529 manageNodesAction = new I18nAction("mainWindow.menu.node.item.manageNodes") {
534 @SuppressWarnings("synthetic-access")
535 public void actionPerformed(ActionEvent actionEvent) {
539 nodeConnectAction = new I18nAction("mainWindow.menu.node.item.connect", false) {
541 @SuppressWarnings("synthetic-access")
542 public void actionPerformed(ActionEvent actionEvent) {
543 List<Node> nodes = core.getNodes();
544 if (nodes.isEmpty()) {
547 nodeConnect(nodes.get(0));
551 nodeDisconnectAction = new I18nAction("mainWindow.menu.node.item.disconnect", false) {
556 @SuppressWarnings("synthetic-access")
557 public void actionPerformed(ActionEvent e) {
558 List<Node> nodes = core.getNodes();
559 if (nodes.isEmpty()) {
562 nodeDisconnect(nodes.get(0));
565 rebuildNodeActions(core.getNodes());
566 List<Locale> availableLanguages = I18n.findAvailableLanguages();
567 for (final Locale locale: availableLanguages) {
568 I18nAction languageAction = new I18nAction("general.language." + locale.getLanguage()) {
570 @SuppressWarnings("synthetic-access")
571 public void actionPerformed(ActionEvent e) {
572 changeLanguage(locale, this);
576 if (I18n.getLocale().getLanguage().equals(locale.getLanguage())) {
577 languageAction.setEnabled(false);
579 languageActions.add(languageAction);
581 helpAboutAction = new I18nAction("mainWindow.menu.help.item.about") {
586 @SuppressWarnings("synthetic-access")
587 public void actionPerformed(ActionEvent actionEvent) {
591 addProjectAction = new I18nAction("mainWindow.button.addProject") {
596 @SuppressWarnings("synthetic-access")
597 public void actionPerformed(ActionEvent actionEvent) {
601 cloneProjectAction = new I18nAction("mainWindow.button.cloneProject") {
606 @SuppressWarnings("synthetic-access")
607 public void actionPerformed(ActionEvent actionEvent) {
611 deleteProjectAction = new I18nAction("mainWindow.button.deleteProject") {
616 @SuppressWarnings("synthetic-access")
617 public void actionPerformed(ActionEvent actionEvent) {
624 * Initializes all child dialogs.
626 private void initDialogs() {
627 manageNodesDialog = new ManageNodesDialog(this);
628 aboutDialog = new AboutDialog(this);
629 configurationDialog = new ConfigurationDialog(this);
637 * Shows the configuration dialog.
639 private void configure() {
640 configurationDialog.setAdvancedMode(advancedMode);
641 configurationDialog.setAntialias(antialias);
642 configurationDialog.setControlFont(controlFont);
643 configurationDialog.setUserFont(userFont);
644 configurationDialog.setLookAndFeel(lookAndFeel);
645 configurationDialog.setVisible(true);
646 if (!configurationDialog.wasCancelled()) {
647 advancedMode = configurationDialog.isAdvancedMode();
648 if (!advancedMode && (nodeList.size() > 1)) {
649 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.message"), I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.title"), JOptionPane.WARNING_MESSAGE);
651 mainWindow.setAdvancedMode(advancedMode);
652 antialias = configurationDialog.isAntialias();
653 controlFont = configurationDialog.getControlFont();
654 userFont = configurationDialog.getUserFont();
655 lookAndFeel = configurationDialog.getLookAndFeel();
661 * Imports old jSite configuration.
663 private void importConfig() {
670 private void quit() {
673 mainWindowX = mainWindow.getX();
674 mainWindowY = mainWindow.getY();
675 mainWindowWidth = mainWindow.getWidth();
676 mainWindowHeight = mainWindow.getHeight();
682 * Rebuilds all node connect and disconnect actions.
687 private void rebuildNodeActions(List<Node> nodes) {
688 logger.fine("rebuilding node actions…");
689 nodeConnectActions.clear();
690 nodeNodeConnectActions.clear();
691 nodeConnectActionNodes.clear();
692 nodeDisconnectActions.clear();
693 nodeNodeDisconnectActions.clear();
694 nodeDisconnectActionNodes.clear();
695 for (Node node: nodes) {
696 logger.finer("adding node “" + node + "” to menus");
697 Action nodeConnectAction = new AbstractAction(node.getName()) {
702 @SuppressWarnings("synthetic-access")
703 public void actionPerformed(ActionEvent e) {
704 Node node = nodeConnectActionNodes.get(this);
708 nodeConnectActions.add(nodeConnectAction);
709 nodeConnectActionNodes.put(nodeConnectAction, node);
710 nodeNodeConnectActions.put(node, nodeConnectAction);
711 Action nodeDisconnectAction = new AbstractAction(node.getName()) {
716 @SuppressWarnings("synthetic-access")
717 public void actionPerformed(ActionEvent e) {
718 Node node = nodeDisconnectActionNodes.get(this);
719 nodeDisconnect(node);
722 // nodeDisconnectActions.add(nodeDisconnectAction);
723 nodeDisconnectActionNodes.put(nodeDisconnectAction, node);
724 nodeNodeDisconnectActions.put(node, nodeDisconnectAction);
729 * Pops up the “manage nodes” dialog.
731 private void manageNodes() {
733 manageNodesDialog.setNodeList(nodeList);
734 manageNodesDialog.setVisible(true);
735 nodeList = manageNodesDialog.getNodeList();
736 rebuildNodeActions(nodeList);
737 mainWindow.refreshNodeMenuItems();
739 if (nodeList.isEmpty()) {
740 Node newNode = new Node();
741 newNode.setName(I18n.get("general.defaultNode.name"));
742 newNode.setHostname("localhost");
743 newNode.setPort(9481);
744 nodeList.add(newNode);
746 Node firstNode = nodeList.get(0);
747 EditNodeDialog editNodeDialog = manageNodesDialog.getEditNodeDialog();
748 editNodeDialog.setNodeName(firstNode.getName());
749 editNodeDialog.setNodeHostname(firstNode.getHostname());
750 editNodeDialog.setNodePort(firstNode.getPort());
751 editNodeDialog.setVisible(true);
752 if (!editNodeDialog.wasCancelled()) {
753 firstNode.setName(editNodeDialog.getNodeName());
754 firstNode.setHostname(editNodeDialog.getNodeHostname());
755 firstNode.setPort(editNodeDialog.getNodePort());
756 /* TODO - give to core. */
762 * Connects to the node.
765 * The node to connect to
767 private void nodeConnect(final Node node) {
768 threadPool.execute(new Runnable() {
773 @SuppressWarnings("synthetic-access")
775 logger.log(Level.INFO, "connecting to node “" + node.getName() + "”…");
776 core.connectToNode(node);
782 * Disconnects from the node.
785 * The node to disconnect from
787 private void nodeDisconnect(Node node) {
788 logger.log(Level.INFO, "disconnecting from node “" + node.getName() + "”…");
789 core.disconnectFromNode(node);
793 * Changes the language of the interface. This method also disables the
794 * action for the newly set language and enables all others.
798 * @param languageAction
799 * The action that triggered the change
801 private void changeLanguage(Locale newLocale, I18nAction languageAction) {
802 for (I18nAction i18nAction: languageActions) {
803 i18nAction.setEnabled(i18nAction != languageAction);
805 I18n.setLocale(newLocale);
809 * Shows the “about” dialog.
811 private void helpAbout() {
812 aboutDialog.setVisible(true);
818 private void addProject() {
819 Project project = new Project();
820 project.setName("New Project");
821 project.setDescription("");
827 private void cloneProject() {
834 private void deleteProject() {
839 // INTERFACE CoreListener
845 public void loadingProjectsDone(String directory) {
846 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectLoadingDone"));
852 public void loadingProjectsFailed(String directory, Throwable throwable) {
853 JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.projectLoadingFailed.message", directory), I18n.get("mainWindow.error.projectLoadingFailed.title"), JOptionPane.ERROR_MESSAGE);
859 public void savingProjectsDone(String directory) {
860 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectSavingDone"));
866 public void savingProjectsFailed(String directory, Throwable throwabled) {
873 public void loadingNodesDone(String directory) {
874 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.loadingNodesDone"));
880 public void loadingNodesFailed(String directory, Throwable throwable) {
887 public void savingNodesDone(String directory) {
888 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.savingNodesDone"));
894 public void savingNodesFailed(String directory, Throwable throwable) {
901 public void coreLoaded() {
902 mainWindow.setVisible(true);
903 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreLoaded"));
909 public void coreStopped() {
910 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreStopped"));
916 public void nodeAdded(Node node) {
917 logger.log(Level.INFO, "node added: " + node);
919 logger.log(Level.FINE, "nodeList.size(): " + nodeList.size());
920 manageNodesDialog.setNodeList(nodeList);
921 rebuildNodeActions(nodeList);
922 mainWindow.refreshNodeMenuItems();
928 public void nodeRemoved(Node node) {
929 logger.log(Level.INFO, "node removed: " + node);
930 nodeList.remove(node);
931 rebuildNodeActions(nodeList);
932 mainWindow.refreshNodeMenuItems();
938 public void nodeConnecting(Node node) {
939 Action nodeConnectAction = nodeNodeConnectActions.get(node);
940 nodeConnectActions.remove(nodeConnectAction);
941 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectingToNode", node.getName(), node.getHostname(), node.getPort()));
942 mainWindow.refreshNodeMenuItems();
948 public void nodeConnected(Node node) {
949 Action nodeDisconnectAction = nodeNodeDisconnectActions.get(node);
950 nodeDisconnectActions.add(nodeDisconnectAction);
951 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectedToNode", node.getName(), node.getHostname(), node.getPort()));
952 mainWindow.refreshNodeMenuItems();
958 public void nodeConnectionFailed(Node node, Throwable cause) {
959 Action nodeConnectAction = nodeNodeConnectActions.get(node);
960 nodeConnectActions.add(nodeConnectAction);
961 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectionToNodeFailed", node.getName(), node.getHostname(), node.getPort(), (cause != null) ? cause.getMessage() : "no reason given"));
962 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);
963 mainWindow.refreshNodeMenuItems();
969 public void nodeDisconnected(Node node, Throwable throwable) {
970 Action nodeConnectAction = nodeNodeConnectActions.get(node);
971 nodeConnectActions.add(nodeConnectAction);
972 Action nodeDisconnectAction = nodeNodeDisconnectActions.get(node);
973 nodeDisconnectActions.remove(nodeDisconnectAction);
974 mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.disconnectedFromNode", node.getName(), node.getHostname(), node.getPort()));
975 mainWindow.refreshNodeMenuItems();
981 public void requestAdded(Request request) {
982 logger.log(Level.INFO, "request added to node: " + request + ", " + request.getNode());
983 /* TODO - implement */
984 requestTableModel.addRequest(request);
990 public void requestProgressed(Request request) {
991 /* TODO - update table model */
995 // INTERFACE LoggingListener
1001 public void logged(LogRecord logRecord) {
1002 logWindow.logged(logRecord);