changeset 1503:ea12b5a9665b

Improved Heap Analysis View with a more accessible export button in the list of heap dumps. Reviewed-by: neugens, omajid Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2014-August/010594.html
author Jie Kang <jkang@redhat.com>
date Wed, 03 Sep 2014 11:52:37 -0400
parents c50bc474711d
children 14e2cef1069a
files vm-heap-analysis/client-core/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/core/HeapDumpListView.java vm-heap-analysis/client-core/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/core/internal/HeapDumpController.java vm-heap-analysis/client-core/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/core/internal/HeapDumpListController.java vm-heap-analysis/client-core/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/core/internal/HeapDumpListControllerTest.java vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/Constants.java vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/HeapSwingView.java vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/SwingHeapDumpListView.java vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/HeapDumpListViewTest.java
diffstat 8 files changed, 363 insertions(+), 120 deletions(-) [+]
line wrap: on
line diff
--- a/vm-heap-analysis/client-core/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/core/HeapDumpListView.java	Thu Aug 21 13:41:38 2014 -0400
+++ b/vm-heap-analysis/client-core/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/core/HeapDumpListView.java	Wed Sep 03 11:52:37 2014 -0400
@@ -49,9 +49,10 @@
  */
 public abstract class HeapDumpListView extends BasicView implements UIComponent {
     public enum ListAction {
-        DUMP_SELECTED,
+        OPEN_DUMP_DETAILS, //Payload HeapDump.class
+        EXPORT_DUMP, //Payload HeapDump.class
     }
-    
+
     protected final ActionNotifier<ListAction> listNotifier;
     protected HeapDumpListView() {
         listNotifier = new ActionNotifier<ListAction>(this);
--- a/vm-heap-analysis/client-core/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/core/internal/HeapDumpController.java	Thu Aug 21 13:41:38 2014 -0400
+++ b/vm-heap-analysis/client-core/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/core/internal/HeapDumpController.java	Wed Sep 03 11:52:37 2014 -0400
@@ -221,14 +221,7 @@
                     
                 case REQUEST_EXPORT: {
                     dump = (HeapDump) actionEvent.getPayload();
-                    DumpFile localHeapDump = new DumpFile();
-                    SimpleDateFormat format = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS");
-                    Date date = new Date(dump.getTimestamp());
-                    String timeStamp = format.format(date);
-                    String id = "heapdump-" + ref.getName() + "-" + timeStamp + "." + dump.getType();
-                    localHeapDump.setFile(new File(id));
-                    localHeapDump.setDump(dump);
-                    view.openExportDialog(localHeapDump);
+                    exportDump(dump);
                 } break;
                 
                 case SAVE_HEAP_DUMP: {                    
@@ -325,6 +318,17 @@
         });
     }
 
+    void exportDump(final HeapDump dump) {
+        DumpFile localHeapDump = new DumpFile();
+        SimpleDateFormat format = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss_SSS");
+        Date date = new Date(dump.getTimestamp());
+        String timeStamp = format.format(date);
+        String id = "heapdump-" + ref.getName() + "-" + timeStamp + "." + dump.getType();
+        localHeapDump.setFile(new File(id));
+        localHeapDump.setDump(dump);
+        view.openExportDialog(localHeapDump);
+    }
+
     private void showHeapDumpDetails(HeapDump dump) {
         HeapDumpDetailsController controller =
                 new HeapDumpDetailsController(appService, detailsViewProvider,
--- a/vm-heap-analysis/client-core/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/core/internal/HeapDumpListController.java	Thu Aug 21 13:41:38 2014 -0400
+++ b/vm-heap-analysis/client-core/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/core/internal/HeapDumpListController.java	Wed Sep 03 11:52:37 2014 -0400
@@ -42,7 +42,6 @@
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.vm.heap.analysis.client.core.HeapDumpListView;
 import com.redhat.thermostat.vm.heap.analysis.client.core.HeapDumpListViewProvider;
-import com.redhat.thermostat.vm.heap.analysis.client.core.HeapDumpListView.ListAction;
 import com.redhat.thermostat.vm.heap.analysis.common.HeapDump;
 
 public class HeapDumpListController {
@@ -53,8 +52,15 @@
         view = viewProvider.createView();
         view.addListListener(new ActionListener<HeapDumpListView.ListAction>() {
             @Override
-            public void actionPerformed(ActionEvent<ListAction> actionEvent) {
-                mainController.analyseDump((HeapDump) actionEvent.getPayload());
+            public void actionPerformed(ActionEvent<HeapDumpListView.ListAction> actionEvent) {
+                switch (actionEvent.getActionId()) {
+                    case OPEN_DUMP_DETAILS:
+                        mainController.analyseDump((HeapDump) actionEvent.getPayload());
+                        break;
+                    case EXPORT_DUMP:
+                        mainController.exportDump((HeapDump) actionEvent.getPayload());
+                        break;
+                }
             }
         });
     }
--- a/vm-heap-analysis/client-core/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/core/internal/HeapDumpListControllerTest.java	Thu Aug 21 13:41:38 2014 -0400
+++ b/vm-heap-analysis/client-core/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/core/internal/HeapDumpListControllerTest.java	Wed Sep 03 11:52:37 2014 -0400
@@ -36,6 +36,13 @@
 
 package com.redhat.thermostat.vm.heap.analysis.client.core.internal;
 
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
 import java.util.List;
 
 import org.junit.Before;
@@ -46,16 +53,8 @@
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.vm.heap.analysis.client.core.HeapDumpListView;
 import com.redhat.thermostat.vm.heap.analysis.client.core.HeapDumpListViewProvider;
-import com.redhat.thermostat.vm.heap.analysis.client.core.HeapDumpListView.ListAction;
 import com.redhat.thermostat.vm.heap.analysis.common.HeapDump;
 
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.junit.Assert.assertNotNull;
-
 public class HeapDumpListControllerTest {
 
     private HeapDumpController mainController;
@@ -82,10 +81,10 @@
         
         HeapDumpListController controller = new HeapDumpListController(provider, mainController);
         
-        ActionListener<ListAction> listener = viewArgumentCaptor.getValue();
+        ActionListener<HeapDumpListView.ListAction> listener = viewArgumentCaptor.getValue();
         assertNotNull(listener);
         
-        ActionEvent<ListAction> actionEvent = new ActionEvent<HeapDumpListView.ListAction>(view, ListAction.DUMP_SELECTED);
+        ActionEvent<HeapDumpListView.ListAction> actionEvent = new ActionEvent<HeapDumpListView.ListAction>(view, HeapDumpListView.ListAction.OPEN_DUMP_DETAILS);
         actionEvent.setPayload(dump);
         listener.actionPerformed(actionEvent);
         
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/Constants.java	Wed Sep 03 11:52:37 2014 -0400
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012-2014 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.vm.heap.analysis.client.swing.internal;
+
+import java.awt.Dimension;
+import java.awt.Insets;
+
+public final class Constants {
+
+    private Constants() {
+        // don't instantiate
+        throw new AssertionError();
+    }
+
+    static final Insets INVISIBLE_INSETS = new Insets(0, 0, 0, 0);
+    static final Insets THIN_INSETS = new Insets(1, 1, 1, 1);
+
+    static final Dimension MINIMUM_SIZE = new Dimension(0, 0);
+
+
+}
--- a/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/HeapSwingView.java	Thu Aug 21 13:41:38 2014 -0400
+++ b/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/HeapSwingView.java	Wed Sep 03 11:52:37 2014 -0400
@@ -66,7 +66,6 @@
 import com.redhat.thermostat.shared.locale.LocalizedString;
 import com.redhat.thermostat.shared.locale.Translate;
 import com.redhat.thermostat.vm.heap.analysis.client.core.HeapDumpListView;
-import com.redhat.thermostat.vm.heap.analysis.client.core.HeapDumpListView.ListAction;
 import com.redhat.thermostat.vm.heap.analysis.client.core.HeapIconResources;
 import com.redhat.thermostat.vm.heap.analysis.client.core.HeapView;
 import com.redhat.thermostat.vm.heap.analysis.client.core.chart.OverviewChart;
@@ -98,7 +97,7 @@
     private JPanel stack;
     
     private JFileChooser fileChooser;
-    
+
     public HeapSwingView() {
         stats = new StatsPanel();
         stats.addHeapDumperListener(new ActionListener() {
@@ -371,14 +370,14 @@
             SwingHeapDumpListView swingView = (SwingHeapDumpListView) view;
             view.addListListener(new com.redhat.thermostat.common.ActionListener<HeapDumpListView.ListAction>() {
                 @Override
-                public void actionPerformed(com.redhat.thermostat.common.ActionEvent<ListAction> actionEvent) {
+                public void actionPerformed(com.redhat.thermostat.common.ActionEvent<HeapDumpListView.ListAction> actionEvent) {
                     switch (actionEvent.getActionId()) {
-                    case DUMP_SELECTED:
-                        closeDumpListView();
-                        break;
-                        
-                    default:
-                        break;
+                        case OPEN_DUMP_DETAILS:
+                            closeDumpListView();
+                            break;
+
+                        default:
+                            break;
                     }
                 }
             });
--- a/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/SwingHeapDumpListView.java	Thu Aug 21 13:41:38 2014 -0400
+++ b/vm-heap-analysis/client-swing/src/main/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/SwingHeapDumpListView.java	Wed Sep 03 11:52:37 2014 -0400
@@ -38,6 +38,12 @@
 
 import java.awt.BorderLayout;
 import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.util.ArrayList;
@@ -45,14 +51,19 @@
 import java.util.Comparator;
 import java.util.List;
 
-import javax.swing.DefaultListModel;
-import javax.swing.JList;
+import javax.swing.BoxLayout;
+import javax.swing.Icon;
+import javax.swing.JButton;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
-import javax.swing.ListCellRenderer;
+import javax.swing.Scrollable;
 import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.border.EmptyBorder;
 
 import com.redhat.thermostat.client.swing.SwingComponent;
+import com.redhat.thermostat.client.swing.components.ActionButton;
+import com.redhat.thermostat.client.swing.components.FontAwesomeIcon;
 import com.redhat.thermostat.client.swing.components.ShadowLabel;
 import com.redhat.thermostat.client.swing.components.ThermostatThinScrollBar;
 import com.redhat.thermostat.client.ui.Palette;
@@ -64,49 +75,42 @@
 
     private JPanel container;
     private JScrollPane scrollPane;
-    private HeapDumpModel model;
-    private JList<HeapDump> list;
+    private HeapDumpPanel table;
 
     public SwingHeapDumpListView() {
         container = new JPanel();
-        container.setName(getClass().getName());
-        container.setLayout(new BorderLayout(0, 0));
+        container.setLayout(new BorderLayout());
         container.setOpaque(false);
 
-        model = new HeapDumpModel();
-        list = new JList<>(model);
-        list.setName(getClass().getName() + "_LIST");
-        list.setBorder(null);
-        list.setOpaque(false);
-        list.addMouseListener(new MouseAdapter() {
-            public void mouseClicked(MouseEvent evt) {
-                if (evt.getClickCount() == 2) {
-                    int index = list.locationToIndex(evt.getPoint());
-                    HeapDump dump = model.get(index);
-                    listNotifier.fireAction(ListAction.DUMP_SELECTED, dump);
-                }
-            }
-        });
-        
-        list.setCellRenderer(new HeapCellRenderer());
-        
-        scrollPane = new JScrollPane(list);
+        table = new HeapDumpPanel();
+        BoxLayout layout = new BoxLayout(table, BoxLayout.Y_AXIS);
+        table.setLayout(layout);
+        table.setBorder(new EmptyBorder(Constants.THIN_INSETS));
+        table.setOpaque(false);
+
+        scrollPane = new JScrollPane(table);
         scrollPane.setVerticalScrollBar(new ThermostatThinScrollBar(ThermostatThinScrollBar.VERTICAL));
-        scrollPane.setBorder(null);
+        scrollPane.setBorder(new EmptyBorder(Constants.INVISIBLE_INSETS));
         scrollPane.setViewportBorder(null);
         scrollPane.getViewport().setOpaque(false);
         scrollPane.setOpaque(false);
 
         container.add(scrollPane, BorderLayout.CENTER);
+
+        JPanel invisibleFixture = new JPanel();
+        invisibleFixture.setOpaque(false);
+        invisibleFixture.setMaximumSize(Constants.MINIMUM_SIZE);
+
+        container.add(invisibleFixture, BorderLayout.SOUTH);
     }
-    
+
     @Override
     public Component getUiComponent() {
         return container;
     }
     
     @Override
-    public void setDumps(List<HeapDump> dumps) {
+    public void setDumps(final List<HeapDump> dumps) {
         
         final List<HeapDump> _dumps = new ArrayList<>(dumps);
         Collections.sort(_dumps, new DumpsComparator());
@@ -114,18 +118,16 @@
         SwingUtilities.invokeLater(new Runnable() {
             @Override
             public void run() {
-                model.clear();
-                for (HeapDump  dump : _dumps) {
-                    model.addElement(dump);
-                    container.repaint();
+                table.clear();
+                for (final HeapDump  dump : dumps) {
+                    final HeapDumpItem item = new HeapDumpItem(dump);
+                    table.add(item);
                 }
+                container.revalidate();
             }
         });
     }
-    
-    @SuppressWarnings("serial")
-    private class HeapDumpModel extends DefaultListModel<HeapDump> {}
-    
+
     private class DumpsComparator implements Comparator<HeapDump> {
         @Override
         public int compare(HeapDump o1, HeapDump o2) {
@@ -135,26 +137,154 @@
             return -result;
         }
     }
-    
-    private class HeapCellRenderer implements ListCellRenderer<HeapDump> {
+
+    private class HeapDumpPanel extends JPanel implements Scrollable {
+        private List<HeapDumpItem> heapdumpList = new ArrayList<>();
+
+        public HeapDumpPanel() {
+            setDoubleBuffered(true);
+        }
+
+        public void heapDumpItemMouseOver(final HeapDumpItem item) {
+            SwingUtilities.invokeLater(new Runnable() {
+                @Override
+                public void run() {
+                    for (HeapDumpItem i : heapdumpList) {
+                        i.toggleDisplayButtonOff();
+                    }
+                    item.toggleDisplayButtonOn();
+                }
+            });
+        }
+
+
+        @Override
+        public java.awt.Component add(java.awt.Component comp) {
+            super.add(comp);
+            heapdumpList.add((HeapDumpItem) comp);
+            return comp;
+        }
+
+        public void clear() {
+            for (HeapDumpItem item : heapdumpList) {
+                super.remove(item);
+            }
+            heapdumpList.clear();
+        }
+
+        @Override
+        public Dimension getPreferredScrollableViewportSize() {
+            return super.getPreferredSize();
+        }
+
+        @Override
+        public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
+            //Unit scroll 1/10th of the panel's height.
+            //Used when scrolling with scrollbar arrows.
+            return (int)(this.getPreferredSize().getHeight() / 10);
+        }
+
+        @Override
+        public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
+            //Block scroll 1/5th of the panel's height.
+            //Used when scrolling with mouse-wheel clicks.
+            return (int)(this.getPreferredSize().getHeight() / 5);
+        }
+
+        @Override
+        public boolean getScrollableTracksViewportWidth() {
+            return true;
+        }
 
         @Override
-        public Component getListCellRendererComponent(JList<? extends HeapDump> list, HeapDump value, int index,
-                                                      boolean isSelected, boolean cellHasFocus) {
-            
-            ShadowLabel label = new ShadowLabel(new LocalizedString(value.toString()));
+        public boolean getScrollableTracksViewportHeight() {
+            return false;
+        }
+
+    }
+
+    private class HeapDumpItem extends JPanel {
+        private HeapDump heapDump;
+        private JButton button;
+
+        public HeapDumpItem(final HeapDump heapDump) {
+            super();
+
+            this.setName(heapDump.toString() + "_panel");
+            this.heapDump = heapDump;
+
+            ShadowLabel label = new ShadowLabel(new LocalizedString(heapDump.toString()));
             label.setForeground(Palette.ROYAL_BLUE.getColor());
+            label.setName(heapDump.toString() + "_label");
+
+            char iconId = '\uF019';
+            Icon icon = new FontAwesomeIcon(iconId, (int) label.getMinimumSize().getHeight());
+            button = new ActionButton(icon);
+
+            button.setToolTipText("Export heap dump.");
+            button.setName(heapDump.toString() + "_button");
+            button.setBackground(null);
+
+            button.addActionListener(new ActionListener() {
+                @Override
+                public void actionPerformed(ActionEvent e) {
+                    listNotifier.fireAction(ListAction.EXPORT_DUMP, HeapDumpItem.this.heapDump);
+                }
+            });
+
+            button.setVisible(false);
+
+            GridBagLayout gbl = new GridBagLayout();
+            setLayout(gbl);
+
+            GridBagConstraints gbc = new GridBagConstraints();
 
-            if (!isSelected) {
-                label.setOpaque(false);
-            } else {
-                label.setOpaque(true);
-                label.setBackground(Palette.ELEGANT_CYAN.getColor());
-            }
-            
-            return label;
+            gbc.gridy = 0;
+            gbc.gridx = GridBagConstraints.RELATIVE;
+            gbc.fill = GridBagConstraints.HORIZONTAL;
+            gbc.weighty = 1;
+
+            gbc.weightx = 1;
+            add(label, gbc);
+
+            gbc.weightx = 0;
+            add(button, gbc);
+
+            setOpaque(false);
+            setBorder(new EmptyBorder(Constants.THIN_INSETS));
+            setPreferredSize(label.getPreferredSize());
+
+            this.addMouseListener(new MouseAdapter() {
+                public void mouseClicked(MouseEvent evt) {
+                    if (evt.getClickCount() == 2) {
+                        listNotifier.fireAction(ListAction.OPEN_DUMP_DETAILS, HeapDumpItem.this.heapDump);
+                    }
+
+                }
+
+                public void mouseEntered(MouseEvent evt) {
+                    table.heapDumpItemMouseOver(HeapDumpItem.this);
+                }
+            });
         }
-        
+
+        private void toggleDisplayButtonOn() {
+            this.setBackground(Palette.ELEGANT_CYAN.getColor());
+            setOpaque(true);
+            button.setVisible(true);
+        }
+
+        private void toggleDisplayButtonOff() {
+            this.setBackground(UIManager.getColor("Panel.background"));
+            setOpaque(false);
+            button.setVisible(false);
+        }
+
+        @Override
+        public Dimension getMaximumSize() {
+            int width = (int) super.getMaximumSize().getWidth();
+            return new Dimension(width, (int) this.getPreferredSize().getHeight());
+        }
     }
 }
 
--- a/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/HeapDumpListViewTest.java	Thu Aug 21 13:41:38 2014 -0400
+++ b/vm-heap-analysis/client-swing/src/test/java/com/redhat/thermostat/vm/heap/analysis/client/swing/internal/HeapDumpListViewTest.java	Wed Sep 03 11:52:37 2014 -0400
@@ -36,27 +36,25 @@
 
 package com.redhat.thermostat.vm.heap.analysis.client.swing.internal;
 
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.TestCase.assertTrue;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertEquals;
-
 import java.util.ArrayList;
 import java.util.List;
 
 import javax.swing.JFrame;
-
-import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
+import javax.swing.JPanel;
 
 import org.fest.swing.annotation.GUITest;
 import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
 import org.fest.swing.edt.GuiActionRunner;
 import org.fest.swing.edt.GuiTask;
 import org.fest.swing.fixture.FrameFixture;
-import org.fest.swing.fixture.JListFixture;
-
+import org.fest.swing.fixture.JButtonFixture;
+import org.fest.swing.fixture.JLabelFixture;
+import org.fest.swing.fixture.JPanelFixture;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -66,9 +64,10 @@
 import com.redhat.thermostat.common.ActionEvent;
 import com.redhat.thermostat.common.ActionListener;
 import com.redhat.thermostat.vm.heap.analysis.client.core.HeapDumpListView;
-import com.redhat.thermostat.vm.heap.analysis.client.core.HeapDumpListView.ListAction;
 import com.redhat.thermostat.vm.heap.analysis.common.HeapDump;
 
+import net.java.openjdk.cacio.ctc.junit.CacioFESTRunner;
+
 @RunWith(CacioFESTRunner.class)
 public class HeapDumpListViewTest {
 
@@ -93,6 +92,7 @@
             }
         });
         frameFixture = new FrameFixture(frame);
+        frameFixture.show();
     }
 
     @After
@@ -103,45 +103,94 @@
     
     @GUITest
     @Test
-    public void testDumpSelectedFired() {
-        
+    public void testDumpDetailsFired() {
         final boolean [] result = new boolean[1];
         final HeapDump [] selectedHeap = new HeapDump[1];
 
         view.addListListener(new ActionListener<HeapDumpListView.ListAction>() {
             @Override
-            public void actionPerformed(ActionEvent<ListAction> actionEvent) {
-                result[0] = true;
-                selectedHeap[0] = (HeapDump) actionEvent.getPayload();
+            public void actionPerformed(ActionEvent<HeapDumpListView.ListAction> actionEvent) {
+                switch (actionEvent.getActionId()) {
+                    case OPEN_DUMP_DETAILS:
+                        result[0] = true;
+                        selectedHeap[0] = (HeapDump) actionEvent.getPayload();
+                        break;
+                }
             }
         });
-        
-        frameFixture.show();
-        
+
         HeapDump dump1 = mock(HeapDump.class);
-        when(dump1.getTimestamp()).thenReturn(1L);
-        
-        HeapDump dump2 = mock(HeapDump.class);
-        when(dump2.getTimestamp()).thenReturn(2L);
-        
+        when(dump1.toString()).thenReturn("dump1");
+
+        List<HeapDump> dumps = new ArrayList<>();
+        dumps.add(dump1);
+
+        view.setDumps(dumps);
+
+        JLabelFixture label = frameFixture.label("dump1_label");
+        label.doubleClick();
+
+        assertTrue(result[0]);
+        assertEquals(dump1, selectedHeap[0]);
+    }
+
+    @GUITest
+    @Test
+    public void testDu1mpSelectFired() {
+        final boolean [] result = new boolean[1];
+        final JPanel[] selectedHeap = new JPanel[1];
+
+
+        HeapDump dump1 = mock(HeapDump.class);
+        when(dump1.toString()).thenReturn("dump1");
+
         List<HeapDump> dumps = new ArrayList<>();
         dumps.add(dump1);
-        dumps.add(dump2);
-        
+
         view.setDumps(dumps);
-        
-        verify(dump1).getTimestamp();
-        verify(dump2).getTimestamp();
-        
-        JListFixture list = frameFixture.list(SwingHeapDumpListView.class.getName() + "_LIST");
-        list.item(0).doubleClick();
-                
-        assertTrue(result[0]);
-        assertEquals(dump2, selectedHeap[0]);
-        
-        result[0] = false;        
-        list.item(1).doubleClick();
-                
+
+        JPanelFixture item = frameFixture.panel("dump1_panel");
+
+        JLabelFixture label = frameFixture.label("dump1_label");
+        label.click();
+
+        JButtonFixture button = frameFixture.button("dump1_button");
+
+        assertTrue(button.target.isVisible());
+    }
+
+    @GUITest
+    @Test
+    public void testExportFired() {
+        final boolean [] result = new boolean[1];
+        final HeapDump [] selectedHeap = new HeapDump[1];
+
+        view.addListListener(new ActionListener<HeapDumpListView.ListAction>() {
+            @Override
+            public void actionPerformed(ActionEvent<HeapDumpListView.ListAction> actionEvent) {
+                switch (actionEvent.getActionId()) {
+                    case EXPORT_DUMP:
+                        result[0] = true;
+                        selectedHeap[0] = (HeapDump) actionEvent.getPayload();
+                        break;
+                }
+            }
+        });
+
+        HeapDump dump1 = mock(HeapDump.class);
+        when(dump1.toString()).thenReturn("dump1");
+
+        List<HeapDump> dumps = new ArrayList<>();
+        dumps.add(dump1);
+
+        view.setDumps(dumps);
+
+        JLabelFixture label = frameFixture.label("dump1_label");
+        label.click();
+
+        JButtonFixture button = frameFixture.button("dump1_button");
+        button.click();
+
         assertTrue(result[0]);
         assertEquals(dump1, selectedHeap[0]);
     }