add status bar texts when connecting and disconnecting
[jSite2.git] / src / net / pterodactylus / jsite / gui / SwingInterface.java
index ecd8612..65e1edd 100644 (file)
@@ -25,26 +25,46 @@ import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Properties;
-
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
 import javax.swing.JOptionPane;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
 
 import net.pterodactylus.jsite.core.Core;
 import net.pterodactylus.jsite.core.CoreListener;
 import net.pterodactylus.jsite.core.Node;
+import net.pterodactylus.jsite.core.Project;
+import net.pterodactylus.jsite.core.Request;
 import net.pterodactylus.jsite.i18n.I18n;
 import net.pterodactylus.jsite.i18n.gui.I18nAction;
+import net.pterodactylus.util.image.IconLoader;
 import net.pterodactylus.util.io.Closer;
+import net.pterodactylus.util.logging.Logging;
+import net.pterodactylus.util.logging.LoggingListener;
 
 /**
- * TODO
+ * The Swing user interface.
  * 
  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
  * @version $Id$
  */
-public class SwingInterface implements CoreListener {
+public class SwingInterface implements CoreListener, LoggingListener {
+
+       /** The logger. */
+       private static final Logger logger = Logging.getLogger(SwingInterface.class.getName());
 
        /** The application core. */
        private final Core core;
@@ -55,6 +75,12 @@ public class SwingInterface implements CoreListener {
        /** The main window. */
        private MainWindow mainWindow;
 
+       /** Thread pool. */
+       private Executor threadPool = Executors.newCachedThreadPool();
+
+       /** The logger window. */
+       private LogWindow logWindow;
+
        /** The “configure” action. */
        private I18nAction configureAction;
 
@@ -67,12 +93,30 @@ public class SwingInterface implements CoreListener {
        /** The “manage nodes” action. */
        private I18nAction manageNodesAction;
 
-       /** The “connect to node” action. */
+       /** The “connect to node” (simple mode) action. */
        private I18nAction nodeConnectAction;
 
-       /** The “disconnect from node” action. */
+       /** The “disconnect from node” (simple mode) action. */
        private I18nAction nodeDisconnectAction;
 
+       /** All node menu items. */
+       private List<Action> nodeConnectActions = Collections.synchronizedList(new ArrayList<Action>());
+
+       /** Mapping from nodes to node connect actions. */
+       private Map<Node, Action> nodeNodeConnectActions = Collections.synchronizedMap(new HashMap<Node, Action>());
+
+       /** Mapping from node connect actions to nodes. */
+       private Map<Action, Node> nodeConnectActionNodes = Collections.synchronizedMap(new HashMap<Action, Node>());
+
+       /** All node disconnect actions. */
+       private List<Action> nodeDisconnectActions = Collections.synchronizedList(new ArrayList<Action>());
+
+       /** Mapping from nodes to node disconnect actions. */
+       private Map<Node, Action> nodeNodeDisconnectActions = Collections.synchronizedMap(new HashMap<Node, Action>());
+
+       /** Mapping from node disconnect actions to nodes. */
+       private Map<Action, Node> nodeDisconnectActionNodes = Collections.synchronizedMap(new HashMap<Action, Node>());
+
        /** The node manager dialog. */
        private ManageNodesDialog manageNodesDialog;
 
@@ -85,6 +129,12 @@ public class SwingInterface implements CoreListener {
        /** The “add project” action. */
        private I18nAction addProjectAction;
 
+       /** The “clone project” action. */
+       private I18nAction cloneProjectAction;
+
+       /** The “delete project” action. */
+       private I18nAction deleteProjectAction;
+
        /** The “about” dialog. */
        private AboutDialog aboutDialog;
 
@@ -92,14 +142,26 @@ public class SwingInterface implements CoreListener {
        private ConfigurationDialog configurationDialog;
 
        /** The list of all defined nodes. */
-       private List<Node> nodeList;
+       private List<Node> nodeList = Collections.synchronizedList(new ArrayList<Node>());
 
        //
        // CONFIGURATION
        //
 
-       /** Whether to beautify the GUI. */
-       private boolean beautify;
+       /** The advanced mode. */
+       private boolean advancedMode;
+
+       /** Whether to antialias the GUI. */
+       private boolean antialias;
+
+       /** The control font. */
+       private String controlFont;
+
+       /** The user font. */
+       private String userFont;
+
+       /** The class name of the look and feel. */
+       private String lookAndFeel;
 
        /**
         * Creates a new swing interface.
@@ -114,13 +176,33 @@ public class SwingInterface implements CoreListener {
                this.configDirectory = configDirectory;
                I18n.setLocale(Locale.ENGLISH);
                loadConfig();
-               if (beautify) {
+               if (lookAndFeel != null) {
+                       try {
+                               UIManager.setLookAndFeel(lookAndFeel);
+                       } catch (ClassNotFoundException cnfe1) {
+                               logger.log(Level.WARNING, "could not load look and feel", cnfe1);
+                       } catch (InstantiationException ie1) {
+                               logger.log(Level.WARNING, "could not load look and feel", ie1);
+                       } catch (IllegalAccessException iae1) {
+                               logger.log(Level.WARNING, "could not load look and feel", iae1);
+                       } catch (UnsupportedLookAndFeelException ulafe1) {
+                               logger.log(Level.WARNING, "could not load look and feel", ulafe1);
+                       }
+               }
+               if (antialias) {
                        System.setProperty("swing.aatext", "true");
-                       System.setProperty("swing.plaf.metal.controlFont", "Tahoma");
-                       System.setProperty("swing.plaf.metal.userFont", "Tahoma");
+               }
+               if (controlFont != null) {
+                       System.setProperty("swing.plaf.metal.controlFont", controlFont);
+               }
+               if (userFont != null) {
+                       System.setProperty("swing.plaf.metal.userFont", userFont);
                }
                initActions();
                initDialogs();
+               mainWindow = new MainWindow(this);
+               mainWindow.setAdvancedMode(advancedMode);
+               logWindow = new LogWindow();
        }
 
        //
@@ -146,6 +228,16 @@ public class SwingInterface implements CoreListener {
        }
 
        /**
+        * Returns whether the advanced mode is activated.
+        * 
+        * @return <code>true</code> if the advanced mode is activated,
+        *         <code>false</code> if the simple mode is activated
+        */
+       boolean isAdvancedMode() {
+               return advancedMode;
+       }
+
+       /**
         * Returns the “configure” action.
         * 
         * @return The “configure” action
@@ -191,6 +283,15 @@ public class SwingInterface implements CoreListener {
        }
 
        /**
+        * Returns all “connect node” actions.
+        * 
+        * @return All “connect node” actions
+        */
+       List<Action> getNodeConnectActions() {
+               return nodeConnectActions;
+       }
+
+       /**
         * Returns the “disconnect from node” action.
         * 
         * @return The “disconnect from node” action
@@ -200,6 +301,15 @@ public class SwingInterface implements CoreListener {
        }
 
        /**
+        * Returns all “disconnect node” actions.
+        * 
+        * @return All “disconnect node” action
+        */
+       List<Action> getNodeDisconnectActions() {
+               return nodeDisconnectActions;
+       }
+
+       /**
         * Returns all language actions.
         * 
         * @return All language actions
@@ -226,6 +336,24 @@ public class SwingInterface implements CoreListener {
                return addProjectAction;
        }
 
+       /**
+        * Returns the “clone project” action.
+        * 
+        * @return The “clone project” action
+        */
+       I18nAction getCloneProjectAction() {
+               return cloneProjectAction;
+       }
+
+       /**
+        * Returns the “delete project” action.
+        * 
+        * @return The “delete project” action
+        */
+       I18nAction getDeleteProjectAction() {
+               return deleteProjectAction;
+       }
+
        //
        // ACTIONS
        //
@@ -234,13 +362,6 @@ public class SwingInterface implements CoreListener {
        // SERVICE METHODS
        //
 
-       /**
-        * Starts the interface.
-        */
-       public void start() {
-               mainWindow = new MainWindow(this);
-       }
-
        //
        // PRIVATE METHODS
        //
@@ -250,9 +371,8 @@ public class SwingInterface implements CoreListener {
         */
        private void loadConfig() {
                /* initialize default stuff. */
-               beautify = false;
+               antialias = false;
                /* now read config. */
-               System.out.println("configDirectory: “" + configDirectory + "”");
                File configFile = new File(configDirectory, "swing-interface.properties");
                if (!configFile.exists() || !configFile.canRead() || !configFile.isFile()) {
                        System.err.println("could not find “" + configFile.getAbsolutePath() + "”!");
@@ -268,8 +388,23 @@ public class SwingInterface implements CoreListener {
                } finally {
                        Closer.close(configInputStream);
                }
-               if (configProperties.containsKey("beautify")) {
-                       beautify = Boolean.valueOf(configProperties.getProperty("beautify"));
+               if (configProperties.containsKey("advancedMode")) {
+                       advancedMode = Boolean.valueOf(configProperties.getProperty("advancedMode"));
+               }
+               if (configProperties.containsKey("antialias")) {
+                       antialias = Boolean.valueOf(configProperties.getProperty("antialias"));
+               }
+               if (configProperties.containsKey("controlFont")) {
+                       controlFont = configProperties.getProperty("controlFont");
+               }
+               if (configProperties.containsKey("userFont")) {
+                       userFont = configProperties.getProperty("userFont");
+               }
+               if (configProperties.containsKey("lookAndFeel")) {
+                       lookAndFeel = configProperties.getProperty("lookAndFeel");
+               }
+               if (configProperties.containsKey("language")) {
+                       I18n.setLocale(new Locale(configProperties.getProperty("language")));
                }
        }
 
@@ -290,7 +425,18 @@ public class SwingInterface implements CoreListener {
                }
                File configFile = new File(configDirectory, "swing-interface.properties");
                Properties configProperties = new Properties();
-               configProperties.setProperty("beautify", String.valueOf(beautify));
+               configProperties.setProperty("advancedMode", String.valueOf(advancedMode));
+               configProperties.setProperty("antialias", String.valueOf(antialias));
+               if (controlFont != null) {
+                       configProperties.setProperty("controlFont", controlFont);
+               }
+               if (userFont != null) {
+                       configProperties.setProperty("userFont", userFont);
+               }
+               if (lookAndFeel != null) {
+                       configProperties.setProperty("lookAndFeel", lookAndFeel);
+               }
+               configProperties.setProperty("language", I18n.getLocale().getLanguage());
                FileOutputStream configOutputStream = null;
                try {
                        configOutputStream = new FileOutputStream(configFile);
@@ -306,7 +452,7 @@ public class SwingInterface implements CoreListener {
         * Initializes all actions.
         */
        private void initActions() {
-               configureAction = new I18nAction("mainWindow.menu.jSite.configure") {
+               configureAction = new I18nAction("mainWindow.menu.jSite.configure", IconLoader.loadIcon("/preferences-system.png")) {
 
                        /**
                         * {@inheritDoc}
@@ -326,7 +472,7 @@ public class SwingInterface implements CoreListener {
                                importConfig();
                        }
                };
-               quitAction = new I18nAction("mainWindow.menu.jSite.quit") {
+               quitAction = new I18nAction("mainWindow.menu.jSite.quit", IconLoader.loadIcon("/system-log-out.png")) {
 
                        /**
                         * {@inheritDoc}
@@ -350,7 +496,11 @@ public class SwingInterface implements CoreListener {
 
                        @SuppressWarnings("synthetic-access")
                        public void actionPerformed(ActionEvent actionEvent) {
-                               nodeConnect();
+                               List<Node> nodes = core.getNodes();
+                               if (nodes.isEmpty()) {
+                                       return;
+                               }
+                               nodeConnect(nodes.get(0));
                        }
 
                };
@@ -361,9 +511,14 @@ public class SwingInterface implements CoreListener {
                         */
                        @SuppressWarnings("synthetic-access")
                        public void actionPerformed(ActionEvent e) {
-                               nodeDisconnect();
+                               List<Node> nodes = core.getNodes();
+                               if (nodes.isEmpty()) {
+                                       return;
+                               }
+                               nodeDisconnect(nodes.get(0));
                        }
                };
+               rebuildNodeActions(core.getNodes());
                List<Locale> availableLanguages = I18n.findAvailableLanguages();
                for (final Locale locale: availableLanguages) {
                        I18nAction languageAction = new I18nAction("general.language." + locale.getLanguage()) {
@@ -399,6 +554,26 @@ public class SwingInterface implements CoreListener {
                                addProject();
                        }
                };
+               cloneProjectAction = new I18nAction("mainWindow.button.cloneProject") {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent actionEvent) {
+                               cloneProject();
+                       }
+               };
+               deleteProjectAction = new I18nAction("mainWindow.button.deleteProject") {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void actionPerformed(ActionEvent actionEvent) {
+                               deleteProject();
+                       }
+               };
        }
 
        /**
@@ -418,10 +593,22 @@ public class SwingInterface implements CoreListener {
         * Shows the configuration dialog.
         */
        private void configure() {
-               configurationDialog.setBeautify(beautify);
+               configurationDialog.setAdvancedMode(advancedMode);
+               configurationDialog.setAntialias(antialias);
+               configurationDialog.setControlFont(controlFont);
+               configurationDialog.setUserFont(userFont);
+               configurationDialog.setLookAndFeel(lookAndFeel);
                configurationDialog.setVisible(true);
                if (!configurationDialog.wasCancelled()) {
-                       beautify = configurationDialog.getBeautify();
+                       advancedMode = configurationDialog.isAdvancedMode();
+                       if (!advancedMode && (nodeList.size() > 1)) {
+                               JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.message"), I18n.get("mainWindow.warning.multipleNodesNotAdvancedMode.title"), JOptionPane.WARNING_MESSAGE);
+                       }
+                       mainWindow.setAdvancedMode(advancedMode);
+                       antialias = configurationDialog.isAntialias();
+                       controlFont = configurationDialog.getControlFont();
+                       userFont = configurationDialog.getUserFont();
+                       lookAndFeel = configurationDialog.getLookAndFeel();
                        saveConfig();
                }
        }
@@ -430,35 +617,128 @@ public class SwingInterface implements CoreListener {
         * Imports old jSite configuration.
         */
        private void importConfig() {
+               /* TODO */
        }
 
        /**
         * Quits jSite.
         */
        private void quit() {
+               /* TODO - ask */
+               core.stop();
                saveConfig();
                System.exit(0);
        }
 
        /**
+        * Rebuilds all node connect and disconnect actions.
+        * 
+        * @param nodes
+        *            The list of nodes
+        */
+       private void rebuildNodeActions(List<Node> nodes) {
+               logger.fine("rebuilding node actions…");
+               nodeConnectActions.clear();
+               nodeNodeConnectActions.clear();
+               nodeConnectActionNodes.clear();
+               nodeDisconnectActions.clear();
+               nodeNodeDisconnectActions.clear();
+               nodeDisconnectActionNodes.clear();
+               for (Node node: nodes) {
+                       logger.finer("adding node “" + node + "” to menu");
+                       Action nodeConnectAction = new AbstractAction(node.getName()) {
+
+                               /**
+                                * {@inheritDoc}
+                                */
+                               @SuppressWarnings("synthetic-access")
+                               public void actionPerformed(ActionEvent e) {
+                                       Node node = nodeConnectActionNodes.get(this);
+                                       nodeConnect(node);
+                               }
+                       };
+                       nodeConnectActions.add(nodeConnectAction);
+                       nodeConnectActionNodes.put(nodeConnectAction, node);
+                       nodeNodeConnectActions.put(node, nodeConnectAction);
+                       Action nodeDisconnectAction = new AbstractAction(node.getName()) {
+
+                               /**
+                                * {@inheritDoc}
+                                */
+                               @SuppressWarnings("synthetic-access")
+                               public void actionPerformed(ActionEvent e) {
+                                       Node node = nodeDisconnectActionNodes.get(this);
+                                       nodeDisconnect(node);
+                               }
+                       };
+// nodeDisconnectActions.add(nodeDisconnectAction);
+                       nodeDisconnectActionNodes.put(nodeDisconnectAction, node);
+                       nodeNodeDisconnectActions.put(node, nodeDisconnectAction);
+               }
+       }
+
+       /**
         * Pops up the “manage nodes” dialog.
         */
        private void manageNodes() {
-               manageNodesDialog.setNodeList(nodeList);
-               manageNodesDialog.setVisible(true);
-               nodeList = manageNodesDialog.getNodeList();
+               if (advancedMode) {
+                       manageNodesDialog.setNodeList(nodeList);
+                       manageNodesDialog.setVisible(true);
+                       nodeList = manageNodesDialog.getNodeList();
+                       rebuildNodeActions(nodeList);
+                       mainWindow.refreshNodeMenuItems();
+               } else {
+                       if (nodeList.isEmpty()) {
+                               Node newNode = new Node();
+                               newNode.setName(I18n.get("general.defaultNode.name"));
+                               newNode.setHostname("localhost");
+                               newNode.setPort(9481);
+                               nodeList.add(newNode);
+                       }
+                       Node firstNode = nodeList.get(0);
+                       EditNodeDialog editNodeDialog = manageNodesDialog.getEditNodeDialog();
+                       editNodeDialog.setNodeName(firstNode.getName());
+                       editNodeDialog.setNodeHostname(firstNode.getHostname());
+                       editNodeDialog.setNodePort(firstNode.getPort());
+                       editNodeDialog.setVisible(true);
+                       if (!editNodeDialog.wasCancelled()) {
+                               firstNode.setName(editNodeDialog.getNodeName());
+                               firstNode.setHostname(editNodeDialog.getNodeHostname());
+                               firstNode.setPort(editNodeDialog.getNodePort());
+                               /* TODO - give to core. */
+                       }
+               }
        }
 
        /**
         * Connects to the node.
+        * 
+        * @param node
+        *            The node to connect to
         */
-       private void nodeConnect() {
+       private void nodeConnect(final Node node) {
+               threadPool.execute(new Runnable() {
+
+                       /**
+                        * {@inheritDoc}
+                        */
+                       @SuppressWarnings("synthetic-access")
+                       public void run() {
+                               logger.log(Level.INFO, "connecting to node “" + node.getName() + "”…");
+                               core.connectToNode(node);
+                       }
+               });
        }
 
        /**
         * Disconnects from the node.
+        * 
+        * @param node
+        *            The node to disconnect from
         */
-       private void nodeDisconnect() {
+       private void nodeDisconnect(Node node) {
+               logger.log(Level.INFO, "disconnecting from node “" + node.getName() + "”…");
+               core.disconnectFromNode(node);
        }
 
        /**
@@ -488,6 +768,23 @@ public class SwingInterface implements CoreListener {
         * Adds a project.
         */
        private void addProject() {
+               Project project = new Project();
+               project.setName("New Project");
+               project.setDescription("");
+       }
+
+       /**
+        * Clones a project.
+        */
+       private void cloneProject() {
+               /* TODO */
+       }
+
+       /**
+        * Deletes a project.
+        */
+       private void deleteProject() {
+               /* TODO */
        }
 
        //
@@ -497,36 +794,151 @@ public class SwingInterface implements CoreListener {
        /**
         * {@inheritDoc}
         */
-       public void loadingProjectsFailed(String directory) {
+       public void loadingProjectsDone(String directory) {
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectLoadingDone"));
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void loadingProjectsFailed(String directory, Throwable throwable) {
                JOptionPane.showMessageDialog(mainWindow, I18n.get("mainWindow.error.projectLoadingFailed.message", directory), I18n.get("mainWindow.error.projectLoadingFailed.title"), JOptionPane.ERROR_MESSAGE);
        }
 
        /**
         * {@inheritDoc}
         */
+       public void savingProjectsDone(String directory) {
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.projectSavingDone"));
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void savingProjectsFailed(String directory, Throwable throwabled) {
+               /* TODO */
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void loadingNodesDone(String directory) {
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.loadingNodesDone"));
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void loadingNodesFailed(String directory, Throwable throwable) {
+               /* TODO */
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void savingNodesDone(String directory) {
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.savingNodesDone"));
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void savingNodesFailed(String directory, Throwable throwable) {
+               /* TODO */
+       }
+
+       /**
+        * {@inheritDoc}
+        */
        public void coreLoaded() {
-               this.nodeList = core.getNodes();
-               manageNodesDialog.setNodeList(nodeList);
                mainWindow.setVisible(true);
-               mainWindow.setStatusBarText("Core loaded.");
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreLoaded"));
        }
 
        /**
         * {@inheritDoc}
         */
-       public void nodeConnected(Node node) {
+       public void coreStopped() {
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.coreStopped"));
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void nodeAdded(Node node) {
+               logger.log(Level.INFO, "node added: " + node);
+               nodeList.add(node);
+               manageNodesDialog.setNodeList(nodeList);
+               rebuildNodeActions(nodeList);
+               mainWindow.refreshNodeMenuItems();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void nodeRemoved(Node node) {
+               logger.log(Level.INFO, "node removed: " + node);
+               nodeList.remove(node);
+               rebuildNodeActions(nodeList);
+               mainWindow.refreshNodeMenuItems();
        }
 
        /**
         * {@inheritDoc}
         */
        public void nodeConnecting(Node node) {
+               Action nodeConnectAction = nodeNodeConnectActions.get(node);
+               nodeConnectActions.remove(nodeConnectAction);
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectingToNode", node.getName(), node.getHostname(), node.getPort()));
+               mainWindow.refreshNodeMenuItems();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void nodeConnected(Node node) {
+               Action nodeDisconnectAction = nodeNodeDisconnectActions.get(node);
+               nodeDisconnectActions.add(nodeDisconnectAction);
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.connectedToNode", node.getName(), node.getHostname(), node.getPort()));
+               mainWindow.refreshNodeMenuItems();
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void nodeDisconnected(Node node, Throwable throwable) {
+               Action nodeConnectAction = nodeNodeConnectActions.get(node);
+               nodeConnectActions.add(nodeConnectAction);
+               Action nodeDisconnectAction = nodeNodeDisconnectActions.get(node);
+               nodeDisconnectActions.remove(nodeDisconnectAction);
+               mainWindow.setStatusBarText(I18n.get("mainWindow.statusBar.disconnectedFromNode", node.getName(), node.getHostname(), node.getPort()));
+               mainWindow.refreshNodeMenuItems();
        }
 
        /**
         * {@inheritDoc}
         */
-       public void nodeDisconnected(Node node) {
+       public void requestAdded(Node node, Request request) {
+               logger.log(Level.INFO, "request added to node: " + request + ", " + node);
+               /* TODO - implement */
+       }
+
+       /**
+        * {@inheritDoc}
+        */
+       public void requestProgressed(Request request, int totalBlocks, int requiredBlocks, int successfulBlocks, int failedBlocks, int fatallyFailedBlocks, boolean finalizedTotal) {
+               /* TODO - update table model */
+       }
+
+       //
+       // INTERFACE LoggingListener
+       //
+
+       /**
+        * {@inheritDoc}
+        */
+       public void logged(LogRecord logRecord) {
+               logWindow.logged(logRecord);
        }
 
 }