changeset 248:e2de019ff8d5

Merge
author Roman Kennke <rkennke@redhat.com>
date Thu, 19 Apr 2012 21:19:06 +0200
parents 8c612ce65625 (current diff) faefb5e966dd (diff)
children dae26ae4f542 beb978ab0a6f
files client/src/main/java/com/redhat/thermostat/client/VmPanelFacade.java client/src/main/java/com/redhat/thermostat/client/VmPanelFacadeImpl.java client/src/main/java/com/redhat/thermostat/client/ui/VmPanel.java client/src/test/java/com/redhat/thermostat/client/VmClassStatControllerTest.java
diffstat 23 files changed, 695 insertions(+), 422 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/main/java/com/redhat/thermostat/client/MainWindowControllerImpl.java	Thu Apr 19 21:16:00 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/MainWindowControllerImpl.java	Thu Apr 19 21:19:06 2012 +0200
@@ -48,7 +48,7 @@
 import com.redhat.thermostat.client.ui.ClientConfigurationView;
 import com.redhat.thermostat.client.ui.HostPanel;
 import com.redhat.thermostat.client.ui.SummaryPanel;
-import com.redhat.thermostat.client.ui.VmPanel;
+import com.redhat.thermostat.client.ui.VmInformationController;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.common.Timer;
@@ -76,6 +76,10 @@
     private UiFacadeFactory facadeFactory;
 
     private boolean showHistory;
+
+    private AsyncUiFacade oldController = null;
+
+    private VmInformationControllerProvider vmInfoControllerProvider;
     
     public MainWindowControllerImpl(UiFacadeFactory facadeFactory, MainView view) {
         this.facadeFactory = facadeFactory;
@@ -86,6 +90,9 @@
         vmsDAO = daoFactory.getVmInfoDAO();
 
         initView(view);
+        
+        vmInfoControllerProvider = new VmInformationControllerProvider();
+        
         appInfo = new ApplicationInfo();
         view.setWindowTitle(appInfo.getName());
         initializeTimer();
@@ -209,7 +216,7 @@
         ClientConfigurationController controller = new ClientConfigurationController(prefs, view);
         controller.showDialog();
     }
-    
+
     private void switchHistoryMode() {
         showHistory = !showHistory;
         doUpdateTreeAsync();
@@ -218,6 +225,12 @@
     private void updateView() {
         // this is quite an ugly method. there must be a cleaner way to do this
         Ref ref = view.getSelectedHostOrVm();
+
+        if (oldController != null) {
+            oldController.stop();
+            oldController = null;
+        }
+
         if (ref == null) {
             view.setSubView(new SummaryPanel(facadeFactory.getSummaryPanel()));
         } else if (ref instanceof HostRef) {
@@ -225,10 +238,29 @@
             view.setSubView(new HostPanel(facadeFactory.getHostPanel(hostRef)));
         } else if (ref instanceof VmRef) {
             VmRef vmRef = (VmRef) ref;
-            view.setSubView(new VmPanel(facadeFactory.getVmPanel(vmRef)));
+            VmInformationController vmInformation =
+                    vmInfoControllerProvider.getVmInfoController(vmRef);
+            view.setSubView(vmInformation.getComponent());
+            vmInformation.start();
+            oldController = vmInformation;
         } else {
             throw new IllegalArgumentException("unknown type of ref");
         }
     }
 
+    private class VmInformationControllerProvider {
+        private VmInformationController lastSelectedVM;
+
+        VmInformationController getVmInfoController(VmRef vmRef) {
+            int id = 0;
+            if (lastSelectedVM != null) {
+                id = lastSelectedVM.getSelectedChildID();
+            }
+            lastSelectedVM = facadeFactory.getVmController(vmRef);
+            lastSelectedVM.selectChildID(id);
+
+            return lastSelectedVM;
+        }
+    }
+
 }
--- a/client/src/main/java/com/redhat/thermostat/client/SwingViewFactory.java	Thu Apr 19 21:16:00 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/SwingViewFactory.java	Thu Apr 19 21:19:06 2012 +0200
@@ -53,6 +53,8 @@
 import com.redhat.thermostat.client.ui.VmCpuView;
 import com.redhat.thermostat.client.ui.VmGcPanel;
 import com.redhat.thermostat.client.ui.VmGcView;
+import com.redhat.thermostat.client.ui.VmInformationPanel;
+import com.redhat.thermostat.client.ui.VmInformationView;
 import com.redhat.thermostat.client.ui.VmMemoryPanel;
 import com.redhat.thermostat.client.ui.VmMemoryView;
 import com.redhat.thermostat.client.ui.VmOverviewPanel;
@@ -65,6 +67,8 @@
         setViewClass(AgentConfigurationView.class, AgentConfigurationFrame.class);
         setViewClass(ClientConfigurationView.class, ClientConfigurationFrame.class);
 
+        setViewClass(VmInformationView.class, VmInformationPanel.class);
+
         setViewClass(HostCpuView.class, HostCpuPanel.class);
         setViewClass(HostMemoryView.class, HostMemoryPanel.class);
         setViewClass(HostOverviewView.class, HostOverviewPanel.class);
--- a/client/src/main/java/com/redhat/thermostat/client/UiFacadeFactory.java	Thu Apr 19 21:16:00 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/UiFacadeFactory.java	Thu Apr 19 21:19:06 2012 +0200
@@ -36,6 +36,7 @@
 
 package com.redhat.thermostat.client;
 
+import com.redhat.thermostat.client.ui.VmInformationController;
 import com.redhat.thermostat.common.dao.HostRef;
 import com.redhat.thermostat.common.dao.VmRef;
 
@@ -47,6 +48,6 @@
 
     public HostPanelFacade getHostPanel(HostRef ref);
 
-    public VmPanelFacade getVmPanel(VmRef ref);
+    public VmInformationController getVmController(VmRef ref);
 
 }
--- a/client/src/main/java/com/redhat/thermostat/client/UiFacadeFactoryImpl.java	Thu Apr 19 21:16:00 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/UiFacadeFactoryImpl.java	Thu Apr 19 21:19:06 2012 +0200
@@ -37,6 +37,7 @@
 package com.redhat.thermostat.client;
 
 import com.redhat.thermostat.client.ui.MainWindow;
+import com.redhat.thermostat.client.ui.VmInformationController;
 import com.redhat.thermostat.common.dao.HostRef;
 import com.redhat.thermostat.common.dao.VmRef;
 
@@ -61,8 +62,8 @@
     }
 
     @Override
-    public VmPanelFacade getVmPanel(VmRef ref) {
-        return new VmPanelFacadeImpl(ref);
+    public VmInformationController getVmController(VmRef ref) {
+        return new VmInformationController(ref);
 
     }
 
--- a/client/src/main/java/com/redhat/thermostat/client/VmPanelFacade.java	Thu Apr 19 21:16:00 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.client;
-
-import com.redhat.thermostat.client.ui.VmClassStatController;
-import com.redhat.thermostat.client.ui.VmCpuController;
-import com.redhat.thermostat.client.ui.VmGcController;
-import com.redhat.thermostat.client.ui.VmMemoryController;
-import com.redhat.thermostat.client.ui.VmOverviewController;
-
-/**
- * Represents information specific to a JVM running on a host somewhere. This is
- * used to populate the UI for a VM's information.
- */
-public interface VmPanelFacade extends AsyncUiFacade {
-
-    public VmOverviewController getOverviewController();
-
-    public VmCpuController getCpuController();
-
-    public VmMemoryController getMemoryController();
-
-    public VmClassStatController getClassesController();
-
-    public VmGcController getGcController();
-
-
-}
--- a/client/src/main/java/com/redhat/thermostat/client/VmPanelFacadeImpl.java	Thu Apr 19 21:16:00 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.client;
-
-import com.redhat.thermostat.client.ui.VmClassStatController;
-import com.redhat.thermostat.client.ui.VmCpuController;
-import com.redhat.thermostat.client.ui.VmGcController;
-import com.redhat.thermostat.client.ui.VmMemoryController;
-import com.redhat.thermostat.client.ui.VmOverviewController;
-import com.redhat.thermostat.common.dao.VmRef;
-
-public class VmPanelFacadeImpl implements VmPanelFacade {
-
-    private final VmOverviewController overviewController;
-    private final VmCpuController cpuController;
-    private final VmMemoryController memoryController;
-    private final VmClassStatController classesController;
-    private final VmGcController gcController;
-
-    public VmPanelFacadeImpl(VmRef vmRef) {
-        overviewController = new VmOverviewController(vmRef);
-        cpuController = new VmCpuController(vmRef);
-        memoryController = new VmMemoryController(vmRef);
-        gcController = new VmGcController(vmRef);
-        classesController = new VmClassStatController(vmRef);
-    }
-
-    @Override
-    public void start() {
-        overviewController.start();
-        cpuController.start();
-        memoryController.start();
-        gcController.start();
-        classesController.start();
-
-    }
-
-    @Override
-    public void stop() {
-        overviewController.stop();
-        cpuController.stop();
-        memoryController.stop();
-        gcController.stop();
-        classesController.stop();
-    }
-
-    @Override
-    public VmOverviewController getOverviewController() {
-        return overviewController;
-    }
-
-    @Override
-    public VmCpuController getCpuController() {
-        return cpuController;
-    }
-
-    @Override
-    public VmMemoryController getMemoryController() {
-        return memoryController;
-    }
-
-    @Override
-    public VmGcController getGcController() {
-        return gcController;
-    }
-
-    @Override
-    public VmClassStatController getClassesController() {
-        return classesController;
-    }
-
-}
--- a/client/src/main/java/com/redhat/thermostat/client/ui/AgentConfigurationFrame.java	Thu Apr 19 21:16:00 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/AgentConfigurationFrame.java	Thu Apr 19 21:19:06 2012 +0200
@@ -68,7 +68,7 @@
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
 
-public class AgentConfigurationFrame extends JFrame implements AgentConfigurationView, java.awt.event.ActionListener, ListSelectionListener {
+public class AgentConfigurationFrame extends JFrame implements AgentConfigurationView {
 
     private static final long serialVersionUID = -6049272471909474886L;
 
@@ -79,6 +79,10 @@
     private final JPanel availableBackendsPanel;
     private final GridBagConstraints availableBackendsPanelContstraints = new GridBagConstraints();
 
+    private final ConfigurationCompleteListener configurationComplete;
+    private final AgentChangedListener agentChanged;
+    private final WindowClosingListener windowListener;
+
     private final JButton okayButton;
     private final JButton cancelButton;
 
@@ -89,17 +93,22 @@
     public AgentConfigurationFrame() {
         assertInEDT();
 
+        configurationComplete = new ConfigurationCompleteListener();
+        agentChanged = new AgentChangedListener();
+        windowListener = new WindowClosingListener();
+
         setTitle(localize(LocaleResources.CONFIGURE_AGENT_WINDOW_TITLE));
+        addWindowListener(windowListener);
 
         JLabel lblEnabledisableBackends = new JLabel(localize(LocaleResources.CONFIGURE_ENABLE_BACKENDS));
 
         availableBackendsPanel = new JPanel();
 
         okayButton = new JButton(localize(LocaleResources.BUTTON_OK));
-        okayButton.addActionListener(this);
+        okayButton.addActionListener(configurationComplete);
 
         cancelButton = new JButton(localize(LocaleResources.BUTTON_CANCEL));
-        cancelButton.addActionListener(this);
+        cancelButton.addActionListener(configurationComplete);
 
         JScrollPane scrollPane = new JScrollPane();
 
@@ -150,18 +159,13 @@
 
         listModel = new DefaultListModel<String>();
         agentList = new JList<String>(listModel);
-        agentList.addListSelectionListener(this);
+        agentList.setName("agentList");
+        agentList.addListSelectionListener(agentChanged);
         scrollPane.setViewportView(agentList);
 
         availableBackendsPanel.setLayout(new GridBagLayout());
         getContentPane().setLayout(groupLayout);
 
-        addWindowListener(new WindowAdapter() {
-            @Override
-            public void windowClosing(WindowEvent e) {
-                fireAction(new ActionEvent<>(AgentConfigurationFrame.this, ConfigurationAction.CLOSE_CANCEL));
-            }
-        });
     }
 
     private void resetConstraints() {
@@ -227,7 +231,6 @@
                     JCheckBox checkBox = new JCheckBox(backendName);
                     checkBox.setSelected(checked);
                     checkBox.setActionCommand(backendName);
-                    checkBox.addActionListener(AgentConfigurationFrame.this);
                     backends.put(backendName, checkBox);
                     availableBackendsPanel.add(checkBox, availableBackendsPanelContstraints);
                     availableBackendsPanelContstraints.gridy++;
@@ -270,28 +273,6 @@
         dispose();
     }
 
-    @Override
-    public void actionPerformed(java.awt.event.ActionEvent e) {
-        Object source = e.getSource();
-        if (source == okayButton) {
-            fireAction(new ActionEvent<>(this, ConfigurationAction.CLOSE_ACCEPT));
-        } else if (source == cancelButton) {
-            fireAction(new ActionEvent<>(this, ConfigurationAction.CLOSE_CANCEL));
-        }
-    }
-
-    @Override
-    public void valueChanged(ListSelectionEvent e) {
-        if (e.getSource() == agentList) {
-            if (e.getValueIsAdjusting()) {
-                return;
-            }
-            fireAction(new ActionEvent<>(this, ConfigurationAction.SWITCH_AGENT));
-        } else {
-            throw new IllegalStateException("unknown trigger");
-        }
-    }
-
     private void fireAction(ActionEvent<ConfigurationAction> actionEvent) {
         for (ActionListener<ConfigurationAction> l: listeners) {
             l.actionPerformed(actionEvent);
@@ -304,5 +285,37 @@
         }
     }
 
+    class ConfigurationCompleteListener implements java.awt.event.ActionListener {
+        @Override
+        public void actionPerformed(java.awt.event.ActionEvent e) {
+            Object source = e.getSource();
+            if (source == okayButton) {
+                fireAction(new ActionEvent<>(AgentConfigurationFrame.this, ConfigurationAction.CLOSE_ACCEPT));
+            } else if (source == cancelButton) {
+                fireAction(new ActionEvent<>(AgentConfigurationFrame.this, ConfigurationAction.CLOSE_CANCEL));
+            }
+        }
+    }
+
+    class WindowClosingListener extends WindowAdapter {
+        @Override
+        public void windowClosing(WindowEvent e) {
+            fireAction(new ActionEvent<>(AgentConfigurationFrame.this, ConfigurationAction.CLOSE_CANCEL));
+        }
+    }
+
+    class AgentChangedListener implements ListSelectionListener {
+        @Override
+        public void valueChanged(ListSelectionEvent e) {
+            if (e.getSource() == agentList) {
+                if (e.getValueIsAdjusting()) {
+                    return;
+                }
+                fireAction(new ActionEvent<>(AgentConfigurationFrame.this, ConfigurationAction.SWITCH_AGENT));
+            } else {
+                throw new IllegalStateException("unknown trigger");
+            }
+        }
+    }
 
 }
--- a/client/src/main/java/com/redhat/thermostat/client/ui/ClientConfigurationFrame.java	Thu Apr 19 21:16:00 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/ClientConfigurationFrame.java	Thu Apr 19 21:19:06 2012 +0200
@@ -38,6 +38,8 @@
 
 import static com.redhat.thermostat.client.locale.Translate.localize;
 
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 import javax.swing.GroupLayout;
@@ -46,17 +48,20 @@
 import javax.swing.JFrame;
 import javax.swing.JLabel;
 import javax.swing.JTextField;
+import javax.swing.LayoutStyle.ComponentPlacement;
 import javax.swing.SwingUtilities;
-import javax.swing.LayoutStyle.ComponentPlacement;
 
 import com.redhat.thermostat.client.locale.LocaleResources;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 
-public class ClientConfigurationFrame extends JFrame implements ClientConfigurationView, java.awt.event.ActionListener {
+public class ClientConfigurationFrame extends JFrame implements ClientConfigurationView {
 
     private static final long serialVersionUID = 6888957994092403516L;
 
+    private final ConfigurationCompleteListener configurationCompleteListener;
+    private final WindowClosingListener windowClosingListener;
+
     private final JTextField storageUrl;
     private final JButton btnOk;
     private final JButton btnCancel;
@@ -64,13 +69,17 @@
     private CopyOnWriteArrayList<ActionListener<Action>> listeners = new CopyOnWriteArrayList<>();
 
     public ClientConfigurationFrame() {
+        configurationCompleteListener = new ConfigurationCompleteListener();
+        windowClosingListener = new WindowClosingListener();
+
         setTitle(localize(LocaleResources.CLIENT_PREFS_WINDOW_TITLE));
+        addWindowListener(windowClosingListener);
 
         btnOk = new JButton(localize(LocaleResources.BUTTON_OK));
-        btnOk.addActionListener(this);
+        btnOk.addActionListener(configurationCompleteListener);
         btnOk.setName("ok");
         btnCancel = new JButton(localize(LocaleResources.BUTTON_CANCEL));
-        btnCancel.addActionListener(this);
+        btnCancel.addActionListener(configurationCompleteListener);
         btnCancel.setName("cancel");
         JLabel lblClientConfiguration = new JLabel(localize(LocaleResources.CLIENT_PREFS_GENERAL));
 
@@ -150,15 +159,6 @@
     }
 
     @Override
-    public void actionPerformed(java.awt.event.ActionEvent e) {
-        if (e.getSource() == btnOk) {
-            fireAction(new ActionEvent<>(this, Action.CLOSE_ACCEPT));
-        } else if (e.getSource() == btnCancel) {
-            fireAction(new ActionEvent<>(this, Action.CLOSE_CANCEL));
-        }
-    }
-
-    @Override
     public void addListener(ActionListener<Action> listener) {
         listeners.add(listener);
     }
@@ -179,4 +179,22 @@
             throw new IllegalStateException("must be invoked in the EDT");
         }
     }
+
+    class ConfigurationCompleteListener implements java.awt.event.ActionListener {
+        @Override
+        public void actionPerformed(java.awt.event.ActionEvent e) {
+            if (e.getSource() == btnOk) {
+                fireAction(new ActionEvent<>(ClientConfigurationFrame.this, Action.CLOSE_ACCEPT));
+            } else if (e.getSource() == btnCancel) {
+                fireAction(new ActionEvent<>(ClientConfigurationFrame.this, Action.CLOSE_CANCEL));
+            }
+        }
+    }
+
+    class WindowClosingListener extends WindowAdapter {
+        @Override
+        public void windowClosing(WindowEvent e) {
+            fireAction(new ActionEvent<>(ClientConfigurationFrame.this, Action.CLOSE_CANCEL));
+        }
+    }
 }
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmClassStatController.java	Thu Apr 19 21:16:00 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmClassStatController.java	Thu Apr 19 21:19:06 2012 +0200
@@ -50,7 +50,7 @@
 import com.redhat.thermostat.common.model.DiscreteTimeData;
 import com.redhat.thermostat.common.model.VmClassStat;
 
-public class VmClassStatController implements AsyncUiFacade {
+class VmClassStatController implements AsyncUiFacade {
 
     private class UpdateChartData extends TimerTask {
         @Override
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmCpuController.java	Thu Apr 19 21:16:00 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmCpuController.java	Thu Apr 19 21:19:06 2012 +0200
@@ -50,7 +50,7 @@
 import com.redhat.thermostat.common.model.DiscreteTimeData;
 import com.redhat.thermostat.common.model.VmCpuStat;
 
-public class VmCpuController implements AsyncUiFacade {
+class VmCpuController implements AsyncUiFacade {
 
     private final VmRef ref;
     private final VmCpuStatDAO dao;
@@ -64,7 +64,6 @@
         view = ApplicationContext.getInstance().getViewFactory().getView(VmCpuView.class);
     }
 
-
     @Override
     public void start() {
         timer.scheduleAtFixedRate(new TimerTask() {
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmGcController.java	Thu Apr 19 21:16:00 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmGcController.java	Thu Apr 19 21:19:06 2012 +0200
@@ -61,7 +61,7 @@
 import com.redhat.thermostat.common.model.VmMemoryStat;
 import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
 
-public class VmGcController implements AsyncUiFacade {
+class VmGcController implements AsyncUiFacade {
 
     private final VmRef ref;
     private final VmGcView view;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmInformationController.java	Thu Apr 19 21:19:06 2012 +0200
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.ui;
+
+import static com.redhat.thermostat.client.locale.Translate.localize;
+
+import java.awt.Component;
+
+import com.redhat.thermostat.client.AsyncUiFacade;
+import com.redhat.thermostat.client.locale.LocaleResources;
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.dao.VmRef;
+
+public class VmInformationController implements AsyncUiFacade {
+
+    private final VmInformationView view;
+
+    private final VmOverviewController overviewController;
+    private final VmCpuController cpuController;
+    private final VmMemoryController memoryController;
+    private final VmClassStatController classesController;
+    private final VmGcController gcController;
+
+    public VmInformationController(VmRef vmRef) {
+        overviewController = new VmOverviewController(vmRef);
+        cpuController = new VmCpuController(vmRef);
+        memoryController = new VmMemoryController(vmRef);
+        gcController = new VmGcController(vmRef);
+        classesController = new VmClassStatController(vmRef);
+
+        view = ApplicationContext.getInstance().getViewFactory().getView(VmInformationView.class);
+
+        view.addChildView(localize(LocaleResources.VM_INFO_TAB_OVERVIEW), overviewController.getComponent());
+        view.addChildView(localize(LocaleResources.VM_INFO_TAB_CPU), cpuController.getComponent());
+        view.addChildView(localize(LocaleResources.VM_INFO_TAB_MEMORY), memoryController.getComponent());
+        view.addChildView(localize(LocaleResources.VM_INFO_TAB_GC), gcController.getComponent());
+        view.addChildView(localize(LocaleResources.VM_INFO_TAB_CLASSES), classesController.getComponent());
+    }
+
+    @Override
+    public void start() {
+        overviewController.start();
+        cpuController.start();
+        memoryController.start();
+        gcController.start();
+        classesController.start();
+
+    }
+
+    @Override
+    public void stop() {
+        overviewController.stop();
+        cpuController.stop();
+        memoryController.stop();
+        gcController.stop();
+        classesController.stop();
+    }
+
+    public Component getComponent() {
+        return view.getUiComponent();
+    }
+    
+    public int getSelectedChildID() {
+        return view.getSelectedChildID();
+    }
+    
+    public void selectChildID(int id) {
+        view.selectChildID(id);
+    }
+    
+    public int getNumChildren() {
+        return view.getNumChildren();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmInformationPanel.java	Thu Apr 19 21:19:06 2012 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.ui;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+
+public class VmInformationPanel extends JPanel implements VmInformationView {
+
+    private final JTabbedPane tabPane = new JTabbedPane();
+
+    private int tabCount = 0;
+
+    public VmInformationPanel() {
+        setLayout(new BorderLayout());
+        tabPane.setName("tabPane");
+        add(tabPane);
+    }
+
+    @Override
+    public void addChildView(String title, Component view) {
+        Component component = view;
+        tabPane.insertTab(title, null, component, null, tabCount);
+        tabCount++;
+    }
+
+    @Override
+    public Component getUiComponent() {
+        return this;
+    }
+
+    @Override
+    public int getSelectedChildID() {
+        return tabPane.getSelectedIndex();
+    }
+    
+    @Override
+    public void selectChildID(int id) {
+        tabPane.setSelectedIndex(id);
+    }
+    
+    @Override
+    public int getNumChildren() {
+        return tabPane.getComponentCount();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmInformationView.java	Thu Apr 19 21:19:06 2012 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.ui;
+
+import java.awt.Component;
+
+import com.redhat.thermostat.common.View;
+
+public interface VmInformationView extends View {
+
+    /**
+     * @param view the view. FIXME currently a awt component
+     */
+    void addChildView(String title, Component view);
+
+    Component getUiComponent();
+
+    int getNumChildren();
+    void selectChildID(int id);
+    int getSelectedChildID();
+
+}
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmMemoryController.java	Thu Apr 19 21:16:00 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmMemoryController.java	Thu Apr 19 21:19:06 2012 +0200
@@ -50,7 +50,7 @@
 import com.redhat.thermostat.common.model.VmMemoryStat.Generation;
 import com.redhat.thermostat.common.model.VmMemoryStat.Space;
 
-public class VmMemoryController implements AsyncUiFacade {
+class VmMemoryController implements AsyncUiFacade {
 
     private final VmRef ref;
     private final VmMemoryView view;
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmOverviewController.java	Thu Apr 19 21:16:00 2012 +0200
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/VmOverviewController.java	Thu Apr 19 21:19:06 2012 +0200
@@ -52,7 +52,7 @@
 import com.redhat.thermostat.common.dao.VmRef;
 import com.redhat.thermostat.common.model.VmInfo;
 
-public class VmOverviewController implements AsyncUiFacade {
+class VmOverviewController implements AsyncUiFacade {
 
     private final VmRef ref;
     private final VmInfoDAO dao;
--- a/client/src/main/java/com/redhat/thermostat/client/ui/VmPanel.java	Thu Apr 19 21:16:00 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.client.ui;
-
-import static com.redhat.thermostat.client.locale.Translate.localize;
-
-import java.awt.BorderLayout;
-
-import javax.swing.JPanel;
-import javax.swing.JTabbedPane;
-
-import com.redhat.thermostat.client.VmPanelFacade;
-import com.redhat.thermostat.client.locale.LocaleResources;
-
-
-public class VmPanel extends JPanel {
-
-    private static final long serialVersionUID = 2816226547554943368L;
-
-    private final VmPanelFacade facade;
-
-    public VmPanel(final VmPanelFacade facade) {
-        this.facade = facade;
-        createUI();
-
-        addHierarchyListener(new AsyncFacadeManager(facade));
-    }
-
-    public void createUI() {
-        setLayout(new BorderLayout());
-
-        JTabbedPane tabPane = new JTabbedPane();
-
-        tabPane.insertTab(localize(LocaleResources.VM_INFO_TAB_OVERVIEW), null, facade.getOverviewController().getComponent(), null, 0);
-        tabPane.insertTab(localize(LocaleResources.VM_INFO_TAB_CPU), null, facade.getCpuController().getComponent(), null, 1);
-        tabPane.insertTab(localize(LocaleResources.VM_INFO_TAB_MEMORY), null, facade.getMemoryController().getComponent(), null, 2);
-        tabPane.insertTab(localize(LocaleResources.VM_INFO_TAB_GC), null, facade.getGcController().getComponent(),
-                          localize(LocaleResources.GARBAGE_COLLECTION), 3);
-        tabPane.insertTab(localize(LocaleResources.VM_INFO_TAB_CLASSES), null, facade.getClassesController().getComponent(), null, 4);
-
-        // TODO additional tabs provided by plugins
-        // tabPane.insertTab(title, icon, component, tip, 3)
-
-        this.add(tabPane);
-    }
-
-
-}
--- a/client/src/test/java/com/redhat/thermostat/client/MainWindowControllerImplTest.java	Thu Apr 19 21:16:00 2012 +0200
+++ b/client/src/test/java/com/redhat/thermostat/client/MainWindowControllerImplTest.java	Thu Apr 19 21:19:06 2012 +0200
@@ -45,6 +45,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.times;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -53,7 +54,9 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
+import org.mockito.internal.verification.Times;
 
+import com.redhat.thermostat.client.ui.VmInformationController;
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.common.Timer;
@@ -72,6 +75,8 @@
 
     private MainWindowControllerImpl controller;
 
+    private UiFacadeFactory uiFacadeFactory;
+    
     private MainView view;
 
     private Timer mainWindowTimer;
@@ -92,9 +97,9 @@
         when(summaryPanelFacade.getTotalMonitoredHosts()).thenReturn(new ChangeableText("totalConnectedAgents"));
         when(summaryPanelFacade.getTotalMonitoredVms()).thenReturn(new ChangeableText("connectedVms"));
 
-        UiFacadeFactory uiFacadeFactory = mock(UiFacadeFactory.class);
+        uiFacadeFactory = mock(UiFacadeFactory.class);
         when(uiFacadeFactory.getSummaryPanel()).thenReturn(summaryPanelFacade);
-
+        
         setupDAOs();
 
         view = mock(MainView.class);
@@ -230,4 +235,36 @@
         assertEquals(expected.size(), actual.size());
         assertTrue(expected.containsAll(actual));
     }
+    
+    @Test
+    public void bug954() {
+
+        // see http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=954
+        
+        VmRef vmRef = mock(VmRef.class);
+        when(view.getSelectedHostOrVm()).thenReturn(vmRef);
+                
+        VmInformationController vmInformationController = mock(VmInformationController.class);
+        when(vmInformationController.getSelectedChildID()).thenReturn(3);
+        when(uiFacadeFactory.getVmController(any(VmRef.class))).thenReturn(vmInformationController);
+        
+        l.actionPerformed(new ActionEvent<MainView.Action>(view, MainView.Action.HOST_VM_SELECTION_CHANGED));
+        
+        ArgumentCaptor<Integer> arg = ArgumentCaptor.forClass(Integer.class);
+        verify(vmInformationController).selectChildID(arg.capture());
+        verify(vmInformationController, times(0)).getSelectedChildID();
+        
+        int id = arg.getValue();
+        
+        assertEquals(0, id);
+        
+        l.actionPerformed(new ActionEvent<MainView.Action>(view, MainView.Action.HOST_VM_SELECTION_CHANGED));
+        
+        arg = ArgumentCaptor.forClass(Integer.class);
+        verify(vmInformationController, times(1)).getSelectedChildID();
+        verify(vmInformationController, times(2)).selectChildID(arg.capture());
+        id = arg.getValue();
+        
+        assertEquals(3, id);
+    }
 }
--- a/client/src/test/java/com/redhat/thermostat/client/VmClassStatControllerTest.java	Thu Apr 19 21:16:00 2012 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,101 +0,0 @@
-/*
- * Copyright 2012 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.client;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.Test;
-
-import com.redhat.thermostat.client.ui.VmClassStatController;
-import com.redhat.thermostat.client.ui.VmClassStatView;
-import com.redhat.thermostat.common.ViewFactory;
-import com.redhat.thermostat.common.appctx.ApplicationContext;
-import com.redhat.thermostat.common.dao.DAOFactory;
-import com.redhat.thermostat.common.dao.MongoDAOFactory;
-import com.redhat.thermostat.common.dao.VmClassStatDAO;
-import com.redhat.thermostat.common.dao.VmRef;
-import com.redhat.thermostat.common.model.VmClassStat;
-
-public class VmClassStatControllerTest {
-
-    @SuppressWarnings("unchecked") // any(List.class)
-    @Test
-    public void testChartUpdate() {
-
-        VmClassStat stat1 = new VmClassStat(123, 12345, 1234);
-        List<VmClassStat> stats = new ArrayList<VmClassStat>();
-        stats.add(stat1);
-
-        VmClassStatDAO vmClassStatDAO = mock(VmClassStatDAO.class);
-        when(vmClassStatDAO.getLatestClassStats(any(VmRef.class))).thenReturn(stats).thenReturn(new ArrayList<VmClassStat>());
-
-        DAOFactory daoFactory = mock(MongoDAOFactory.class);
-        when(daoFactory.getVmClassStatsDAO()).thenReturn(vmClassStatDAO);
-
-        ApplicationContext.getInstance().setDAOFactory(daoFactory);
-        VmRef ref = mock(VmRef.class);
-
-        VmClassStatView view = mock(VmClassStatView.class);
-        ViewFactory viewFactory = mock(ViewFactory.class);
-        when(viewFactory.getView(eq(VmClassStatView.class))).thenReturn(view);
-
-        ApplicationContext.getInstance().setViewFactory(viewFactory);
-
-        VmClassStatController controller = new VmClassStatController(ref);
-
-        controller.start();
-
-        try {
-            Thread.sleep(500);
-        } catch (InterruptedException e) {
-            // Get out of here ASAP.
-            return;
-        }
-
-        verify(view, atLeast(1)).addClassCount(any(List.class));
-        // We don't verify atMost() since we might increase the update rate in the future.
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/test/java/com/redhat/thermostat/client/ui/AgentConfigurationFrameTest.java	Thu Apr 19 21:19:06 2012 +0200
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.ui;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
+
+import org.fest.swing.edt.GuiActionRunner;
+import org.fest.swing.edt.GuiQuery;
+import org.fest.swing.edt.GuiTask;
+import org.fest.swing.fixture.FrameFixture;
+import org.fest.swing.fixture.JListFixture;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.redhat.thermostat.common.ActionEvent;
+import com.redhat.thermostat.common.ActionListener;
+
+@RunWith(CacioFESTRunner.class)
+public class AgentConfigurationFrameTest {
+
+    private AgentConfigurationFrame agentConfigFrame;
+    private FrameFixture fixture;
+    private ActionListener<AgentConfigurationView.ConfigurationAction> l;
+
+    @Before
+    public void setUp() {
+        agentConfigFrame = GuiActionRunner.execute(new GuiQuery<AgentConfigurationFrame>() {
+
+            @Override
+            protected AgentConfigurationFrame executeInEDT() throws Throwable {
+                 return new AgentConfigurationFrame();
+            }
+        });
+
+        @SuppressWarnings("unchecked")
+        ActionListener<AgentConfigurationView.ConfigurationAction> listener = mock(ActionListener.class);
+        l = listener;
+        agentConfigFrame.addActionListener(l);
+
+        fixture = new FrameFixture(agentConfigFrame);
+    }
+
+    @After
+    public void tearDown() {
+        GuiActionRunner.execute(new GuiTask() {
+            @Override
+            protected void executeInEDT() throws Throwable {
+                agentConfigFrame.hideDialog();
+            }
+        });
+
+        fixture.requireNotVisible();
+        agentConfigFrame.removeActionListener(l);
+
+        fixture.cleanUp();
+        fixture = null;
+    }
+
+    @Test
+    public void testAddingAgentWorks() {
+        fixture.show();
+        JListFixture list = fixture.list("agentList");
+        assertArrayEquals(new String[0], list.contents());
+
+        agentConfigFrame.addAgent("test-agent");
+
+        assertArrayEquals(new String[] {"test-agent"}, list.contents());
+    }
+
+    @Test
+    public void testSelectingAgentWorks() {
+        fixture.show();
+        agentConfigFrame.addAgent("testAgent");
+        JListFixture list = fixture.list("agentList");
+
+        list.selectItem("testAgent");
+
+        verify(l).actionPerformed(eq(new ActionEvent<>(agentConfigFrame, AgentConfigurationView.ConfigurationAction.SWITCH_AGENT)));
+    }
+
+    @Test
+    public void testRemovingAllAgentsWorks() {
+        fixture.show();
+        agentConfigFrame.addAgent("test-agent");
+        JListFixture list = fixture.list("agentList");
+
+        agentConfigFrame.clearAllAgents();
+
+        assertArrayEquals(new String[0], list.contents());
+    }
+
+    @Test
+    public void testWindowClose() {
+        fixture.show();
+
+        fixture.close();
+
+        verify(l).actionPerformed(eq(new ActionEvent<>(agentConfigFrame, AgentConfigurationView.ConfigurationAction.CLOSE_CANCEL)));
+    }
+
+}
--- a/client/src/test/java/com/redhat/thermostat/client/ui/ClientConfigurationFrameTest.java	Thu Apr 19 21:16:00 2012 +0200
+++ b/client/src/test/java/com/redhat/thermostat/client/ui/ClientConfigurationFrameTest.java	Thu Apr 19 21:19:06 2012 +0200
@@ -44,6 +44,7 @@
 import org.fest.swing.annotation.GUITest;
 import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
 import org.fest.swing.edt.GuiActionRunner;
+import org.fest.swing.edt.GuiQuery;
 import org.fest.swing.edt.GuiTask;
 import org.fest.swing.fixture.FrameFixture;
 import org.fest.swing.fixture.JButtonFixture;
@@ -72,11 +73,11 @@
     @SuppressWarnings("unchecked") // ActionListener
     @Before
     public void setUp() {
-        GuiActionRunner.execute(new GuiTask() {
-            
+        frame = GuiActionRunner.execute(new GuiQuery<ClientConfigurationFrame>() {
+
             @Override
-            protected void executeInEDT() throws Throwable {
-                frame = new ClientConfigurationFrame();
+            protected ClientConfigurationFrame executeInEDT() throws Throwable {
+                 return new ClientConfigurationFrame();
             }
         });
         l = mock(ActionListener.class);
@@ -124,4 +125,14 @@
         verify(l).actionPerformed(eq(new ActionEvent<>(frame, ClientConfigurationView.Action.CLOSE_CANCEL)));
 
     }
+
+    @Category(GUITest.class)
+    @Test
+    public void testCloseWindow() {
+        frameFixture.show();
+
+        frameFixture.close();
+
+        verify(l).actionPerformed(eq(new ActionEvent<>(frame, ClientConfigurationView.Action.CLOSE_CANCEL)));
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/test/java/com/redhat/thermostat/client/ui/VmClassStatControllerTest.java	Thu Apr 19 21:19:06 2012 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.ui;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.redhat.thermostat.client.ui.VmClassStatController;
+import com.redhat.thermostat.client.ui.VmClassStatView;
+import com.redhat.thermostat.common.ViewFactory;
+import com.redhat.thermostat.common.appctx.ApplicationContext;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.dao.MongoDAOFactory;
+import com.redhat.thermostat.common.dao.VmClassStatDAO;
+import com.redhat.thermostat.common.dao.VmRef;
+import com.redhat.thermostat.common.model.VmClassStat;
+
+public class VmClassStatControllerTest {
+
+    @SuppressWarnings("unchecked") // any(List.class)
+    @Test
+    public void testChartUpdate() {
+
+        VmClassStat stat1 = new VmClassStat(123, 12345, 1234);
+        List<VmClassStat> stats = new ArrayList<VmClassStat>();
+        stats.add(stat1);
+
+        VmClassStatDAO vmClassStatDAO = mock(VmClassStatDAO.class);
+        when(vmClassStatDAO.getLatestClassStats(any(VmRef.class))).thenReturn(stats).thenReturn(new ArrayList<VmClassStat>());
+
+        DAOFactory daoFactory = mock(MongoDAOFactory.class);
+        when(daoFactory.getVmClassStatsDAO()).thenReturn(vmClassStatDAO);
+
+        ApplicationContext.getInstance().setDAOFactory(daoFactory);
+        VmRef ref = mock(VmRef.class);
+
+        VmClassStatView view = mock(VmClassStatView.class);
+        ViewFactory viewFactory = mock(ViewFactory.class);
+        when(viewFactory.getView(eq(VmClassStatView.class))).thenReturn(view);
+
+        ApplicationContext.getInstance().setViewFactory(viewFactory);
+
+        VmClassStatController controller = new VmClassStatController(ref);
+
+        controller.start();
+
+        try {
+            Thread.sleep(500);
+        } catch (InterruptedException e) {
+            // Get out of here ASAP.
+            return;
+        }
+
+        verify(view, atLeast(1)).addClassCount(any(List.class));
+        // We don't verify atMost() since we might increase the update rate in the future.
+    }
+
+}
--- a/client/src/test/java/com/redhat/thermostat/client/ui/VmClassStatPanelTest.java	Thu Apr 19 21:16:00 2012 +0200
+++ b/client/src/test/java/com/redhat/thermostat/client/ui/VmClassStatPanelTest.java	Thu Apr 19 21:19:06 2012 +0200
@@ -42,21 +42,39 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
+
+import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
+import org.fest.swing.edt.GuiActionRunner;
+import org.fest.swing.edt.GuiTask;
+import org.junit.BeforeClass;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
 import com.redhat.thermostat.common.model.DiscreteTimeData;
 
+@RunWith(CacioFESTRunner.class)
 public class VmClassStatPanelTest {
 
+    @BeforeClass
+    public static void setUpOnce() {
+        FailOnThreadViolationRepaintManager.install();
+    }
+
     @Test
     public void testAddDataTwice() {
-        VmClassStatPanel panel = new VmClassStatPanel();
-        List<DiscreteTimeData<Long>> data = new ArrayList<>();
-        panel.addClassCount(data);
-        int numComponents = panel.getComponentCount();
-        assertTrue(numComponents > 0);
-        panel.addClassCount(data);
-        assertEquals(numComponents, panel.getComponentCount());
+        GuiActionRunner.execute(new GuiTask() {
+            @Override
+            protected void executeInEDT() throws Throwable {
+                VmClassStatPanel panel = new VmClassStatPanel();
+                List<DiscreteTimeData<Long>> data = new ArrayList<>();
+                panel.addClassCount(data);
+                int numComponents = panel.getComponentCount();
+                assertTrue(numComponents > 0);
+                panel.addClassCount(data);
+                assertEquals(numComponents, panel.getComponentCount());
+            }
+        });
     }
 
 }